most of the optimizations are working, splitter is still missing

This commit is contained in:
hneemann 2018-03-23 14:38:36 +01:00
parent 8811863b12
commit cb1266e35e
21 changed files with 1366 additions and 52 deletions

View File

@ -277,6 +277,9 @@ public class Net {
return visualElement;
}
/**
* @return the set of labels attached to this net
*/
public HashSet<String> getLabels() {
return labelSet;
}

View File

@ -9,7 +9,6 @@ import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.basic.Not;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescription;
import de.neemann.digital.core.io.In;
import de.neemann.digital.core.io.Out;
import de.neemann.digital.core.io.PowerSupply;
@ -23,22 +22,34 @@ import de.neemann.digital.draw.model.InverterConfig;
import de.neemann.digital.draw.model.Net;
import de.neemann.digital.draw.model.NetList;
import de.neemann.digital.gui.components.data.DummyElement;
import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.testing.TestCaseElement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.io.IOException;
import java.util.*;
public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider {
/**
* The representation of a circuit
*/
public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider, Printable {
private final String elementName;
private final ArrayList<HDLPort> outputs;
private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLNet> listOfNets;
private NetList netList;
private ArrayList<HDLNode> nodes;
private HashMap<Net, HDLNet> nets;
private int netNumber;
/**
* Creates a new instance
*
* @param circuit the circuit
* @param elementName the name of the circuit
* @param c the context to create the circuits
* @throws PinException PinException
* @throws HDLException HDLException
* @throws NodeException NodeException
*/
public HDLCircuit(Circuit circuit, String elementName, HDLContext c) throws PinException, HDLException, NodeException {
this.elementName = elementName;
inputs = new ArrayList<>();
@ -64,7 +75,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider {
v.getElementAttributes().getBits())
.setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER)));
else if (isRealElement(v))
addNode(v, c);
nodes.add(c.createNode(v, this));
}
} catch (HDLException e) {
throw new HDLException("error parsing " + circuit.getOrigin(), e);
@ -89,6 +100,19 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider {
}
nodes.addAll(newNodes);
listOfNets = new ArrayList<>();
listOfNets.addAll(nets.values());
nets = null;
for (HDLPort i : inputs)
i.getNet().setIsInput(i.getName());
for (HDLPort o : outputs)
if (o.getNet().needsVariable())
o.getNet().setIsOutput(o.getName(), o.getNet().getInputs().size() == 1);
}
private HDLNode createNot(HDLPort p) throws HDLException, NodeException, PinException {
@ -126,7 +150,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider {
&& !v.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION);
}
private HDLNet getNetOfPin(Pin pin) {
HDLNet getNetOfPin(Pin pin) {
Net n = netList.getNetOfPos(pin.getPos());
if (n == null)
return null;
@ -139,19 +163,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider {
if (labels.size() == 1)
return labels.iterator().next();
else
return Integer.toString(netNumber++);
}
private void addNode(VisualElement v, HDLContext c) throws HDLException {
final HDLNode node = c.createNode(v);
for (Pin p : v.getPins()) {
HDLNet net = getNetOfPin(p);
if (p.getDirection().equals(PinDescription.Direction.input))
node.addInput(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0));
else
node.addOutput(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName())));
}
nodes.add(node);
return null;
}
@Override
@ -167,18 +179,32 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider {
return 0;
}
/**
* @return the elements name
*/
public String getElementName() {
return elementName;
}
/**
* @return the circuits outputs
*/
public ArrayList<HDLPort> getOutputs() {
return outputs;
}
/**
* @return the circuits inputs
*/
public ArrayList<HDLPort> getInputs() {
return inputs;
}
/**
* Traverses all the nodes
*
* @param visitor the visitor to use
*/
public void traverse(HDLVisitor visitor) {
for (HDLNode n : nodes)
n.traverse(visitor);
@ -188,4 +214,109 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLContext.BitProvider {
public String toString() {
return "HDLCircuit{elementName='" + elementName + "'}";
}
/**
* Merges logcal operations if possible
*
* @return this for chained calls
* @throws HDLException HDLException
*/
public HDLCircuit mergeOperations() throws HDLException {
nodes = new OperationMerger(nodes, this).merge();
return this;
}
/**
* Name the unnamed nets
*
* @param netNamer the net naming algorithm
* @return this for chained calls
*/
public HDLCircuit nameNets(NetNamer netNamer) {
for (HDLNet n : listOfNets)
if (n.getName() == null)
n.setName(netNamer.createName(n));
return this;
}
@Override
public void print(CodePrinter out) throws IOException {
out.print("circuit ").println(elementName).inc();
out.print("in");
printList(out, inputs);
out.print("out");
printList(out, outputs);
out.print("sig");
printList(out, listOfNets);
out.println();
for (HDLNode n : nodes) {
out.print("node ").println(n.getElementName()).inc();
n.print(out);
out.dec();
}
out.println();
for (HDLPort p : outputs) {
final HDLNet net = p.getNet();
if (net.needsVariable() || net.isInput()) {
p.print(out);
out.print(" := ");
net.print(out);
out.println();
}
}
out.dec().print("end circuit ").println(elementName);
}
private void printList(CodePrinter out, Collection<? extends Printable> ports) throws IOException {
boolean first = true;
for (Printable p : ports) {
if (first) {
first = false;
out.print("(");
} else
out.print(", ");
p.print(out);
}
out.println(")");
}
private void printList(CodePrinter out, ArrayList<HDLNet> nets) throws IOException {
boolean first = true;
for (HDLNet net : nets) {
if (net.needsVariable()) {
if (first) {
first = false;
out.print("(");
} else
out.print(", ");
net.print(out);
}
}
out.println(")");
}
/**
* Removed an obsolete net
*
* @param net the net to remove
*/
public void removeNet(HDLNet net) {
listOfNets.remove(net);
}
/**
* The net naming algorithm
*/
public interface NetNamer {
/**
* Returns a nem for the given net
*
* @param n the net to name
* @return the name to use
*/
String createName(HDLNet n);
}
}

View File

@ -7,26 +7,50 @@ package de.neemann.digital.hdl.model2;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.ObservableValues;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.core.basic.*;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescription;
import de.neemann.digital.core.io.Const;
import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.Pin;
import de.neemann.digital.draw.elements.PinException;
import de.neemann.digital.draw.elements.VisualElement;
import de.neemann.digital.draw.library.ElementLibrary;
import de.neemann.digital.draw.library.ElementNotFoundException;
import de.neemann.digital.hdl.model2.expression.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
public class HDLContext {
/**
* The context of creating nodes and circuits.
* Ensures that every circuit is only processed one time.
*/
public class HDLContext implements Iterable<HDLCircuit> {
private ElementLibrary elementLibrary;
private HashMap<Circuit, HDLCircuit> circuitMap;
/**
* Creates a new instance
*
* @param elementLibrary the element library
*/
public HDLContext(ElementLibrary elementLibrary) {
this.elementLibrary = elementLibrary;
circuitMap = new HashMap<>();
}
public HDLNode createNode(VisualElement v) throws HDLException {
/**
* Creates a isolated node
*
* @param v the VisualElement of the node
* @param parent the parrents circuit
* @return the node
* @throws HDLException HDLException
*/
public HDLNode createNode(VisualElement v, HDLCircuit parent) throws HDLException {
try {
ElementTypeDescription td = elementLibrary.getElementType(v.getElementName());
if (td instanceof ElementLibrary.ElementTypeDescriptionCustom) {
@ -38,26 +62,106 @@ public class HDLContext {
circuitMap.put(tdc.getCircuit(), c);
}
return new HDLNodeCustom(v.getElementName(), v.getElementAttributes(), c);
return addInputsOutputs(
new HDLNodeCustom(v.getElementName(), v.getElementAttributes(), c),
v, parent);
} else if (v.equalsDescription(Const.DESCRIPTION)) {
final HDLNodeExpression node = createExpression(v, parent, td);
node.setExpression(new ExprConstant(node.getElementAttributes().get(Keys.VALUE), node.getOutput().getBits()));
return node;
} else if (v.equalsDescription(Not.DESCRIPTION)) {
final HDLNodeExpression node = createExpression(v, parent, td);
node.setExpression(new ExprNot(new ExprVar(node.getInputs().get(0).getNet())));
return node;
} else if (v.equalsDescription(Or.DESCRIPTION)) {
final HDLNodeExpression node = createExpression(v, parent, td);
node.setExpression(createOperation(node.getInputs(), ExprOperate.Operation.OR));
return node;
} else if (v.equalsDescription(And.DESCRIPTION)) {
final HDLNodeExpression node = createExpression(v, parent, td);
node.setExpression(createOperation(node.getInputs(), ExprOperate.Operation.AND));
return node;
} else if (v.equalsDescription(XOr.DESCRIPTION)) {
final HDLNodeExpression node = createExpression(v, parent, td);
node.setExpression(createOperation(node.getInputs(), ExprOperate.Operation.XOR));
return node;
} else if (v.equalsDescription(NOr.DESCRIPTION)) {
final HDLNodeExpression node = createExpression(v, parent, td);
node.setExpression(new ExprNot(createOperation(node.getInputs(), ExprOperate.Operation.OR)));
return node;
} else if (v.equalsDescription(NAnd.DESCRIPTION)) {
final HDLNodeExpression node = createExpression(v, parent, td);
node.setExpression(new ExprNot(createOperation(node.getInputs(), ExprOperate.Operation.AND)));
return node;
} else if (v.equalsDescription(XNOr.DESCRIPTION)) {
final HDLNodeExpression node = createExpression(v, parent, td);
node.setExpression(new ExprNot(createOperation(node.getInputs(), ExprOperate.Operation.XOR)));
return node;
} else
return new HDLNode(v.getElementName(),
v.getElementAttributes(),
new ObserVableValuesBits(
td.createElement(v.getElementAttributes()).getOutputs()));
return addInputsOutputs(
new HDLNode(v.getElementName(),
v.getElementAttributes(),
new ObservableValuesBitsProvider(
td.createElement(v.getElementAttributes()).getOutputs())),
v, parent);
} catch (ElementNotFoundException | PinException | NodeException e) {
throw new HDLException("error creating node", e);
}
}
private Expression createOperation(ArrayList<HDLPort> inputs, ExprOperate.Operation op) {
ArrayList<Expression> list = new ArrayList<>();
for (HDLPort p : inputs) {
list.add(new ExprVar(p.getNet()));
}
return new ExprOperate(op, list);
}
private HDLNodeExpression createExpression(VisualElement v, HDLCircuit parent, ElementTypeDescription td) throws HDLException, PinException {
return addInputsOutputs(new HDLNodeExpression(v.getElementName(),
v.getElementAttributes(),
new ObservableValuesBitsProvider(
td.createElement(v.getElementAttributes()).getOutputs())),
v, parent);
}
private <N extends HDLNode> N addInputsOutputs(N node, VisualElement v, HDLCircuit c) throws HDLException {
for (Pin p : v.getPins()) {
HDLNet net = c.getNetOfPin(p);
if (p.getDirection().equals(PinDescription.Direction.input))
node.addInput(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0));
else
node.addOutput(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName())));
}
return node;
}
@Override
public Iterator<HDLCircuit> iterator() {
return circuitMap.values().iterator();
}
/**
* The bit provider interface
*/
public interface BitProvider {
/**
* Returns the number of bits of the signal with the given name
*
* @param name the signal name
* @return the number of bits
*/
int getBits(String name);
}
private class ObserVableValuesBits implements BitProvider {
private static final class ObservableValuesBitsProvider implements BitProvider {
private final ObservableValues values;
private ObserVableValuesBits(ObservableValues values) {
private ObservableValuesBitsProvider(ObservableValues values) {
this.values = values;
}

View File

@ -5,11 +5,25 @@
*/
package de.neemann.digital.hdl.model2;
/**
* Exception thrown during model building
*/
public class HDLException extends Exception {
/**
* Creates a new instance
*
* @param message the message
* @param cause the cause
*/
public HDLException(String message, Exception cause) {
super(message, cause);
}
/**
* Creates a new instance
*
* @param message the message
*/
public HDLException(String message) {
super(message);
}

View File

@ -5,18 +5,38 @@
*/
package de.neemann.digital.hdl.model2;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
import java.util.ArrayList;
public class HDLNet {
/**
* Represents a net.
* A net can have only one input and several outputs.
*/
public class HDLNet implements Printable {
private String name;
private ArrayList<HDLPort> inputs;
private HDLPort output;
private boolean needsVariable = true;
private boolean isInput;
/**
* Creates a new net
*
* @param name the nets name
*/
public HDLNet(String name) {
this.name = name;
inputs = new ArrayList<>();
}
/**
* Adds a port to this net.
*
* @param hdlPort the port to add
* @throws HDLException HDLException
*/
public void addPort(HDLPort hdlPort) throws HDLException {
if (hdlPort.getDirection().equals(HDLPort.Direction.OUT)) {
if (output != null)
@ -26,12 +46,26 @@ public class HDLNet {
inputs.add(hdlPort);
}
/**
* @return the inputs which are connected to this net.
*/
public ArrayList<HDLPort> getInputs() {
return inputs;
}
/**
* @return the output which defines the nets value
*/
public HDLPort getOutput() {
return output;
}
@Override
public String toString() {
return name + " (" + output + " " + inputs + ")";
}
public void fixBits() throws HDLException {
void fixBits() throws HDLException {
if (output == null)
throw new HDLException("no output connected to net");
final int bits = output.getBits();
@ -43,7 +77,56 @@ public class HDLNet {
}
public void remove(HDLPort p) {
void remove(HDLPort p) {
inputs.remove(p);
}
@Override
public void print(CodePrinter out) throws IOException {
out.print(name).print(":").print(output.getBits());
}
/**
* @return the name of the net
*/
public String getName() {
return name;
}
/**
* Sets the name of the net
*
* @param name the name to use
*/
public void setName(String name) {
this.name = name;
}
void setIsInput(String name) {
this.needsVariable = false;
this.isInput = true;
this.name = name;
}
/**
* @return true if tins net represents a nodes input
*/
public boolean isInput() {
return isInput;
}
/**
* @return true if this net needs a temp variable to represent the value
*/
public boolean needsVariable() {
return needsVariable;
}
void setIsOutput(String name, boolean singleRead) {
if (singleRead) {
this.name = name;
needsVariable = false;
} else
this.name = name + "_temp";
}
}

View File

@ -6,9 +6,14 @@
package de.neemann.digital.hdl.model2;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
import java.util.ArrayList;
/**
* A node which represents a built-in component
*/
public class HDLNode {
private final String elementName;
private final ElementAttributes elementAttributes;
@ -16,6 +21,13 @@ public class HDLNode {
private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLPort> outputs;
/**
* Creates e new intance
*
* @param elementName the instances name
* @param elementAttributes the attributes
* @param bitProvider the bit provider which provides the outputs bit width
*/
public HDLNode(String elementName, ElementAttributes elementAttributes, HDLContext.BitProvider bitProvider) {
this.elementName = elementName;
this.elementAttributes = elementAttributes;
@ -24,14 +36,12 @@ public class HDLNode {
outputs = new ArrayList<>();
}
public void addInput(HDLPort port) {
void addInput(HDLPort port) {
inputs.add(port);
port.setNode(this);
}
public void addOutput(HDLPort port) {
void addOutput(HDLPort port) {
outputs.add(port);
port.setNode(this);
}
@Override
@ -39,27 +49,99 @@ public class HDLNode {
return elementName + " " + inputs + " " + outputs;
}
/**
* @return the elements name
*/
public String getElementName() {
return elementName;
}
/**
* @return the elements attributes
*/
public ElementAttributes getElementAttributes() {
return elementAttributes;
}
/**
* @return the nodes inputs
*/
public ArrayList<HDLPort> getInputs() {
return inputs;
}
/**
* @return the nodes single outputs
*/
public HDLPort getOutput() {
return outputs.get(0);
}
/**
* @return the list of outputs
*/
public ArrayList<HDLPort> getOutputs() {
return outputs;
}
/**
* Traverses all the nodes
*
* @param visitor the visitor to use
*/
public void traverse(HDLVisitor visitor) {
visitor.visit(this);
}
public int getBits(String name) {
int getBits(String name) {
return bitProvider.getBits(name);
}
/**
* Prints a simple text representation of the node
*
* @param out the CondePrinter to print to
* @throws IOException IOException
*/
public void print(CodePrinter out) throws IOException {
out.print("in");
printWithLocal(out, inputs);
out.print("out");
printWithLocal(out, outputs);
}
private void printWithLocal(CodePrinter out, ArrayList<HDLPort> ports) throws IOException {
boolean first = true;
for (HDLPort p : ports) {
if (first) {
first = false;
out.print("(");
} else
out.print(", ");
p.print(out);
if (p.getNet() == null)
out.print(" is not used");
else {
out.print(" is ");
p.getNet().print(out);
}
}
if (first)
out.println("(");
out.println(")");
}
/**
* Returns true if the node has the given port as an input
*
* @param i the port to search for
* @return true if the given port is a input of this node
*/
public boolean hasInput(HDLPort i) {
for (HDLPort p : inputs)
if (p.getNet() == i.getNet())
return true;
return false;
}
}

View File

@ -7,9 +7,19 @@ package de.neemann.digital.hdl.model2;
import de.neemann.digital.core.element.ElementAttributes;
/**
* Represents a node which is build from a circuit.
*/
public class HDLNodeCustom extends HDLNode {
private final HDLCircuit hdlCircuit;
/**
* Creates a new instance
*
* @param elementName the elements name
* @param elementAttributes the attributes
* @param hdlCircuit the circuit to use to create this node
*/
public HDLNodeCustom(String elementName, ElementAttributes elementAttributes, HDLCircuit hdlCircuit) {
super(elementName, elementAttributes, hdlCircuit);
this.hdlCircuit = hdlCircuit;

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.hdl.model2;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.hdl.model2.expression.Expression;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
/**
* A node which represents a simple expression
*/
public class HDLNodeExpression extends HDLNode {
private Expression expression;
/**
* Creates a new instace
*
* @param elementName the elements name
* @param elementAttributes the attributes
* @param bitProvider the bit provider which provides the outputs bit width
*/
public HDLNodeExpression(String elementName, ElementAttributes elementAttributes, HDLContext.BitProvider bitProvider) {
super(elementName, elementAttributes, bitProvider);
}
/**
* Sets the expression tu use
*
* @param expression the expression
*/
public void setExpression(Expression expression) {
this.expression = expression;
}
/**
* @return the expression
*/
public Expression getExpression() {
return expression;
}
@Override
public void print(CodePrinter out) throws IOException {
getOutput().getNet().print(out);
out.print(" := ");
expression.print(out);
out.println();
}
}

View File

@ -5,19 +5,44 @@
*/
package de.neemann.digital.hdl.model2;
public class HDLPort {
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
/**
* A port
*/
public class HDLPort implements Printable {
/**
* The ports direction
*/
public enum Direction {
IN, OUT
/**
* input
*/
IN,
/**
* output
*/
OUT
}
private final String name;
private final Direction direction;
private int bits;
private HDLNet net;
private HDLNode node;
private String pinNumber;
/**
* Creates a new instance
*
* @param name the name of the port
* @param net the net of this port
* @param direction the ports direction
* @param bits the bit width
* @throws HDLException HDLException
*/
public HDLPort(String name, HDLNet net, Direction direction, int bits) throws HDLException {
this.name = name;
this.net = net;
@ -28,42 +53,70 @@ public class HDLPort {
net.addPort(this);
}
/**
* Sets the pin number to this port
*
* @param pinNumber the pin number
* @return this for chained calls
*/
public HDLPort setPinNumber(String pinNumber) {
this.pinNumber = pinNumber;
return this;
}
/**
* @return the net of this port
*/
public HDLNet getNet() {
return net;
}
/**
* Sets the net of this port
*
* @param net the net
* @throws HDLException HDLException
*/
public void setNet(HDLNet net) throws HDLException {
this.net = net;
net.addPort(this);
}
/**
* @return the name of this port
*/
public String getName() {
return name;
}
/**
* @return the bit width of this port
*/
public int getBits() {
return bits;
}
/**
* Sets the bit width of this port
*
* @param bits the number of bits
*/
public void setBits(int bits) {
this.bits = bits;
}
/**
* @return the ports direction
*/
public Direction getDirection() {
return direction;
}
public HDLNode getNode() {
return node;
}
public void setNode(HDLNode node) {
this.node = node;
/**
* @return the pin number of this port
*/
public String getPinNumber() {
return pinNumber;
}
@Override
@ -71,4 +124,8 @@ public class HDLPort {
return direction + " " + name + "(" + bits + ")";
}
@Override
public void print(CodePrinter out) throws IOException {
out.print(name).print(":").print(bits);
}
}

View File

@ -5,6 +5,14 @@
*/
package de.neemann.digital.hdl.model2;
/**
* Visitor to visit the nodes.
*/
public interface HDLVisitor {
/**
* Visits a node
*
* @param hdlNode the node to visit
*/
void visit(HDLNode hdlNode);
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.hdl.model2;
import de.neemann.digital.hdl.model2.expression.Expression;
import java.util.ArrayList;
/**
* Helper to merge expressions
*/
class OperationMerger {
private final ArrayList<HDLNode> nodes;
private final HDLCircuit circuit;
OperationMerger(ArrayList<HDLNode> nodes, HDLCircuit circuit) {
this.nodes = nodes;
this.circuit = circuit;
}
ArrayList<HDLNode> merge() throws HDLException {
boolean wasOptimization;
do {
wasOptimization = false;
outer:
for (int i = 0; i < nodes.size(); i++) {
HDLNode n1 = nodes.get(i);
if (n1 instanceof HDLNodeExpression) {
for (HDLPort p : n1.getInputs()) {
HDLNode n2 = searchCreator(p.getNet());
if (n2 != null && n2 instanceof HDLNodeExpression) {
if (n2.getOutputs().size() == 1 && n2.getOutput().getNet().getInputs().size() == 1) {
nodes.set(i, merge((HDLNodeExpression) n1, (HDLNodeExpression) n2));
nodes.remove(n2);
wasOptimization = true;
break outer;
}
}
}
}
}
} while (wasOptimization);
return nodes;
}
private HDLNodeExpression merge(HDLNodeExpression host, HDLNodeExpression include) throws HDLException {
final Expression expression = host.getExpression();
expression.replace(include.getOutput().getNet(), include.getExpression());
HDLNodeExpression node = new HDLNodeExpression("merged expression",
null, name -> host.getOutput().getBits());
node.setExpression(expression);
circuit.removeNet(include.getOutput().getNet());
node.addOutput(host.getOutput());
for (HDLPort i : host.getInputs())
node.addInput(i);
for (HDLPort i : include.getInputs())
if (!node.hasInput(i))
node.addInput(i);
return node;
}
private HDLNode searchCreator(HDLNet net) {
for (HDLNode n : nodes)
for (HDLPort p : n.getOutputs())
if (p.getNet() == net)
return n;
return null;
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.hdl.model2;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
/**
* Something which can print itself to a CodePrinter
*/
public interface Printable {
/**
* Prints itfels to the CodePrinter
*
* @param out the CodePrinter instance
* @throws IOException IOException
*/
void print(CodePrinter out) throws IOException;
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.hdl.model2.expression;
import de.neemann.digital.hdl.model2.HDLNet;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
/**
* Represents a constant
*/
public class ExprConstant implements Expression {
private long value;
private int bits;
/**
* Creates a new constant
* @param value the value
* @param bits the number of bits
*/
public ExprConstant(long value, int bits) {
this.value = value;
this.bits = bits;
}
/**
* @return the value
*/
public long getValue() {
return value;
}
/**
* @return the number of bits
*/
public int getBits() {
return bits;
}
@Override
public void print(CodePrinter out) throws IOException {
out.print(value).print(":").print(bits);
}
@Override
public void replace(HDLNet net, Expression expression) {
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.hdl.model2.expression;
import de.neemann.digital.hdl.model2.HDLNet;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
/**
* Represents a NOT operation
*/
public class ExprNot implements Expression {
private Expression expr;
/**
* Creates a new NOT expression
*
* @param expr the enxpression to invert
*/
public ExprNot(Expression expr) {
this.expr = expr;
}
/**
* @return the expression
*/
public Expression getExpression() {
return expr;
}
@Override
public void print(CodePrinter out) throws IOException {
out.print("NOT ");
expr.print(out);
}
@Override
public void replace(HDLNet net, Expression expression) {
if (isVar(expr, net))
expr = expression;
else
expr.replace(net, expression);
}
/**
* Help er to check if a expression is a net reference
*
* @param expr the expression to check
* @param net the net
* @return true if the expression is a reference to the given net
*/
public static boolean isVar(Expression expr, HDLNet net) {
return expr instanceof ExprVar && ((ExprVar) expr).getNet() == net;
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.hdl.model2.expression;
import de.neemann.digital.hdl.model2.HDLNet;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
import java.util.ArrayList;
import static de.neemann.digital.hdl.model2.expression.ExprNot.isVar;
/**
* Represenst a operation
*/
public class ExprOperate implements Expression {
/**
* the possible operation
*/
public enum Operation {
/**
* And operation
*/
AND,
/**
* Or operation
*/
OR,
/**
* xor operation
*/
XOR
}
private Operation operation;
private ArrayList<Expression> operands;
/**
* Creates a new instance
*
* @param operation the operation
* @param operands the operandes
*/
public ExprOperate(Operation operation, ArrayList<Expression> operands) {
this.operation = operation;
this.operands = operands;
}
/**
* @return the operation
*/
public Operation getOperation() {
return operation;
}
/**
* @return the operands
*/
public ArrayList<Expression> getOperands() {
return operands;
}
@Override
public void print(CodePrinter out) throws IOException {
out.print("(");
boolean first = true;
for (Expression op : operands) {
if (first)
first = false;
else
out.print(" ").print(operation.name()).print(" ");
op.print(out);
}
out.print(")");
}
@Override
public void replace(HDLNet net, Expression expression) {
for (int i = 0; i < operands.size(); i++) {
final Expression op = operands.get(i);
if (isVar(op, net))
operands.set(i, expression);
else
op.replace(net, expression);
}
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.hdl.model2.expression;
import de.neemann.digital.hdl.model2.HDLNet;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
/**
* A reference to a net
*/
public class ExprVar implements Expression {
private HDLNet net;
/**
* creates a new net reference
*
* @param net the net
*/
public ExprVar(HDLNet net) {
this.net = net;
}
/**
* @return the net
*/
public HDLNet getNet() {
return net;
}
@Override
public void print(CodePrinter out) throws IOException {
net.print(out);
}
@Override
public void replace(HDLNet net, Expression expression) {
if (net == this.net)
throw new RuntimeException("should not happen!");
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.hdl.model2.expression;
import de.neemann.digital.hdl.model2.HDLNet;
import de.neemann.digital.hdl.model2.Printable;
/**
* Represents a expression
*/
public interface Expression extends Printable {
/**
* Replaces a net with and expression
*
* @param net the net to replace
* @param expression the expression to use instead ot the net
*/
void replace(HDLNet net, Expression expression);
}

View File

@ -0,0 +1,10 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
/**
* Classes to describe a model expression
*/
package de.neemann.digital.hdl.model2.expression;

View File

@ -0,0 +1,10 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
/**
* The hdl representation of a circuit
*/
package de.neemann.digital.hdl.model2;

View File

@ -5,6 +5,8 @@ import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.PinException;
import de.neemann.digital.draw.library.ElementLibrary;
import de.neemann.digital.draw.shapes.ShapeFactory;
import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.hdl.printer.CodePrinterStr;
import de.neemann.digital.integration.Resources;
import junit.framework.TestCase;
@ -14,7 +16,7 @@ import java.io.IOException;
public class HDLCircuitTest extends TestCase {
public void testSimple() throws IOException, PinException, HDLException, NodeException {
File file = new File(Resources.getRoot(), "../../main/dig/processor/VHDLExample.dig");
File file = new File(Resources.getRoot(), "dig/hdl/model2/comb.dig");
ElementLibrary library = new ElementLibrary();
library.setRootFilePath(file.getParentFile());
ShapeFactory shapeFactory = new ShapeFactory(library);
@ -23,8 +25,25 @@ public class HDLCircuitTest extends TestCase {
final HDLContext hdlContext = new HDLContext(library);
HDLCircuit hdl = new HDLCircuit(c, "main", hdlContext);
System.out.println(hdl);
hdl.traverse(System.out::println);
CodePrinterStr out = new CodePrinterStr();
for (HDLCircuit cir : hdlContext) {
cir.mergeOperations();
cir.print(out);
out.println();
}
hdl.mergeOperations().nameNets(new HDLCircuit.NetNamer() {
private int num;
@Override
public String createName(HDLNet n) {
return "s" + (num++);
}
});
hdl.print(out);
System.out.print(out);
System.out.println();
}
}

View File

@ -0,0 +1,352 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>1</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>X</string>
</entry>
<entry>
<string>Inputs</string>
<int>1</int>
</entry>
</elementAttributes>
<pos x="360" y="140"/>
</visualElement>
<visualElement>
<elementName>And</elementName>
<elementAttributes>
<entry>
<string>Inputs</string>
<int>5</int>
</entry>
</elementAttributes>
<pos x="160" y="100"/>
</visualElement>
<visualElement>
<elementName>Or</elementName>
<elementAttributes/>
<pos x="20" y="0"/>
</visualElement>
<visualElement>
<elementName>Or</elementName>
<elementAttributes/>
<pos x="20" y="80"/>
</visualElement>
<visualElement>
<elementName>Or</elementName>
<elementAttributes/>
<pos x="20" y="240"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="3"/>
</entry>
<entry>
<string>Label</string>
<string>A</string>
</entry>
</elementAttributes>
<pos x="-120" y="-100"/>
</visualElement>
<visualElement>
<elementName>Not</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="3"/>
</entry>
</elementAttributes>
<pos x="-100" y="-60"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="3"/>
</entry>
<entry>
<string>Label</string>
<string>B</string>
</entry>
</elementAttributes>
<pos x="-80" y="-100"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="3"/>
</entry>
<entry>
<string>Label</string>
<string>C</string>
</entry>
</elementAttributes>
<pos x="-40" y="-100"/>
</visualElement>
<visualElement>
<elementName>Not</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="3"/>
</entry>
</elementAttributes>
<pos x="-20" y="-60"/>
</visualElement>
<visualElement>
<elementName>NOr</elementName>
<elementAttributes/>
<pos x="20" y="160"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>Y</string>
</entry>
</elementAttributes>
<pos x="360" y="260"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>Z</string>
</entry>
</elementAttributes>
<pos x="360" y="300"/>
</visualElement>
<visualElement>
<elementName>Const</elementName>
<elementAttributes/>
<pos x="140" y="140"/>
</visualElement>
<visualElement>
<elementName>D_FF</elementName>
<elementAttributes/>
<pos x="280" y="140"/>
</visualElement>
<visualElement>
<elementName>Const</elementName>
<elementAttributes/>
<pos x="260" y="160"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>Aident</string>
</entry>
</elementAttributes>
<pos x="360" y="340"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="-120" y="0"/>
<p2 x="20" y="0"/>
</wire>
<wire>
<p1 x="-80" y="160"/>
<p2 x="20" y="160"/>
</wire>
<wire>
<p1 x="120" y="160"/>
<p2 x="160" y="160"/>
</wire>
<wire>
<p1 x="260" y="160"/>
<p2 x="280" y="160"/>
</wire>
<wire>
<p1 x="140" y="100"/>
<p2 x="160" y="100"/>
</wire>
<wire>
<p1 x="80" y="100"/>
<p2 x="120" y="100"/>
</wire>
<wire>
<p1 x="80" y="260"/>
<p2 x="140" y="260"/>
</wire>
<wire>
<p1 x="140" y="260"/>
<p2 x="360" y="260"/>
</wire>
<wire>
<p1 x="-40" y="40"/>
<p2 x="20" y="40"/>
</wire>
<wire>
<p1 x="-40" y="200"/>
<p2 x="20" y="200"/>
</wire>
<wire>
<p1 x="220" y="140"/>
<p2 x="280" y="140"/>
</wire>
<wire>
<p1 x="140" y="140"/>
<p2 x="160" y="140"/>
</wire>
<wire>
<p1 x="340" y="140"/>
<p2 x="360" y="140"/>
</wire>
<wire>
<p1 x="-100" y="300"/>
<p2 x="360" y="300"/>
</wire>
<wire>
<p1 x="-120" y="-80"/>
<p2 x="-100" y="-80"/>
</wire>
<wire>
<p1 x="-40" y="-80"/>
<p2 x="-20" y="-80"/>
</wire>
<wire>
<p1 x="-100" y="80"/>
<p2 x="20" y="80"/>
</wire>
<wire>
<p1 x="-80" y="240"/>
<p2 x="20" y="240"/>
</wire>
<wire>
<p1 x="80" y="20"/>
<p2 x="140" y="20"/>
</wire>
<wire>
<p1 x="100" y="180"/>
<p2 x="120" y="180"/>
</wire>
<wire>
<p1 x="140" y="180"/>
<p2 x="160" y="180"/>
</wire>
<wire>
<p1 x="-120" y="340"/>
<p2 x="360" y="340"/>
</wire>
<wire>
<p1 x="-40" y="120"/>
<p2 x="20" y="120"/>
</wire>
<wire>
<p1 x="120" y="120"/>
<p2 x="160" y="120"/>
</wire>
<wire>
<p1 x="-20" y="280"/>
<p2 x="20" y="280"/>
</wire>
<wire>
<p1 x="-100" y="-80"/>
<p2 x="-100" y="-60"/>
</wire>
<wire>
<p1 x="-100" y="-20"/>
<p2 x="-100" y="80"/>
</wire>
<wire>
<p1 x="-100" y="80"/>
<p2 x="-100" y="300"/>
</wire>
<wire>
<p1 x="-100" y="300"/>
<p2 x="-100" y="360"/>
</wire>
<wire>
<p1 x="-20" y="-80"/>
<p2 x="-20" y="-60"/>
</wire>
<wire>
<p1 x="-20" y="-20"/>
<p2 x="-20" y="280"/>
</wire>
<wire>
<p1 x="-20" y="280"/>
<p2 x="-20" y="360"/>
</wire>
<wire>
<p1 x="-120" y="-100"/>
<p2 x="-120" y="-80"/>
</wire>
<wire>
<p1 x="-120" y="0"/>
<p2 x="-120" y="340"/>
</wire>
<wire>
<p1 x="-120" y="340"/>
<p2 x="-120" y="360"/>
</wire>
<wire>
<p1 x="-120" y="-80"/>
<p2 x="-120" y="0"/>
</wire>
<wire>
<p1 x="-40" y="-100"/>
<p2 x="-40" y="-80"/>
</wire>
<wire>
<p1 x="-40" y="200"/>
<p2 x="-40" y="360"/>
</wire>
<wire>
<p1 x="-40" y="-80"/>
<p2 x="-40" y="40"/>
</wire>
<wire>
<p1 x="-40" y="40"/>
<p2 x="-40" y="120"/>
</wire>
<wire>
<p1 x="-40" y="120"/>
<p2 x="-40" y="200"/>
</wire>
<wire>
<p1 x="120" y="100"/>
<p2 x="120" y="120"/>
</wire>
<wire>
<p1 x="120" y="160"/>
<p2 x="120" y="180"/>
</wire>
<wire>
<p1 x="140" y="20"/>
<p2 x="140" y="100"/>
</wire>
<wire>
<p1 x="140" y="180"/>
<p2 x="140" y="260"/>
</wire>
<wire>
<p1 x="-80" y="-100"/>
<p2 x="-80" y="160"/>
</wire>
<wire>
<p1 x="-80" y="160"/>
<p2 x="-80" y="240"/>
</wire>
<wire>
<p1 x="-80" y="240"/>
<p2 x="-80" y="360"/>
</wire>
</wires>
</circuit>