Skip to content

Commit

Permalink
Merge pull request #128 from mtrberzi/issue118-netlist-construction
Browse files Browse the repository at this point in the history
Netlist construction from schematic
mtrberzi committed Jul 21, 2014

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents e68d458 + c614351 commit babea4b
Showing 5 changed files with 435 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/main/java/org/manifold/compiler/back/digital/Net.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.manifold.compiler.back.digital;

import java.util.HashSet;
import java.util.Set;

import org.manifold.compiler.PortValue;
import org.manifold.compiler.UndefinedBehaviourError;

import com.google.common.collect.ImmutableSet;

// In digital design, a "net" is a wire that connects multiple ports together.
// Because the connections supported by the compiler are
// traditional graph edges, which connect only two ports at a time,
// Nets make it easier to work with instances where one port
// is connected to two or more other ports to supply them with signal.

public class Net {
private String name;

public String getName() {
return name;
}

public Net(String name) {
this.name = name;
}

private Set<PortValue> connectedPorts = new HashSet<>();

public Set<PortValue> getConnectedPorts() {
return ImmutableSet.copyOf(connectedPorts);
}

public void addPort(PortValue port) {
if (connectedPorts.contains(port)) {
throw new UndefinedBehaviourError(
"port is connected to the same net twice");
} else {
connectedPorts.add(port);
}
}
}
110 changes: 110 additions & 0 deletions src/main/java/org/manifold/compiler/back/digital/Netlist.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package org.manifold.compiler.back.digital;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.manifold.compiler.ConnectionType;
import org.manifold.compiler.ConnectionValue;
import org.manifold.compiler.PortTypeValue;
import org.manifold.compiler.PortValue;
import org.manifold.compiler.TypeMismatchException;
import org.manifold.compiler.UndeclaredIdentifierException;
import org.manifold.compiler.middle.Schematic;

import com.google.common.collect.ImmutableMap;

public class Netlist {

private ConnectionType digitalWireType;
private PortTypeValue digitalInType;
private PortTypeValue digitalOutType;

private Map<String, Net> nets = new HashMap<>();

public Map<String, Net> getNets() {
return ImmutableMap.copyOf(nets);
}

private Map<PortValue, Net> connectedNet = new HashMap<>();

public Net getConnectedNet(PortValue port) {
if (connectedNet.containsKey(port)) {
return connectedNet.get(port);
} else {
throw new IllegalArgumentException("port not connected to any nets");
}
}

public Netlist(Schematic schematic) throws UndeclaredIdentifierException,
TypeMismatchException {
digitalWireType = schematic.getConnectionType("digitalWire");
digitalInType = schematic.getPortType("digitalIn");
digitalOutType = schematic.getPortType("digitalOut");

// iterate over connections in the schematic and build nets
for (Entry<String, ConnectionValue> connEntry : schematic.getConnections()
.entrySet()) {
String connectionName = connEntry.getKey();
ConnectionValue connection = connEntry.getValue();

verifyConnectionIsDigitalWire(connection);

// get both ports
PortValue portFrom = connection.getFrom();
PortValue portTo = connection.getTo();

verifyPortIsDigitalOut(portFrom);
verifyPortIsDigitalIn(portTo);

// now we can take both ports and attach them to a net
if (connectedNet.containsKey(portFrom)) {
Net existingNet = connectedNet.get(portFrom);
if (connectedNet.containsKey(portTo)) {
// both ports already connected to a net
} else {
connectToNet(portTo, existingNet);
}
} else {
// portFrom not connected to a net
if (connectedNet.containsKey(portTo)) {
Net existingNet = connectedNet.get(portTo);
connectToNet(portFrom, existingNet);
} else {
// neither port is connected to a net, so create a new one
String netName = "n_" + connectionName;
Net newNet = new Net(netName);
nets.put(netName, newNet);
connectToNet(portFrom, newNet);
connectToNet(portTo, newNet);
}
}
}
}

private void verifyConnectionIsDigitalWire(ConnectionValue connection)
throws TypeMismatchException {
if (!connection.getType().equals(digitalWireType)) {
throw new TypeMismatchException(digitalWireType, connection.getType());
}
}

private void verifyPortIsDigitalOut(PortValue port)
throws TypeMismatchException {
if (!port.getType().equals(digitalOutType)) {
throw new TypeMismatchException(digitalOutType, port.getType());
}
}

private void verifyPortIsDigitalIn(PortValue port)
throws TypeMismatchException {
if (!port.getType().equals(digitalInType)) {
throw new TypeMismatchException(digitalInType, port.getType());
}
}

private void connectToNet(PortValue port, Net net) {
net.addPort(port);
connectedNet.put(port, net);
}
}
6 changes: 6 additions & 0 deletions src/main/java/org/manifold/compiler/middle/Schematic.java
Original file line number Diff line number Diff line change
@@ -15,6 +15,8 @@
import org.manifold.compiler.UndefinedBehaviourError;
import org.manifold.compiler.BooleanTypeValue;
import org.manifold.compiler.IntegerTypeValue;

import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

