More clear handling of entity input expressions.

Moves a bit more more logic to the model.
This commit is contained in:
hneemann 2018-03-29 10:52:22 +02:00
parent ded20a5462
commit 6cc350e488
16 changed files with 265 additions and 98 deletions

View File

@ -28,6 +28,7 @@ import de.neemann.digital.hdl.model2.clock.ClockInfo;
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
import de.neemann.digital.hdl.model2.expression.ExprNot;
import de.neemann.digital.hdl.model2.expression.ExprVar;
import de.neemann.digital.hdl.model2.expression.Expression;
import de.neemann.digital.hdl.model2.optimizations.*;
import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.lang.Lang;
@ -486,6 +487,8 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
.addPort(new HDLPort("cout", outNet, HDLPort.Direction.OUT, 1))
.addPort(new HDLPort("cin", inNet, HDLPort.Direction.IN, 1));
clockNode.createExpressions();
nodes.add(clockNode);
}
@ -524,6 +527,17 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
return nameUnnamedSignals();
}
/**
* Called to replace a net by an expression
*
* @param net the net to replace
* @param expression the expression to use instead
*/
public void replaceNetByExpression(HDLNet net, Expression expression) {
for (HDLNode n : nodes)
n.replaceNetByExpression(net, expression);
}
/**
* The net naming algorithm
*/

View File

