From df843cb1ad6a98e6001d1bc773422dc1e9f6bbe5 Mon Sep 17 00:00:00 2001 From: hneemann Date: Tue, 5 Jan 2021 23:06:38 +0100 Subject: [PATCH 1/3] fixes a Quartus VHDL issue --- .../java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java index 0725e9176..b61d857ca 100644 --- a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java @@ -290,7 +290,13 @@ public class VHDLCreator { out.print(value(constant)); } else if (expression instanceof ExprNot) { out.print("NOT "); - printExpression(((ExprNot) expression).getExpression()); + Expression inner = ((ExprNot) expression).getExpression(); + if (inner instanceof ExprNot) { // Quartus does not like a NOT NOT + out.print("("); + printExpression(inner); + out.print(")"); + } else + printExpression(inner); } else if (expression instanceof ExprOperate) { out.print("("); boolean first = true; From 4c0b0aafc1a8988d67cbfbdc434c4023995423ea Mon Sep 17 00:00:00 2001 From: hneemann Date: Wed, 6 Jan 2021 09:46:08 +0100 Subject: [PATCH 2/3] Adds a HDL expression optimization infrastructure and a not(not x) optimization. --- .../digital/hdl/model2/HDLCircuit.java | 1 + .../digital/hdl/model2/HDLNodeAssignment.java | 9 +++++ .../hdl/model2/expression/ExprNot.java | 21 ++++++++++ .../hdl/model2/expression/ExprOperate.java | 9 +++++ .../hdl/model2/expression/Expression.java | 9 +++++ .../expression/ExpressionOptimizer.java | 22 +++++++++++ .../optimizations/OptimizeExpressions.java | 39 +++++++++++++++++++ .../digital/hdl/verilog2/VerilogCreator.java | 8 +++- 8 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/neemann/digital/hdl/model2/expression/ExpressionOptimizer.java create mode 100644 src/main/java/de/neemann/digital/hdl/model2/optimizations/OptimizeExpressions.java diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java index e7b7dae9a..d69f96baa 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java @@ -535,6 +535,7 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin public HDLCircuit applyDefaultOptimizations() throws HDLException { apply(new ReplaceOneToMany()); apply(new MergeAssignments()); + apply(new OptimizeExpressions(new ExprNot.OptimizeNotNot())); apply(new InlineManyToOne()); apply(new RemoveConstantSignals()); apply(new MergeConstants()); // under certain circumstances there are still constants diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLNodeAssignment.java b/src/main/java/de/neemann/digital/hdl/model2/HDLNodeAssignment.java index 6a9b363a0..23cf261ff 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNodeAssignment.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNodeAssignment.java @@ -9,6 +9,7 @@ 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 de.neemann.digital.hdl.model2.expression.ExpressionOptimizer; import de.neemann.digital.hdl.model2.expression.Visitor; import de.neemann.digital.hdl.printer.CodePrinter; @@ -80,4 +81,12 @@ public class HDLNodeAssignment extends HDLNode { return getOutput().getNet(); } + /** + * Optimizes the expression + * + * @param eo the optimizer + */ + public void optimize(ExpressionOptimizer eo) { + expression = eo.optimize(expression); + } } diff --git a/src/main/java/de/neemann/digital/hdl/model2/expression/ExprNot.java b/src/main/java/de/neemann/digital/hdl/model2/expression/ExprNot.java index daee4cd50..7e8b8801f 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/expression/ExprNot.java +++ b/src/main/java/de/neemann/digital/hdl/model2/expression/ExprNot.java @@ -53,4 +53,25 @@ public class ExprNot implements Expression { visitor.visit(this); expr.traverse(visitor); } + + @Override + public void optimize(ExpressionOptimizer eo) { + expr = eo.optimize(expr); + expr.optimize(eo); + } + + /** + * Optimizes not(not a) expressions to a + */ + public static class OptimizeNotNot implements ExpressionOptimizer { + @Override + public Expression optimize(Expression expression) { + if (expression instanceof ExprNot) { + ExprNot not = (ExprNot) expression; + if (not.expr instanceof ExprNot) + return optimize(((ExprNot) not.expr).expr); + } + return expression; + } + } } diff --git a/src/main/java/de/neemann/digital/hdl/model2/expression/ExprOperate.java b/src/main/java/de/neemann/digital/hdl/model2/expression/ExprOperate.java index 5f5ffbe6c..ed469db09 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/expression/ExprOperate.java +++ b/src/main/java/de/neemann/digital/hdl/model2/expression/ExprOperate.java @@ -93,4 +93,13 @@ public class ExprOperate implements Expression { for (Expression o : operands) o.traverse(visitor); } + + @Override + public void optimize(ExpressionOptimizer eo) { + for (int i = 0; i < operands.size(); i++) { + Expression expr = eo.optimize(operands.get(i)); + expr.optimize(eo); + operands.set(i, expr); + } + } } diff --git a/src/main/java/de/neemann/digital/hdl/model2/expression/Expression.java b/src/main/java/de/neemann/digital/hdl/model2/expression/Expression.java index e4144f906..15169b6cf 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/expression/Expression.java +++ b/src/main/java/de/neemann/digital/hdl/model2/expression/Expression.java @@ -30,6 +30,15 @@ public interface Expression extends Printable { visitor.visit(this); } + + /** + * Tries to optimize the expression by replacing it by a optimized one. + * + * @param eo the optimizer + */ + default void optimize(ExpressionOptimizer eo) { + } + /** * Helper to check if an expression is a net reference * diff --git a/src/main/java/de/neemann/digital/hdl/model2/expression/ExpressionOptimizer.java b/src/main/java/de/neemann/digital/hdl/model2/expression/ExpressionOptimizer.java new file mode 100644 index 000000000..947eb53c6 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/model2/expression/ExpressionOptimizer.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021 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; + +/** + * Interface to optimize an expression + */ +public interface ExpressionOptimizer { + + /** + * Optimizes the given expression. + * Should call itself on the returned expression if a optimization was made. + * See {@link ExprNot.OptimizeNotNot} as an example. + * + * @param expression the expression to optimize + * @return the optimizes expression or the given expression if optimization is not possible + */ + Expression optimize(Expression expression); +} diff --git a/src/main/java/de/neemann/digital/hdl/model2/optimizations/OptimizeExpressions.java b/src/main/java/de/neemann/digital/hdl/model2/optimizations/OptimizeExpressions.java new file mode 100644 index 000000000..4462ebe57 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/model2/optimizations/OptimizeExpressions.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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.optimizations; + +import de.neemann.digital.hdl.model2.HDLCircuit; +import de.neemann.digital.hdl.model2.HDLException; +import de.neemann.digital.hdl.model2.HDLNode; +import de.neemann.digital.hdl.model2.HDLNodeAssignment; +import de.neemann.digital.hdl.model2.expression.ExpressionOptimizer; + +/** + * Optimization which addresses the used expressions. + */ +public class OptimizeExpressions implements Optimization { + + private final ExpressionOptimizer eo; + + /** + * Creates a new instance + * + * @param eo the expression optimizer to use. + */ + public OptimizeExpressions(ExpressionOptimizer eo) { + this.eo = eo; + } + + @Override + public void optimize(HDLCircuit circuit) throws HDLException { + for (HDLNode n : circuit.getNodes()) { + if (n instanceof HDLNodeAssignment) { + HDLNodeAssignment a = (HDLNodeAssignment) n; + a.optimize(eo); + } + } + } +} diff --git a/src/main/java/de/neemann/digital/hdl/verilog2/VerilogCreator.java b/src/main/java/de/neemann/digital/hdl/verilog2/VerilogCreator.java index 9089bdc16..7a6d762e5 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog2/VerilogCreator.java +++ b/src/main/java/de/neemann/digital/hdl/verilog2/VerilogCreator.java @@ -300,7 +300,13 @@ public class VerilogCreator { out.print(value(constant)); } else if (expression instanceof ExprNot) { out.print("~ "); - printExpression(((ExprNot) expression).getExpression()); + Expression inner = ((ExprNot) expression).getExpression(); + if (inner instanceof ExprNot) { // Quartus does not like a NOT NOT + out.print("("); + printExpression(inner); + out.print(")"); + } else + printExpression(inner); } else if (expression instanceof ExprOperate) { out.print("("); boolean first = true; From a93ebf3554b64830f997b85a60d1dd8cd00fdd57 Mon Sep 17 00:00:00 2001 From: hneemann Date: Thu, 7 Jan 2021 10:01:00 +0100 Subject: [PATCH 3/3] adds a NOT optimizing test case --- .../hdl/verilog2/VerilogSimulatorTest.java | 4 +- .../digital/hdl/vhdl2/VHDLSimulatorTest.java | 4 +- .../digital/integration/TestExamples.java | 4 +- src/test/resources/dig/test/vhdl/not.dig | 281 ++++++++++++++++++ 4 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 src/test/resources/dig/test/vhdl/not.dig diff --git a/src/test/java/de/neemann/digital/hdl/verilog2/VerilogSimulatorTest.java b/src/test/java/de/neemann/digital/hdl/verilog2/VerilogSimulatorTest.java index 85d77554a..682b43c3a 100644 --- a/src/test/java/de/neemann/digital/hdl/verilog2/VerilogSimulatorTest.java +++ b/src/test/java/de/neemann/digital/hdl/verilog2/VerilogSimulatorTest.java @@ -51,8 +51,8 @@ public class VerilogSimulatorTest extends TestCase { File examples = new File(Resources.getRoot(), "/dig/test/vhdl"); try { int tested = new FileScanner(this::checkVerilogExport).noOutput().scan(examples); - assertEquals(60, tested); - assertEquals(53, testBenches); + assertEquals(61, tested); + assertEquals(54, testBenches); } catch (FileScanner.SkipAllException e) { // if iverilog is not installed its also ok } diff --git a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java index 91a9573b4..5f879bced 100644 --- a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java @@ -43,8 +43,8 @@ public class VHDLSimulatorTest extends TestCase { File examples = new File(Resources.getRoot(), "/dig/test/vhdl"); try { int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples); - assertEquals(60, tested); - assertEquals(53, testBenches); + assertEquals(61, tested); + assertEquals(54, testBenches); } catch (FileScanner.SkipAllException e) { // if ghdl is not installed its also ok } diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index 46b2455f4..050ed6be3 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -50,8 +50,8 @@ public class TestExamples extends TestCase { */ public void testTestExamples() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test"); - assertEquals(199, new FileScanner(this::check).scan(examples)); - assertEquals(188, testCasesInFiles); + assertEquals(200, new FileScanner(this::check).scan(examples)); + assertEquals(189, testCasesInFiles); } /** diff --git a/src/test/resources/dig/test/vhdl/not.dig b/src/test/resources/dig/test/vhdl/not.dig new file mode 100644 index 000000000..0ba70dff1 --- /dev/null +++ b/src/test/resources/dig/test/vhdl/not.dig @@ -0,0 +1,281 @@ + + + 1 + + + + In + + + Label + A + + + + + + Not + + + + + In + + + Label + B + + + + + + Not + + + + + Not + + + + + In + + + Label + C + + + + + + Not + + + + + Not + + + + + Not + + + + + In + + + Label + D + + + + + + Not + + + + + Not + + + + + Not + + + + + Not + + + + + In + + + Label + E + + + + + + Not + + + + + Not + + + + + Not + + + + + Not + + + + + Not + + + + + Out + + + Label + Y + + + + + + Out + + + Label + X + + + + + + Out + + + Label + Z + + + + + + Out + + + Label + U + + + + + + Out + + + Label + V + + + + + + Testcase + + + Testdata + + A B C D E Y X Z U V + + 0 0 0 0 0 1 0 1 0 1 + 1 1 1 1 1 0 1 0 1 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file