@@ -215,6 +217,10 @@ public ConnectionValue getConnection(String instanceName)
}
}

public Map<String, ConnectionValue> getConnections() {
return ImmutableMap.copyOf(connections);
}

public void addConstraint(String instanceName, ConstraintValue constraint)
throws MultipleAssignmentException {
if (constraints.containsKey(instanceName)){
49 changes: 49 additions & 0 deletions src/test/java/org/manifold/compiler/back/TestNet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.manifold.compiler.back;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import org.manifold.compiler.NodeTypeValue;
import org.manifold.compiler.NodeValue;
import org.manifold.compiler.PortTypeValue;
import org.manifold.compiler.PortValue;
import org.manifold.compiler.TypeValue;
import org.manifold.compiler.Value;
import org.manifold.compiler.back.digital.Net;
import org.manifold.compiler.middle.SchematicException;

public class TestNet {

@Test
public void testGetName() {
String name = "asdf";
Net n = new Net(name);
assertEquals(name, n.getName());
}

@Test
public void testGetConnectedPorts_initiallyEmpty() {
Net n = new Net("asdf");
assertTrue(n.getConnectedPorts().isEmpty());
}

@Test
public void testAddPort() throws SchematicException {
Net n = new Net("asdf");
PortTypeValue portType = new PortTypeValue(
new HashMap<String, TypeValue>());
NodeTypeValue nodeType = new NodeTypeValue(new HashMap<String, TypeValue>(),
new HashMap<String, PortTypeValue>());
Map<String, Map<String, Value>> portAttrMaps =
new HashMap<String, Map<String, Value>>();
NodeValue parent = new NodeValue(nodeType, new HashMap<String, Value>(),
portAttrMaps);
PortValue p = new PortValue(portType, parent, new HashMap<String, Value>());
n.addPort(p);
assertTrue(n.getConnectedPorts().contains(p));
}

}
228 changes: 228 additions & 0 deletions src/test/java/org/manifold/compiler/back/TestNetlist.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package org.manifold.compiler.back;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;

import org.junit.BeforeClass;
import org.junit.Test;
import org.manifold.compiler.BooleanTypeValue;
import org.manifold.compiler.BooleanValue;
import org.manifold.compiler.ConnectionType;
import org.manifold.compiler.ConnectionValue;
import org.manifold.compiler.InvalidAttributeException;
import org.manifold.compiler.MultipleDefinitionException;
import org.manifold.compiler.NodeTypeValue;
import org.manifold.compiler.NodeValue;
import org.manifold.compiler.PortTypeValue;
import org.manifold.compiler.PortValue;
import org.manifold.compiler.TypeValue;
import org.manifold.compiler.UndeclaredAttributeException;
import org.manifold.compiler.Value;
import org.manifold.compiler.back.digital.Net;
import org.manifold.compiler.back.digital.Netlist;
import org.manifold.compiler.middle.Schematic;
import org.manifold.compiler.middle.SchematicException;

public class TestNetlist {

private static PortTypeValue digitalInPortType;
private static PortTypeValue digitalOutPortType;

private static final Map<String, TypeValue> noTypeAttributes
= new HashMap<>();
private static final Map<String, Value> noAttributes
= new HashMap<>();

private static Map<String, TypeValue> registerTypeAttributes
= new HashMap<>();
private static Map<String, PortTypeValue> registerTypePorts
= new HashMap<>();
private static NodeTypeValue registerType;

private static Map<String, PortTypeValue> inputPinTypePorts
= new HashMap<>();
private static NodeTypeValue inputPinType;

private static Map<String, PortTypeValue> outputPinTypePorts
= new HashMap<>();
private static NodeTypeValue outputPinType;

private static ConnectionType digitalWireType;


@BeforeClass
public static void setupIntermediateTypes(){

digitalInPortType = new PortTypeValue(noTypeAttributes);
digitalOutPortType = new PortTypeValue(noTypeAttributes);

registerTypeAttributes.put("initialValue",
BooleanTypeValue.getInstance());
registerTypeAttributes.put("resetActiveHigh",
BooleanTypeValue.getInstance());
registerTypeAttributes.put("resetAsynchronous",
BooleanTypeValue.getInstance());
registerTypeAttributes.put("clockActiveHigh",
BooleanTypeValue.getInstance());
registerTypePorts.put("in", digitalInPortType);
registerTypePorts.put("out", digitalOutPortType);
registerTypePorts.put("clock", digitalInPortType);
registerTypePorts.put("reset", digitalInPortType);
registerType = new NodeTypeValue(registerTypeAttributes, registerTypePorts);

inputPinTypePorts.put("out", digitalOutPortType);
inputPinType = new NodeTypeValue(noTypeAttributes, inputPinTypePorts);

outputPinTypePorts.put("in", digitalInPortType);
outputPinType = new NodeTypeValue(noTypeAttributes, outputPinTypePorts);

digitalWireType = new ConnectionType(noTypeAttributes);
}

/**
* Instantiate a Schematic, but with varying degrees of "completeness"
* in terms of what object types are included. If types are missing,
* it will not be possible to construct a Netlist.
* @throws MultipleDefinitionException
*/
public static Schematic instantiateSchematic(String name,
boolean includePortTypes, boolean includeNodeTypes,
boolean includeConnectionTypes)
throws MultipleDefinitionException {
Schematic s = new Schematic(name);
if (includePortTypes) {
s.addPortType("digitalIn", digitalInPortType);
s.addPortType("digitalOut", digitalOutPortType);
}

if (includeNodeTypes) {
s.addNodeType("register", registerType);
s.addNodeType("inputPin", inputPinType);
s.addNodeType("outputPin", outputPinType);
}

if (includeConnectionTypes) {
s.addConnectionType("digitalWire", digitalWireType);
}

return s;
}

/**
* Instantiate a Schematic and include all object types.
*/
public static Schematic instantiateSchematic(String name)
throws MultipleDefinitionException {
return instantiateSchematic(name, true, true, true);
}

public static NodeValue instantiateRegister(boolean initialValue,
boolean resetActiveHigh, boolean resetAsynchronous,
boolean clockActiveHigh)
throws SchematicException {
Map<String, Value> registerAttrs = new HashMap<>();
registerAttrs.put("initialValue",
BooleanValue.getInstance(initialValue));
registerAttrs.put("resetActiveHigh",
BooleanValue.getInstance(resetActiveHigh));
registerAttrs.put("resetAsynchronous",
BooleanValue.getInstance(resetAsynchronous));
registerAttrs.put("clockActiveHigh",
BooleanValue.getInstance(clockActiveHigh));
Map<String, Map<String, Value>> registerPortAttrs = new HashMap<>();
registerPortAttrs.put("in", noAttributes);
registerPortAttrs.put("out", noAttributes);
registerPortAttrs.put("clock", noAttributes);
registerPortAttrs.put("reset", noAttributes);
NodeValue register = new NodeValue(
registerType, registerAttrs, registerPortAttrs);
return register;
}

public static NodeValue instantiateInputPin() throws SchematicException {
Map<String, Map<String, Value>> inputPinPortAttrs = new HashMap<>();
inputPinPortAttrs.put("out", noAttributes);
NodeValue inputPin = new NodeValue(
inputPinType, noAttributes, inputPinPortAttrs);
return inputPin;
}

public static NodeValue instantiateOutputPin() throws SchematicException {
Map<String, Map<String, Value>> outputPinPortAttrs = new HashMap<>();
outputPinPortAttrs.put("in", noAttributes);
NodeValue outputPin = new NodeValue(
outputPinType, noAttributes, outputPinPortAttrs);
return outputPin;
}

public static ConnectionValue instantiateWire(
PortValue from, PortValue to)
throws UndeclaredAttributeException, InvalidAttributeException{
ConnectionValue wire = new ConnectionValue(
digitalWireType, from, to, noAttributes);
return wire;
}

@Test
public void testConstruction() throws SchematicException {
// [digitalIn] -> [digitalOut]
Schematic sch = instantiateSchematic("case0");
NodeValue in = instantiateInputPin();
NodeValue out = instantiateOutputPin();
ConnectionValue in_to_out = instantiateWire(
in.getPort("out"), out.getPort("in"));
sch.addNode("in", in);
sch.addNode("out", out);
sch.addConnection("in_to_out", in_to_out);

Netlist netlist = new Netlist(sch);
}

@Test
public void testGetNets() throws SchematicException {
// [digitalIn] -> [digitalOut]
Schematic sch = instantiateSchematic("case0");
NodeValue in = instantiateInputPin();
NodeValue out = instantiateOutputPin();
ConnectionValue in_to_out = instantiateWire(
in.getPort("out"), out.getPort("in"));
sch.addNode("in", in);
sch.addNode("out", out);
sch.addConnection("in_to_out", in_to_out);

Netlist netlist = new Netlist(sch);

Map<String, Net> nets = netlist.getNets();
// there should be exactly one net
assertEquals(1, nets.values().size());
// and this net should contain both ports
Net n_in_to_out = (Net) nets.values().toArray()[0];
assertTrue(n_in_to_out.getConnectedPorts().contains(in.getPort("out")));
assertTrue(n_in_to_out.getConnectedPorts().contains(out.getPort("in")));
}

@Test
public void testGetConnectedNet() throws SchematicException {
// [digitalIn] -> [digitalOut]
Schematic sch = instantiateSchematic("case0");
NodeValue in = instantiateInputPin();
NodeValue out = instantiateOutputPin();
ConnectionValue in_to_out = instantiateWire(
in.getPort("out"), out.getPort("in"));
sch.addNode("in", in);
sch.addNode("out", out);
sch.addConnection("in_to_out", in_to_out);

Netlist netlist = new Netlist(sch);

// `in` and `out` should both be connected to the same net
Net n_in = netlist.getConnectedNet(in.getPort("out"));
assertNotNull(n_in);
Net n_out = netlist.getConnectedNet(out.getPort("in"));
assertNotNull(n_out);
assertEquals(n_in, n_out);
}

}

0 comments on commit babea4b

Please sign in to comment.