@ -69,7 +69,7 @@ public class HDLModel implements Iterable<HDLCircuit> {
return addInputsOutputs(
new HDLNodeCustom(v.getElementName(), v.getElementAttributes(), c),
v, parent);
v, parent).createExpressions();
} else if (v.equalsDescription(Const.DESCRIPTION)) {
final HDLNodeAssignment node = createExpression(v, parent, td);
@ -117,7 +117,7 @@ public class HDLModel implements Iterable<HDLCircuit> {
v.getElementAttributes(),
new ObservableValuesBitsProvider(
td.createElement(v.getElementAttributes()).getOutputs())),
v, parent);
v, parent).createExpressions();
} catch (ElementNotFoundException | PinException | NodeException e) {

View File

@ -6,6 +6,7 @@
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;
@ -14,7 +15,7 @@ import java.util.ArrayList;
/**
* The base class of all nodes
*/
public class HDLNode {
public abstract class HDLNode {
private final String elementName;
private final ElementAttributes elementAttributes;
private final HDLModel.BitProvider bitProvider;
@ -165,16 +166,6 @@ public class HDLNode {
return hdlEntityName;
}
/**
* Checks is inlining is possible
*
* @param net the net which should be inlined
* @return true if inlining of the given net is possible
*/
public boolean inliningPossible(HDLNet net) {
return true;
}
/**
* Renames the signals in this node.
*
@ -186,4 +177,12 @@ public class HDLNode {
for (HDLPort p : inputs)
p.rename(renaming);
}
/**
* Called to replace a net by an expression.
*
* @param net the net to replace
* @param expression the expression to use instead
*/
public abstract void replaceNetByExpression(HDLNet net, Expression expression);
}

View File

@ -61,6 +61,11 @@ public class HDLNodeAssignment extends HDLNode {
expression.replace(oldNet, new ExprVar(newNet));
}
@Override
public void replaceNetByExpression(HDLNet net, Expression expression) {
expression.replace(net, expression);
}
/**
* @return the target net of this expression.
*/

View File

@ -6,11 +6,18 @@
package de.neemann.digital.hdl.model2;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.hdl.model2.expression.ExprVar;
import de.neemann.digital.hdl.model2.expression.Expression;
import java.util.ArrayList;
import java.util.Iterator;
/**
* A node which represents a build-in component
*/
public class HDLNodeBuildIn extends HDLNode {
public class HDLNodeBuildIn extends HDLNode implements Iterable<HDLNodeBuildIn.InputAssignment> {
private ArrayList<InputAssignment> inputAssignement;
/**
* Creates e new instance
*
@ -20,5 +27,73 @@ public class HDLNodeBuildIn extends HDLNode {
*/
public HDLNodeBuildIn(String elementName, ElementAttributes elementAttributes, HDLModel.BitProvider bitProvider) {
super(elementName, elementAttributes, bitProvider);
inputAssignement = new ArrayList<>();
}
@Override
public void replaceNetByExpression(HDLNet net, Expression expression) {
for (InputAssignment ia : inputAssignement)
ia.replaceNetByExpression(net, expression);
}
HDLNode createExpressions() {
for (HDLPort in : getInputs())
inputAssignement.add(new InputAssignment(in.getName(), new ExprVar(in.getNet())));
return this;
}
@Override
public Iterator<InputAssignment> iterator() {
if (getInputs().size() != inputAssignement.size())
throw new RuntimeException("no expressions created for " + getElementName());
return inputAssignement.iterator();
}
@Override
public void rename(HDLModel.Renaming renaming) {
super.rename(renaming);
for (InputAssignment in : inputAssignement)
in.rename(renaming);
}
/**
* A port assignment.
* Connects a port to an expression
*/
public static final class InputAssignment {
private String name;
private Expression expression;
private InputAssignment(String name, Expression expression) {
this.name = name;
this.expression = expression;
}
/**
* @return the targtet signal name
*/
public String getTargetName() {
return name;
}
/**
* @return the expression to assign
*/
public Expression getExpression() {
return expression;
}
private void replaceNetByExpression(HDLNet net, Expression expr) {
if (Expression.isVar(expression, net))
expression = expr;
else
expr.replace(net, expr);
}
private void rename(HDLModel.Renaming renaming) {
name = renaming.checkName(name);
}
}
}

View File

@ -10,7 +10,7 @@ import de.neemann.digital.core.element.ElementAttributes;
/**
* Represents a node which is build from a circuit.
*/
public class HDLNodeCustom extends HDLNode {
public class HDLNodeCustom extends HDLNodeBuildIn {
private final HDLCircuit hdlCircuit;
/**

View File

@ -6,16 +6,20 @@
package de.neemann.digital.hdl.model2;
import de.neemann.digital.core.wiring.Splitter;
import de.neemann.digital.hdl.model2.expression.ExprVar;
import de.neemann.digital.hdl.model2.expression.Expression;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
/**
* The Many to One splitter.
* A Many to Many splitter is build with a ManyToOne and a OneToMany splitter.
*/
public class HDLNodeSplitterManyToOne extends HDLNode {
private final Splitter.Ports inputSplit;
public class HDLNodeSplitterManyToOne extends HDLNode implements Iterable<HDLNodeSplitterManyToOne.SplitterAssignment> {
private final ArrayList<SplitterAssignment> outputs;
/**
* Creates a new instance
@ -25,20 +29,23 @@ public class HDLNodeSplitterManyToOne extends HDLNode {
*/
HDLNodeSplitterManyToOne(HDLNode node, Splitter.Ports inputSplit) {
super(node.getElementName(), node.getElementAttributes(), null);
this.inputSplit = inputSplit;
outputs = new ArrayList<>();
int i = 0;
for (Splitter.Port p : inputSplit) {
outputs.add(new SplitterAssignment(
p.getPos() + p.getBits() - 1,
p.getPos(),
new ExprVar(node.getInputs().get(i).getNet())));
i++;
}
for (HDLPort p : node.getInputs())
addPort(p);
for (HDLPort p : node.getOutputs())
addPort(p);
}
/**
* @return the input splitting
*/
public Splitter.Ports getInputSplit() {
return inputSplit;
}
/**
* @return the targets signal name
*/
@ -51,13 +58,70 @@ public class HDLNodeSplitterManyToOne extends HDLNode {
super.print(out);
int i = 0;
HDLPort o = getOutput();
for (Splitter.Port sp : inputSplit) {
HDLPort p = getInputs().get(i++);
out.print(o.getNet().getName())
.print("(").print(sp.getPos()).print("-").print(sp.getPos() + sp.getBits() - 1).print(")")
.print(" := ").println(p.getNet().getName());
for (SplitterAssignment sp : this) {
out.print(o.getNet().getName());
outputs.get(i++).print(out);
out.println();
}
}
@Override
public void replaceNetByExpression(HDLNet net, Expression expression) {
for (SplitterAssignment p : this)
p.replace(net, expression);
}
@Override
public Iterator<SplitterAssignment> iterator() {
return outputs.iterator();
}
/**
* The splitter assignment
*/
public final static class SplitterAssignment implements Printable {
private final int msb;
private final int lsb;
private Expression expression;
private SplitterAssignment(int msb, int lsb, Expression expression) {
this.msb = msb;
this.lsb = lsb;
this.expression = expression;
}
@Override
public void print(CodePrinter out) throws IOException {
out.print("(").print(msb).print("-").print(lsb).print(")").print(" := ");
expression.print(out);
}
/**
* @return the msb of the assignment
*/
public int getMsb() {
return msb;
}
/**
* @return the lsb of the assignment
*/
public int getLsb() {
return lsb;
}
/**
* @return the expression to assign
*/
public Expression getExpression() {
return expression;
}
private void replace(HDLNet net, Expression expr) {
if (Expression.isVar(expression, net))
expression = expr;
else
expression.replace(net, expr);
}
}
}

View File

@ -6,6 +6,7 @@
package de.neemann.digital.hdl.model2;
import de.neemann.digital.core.wiring.Splitter;
import de.neemann.digital.hdl.model2.expression.Expression;
import de.neemann.digital.hdl.printer.CodePrinter;
import java.io.IOException;
@ -51,6 +52,10 @@ public class HDLNodeSplitterOneToMany extends HDLNode {
}
}
@Override
public void replaceNetByExpression(HDLNet net, Expression expression) {
}
/**
* @return the source signals name
*/

View File

@ -21,6 +21,15 @@ public class ExprConstant implements Expression {
private long value;
private int bits;
/**
* Creates a new constant
*
* @param constant the constant
*/
public ExprConstant(ExprConstant constant) {
this(constant.getValue(), constant.getBits());
}
/**
* Creates a new constant
*

View File

@ -42,20 +42,10 @@ public class ExprNot implements Expression {
@Override
public void replace(HDLNet net, Expression expression) {
if (isVar(expr, net))
if (Expression.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
*/
static boolean isVar(Expression expr, HDLNet net) {
return expr instanceof ExprVar && ((ExprVar) expr).getNet() == net;
}
}

View File

@ -12,8 +12,6 @@ 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
*/
@ -82,7 +80,7 @@ public class ExprOperate implements Expression {
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))
if (Expression.isVar(op, net))
operands.set(i, expression);
else
op.replace(net, expression);

View File

@ -22,6 +22,8 @@ public class ExprVar implements Expression {
* @param net the net
*/
public ExprVar(HDLNet net) {
if (net == null)
throw new NullPointerException("net is null");
this.net = net;
}

View File

@ -21,4 +21,15 @@ public interface Expression extends Printable {
*/
void replace(HDLNet net, Expression 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
*/
static boolean isVar(Expression expr, HDLNet net) {
return expr instanceof ExprVar && ((ExprVar) expr).getNet() == net;
}
}

View File

@ -6,6 +6,7 @@
package de.neemann.digital.hdl.model2.optimizations;
import de.neemann.digital.hdl.model2.*;
import de.neemann.digital.hdl.model2.expression.ExprConstant;
import java.util.Iterator;
@ -21,10 +22,11 @@ public class RemoveConstantSignals implements Optimization {
Iterator<HDLNet> it = circuit.getNets().iterator();
while (it.hasNext()) {
HDLNet net = it.next();
if (net.isConstant() != null && isOnlyUsedInSupportedNodes(net)) {
final ExprConstant constant = net.isConstant();
if (constant != null && isOnlyUsedInSupportedNodes(net)) {
circuit.getNodes().remove(net.getOutput().getParent());
it.remove();
// keep net in ports to allow the nodes to access the constant for inlining.
circuit.replaceNetByExpression(net, new ExprConstant(constant));
}
}
}

View File

@ -12,6 +12,8 @@ import de.neemann.digital.hdl.model2.*;
import de.neemann.digital.hdl.model2.expression.*;
import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.hdl.vhdl2.entities.VHDLEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashSet;
@ -20,6 +22,7 @@ import java.util.HashSet;
* Create the vhdl output
*/
public class VHDLCreator {
private static final Logger LOGGER = LoggerFactory.getLogger(VHDLCreator.class);
private static final String ZEROS = "0000000000000000000000000000000000000000000000000000000000000000";
private final CodePrinter out;
private final VHDLLibrary library;
@ -105,13 +108,14 @@ public class VHDLCreator {
public void printHDLCircuit(HDLCircuit circuit) throws IOException, HDLException, HGSEvalException {
// at first print all used entities to maintain the correct order
for (HDLNode node : circuit)
if (node instanceof HDLNodeBuildIn)
printNodeBuiltIn((HDLNodeBuildIn) node);
else if (node instanceof HDLNodeCustom)
if (node instanceof HDLNodeCustom)
printNodeCustom((HDLNodeCustom) node);
else if (node instanceof HDLNodeBuildIn)
printNodeBuiltIn((HDLNodeBuildIn) node);
LOGGER.info("export " + circuit.getElementName());
// after that print this entity
out.println()
.println("LIBRARY ieee;")
.println("USE ieee.std_logic_1164.all;")
@ -139,10 +143,10 @@ public class VHDLCreator {
for (HDLNode node : circuit)
if (node instanceof HDLNodeAssignment)
printExpression((HDLNodeAssignment) node);
else if (node instanceof HDLNodeBuildIn || node instanceof HDLNodeCustom)
printEntityInstantiation(node, num++);
// else if (node instanceof HDLNodeSplitterOneToMany)
// printOneToMany((HDLNodeSplitterOneToMany) node);
else if (node instanceof HDLNodeBuildIn)
printEntityInstantiation((HDLNodeBuildIn) node, num++);
else if (node instanceof HDLNodeSplitterOneToMany)
printOneToMany((HDLNodeSplitterOneToMany) node);
else if (node instanceof HDLNodeSplitterManyToOne)
printManyToOne((HDLNodeSplitterManyToOne) node);
else
@ -183,51 +187,42 @@ public class VHDLCreator {
out.println(");").dec();
}
private void printManyToOne(HDLNodeSplitterManyToOne node) throws IOException {
private void printManyToOne(HDLNodeSplitterManyToOne node) throws IOException, HDLException {
String target = node.getTargetSignal();
Splitter.Ports is = node.getInputSplit();
int i = 0;
for (HDLPort in : node.getInputs()) {
Splitter.Port sp = is.getPort(i++);
for (HDLNodeSplitterManyToOne.SplitterAssignment in : node) {
out.print(target).print("(");
if (in.getBits() == 1)
out.print(sp.getPos());
if (in.getLsb() == in.getMsb())
out.print(in.getLsb());
else
out.print(sp.getPos() + sp.getBits() - 1).print(" downto ").print(sp.getPos());
out.print(in.getMsb()).print(" downto ").print(in.getLsb());
out.print(") <= ");
printInlineConstant(in);
printExpression(in.getExpression());
out.println(";");
}
}
private void printInlineConstant(HDLPort in) throws IOException {
ExprConstant con = ExprConstant.isConstant(in.getNet().getOutput().getParent());
if (con == null)
out.print(in.getNet().getName());
else
out.print(VHDLCreator.value(con));
/**
* After ReplaceOneToMany optimization there are no such nodes in the model!
*/
private void printOneToMany(HDLNodeSplitterOneToMany node) throws IOException {
String source = node.getSourceSignal();
Splitter.Ports is = node.getOutputSplit();
int i = 0;
for (HDLPort outPort : node.getOutputs()) {
Splitter.Port sp = is.getPort(i++);
if (outPort.getNet() != null) {
out.print(outPort.getNet().getName()).print(" <= ").print(source).print("(");
if (outPort.getBits() == 1)
out.print(sp.getPos());
else
out.print(sp.getPos() + sp.getBits() - 1).print(" downto ").print(sp.getPos());
out.println(");");
}
}
}
// After ReplaceOneToMany optimization there are no such nodes in the model.
//
// private void printOneToMany(HDLNodeSplitterOneToMany node) throws IOException {
// String source = node.getSourceSignal();
// Splitter.Ports is = node.getOutputSplit();
// int i = 0;
// for (HDLPort outPort : node.getOutputs()) {
// Splitter.Port sp = is.getPort(i++);
// if (outPort.getNet() != null) {
// out.print(outPort.getNet().getName()).print(" <= ").print(source).print("(");
// if (outPort.getBits() == 1)
// out.print(sp.getPos());
// else
// out.print(sp.getPos() + sp.getBits() - 1).print(" downto ").print(sp.getPos());
// out.println(");");
// }
// }
// }
private void printEntityInstantiation(HDLNode node, int num) throws IOException, HDLException {
private void printEntityInstantiation(HDLNodeBuildIn node, int num) throws IOException, HDLException {
String entityName = node.getHdlEntityName();
out.print("gate").print(num).print(": entity work.").print(entityName);
@ -241,12 +236,10 @@ public class VHDLCreator {
library.getEntity(node).writeGenericMap(out, node);
out.println("port map (").inc();
Separator sep = new Separator(out, ",\n");
for (HDLPort i : node.getInputs()) {
if (i.getNet() == null)
throw new HDLException("A input port without a net: " + i.getName() + " in " + entityName);
for (HDLNodeBuildIn.InputAssignment i : node) {
sep.check();
out.print(i.getName()).print(" => ");
printInlineConstant(i);
out.print(i.getTargetName()).print(" => ");
printExpression(i.getExpression());
}
for (HDLPort o : node.getOutputs())

View File

@ -155,8 +155,8 @@ public class HDLModelTest extends TestCase {
" node Splitter\n" +
" in(0,1:2 reads (A->1), 2,3:2 reads (B->1))\n" +
" out(single:4 defines (s0->2))\n" +
" s0(0-1) := A\n" +
" s0(2-3) := B\n" +
" s0(1-0) := A\n" +
" s0(3-2) := B\n" +
" node splitter\n" +
" in(in:4 reads (s0->2))\n" +
" out(0:1 defines (X->1))\n" +
@ -314,8 +314,8 @@ public class HDLModelTest extends TestCase {
" node Splitter\n" +
" in(0,1:2 reads (s0->1), 2,3:2 reads (s1->1))\n" +
" out(0-3:4 defines (S->1))\n" +
" S(0-1) := s0\n" +
" S(2-3) := s1\n" +
" S(1-0) := s0\n" +
" S(3-2) := s1\n" +
"\n" +
"end circuit main\n", cp.toString());
}