From 89a4b43cf91b0ce6944eebde2826c1c4169255f4 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 25 Mar 2018 11:57:06 +0200 Subject: [PATCH] clock integration is mostly working --- .../digital/hdl/model2/HDLCircuit.java | 68 +++++- .../neemann/digital/hdl/model2/HDLModel.java | 14 +- .../de/neemann/digital/hdl/model2/HDLNet.java | 11 +- .../neemann/digital/hdl/model2/HDLNode.java | 24 +-- .../digital/hdl/model2/HDLNodeBuildIn.java | 2 +- .../neemann/digital/hdl/model2/HDLPort.java | 16 +- .../digital/hdl/model2/OperationMerger.java | 6 +- .../digital/hdl/model2/clock/ClockInfo.java | 41 ++++ .../model2/clock/ClockIntegratorGeneric.java | 51 +++++ .../hdl/model2/clock/HDLClockIntegrator.java | 28 +++ .../hdl/model2/clock/package-info.java | 10 + .../hdl/model2/expression/ExprVar.java | 2 +- .../digital/hdl/vhdl2/VHDLGenerator.java | 36 +++- .../hdl/vhdl2/boards/BoardInterface.java | 32 +++ .../hdl/vhdl2/boards/BoardProvider.java | 61 ++++++ .../vhdl2/boards/ClockIntegratorARTIX7.java | 198 ++++++++++++++++++ .../digital/hdl/vhdl2/boards/Vivado.java | 150 +++++++++++++ .../hdl/vhdl2/boards/package-info.java | 12 ++ .../digital/hdl/model2/HDLCircuitTest.java | 77 ++++--- .../digital/hdl/vhdl2/VHDLGeneratorTest.java | 8 +- src/test/resources/dig/hdl/model2/clock.dig | 69 ++++++ 21 files changed, 843 insertions(+), 73 deletions(-) create mode 100644 src/main/java/de/neemann/digital/hdl/model2/clock/ClockInfo.java create mode 100644 src/main/java/de/neemann/digital/hdl/model2/clock/ClockIntegratorGeneric.java create mode 100644 src/main/java/de/neemann/digital/hdl/model2/clock/HDLClockIntegrator.java create mode 100644 src/main/java/de/neemann/digital/hdl/model2/clock/package-info.java create mode 100644 src/main/java/de/neemann/digital/hdl/vhdl2/boards/BoardInterface.java create mode 100644 src/main/java/de/neemann/digital/hdl/vhdl2/boards/BoardProvider.java create mode 100644 src/main/java/de/neemann/digital/hdl/vhdl2/boards/ClockIntegratorARTIX7.java create mode 100644 src/main/java/de/neemann/digital/hdl/vhdl2/boards/Vivado.java create mode 100644 src/main/java/de/neemann/digital/hdl/vhdl2/boards/package-info.java create mode 100644 src/test/resources/dig/hdl/model2/clock.dig 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 d6645f2da..9cc3f7a72 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java @@ -24,6 +24,8 @@ 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.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.printer.CodePrinter; @@ -57,6 +59,20 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin * @throws NodeException NodeException */ HDLCircuit(Circuit circuit, String elementName, HDLModel c) throws PinException, HDLException, NodeException { + this(circuit, elementName, c, null); + } + + /** + * 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 + */ + HDLCircuit(Circuit circuit, String elementName, HDLModel c, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, NodeException { this.elementName = elementName; if (elementName.toLowerCase().endsWith(".dig")) @@ -71,20 +87,26 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin nets = new HashMap<>(); listOfNets = new ArrayList<>(); netList = new NetList(circuit); + + ArrayList clocks = new ArrayList<>(); + try { for (VisualElement v : circuit.getElements()) { - if (v.equalsDescription(In.DESCRIPTION) || v.equalsDescription(Clock.DESCRIPTION)) - addInput(new HDLPort( + if (v.equalsDescription(In.DESCRIPTION) || v.equalsDescription(Clock.DESCRIPTION)) { + final HDLPort port = new HDLPort( v.getElementAttributes().getCleanLabel(), getNetOfPin(v.getPins().get(0)), - HDLPort.Direction.OUT, + HDLPort.Direction.OUT, // from inside the node this is an output because it defines a value v.getElementAttributes().getBits()) - .setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER))); - else if (v.equalsDescription(Out.DESCRIPTION)) + .setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER)); + addInput(port); + if (v.equalsDescription(Clock.DESCRIPTION)) + clocks.add(new ClockInfo(port, v.getElementAttributes().get(Keys.FREQUENCY))); + } else if (v.equalsDescription(Out.DESCRIPTION)) addOutput(new HDLPort( v.getElementAttributes().getCleanLabel(), getNetOfPin(v.getPins().get(0)), - HDLPort.Direction.IN, + HDLPort.Direction.IN, // from inside the node this is an input because it reads the value to output v.getElementAttributes().getBits()) .setPinNumber(v.getElementAttributes().get(Keys.PINNUMBER))); else if (v.equalsDescription(Splitter.DESCRIPTION)) @@ -99,6 +121,9 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin netList = null; nets = null; + if (clockIntegrator != null && !clocks.isEmpty()) + clockIntegrator.integrateClocks(this, clocks); + for (HDLNet n : listOfNets) n.fixBits(); @@ -147,10 +172,10 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin HDLNodeSplitterOneToMany oneToMany = new HDLNodeSplitterOneToMany(node, outputSplit); manyToOne.getOutputs().clear(); - manyToOne.addOutput(left); + manyToOne.addPort(left); oneToMany.getInputs().clear(); - oneToMany.addInput(right); + oneToMany.addPort(right); nodes.add(manyToOne); nodes.add(oneToMany); @@ -164,8 +189,8 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin HDLNet inNet = p.getNet(); inNet.remove(p); - n.addInput(new HDLPort(Not.DESCRIPTION.getInputDescription(attr).get(0).getName(), inNet, HDLPort.Direction.IN, p.getBits())); - n.addOutput(new HDLPort(Not.DESCRIPTION.getOutputDescriptions(attr).get(0).getName(), outNet, HDLPort.Direction.OUT, p.getBits())); + n.addPort(new HDLPort(Not.DESCRIPTION.getInputDescription(attr).get(0).getName(), inNet, HDLPort.Direction.IN, p.getBits())); + n.addPort(new HDLPort(Not.DESCRIPTION.getOutputDescriptions(attr).get(0).getName(), outNet, HDLPort.Direction.OUT, p.getBits())); p.setNet(outNet); node.replaceNet(inNet, outNet); @@ -269,7 +294,7 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin } /** - * Merges logcal operations if possible + * Merges logical operations if possible * * @return this for chained calls */ @@ -398,6 +423,27 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin return hdlEntityName; } + /** + * Integrates a clock node. + * + * @param clock the clock port + * @param clockNode the new clock node + * @throws HDLException HDLException + */ + public void integrateClockNode(HDLPort clock, HDLNodeBuildIn clockNode) throws HDLException { + HDLNet outNet = clock.getNet(); + HDLNet inNet = new HDLNet(null); + outNet.resetOutput(); + clock.setNet(inNet); + listOfNets.add(inNet); + + clockNode + .addPort(new HDLPort("cout", outNet, HDLPort.Direction.OUT, 1)) + .addPort(new HDLPort("cin", inNet, HDLPort.Direction.IN, 1)); + + nodes.add(clockNode); + } + /** * The net naming algorithm */ diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java index eb03e5ad8..dba8052a7 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java @@ -20,6 +20,7 @@ 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.clock.HDLClockIntegrator; import de.neemann.digital.hdl.model2.expression.*; import java.util.ArrayList; @@ -144,9 +145,9 @@ public class HDLModel implements Iterable { 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)); + node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0)); else - node.addOutput(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); + node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); } return node; } @@ -160,14 +161,15 @@ public class HDLModel implements Iterable { /** * Analyses the given circuit * - * @param circuit the circuit + * @param circuit the circuit + * @param clockIntegrator the clock integrator. Meybe null * @return this for chained calls * @throws PinException PinException * @throws HDLException HDLException * @throws NodeException NodeException */ - public HDLModel create(Circuit circuit) throws PinException, HDLException, NodeException { - main = new HDLCircuit(circuit, "main", this); + public HDLModel create(Circuit circuit, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, NodeException { + main = new HDLCircuit(circuit, "main", this, clockIntegrator); circuitMap.put(circuit, main); return this; } @@ -234,7 +236,7 @@ public class HDLModel implements Iterable { /** * The bit provider interface */ - interface BitProvider { + public interface BitProvider { /** * Returns the number of bits of the signal with the given name * diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java b/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java index 10ca551de..4f992407e 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java @@ -86,7 +86,7 @@ public class HDLNet implements Printable { @Override public void print(CodePrinter out) throws IOException { - out.print(name).print(":").print(output.getBits()); + out.print(name).print("->").print(inputs.size()); } /** @@ -140,6 +140,14 @@ public class HDLNet implements Printable { return output.getBits(); } + /** + * resets the output of this net + */ + public void resetOutput() { + output = null; + name = null; + } + /** * Renames this net. * @@ -148,4 +156,5 @@ public class HDLNet implements Printable { public void rename(HDLModel.Renaming renaming) { name = renaming.checkName(name); } + } diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLNode.java b/src/main/java/de/neemann/digital/hdl/model2/HDLNode.java index c281e53c2..4a628ce80 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNode.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNode.java @@ -37,12 +37,18 @@ public class HDLNode { outputs = new ArrayList<>(); } - void addInput(HDLPort port) { - inputs.add(port); - } - - void addOutput(HDLPort port) { - outputs.add(port); + /** + * Adds a port to this node + * + * @param port the port to add + * @return this for chained calls + */ + public HDLNode addPort(HDLPort port) { + if (port.getDirection().equals(HDLPort.Direction.OUT)) + outputs.add(port); + else + inputs.add(port); + return this; } @Override @@ -111,12 +117,6 @@ public class HDLNode { } 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.print("("); diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLNodeBuildIn.java b/src/main/java/de/neemann/digital/hdl/model2/HDLNodeBuildIn.java index ef643cd89..e4b4c9f17 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNodeBuildIn.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNodeBuildIn.java @@ -18,7 +18,7 @@ public class HDLNodeBuildIn extends HDLNode { * @param elementAttributes the attributes * @param bitProvider the bit provider which provides the outputs bit width */ - HDLNodeBuildIn(String elementName, ElementAttributes elementAttributes, HDLModel.BitProvider bitProvider) { + public HDLNodeBuildIn(String elementName, ElementAttributes elementAttributes, HDLModel.BitProvider bitProvider) { super(elementName, elementAttributes, bitProvider); } } diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java b/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java index f8ad6bb83..5c9c43a6a 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java @@ -20,10 +20,14 @@ public class HDLPort implements Printable { public enum Direction { /** * input + * Caution: a circuits output components port has type IN because it reads the value to + * output, seen from inside the node. */ IN, /** * output + * Caution: a circuits input components port has type OUT because it defines a value, + * seen from inside the node. */ OUT } @@ -81,7 +85,8 @@ public class HDLPort implements Printable { if (this.net != null) this.net.remove(this); this.net = net; - net.addPort(this); + if (net != null) + net.addPort(this); } /** @@ -129,6 +134,15 @@ public class HDLPort implements Printable { @Override public void print(CodePrinter out) throws IOException { out.print(name).print(":").print(bits); + if (net != null) { + if (net.getOutput() == this) + out.print(" defines ("); + else + out.print(" reads ("); + net.print(out); + out.print(")"); + } else + out.print(" is not used"); } /** diff --git a/src/main/java/de/neemann/digital/hdl/model2/OperationMerger.java b/src/main/java/de/neemann/digital/hdl/model2/OperationMerger.java index 04ed73084..44f37b63c 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/OperationMerger.java +++ b/src/main/java/de/neemann/digital/hdl/model2/OperationMerger.java @@ -58,14 +58,14 @@ class OperationMerger { circuit.removeNet(obsoleteNet); - node.addOutput(host.getOutput()); + node.addPort(host.getOutput()); for (HDLPort i : host.getInputs()) if (i.getNet() != obsoleteNet) - node.addInput(i); + node.addPort(i); for (HDLPort i : include.getInputs()) if (!node.hasInput(i)) - node.addInput(i); + node.addPort(i); return node; } diff --git a/src/main/java/de/neemann/digital/hdl/model2/clock/ClockInfo.java b/src/main/java/de/neemann/digital/hdl/model2/clock/ClockInfo.java new file mode 100644 index 000000000..9c36540a1 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/model2/clock/ClockInfo.java @@ -0,0 +1,41 @@ +/* + * 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.clock; + +import de.neemann.digital.hdl.model2.HDLPort; + +/** + * A clock information bean. + */ +public class ClockInfo { + private HDLPort clockPort; + private int frequency; + + /** + * Creates a new instance. + * + * @param clockPort the clock port + * @param frequency the clock frequency + */ + public ClockInfo(HDLPort clockPort, int frequency) { + this.clockPort = clockPort; + this.frequency = frequency; + } + + /** + * @return the clock port + */ + public HDLPort getClockPort() { + return clockPort; + } + + /** + * @return the clocks frequency + */ + public int getFrequency() { + return frequency; + } +} diff --git a/src/main/java/de/neemann/digital/hdl/model2/clock/ClockIntegratorGeneric.java b/src/main/java/de/neemann/digital/hdl/model2/clock/ClockIntegratorGeneric.java new file mode 100644 index 000000000..b9099e642 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/model2/clock/ClockIntegratorGeneric.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017 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.clock; + +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.Key; +import de.neemann.digital.hdl.model2.*; +import de.neemann.digital.hdl.model2.HDLCircuit; + +import java.util.ArrayList; + +/** + * Creates a simple generic clock divider. + * Inserts a simple clock divider to match the frequency given in the model. + * Not suited for real world applications because a logical signal is used + * to clock the entities. + * You should use the FPGA-dependant clock resources to generate a clock signal. + */ +public class ClockIntegratorGeneric implements HDLClockIntegrator { + private static final Key COUNTER_KEY = new Key<>("maxCounter", 0); + private double periodns; + + /** + * Creates a new instance + * + * @param periodns the clock period in ns + */ + public ClockIntegratorGeneric(double periodns) { + this.periodns = periodns; + } + + @Override + public void integrateClocks(HDLCircuit circuit, ArrayList clocks) throws HDLException { + for (ClockInfo ci : clocks) { + int freq = ci.getFrequency(); + int counter = (int) (1000000000.0 / (periodns * 2 * freq)); + + if (counter >= 2) { + HDLNodeBuildIn node = new HDLNodeBuildIn("simpleClockDivider", + new ElementAttributes().set(COUNTER_KEY, counter), + name -> 1); + + circuit.integrateClockNode(ci.getClockPort(), node); + } + } + } + +} diff --git a/src/main/java/de/neemann/digital/hdl/model2/clock/HDLClockIntegrator.java b/src/main/java/de/neemann/digital/hdl/model2/clock/HDLClockIntegrator.java new file mode 100644 index 000000000..83bcab3ce --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/model2/clock/HDLClockIntegrator.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017 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.clock; + +import de.neemann.digital.hdl.model2.HDLCircuit; +import de.neemann.digital.hdl.model2.HDLException; + +import java.util.ArrayList; + +/** + * Used to utilize the board specific clock resources + */ +public interface HDLClockIntegrator { + + /** + * Modifies the circuit to integrate the clock sources + * + * @param circuit the circuit + * @param clocks the clock input ports + * @throws HDLException HDLException + */ + void integrateClocks(HDLCircuit circuit, ArrayList clocks) throws HDLException; + +} + diff --git a/src/main/java/de/neemann/digital/hdl/model2/clock/package-info.java b/src/main/java/de/neemann/digital/hdl/model2/clock/package-info.java new file mode 100644 index 000000000..c627b5390 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/model2/clock/package-info.java @@ -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 be used to modify the clock source of a circuit + */ +package de.neemann.digital.hdl.model2.clock; diff --git a/src/main/java/de/neemann/digital/hdl/model2/expression/ExprVar.java b/src/main/java/de/neemann/digital/hdl/model2/expression/ExprVar.java index 64ae8bcbd..e45d6e326 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/expression/ExprVar.java +++ b/src/main/java/de/neemann/digital/hdl/model2/expression/ExprVar.java @@ -34,7 +34,7 @@ public class ExprVar implements Expression { @Override public void print(CodePrinter out) throws IOException { - net.print(out); + out.print(net.getName()); } @Override diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLGenerator.java b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLGenerator.java index 33b00c549..7dce8b179 100644 --- a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLGenerator.java +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLGenerator.java @@ -11,13 +11,18 @@ import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.hdl.hgs.HGSEvalException; import de.neemann.digital.hdl.model2.HDLCircuit; -import de.neemann.digital.hdl.model2.HDLModel; import de.neemann.digital.hdl.model2.HDLException; +import de.neemann.digital.hdl.model2.HDLModel; +import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator; import de.neemann.digital.hdl.printer.CodePrinter; import de.neemann.digital.hdl.printer.CodePrinterStr; +import de.neemann.digital.hdl.vhdl2.boards.BoardInterface; +import de.neemann.digital.hdl.vhdl2.boards.BoardProvider; import de.neemann.digital.lang.Lang; -import java.io.*; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; /** @@ -28,6 +33,7 @@ public class VHDLGenerator implements Closeable { private final ElementLibrary library; private final CodePrinter out; private ArrayList testBenches; + private boolean useClockIntegration = true; /** * Creates a new exporter @@ -58,8 +64,15 @@ public class VHDLGenerator implements Closeable { * @throws IOException IOException */ public VHDLGenerator export(Circuit circuit) throws IOException { + + BoardInterface board = BoardProvider.getInstance().getBoard(circuit); + + HDLClockIntegrator clockIntegrator = null; + if (board != null && useClockIntegration) + clockIntegrator = board.getClockIntegrator(); + try { - HDLModel model = new HDLModel(library).create(circuit); + HDLModel model = new HDLModel(library).create(circuit, clockIntegrator); for (HDLCircuit c : model) c.mergeOperations().nameNets(new HDLCircuit.SimpleNetNaming()); @@ -87,11 +100,15 @@ public class VHDLGenerator implements Closeable { new VHDLCreator(out).printHDLCircuit(model.getMain()); File outFile = out.getFile(); - if (outFile != null) + if (outFile != null) { testBenches = new VHDLTestBenchCreator(circuit, model) .write(outFile) .getTestFileWritten(); + if (board != null) + board.writeFiles(outFile.getParentFile(), model); + } + return this; } catch (PinException | NodeException | HDLException | HGSEvalException e) { throw new IOException(Lang.get("err_vhdlExporting"), e); @@ -114,4 +131,15 @@ public class VHDLGenerator implements Closeable { public void close() throws IOException { out.close(); } + + /** + * Disables the clock integration. + * Used only for the tests. + * + * @return this for chained calls + */ + public VHDLGenerator disableClockIntegration() { + useClockIntegration = false; + return this; + } } diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/boards/BoardInterface.java b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/BoardInterface.java new file mode 100644 index 000000000..dc27e4771 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/BoardInterface.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 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.vhdl2.boards; + +import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator; +import de.neemann.digital.hdl.model2.HDLModel; + +import java.io.File; +import java.io.IOException; + +/** + * Interface to write the additional files + */ +public interface BoardInterface { + /** + * Writes additional files + * + * @param path the target path + * @param model the model + * @throws IOException IOException + */ + void writeFiles(File path, HDLModel model) throws IOException; + + /** + * @return returns the board specific clock integrator + */ + HDLClockIntegrator getClockIntegrator(); + +} diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/boards/BoardProvider.java b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/BoardProvider.java new file mode 100644 index 000000000..8ca683a6e --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/BoardProvider.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 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.vhdl2.boards; + +import de.neemann.digital.core.element.Keys; +import de.neemann.digital.draw.elements.Circuit; +import de.neemann.digital.draw.elements.VisualElement; +import de.neemann.digital.gui.components.data.DummyElement; + +/** + * Provides additional information for a specific board + */ +public final class BoardProvider { + + private static final class InstanceHolder { + static final BoardProvider INSTANCE = new BoardProvider(); + } + + /** + * @return the BoardProvider instance + */ + public static BoardProvider getInstance() { + return InstanceHolder.INSTANCE; + } + + private BoardProvider() { + } + + /** + * Returns a spscific board + * + * @param circuit the circuit + * @return the board or null + */ + public BoardInterface getBoard(Circuit circuit) { + String board = null; + for (VisualElement element : circuit.getElements()) { + if (element.equalsDescription(DummyElement.TEXTDESCRIPTION)) { + String text = element.getElementAttributes().get(Keys.DESCRIPTION).toLowerCase(); + if (text.startsWith("board:")) { + board = text.substring(6).trim(); + } + } + } + + if (board == null) + return null; + + if (board.equals("basys3")) + return new Vivado("LVCMOS33", + "W5", + 10, + new ClockIntegratorARTIX7(10), + "xc7a35ticpg236-1L"); + + return null; + } +} diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/boards/ClockIntegratorARTIX7.java b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/ClockIntegratorARTIX7.java new file mode 100644 index 000000000..a0fcb79fd --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/ClockIntegratorARTIX7.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2017 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.vhdl2.boards; + +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.Key; +import de.neemann.digital.hdl.model2.*; +import de.neemann.digital.hdl.model2.clock.ClockInfo; +import de.neemann.digital.hdl.model2.clock.ClockIntegratorGeneric; +import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator; + +import java.util.ArrayList; + +/** + * Implements clocking on Artix 7 + */ +public class ClockIntegratorARTIX7 implements HDLClockIntegrator { + private static final int F_PFD_MIN_MHZ = 10; + private static final int F_PFD_MAX_MHZ = 450; + + private static final int F_VCO_MIN_MHZ = 600; + private static final int F_VCO_MAX_MHZ = 1200; + + private static final int MAX_CLOCK_DIVIDE = 128; + + private final double clkInPeriod; + + /** + * Creates a new instance + * + * @param clkInPeriod clock in period in ns + */ + ClockIntegratorARTIX7(double clkInPeriod) { + this.clkInPeriod = clkInPeriod; + } + + @Override + public void integrateClocks(HDLCircuit model, ArrayList clocks) throws HDLException { + if (clocks.size() > 1) + throw new HDLException("up to now only a single clock is supported on ARTIX-7"); + + + Params p = new Parameters(clocks.get(0).getFrequency(), clkInPeriod).getBest(); + if (p == null) + new ClockIntegratorGeneric(clkInPeriod).integrateClocks(model, clocks); + else + insertMMCMClock(model, p, clocks.get(0).getClockPort()); + } + + private void insertMMCMClock(HDLCircuit model, Params p, HDLPort clock) throws HDLException { + ElementAttributes attr = new ElementAttributes() + .set(new Key<>("cascading", 0), p.isCascading()) + .set(new Key<>("D_PARAM", 0), p.d) + .set(new Key<>("M_PARAM", 0), p.m) + .set(new Key<>("DIV_PARAM", 0), p.divider) + .set(new Key<>("DIV4_PARAM", 0), p.divider4) + .set(new Key<>("PERIOD_PARAM", 0.0), clkInPeriod); + + model.integrateClockNode(clock, new HDLNodeBuildIn("MMCME2_BASE", attr, name -> 1)); + } + + static final class Parameters { + + private final Params best; + + Parameters(int frequency, double clkInPeriod) { + double fInMHz = 1000 / clkInPeriod; + double targetFreqInMHz = ((double) frequency) / 1000 / 1000; + + int dMin = (int) Math.ceil(fInMHz / F_PFD_MAX_MHZ); + int dMax = (int) Math.floor(fInMHz / F_PFD_MIN_MHZ); + int mMin = (int) Math.ceil(F_VCO_MIN_MHZ / fInMHz * dMin); + int mMax = (int) Math.floor(F_VCO_MIN_MHZ / fInMHz * dMax); + + int mIdeal = (int) Math.floor(dMin * F_VCO_MAX_MHZ / fInMHz); + + Params best = null; + + for (int m = mMin; m <= mMax; m++) + for (int d = dMin; d <= dMax; d++) { + double fVco = fInMHz * m / d; + double fpdf = fVco / m; + + boolean valid = (F_VCO_MIN_MHZ <= fVco) && (fVco <= F_VCO_MAX_MHZ) + && (F_PFD_MIN_MHZ <= fpdf) && (fpdf <= F_PFD_MAX_MHZ); + + if (valid) { + int divider = (int) (fVco / targetFreqInMHz); + if (divider >= 1 && divider <= MAX_CLOCK_DIVIDE) { + double f = fVco / divider; + + double error = (F_VCO_MAX_MHZ - fVco) + Math.abs(f - targetFreqInMHz) * 10 + (Math.abs(m - mIdeal) * 10); + + if (best == null || best.error > error) + best = new Params(m, d, divider, f, error); + + } else { + if (divider > MAX_CLOCK_DIVIDE && divider <= MAX_CLOCK_DIVIDE * MAX_CLOCK_DIVIDE) { + int divider4 = 0; + int divider6 = 0; + + int bestErr = Integer.MAX_VALUE; + for (int d6 = 1; d6 <= MAX_CLOCK_DIVIDE; d6++) + for (int d4 = 1; d4 <= MAX_CLOCK_DIVIDE; d4++) { + int dd = d4 * d6; + int err = Math.abs(divider - dd); + if (err < bestErr) { + bestErr = err; + divider4 = d4; + divider6 = d6; + } + } + + + if (divider4 > 0 && divider6 > 0) { + double f = fVco / divider6 / divider4; + + double error = (F_VCO_MAX_MHZ - fVco) + Math.abs(f - targetFreqInMHz) * 10 + (Math.abs(m - mIdeal) * 10); + + if (best == null || best.error > error) + best = new Params(m, d, divider6, divider4, f, error); + } + } + } + } + } + this.best = best; + } + + Params getBest() { + return best; + } + } + + static final class Params { + private final int m; + private final int d; + private final int divider; + private final double error; + private final double f; + private final int divider4; + + private Params(int m, int d, int divider, double f, double error) { + this.m = m; + this.d = d; + this.divider = divider; + this.divider4 = 0; + this.f = f; + this.error = error; + } + + private Params(int m, int d, int divider, int divider4, double f, double error) { + this.m = m; + this.d = d; + this.divider = divider; + this.divider4 = divider4; + this.f = f; + this.error = error; + } + + + @Override + public String toString() { + return "Params{" + + "m=" + m + + ", d=" + d + + ", divider=" + divider + + ", div4=" + divider4 + + ", error=" + error + + ", f=" + f + + '}'; + } + + public int getD() { + return d; + } + + public int getM() { + return m; + } + + public int getDivider() { + return divider; + } + + public boolean isCascading() { + return divider4 != 0; + } + + public int getDivider4() { + return divider4; + } + } + +} diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/boards/Vivado.java b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/Vivado.java new file mode 100644 index 000000000..953d57c45 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/Vivado.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2017 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.vhdl2.boards; + +import de.neemann.digital.analyse.SplitPinString; +import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator; +import de.neemann.digital.hdl.model2.HDLModel; +import de.neemann.digital.hdl.model2.HDLPort; +import de.neemann.digital.hdl.printer.CodePrinter; +import de.neemann.digital.lang.Lang; + +import java.io.*; + +/** + * Creates the needed vivado files. + * Up to now only the constraints file containing the pin assignments is created + */ +public class Vivado implements BoardInterface { + + private final String pinIoType; + private final String clockPin; + private final int periodns; + private final HDLClockIntegrator clockIntegrator; + private final String device; + + /** + * Creates a new instance + * + * @param pinIoType the pin output type + * @param clockPin the pin the clock is connected to + * @param periodns the clock period in nano seconds + * @param clockIntegrator the clock integrator to use + * @param device the xilinx device code + */ + public Vivado(String pinIoType, String clockPin, int periodns, HDLClockIntegrator clockIntegrator, String device) { + this.pinIoType = pinIoType; + this.clockPin = clockPin; + this.periodns = periodns; + this.clockIntegrator = clockIntegrator; + this.device = device; + } + + @Override + public void writeFiles(File path, HDLModel model) throws IOException { + String projectName = path.getName(); + if (projectName.endsWith(".vhdl")) + projectName = projectName.substring(0, projectName.length() - 5); + File constraints = new File(path.getParentFile(), projectName.replace('.', '_') + "_constraints.xdc"); + try (CodePrinter out = new CodePrinter(new FileOutputStream(constraints))) { + writeConstraints(out, model); + } + createVivadoProject(path.getParentFile(), projectName, path, constraints); + } + + private void writeConstraints(CodePrinter out, HDLModel model) throws IOException { + for (HDLPort p : model.getMain().getPorts()) { + if (p.getBits() == 1) { + writePin(out, p.getName(), p.getPinNumber()); + if (p.getPinNumber().equals(clockPin)) + out + .print("create_clock -add -name sys_clk_pin -period ") + .print(periodns) + .print(" -waveform {0 5} [get_ports ") + .print(p.getName()) + .println("]"); + } else { + SplitPinString pins = SplitPinString.create(p.getPinNumber()); + for (int i = 0; i < p.getBits(); i++) + writePin(out, p.getName() + "[" + i + "]", pins.getPin(i)); + } + + + out.println(); + } + + out.println("set_property CFGBVS VCCO [current_design]"); + out.println("set_property CONFIG_VOLTAGE 3.3 [current_design]"); + } + + private void writePin(CodePrinter out, String name, String pinNumber) throws IOException { + if (pinNumber == null || pinNumber.length() == 0) + throw new IOException(Lang.get("err_vhdlPin_N_hasNoNumber", name)); + + out.print("set_property PACKAGE_PIN ").print(pinNumber).print(" [get_ports ").print(name).println("]"); + out.print("set_property IOSTANDARD ").print(pinIoType).print(" [get_ports ").print(name).println("]"); + } + + @Override + public HDLClockIntegrator getClockIntegrator() { + return clockIntegrator; + } + + private void createVivadoProject(File path, String projectName, File vhdl, File constraints) throws IOException { + String projectDir = projectName + "_vivado"; + File projectPath = new File(path, projectDir); + // don't overwrite existing projects! + if (!projectPath.exists()) { + if (projectPath.mkdirs()) { + File projectFile = new File(projectPath, projectName + ".xpr"); + try (BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(projectFile), "utf-8"))) { + writeVivadoProject(w, projectFile, vhdl, constraints); + } + } + } + } + + private void writeVivadoProject(BufferedWriter w, File project, File vhdl, File constraints) throws IOException { + w.write("\n" + + "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""); + } + +} diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/boards/package-info.java b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/package-info.java new file mode 100644 index 000000000..e4e618879 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/boards/package-info.java @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017 Helmut Neemann + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ + +/** + * Support fpr different boards. + * The classes in this package are able to create the files neede + * to run a vhdl file on a board. + */ +package de.neemann.digital.hdl.vhdl2.boards; diff --git a/src/test/java/de/neemann/digital/hdl/model2/HDLCircuitTest.java b/src/test/java/de/neemann/digital/hdl/model2/HDLCircuitTest.java index 253112504..20f64b80a 100644 --- a/src/test/java/de/neemann/digital/hdl/model2/HDLCircuitTest.java +++ b/src/test/java/de/neemann/digital/hdl/model2/HDLCircuitTest.java @@ -10,6 +10,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.model2.clock.ClockIntegratorGeneric; +import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator; import de.neemann.digital.hdl.printer.CodePrinterStr; import de.neemann.digital.integration.Resources; import junit.framework.TestCase; @@ -19,55 +21,55 @@ import java.io.IOException; public class HDLCircuitTest extends TestCase { - HDLCircuit getCircuit(String filename) throws IOException, PinException, HDLException, NodeException { + HDLCircuit getCircuit(String filename, HDLClockIntegrator ci) throws IOException, PinException, HDLException, NodeException { File file = new File(Resources.getRoot(), filename); ElementLibrary library = new ElementLibrary(); library.setRootFilePath(file.getParentFile()); ShapeFactory shapeFactory = new ShapeFactory(library); Circuit c = Circuit.loadCircuit(file, shapeFactory); - return new HDLCircuit(c, "main", new HDLModel(library)); + return new HDLCircuit(c, "main", new HDLModel(library), ci); } public void testSimple() throws IOException, PinException, HDLException, NodeException { - HDLCircuit hdl = getCircuit("dig/hdl/model2/comb.dig"); + HDLCircuit hdl = getCircuit("dig/hdl/model2/comb.dig", null); hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNetNaming()); CodePrinterStr cp = new CodePrinterStr(); hdl.print(cp); assertEquals("circuit main\n" + - " in(A:1, B:1, C:1)\n" + - " out(X:1, Y:1, Z:1, Aident:1)\n" + - " sig(Y_temp:1, s0:1, Z_temp:1, s1:1)\n" + + " in(A:1 defines (A->3), B:1 defines (B->2), C:1 defines (C->2))\n" + + " out(X:1 reads (X->1), Y:1 reads (Y_temp->2), Z:1 reads (Z_temp->2), Aident:1 reads (A->3))\n" + + " sig(Y_temp->2, s0->1, Z_temp->2, s1->1)\n" + "\n" + " node Const\n" + " in()\n" + - " out(out:1 is s1:1)\n" + - " s1:1 := 1:1\n" + + " out(out:1 defines (s1->1))\n" + + " s1->1 := 1:1\n" + " node Not\n" + - " in(in:1 is A:1)\n" + - " out(out:1 is Z_temp:1)\n" + - " Z_temp:1 := NOT A:1\n" + + " in(in:1 reads (A->3))\n" + + " out(out:1 defines (Z_temp->2))\n" + + " Z_temp->2 := NOT A\n" + " node merged expression\n" + - " in(In_1:1 is B:1, in:1 is C:1)\n" + - " out(out:1 is Y_temp:1)\n" + - " Y_temp:1 := (B:1 OR NOT C:1)\n" + + " in(In_1:1 reads (B->2), in:1 reads (C->2))\n" + + " out(out:1 defines (Y_temp->2))\n" + + " Y_temp->2 := (B OR NOT C)\n" + " node merged expression\n" + - " in(In_5:1 is Y_temp:1, In_1:1 is A:1, In_2:1 is C:1, In_1:1 is Z_temp:1, In_1:1 is B:1)\n" + - " out(out:1 is s0:1)\n" + - " s0:1 := ((A:1 OR C:1) AND (Z_temp:1 OR C:1) AND 1:1 AND NOT (B:1 OR C:1) AND Y_temp:1)\n" + + " in(In_5:1 reads (Y_temp->2), In_1:1 reads (A->3), In_2:1 reads (C->2), In_1:1 reads (Z_temp->2), In_1:1 reads (B->2))\n" + + " out(out:1 defines (s0->1))\n" + + " s0->1 := ((A OR C) AND (Z_temp OR C) AND 1:1 AND NOT (B OR C) AND Y_temp)\n" + " node D_FF\n" + - " in(D:1 is s0:1, C:1 is s1:1)\n" + - " out(Q:1 is X:1, ~Q:1 is not used)\n" + + " in(D:1 reads (s0->1), C:1 reads (s1->1))\n" + + " out(Q:1 defines (X->1), ~Q:1 is not used)\n" + "\n" + - " Y:1 := Y_temp:1\n" + - " Z:1 := Z_temp:1\n" + - " Aident:1 := A:1\n" + + " Y:1 reads (Y_temp->2) := Y_temp->2\n" + + " Z:1 reads (Z_temp->2) := Z_temp->2\n" + + " Aident:1 reads (A->3) := A->3\n" + "end circuit main\n", cp.toString()); } public void testSimple2() throws IOException, PinException, HDLException, NodeException { - HDLCircuit hdl = getCircuit("dig/hdl/model2/comb2.dig"); + HDLCircuit hdl = getCircuit("dig/hdl/model2/comb2.dig", null); hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNetNaming()); CodePrinterStr cp = new CodePrinterStr(); @@ -86,7 +88,7 @@ public class HDLCircuitTest extends TestCase { } public void testInputInvert() throws IOException, PinException, HDLException, NodeException { - HDLCircuit hdl = getCircuit("dig/hdl/model2/inputInvert.dig"); + HDLCircuit hdl = getCircuit("dig/hdl/model2/inputInvert.dig", null); hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNetNaming()); CodePrinterStr cp = new CodePrinterStr(); @@ -105,7 +107,7 @@ public class HDLCircuitTest extends TestCase { } public void testInputInvert2() throws IOException, PinException, HDLException, NodeException { - HDLCircuit hdl = getCircuit("dig/hdl/model2/inputInvert2.dig"); + HDLCircuit hdl = getCircuit("dig/hdl/model2/inputInvert2.dig", null); hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNetNaming()); CodePrinterStr cp = new CodePrinterStr(); @@ -124,7 +126,7 @@ public class HDLCircuitTest extends TestCase { } public void testSplitter() throws IOException, PinException, HDLException, NodeException { - HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter.dig"); + HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter.dig", null); hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNetNaming()); CodePrinterStr cp = new CodePrinterStr(); @@ -148,7 +150,7 @@ public class HDLCircuitTest extends TestCase { } public void testSplitter2() throws IOException, PinException, HDLException, NodeException { - HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter2.dig"); + HDLCircuit hdl = getCircuit("dig/hdl/model2/splitter2.dig", null); hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNetNaming()); CodePrinterStr cp = new CodePrinterStr(); @@ -172,4 +174,25 @@ public class HDLCircuitTest extends TestCase { "end circuit main\n", cp.toString()); } + public void testClock() throws IOException, PinException, HDLException, NodeException { + HDLCircuit hdl = getCircuit("dig/hdl/model2/clock.dig", new ClockIntegratorGeneric(10)); + hdl.mergeOperations().nameNets(new HDLCircuit.SimpleNetNaming()); + + CodePrinterStr cp = new CodePrinterStr(); + hdl.print(cp); + assertEquals("circuit main\n" + + " in(A:1 defines (A->1), C:1 defines (C->1))\n" + + " out(X:1 reads (X->1))\n" + + " sig(s0->1)\n" + + "\n" + + " node simpleClockDivider\n" + + " in(cin:1 reads (C->1))\n" + + " out(cout:1 defines (s0->1))\n" + + " node D_FF\n" + + " in(D:1 reads (A->1), C:1 reads (s0->1))\n" + + " out(Q:1 defines (X->1), ~Q:1 is not used)\n" + + "\n" + + "end circuit main\n", cp.toString()); + } + } \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLGeneratorTest.java b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLGeneratorTest.java index 319a851ce..32891d1d2 100644 --- a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLGeneratorTest.java +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLGeneratorTest.java @@ -9,16 +9,12 @@ import de.neemann.digital.core.ExceptionWithOrigin; import de.neemann.digital.core.NodeException; import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.extern.ProcessStarter; -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.library.ElementNotFoundException; -import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.gui.Settings; import de.neemann.digital.hdl.hgs.HGSEvalException; import de.neemann.digital.hdl.model.HDLException; import de.neemann.digital.hdl.printer.CodePrinter; -import de.neemann.digital.hdl.printer.CodePrinterStr; import de.neemann.digital.integration.FileScanner; import de.neemann.digital.integration.Resources; import de.neemann.digital.integration.ToBreakRunner; @@ -63,7 +59,7 @@ public class VHDLGeneratorTest extends TestCase { File examples = new File(Resources.getRoot(), "/dig/hdl"); try { int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples); - assertEquals(35, tested); + assertEquals(36, tested); } catch (FileScanner.SkipAllException e) { // if ghdl is not installed its also ok } @@ -122,7 +118,7 @@ public class VHDLGeneratorTest extends TestCase { .replace('-', '_')+ ".vhdl"); CodePrinter out = new CodePrinter(vhdlFile); try (VHDLGenerator vhdl = new VHDLGenerator(br.getLibrary(), out)) { - vhdl.export(br.getCircuit()); + vhdl.disableClockIntegration().export(br.getCircuit()); ArrayList testFiles = vhdl.getTestBenches(); out.close(); runGHDL(vhdlFile, testFiles); diff --git a/src/test/resources/dig/hdl/model2/clock.dig b/src/test/resources/dig/hdl/model2/clock.dig new file mode 100644 index 000000000..aa90416e4 --- /dev/null +++ b/src/test/resources/dig/hdl/model2/clock.dig @@ -0,0 +1,69 @@ + + + 1 + + + + Out + + + Label + X + + + Inputs + 1 + + + + + + In + + + Label + A + + + + + + D_FF + + + + + Clock + + + Label + C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file