fixed a merging issue

This commit is contained in:
hneemann 2018-04-14 14:14:15 +02:00
parent cf4ce1ec52
commit ea09282bc3
8 changed files with 160 additions and 18 deletions

View File

@ -524,7 +524,7 @@ public class HDLCircuit implements Iterable<HDLNode>, HDLModel.BitProvider, Prin
*/ */
public HDLCircuit applyDefaultOptimizations() throws HDLException { public HDLCircuit applyDefaultOptimizations() throws HDLException {
apply(new ReplaceOneToMany()); apply(new ReplaceOneToMany());
apply(new MergeAssignements()); apply(new MergeAssignments());
apply(new InlineManyToOne()); apply(new InlineManyToOne());
apply(new RemoveConstantSignals()); apply(new RemoveConstantSignals());
apply(new MergeConstants()); // under certain circumstances there are still constants apply(new MergeConstants()); // under certain circumstances there are still constants

View File

@ -14,7 +14,7 @@ import de.neemann.digital.hdl.model2.Printable;
public interface Expression extends Printable { public interface Expression extends Printable {
/** /**
* Replaces a net with and expression * Replaces a net with an expression
* *
* @param net the net to replace * @param net the net to replace
* @param expression the expression to use instead ot the net * @param expression the expression to use instead ot the net
@ -31,7 +31,7 @@ public interface Expression extends Printable {
} }
/** /**
* Help er to check if a expression is a net reference * Helper to check if an expression is a net reference
* *
* @param expr the expression to check * @param expr the expression to check
* @param net the net * @param net the net

View File

@ -6,14 +6,16 @@
package de.neemann.digital.hdl.model2.optimizations; package de.neemann.digital.hdl.model2.optimizations;
import de.neemann.digital.hdl.model2.*; import de.neemann.digital.hdl.model2.*;
import de.neemann.digital.hdl.model2.expression.ExprVarRange;
import de.neemann.digital.hdl.model2.expression.Expression; import de.neemann.digital.hdl.model2.expression.Expression;
import de.neemann.digital.hdl.model2.expression.Visitor;
import java.util.ArrayList; import java.util.ArrayList;
/** /**
* Merges the bool expression by inlining nodes which also represent a bool expression. * Merges the bool expression by inlining nodes which also represent a bool expression.
*/ */
public class MergeAssignements implements Optimization { public class MergeAssignments implements Optimization {
private HDLCircuit circuit; private HDLCircuit circuit;
private ArrayList<HDLNode> nodes; private ArrayList<HDLNode> nodes;
@ -29,14 +31,18 @@ public class MergeAssignements implements Optimization {
for (int i = 0; i < nodes.size(); i++) { for (int i = 0; i < nodes.size(); i++) {
HDLNode n1 = nodes.get(i); HDLNode n1 = nodes.get(i);
if (n1 instanceof HDLNodeAssignment) { if (n1 instanceof HDLNodeAssignment) {
for (HDLPort p : n1.getInputs()) { HDLNodeAssignment host = (HDLNodeAssignment) n1;
for (HDLPort p : host.getInputs()) {
HDLNode n2 = searchCreator(p.getNet()); HDLNode n2 = searchCreator(p.getNet());
if (n2 != null && n2 instanceof HDLNodeAssignment) { if (n2 != null && n2 instanceof HDLNodeAssignment) {
if (n2.getOutputs().size() == 1 && n2.getOutput().getNet().getInputs().size() == 1) { HDLNodeAssignment include = (HDLNodeAssignment) n2;
nodes.set(i, merge((HDLNodeAssignment) n1, (HDLNodeAssignment) n2)); if (include.getOutputs().size() == 1 && include.getOutput().getNet().getInputs().size() == 1) {
nodes.remove(n2); if (allowedToReplaceNet(host.getExpression(), include.getOutput().getNet())) {
wasOptimization = true; nodes.set(i, merge(host, include));
break outer; nodes.remove(n2);
wasOptimization = true;
break outer;
}
} }
} }
} }
@ -45,6 +51,12 @@ public class MergeAssignements implements Optimization {
} while (wasOptimization); } while (wasOptimization);
} }
private boolean allowedToReplaceNet(Expression expression, HDLNet net) {
final CheckVarRangeVisitor visitor = new CheckVarRangeVisitor(net);
expression.traverse(visitor);
return visitor.ok;
}
private HDLNodeAssignment merge(HDLNodeAssignment host, HDLNodeAssignment include) { private HDLNodeAssignment merge(HDLNodeAssignment host, HDLNodeAssignment include) {
final Expression expression = host.getExpression(); final Expression expression = host.getExpression();
final HDLNet obsoleteNet = include.getOutput().getNet(); final HDLNet obsoleteNet = include.getOutput().getNet();
@ -77,4 +89,23 @@ public class MergeAssignements implements Optimization {
return n; return n;
return null; return null;
} }
private static final class CheckVarRangeVisitor implements Visitor {
private final HDLNet net;
private boolean ok;
private CheckVarRangeVisitor(HDLNet net) {
this.net = net;
ok = true;
}
@Override
public void visit(Expression expression) {
if (expression instanceof ExprVarRange) {
ExprVarRange evr = (ExprVarRange) expression;
if (evr.getNet() == net)
ok = false;
}
}
}
} }

View File

@ -26,7 +26,7 @@ public class HDLModelTest extends TestCase {
public void testSimple() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException { public void testSimple() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException {
HDLCircuit hdl = getCircuit("dig/hdl/model2/comb.dig", null) HDLCircuit hdl = getCircuit("dig/hdl/model2/comb.dig", null)
.apply(new MergeAssignements()) .apply(new MergeAssignments())
.apply(new NodeSorterExpressionBased()) .apply(new NodeSorterExpressionBased())
.nameUnnamedSignals(); .nameUnnamedSignals();
@ -215,7 +215,7 @@ public class HDLModelTest extends TestCase {
public void testConstantMerge() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException { public void testConstantMerge() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException {
HDLCircuit hdl = getCircuit("dig/hdl/model2/constMerge.dig", null) HDLCircuit hdl = getCircuit("dig/hdl/model2/constMerge.dig", null)
.apply(new MergeAssignements()) .apply(new MergeAssignments())
.apply(new MergeConstants()) .apply(new MergeConstants())
.apply(new NameConstantSignals()) .apply(new NameConstantSignals())
.apply(new NodeSorterExpressionBased()) .apply(new NodeSorterExpressionBased())
@ -292,7 +292,7 @@ public class HDLModelTest extends TestCase {
public void testSplitter3() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException { public void testSplitter3() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException {
HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter3.dig", null) HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter3.dig", null)
.apply(new ReplaceOneToMany()) .apply(new ReplaceOneToMany())
.apply(new MergeAssignements()) .apply(new MergeAssignments())
.apply(new NodeSorterExpressionBased()) .apply(new NodeSorterExpressionBased())
.nameUnnamedSignals(); .nameUnnamedSignals();
@ -323,7 +323,7 @@ public class HDLModelTest extends TestCase {
public void testSplitter4() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException { public void testSplitter4() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException {
HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter4.dig", null) HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter4.dig", null)
.apply(new ReplaceOneToMany()) .apply(new ReplaceOneToMany())
.apply(new MergeAssignements()) .apply(new MergeAssignments())
.apply(new NodeSorterExpressionBased()) .apply(new NodeSorterExpressionBased())
.nameUnnamedSignals(); .nameUnnamedSignals();

View File

@ -14,7 +14,6 @@ import de.neemann.digital.hdl.model2.HDLException;
import de.neemann.digital.hdl.model2.HDLModel; import de.neemann.digital.hdl.model2.HDLModel;
import de.neemann.digital.hdl.model2.clock.ClockIntegratorGeneric; import de.neemann.digital.hdl.model2.clock.ClockIntegratorGeneric;
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator; import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
import de.neemann.digital.hdl.model2.optimizations.MergeAssignements;
import de.neemann.digital.hdl.printer.CodePrinter; import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.hdl.printer.CodePrinterStr; import de.neemann.digital.hdl.printer.CodePrinterStr;
import de.neemann.digital.hdl.vhdl2.boards.ClockIntegratorARTIX7; import de.neemann.digital.hdl.vhdl2.boards.ClockIntegratorARTIX7;

View File

@ -12,8 +12,6 @@ import de.neemann.digital.hdl.hgs.HGSEvalException;
import de.neemann.digital.hdl.model2.HDLCircuit; import de.neemann.digital.hdl.model2.HDLCircuit;
import de.neemann.digital.hdl.model2.HDLException; import de.neemann.digital.hdl.model2.HDLException;
import de.neemann.digital.hdl.model2.HDLModel; import de.neemann.digital.hdl.model2.HDLModel;
import de.neemann.digital.hdl.model2.optimizations.MergeConstants;
import de.neemann.digital.hdl.model2.optimizations.MergeAssignements;
import de.neemann.digital.hdl.printer.CodePrinterStr; import de.neemann.digital.hdl.printer.CodePrinterStr;
import de.neemann.digital.integration.ToBreakRunner; import de.neemann.digital.integration.ToBreakRunner;
import junit.framework.TestCase; import junit.framework.TestCase;

View File

@ -59,7 +59,7 @@ public class VHDLSimulatorTest extends TestCase {
File examples = new File(Resources.getRoot(), "/dig/hdl"); File examples = new File(Resources.getRoot(), "/dig/hdl");
try { try {
int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples); int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples);
assertEquals(45, tested); assertEquals(46, tested);
} catch (FileScanner.SkipAllException e) { } catch (FileScanner.SkipAllException e) {
// if ghdl is not installed its also ok // if ghdl is not installed its also ok
} }

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>1</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>A</string>
</entry>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
</elementAttributes>
<pos x="40" y="100"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>B</string>
</entry>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
</elementAttributes>
<pos x="40" y="140"/>
</visualElement>
<visualElement>
<elementName>And</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
</elementAttributes>
<pos x="60" y="100"/>
</visualElement>
<visualElement>
<elementName>Splitter</elementName>
<elementAttributes>
<entry>
<string>Input Splitting</string>
<string>8</string>
</entry>
<entry>
<string>Output Splitting</string>
<string>4</string>
</entry>
</elementAttributes>
<pos x="160" y="120"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>Y</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="220" y="120"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Testdata</string>
<testData>
<dataString>A B Y
0 0 0
0 1 0
1 0 0
1 1 1
0 0 0
0 255 0
255 0 0
255 255 15
</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="80" y="180"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="40" y="100"/>
<p2 x="60" y="100"/>
</wire>
<wire>
<p1 x="120" y="120"/>
<p2 x="160" y="120"/>
</wire>
<wire>
<p1 x="180" y="120"/>
<p2 x="220" y="120"/>
</wire>
<wire>
<p1 x="40" y="140"/>
<p2 x="60" y="140"/>
</wire>
</wires>
<measurementOrdering/>
</circuit>