From a4d65b9d024e033bb41a6a2f46f18f4030144160 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 14 Dec 2019 10:20:04 +0100 Subject: [PATCH 01/11] adds a pin control logic, see #394 --- .../neemann/digital/core/io/PinControl.java | 82 +++++++++++++++++++ .../digital/draw/library/ElementLibrary.java | 3 +- .../digital/draw/shapes/PinControlShape.java | 60 ++++++++++++++ .../digital/draw/shapes/ShapeFactory.java | 1 + src/main/resources/lang/lang_de.xml | 30 +++++-- src/main/resources/lang/lang_en.xml | 15 +++- .../resources/dig/backtrack/AllComponents.dig | 58 ++++++++++++- 7 files changed, 241 insertions(+), 8 deletions(-) create mode 100644 src/main/java/de/neemann/digital/core/io/PinControl.java create mode 100644 src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java diff --git a/src/main/java/de/neemann/digital/core/io/PinControl.java b/src/main/java/de/neemann/digital/core/io/PinControl.java new file mode 100644 index 000000000..be9b3f3de --- /dev/null +++ b/src/main/java/de/neemann/digital/core/io/PinControl.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019 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.core.io; + +import de.neemann.digital.core.Node; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.ObservableValues; +import de.neemann.digital.core.element.Element; +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.ElementTypeDescription; +import de.neemann.digital.core.element.Keys; + +import static de.neemann.digital.core.element.PinInfo.input; + +/** + * The pin control logic + */ +public class PinControl extends Node implements Element { + + /** + * The description of the pin control logic + */ + public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(PinControl.class, input("wr"), input("oe")) + .addAttribute(Keys.ROTATE) + .addAttribute(Keys.BITS); + + private final int bits; + private final ObservableValue rdValue; + private final ObservableValue outWriteValue; + private ObservableValue wrValue; + private ObservableValue oeValue; + private ObservableValue outReadValue; + private long wr; + private boolean oe; + private long outRead; + + /** + * Creates a new instance + * + * @param attr the elements attributes + */ + public PinControl(ElementAttributes attr) { + bits = attr.getBits(); + rdValue = new ObservableValue("rd", bits).setPinDescription(DESCRIPTION); + outWriteValue = new ObservableValue("out", bits).setPinDescription(DESCRIPTION).setBidirectional(); + } + + @Override + public void setInputs(ObservableValues inputs) throws NodeException { + wrValue = inputs.get(0).addObserverToValue(this).checkBits(bits, this); + oeValue = inputs.get(1).addObserverToValue(this).checkBits(1, this); + outReadValue = inputs.get(2).addObserverToValue(this).checkBits(bits, this); + } + + @Override + public void readInputs() throws NodeException { + wr = wrValue.getValue(); + oe = oeValue.getBool(); + outRead = outReadValue.getValue(); + } + + @Override + public void writeOutputs() throws NodeException { + if (oe) { + outWriteValue.setValue(wr); + rdValue.setValue(wr); + } else { + outWriteValue.setToHighZ(); + rdValue.setValue(outRead); + } + } + + + @Override + public ObservableValues getOutputs() { + return new ObservableValues(rdValue, outWriteValue); + } +} diff --git a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java index f981e04be..c29c20e47 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -143,7 +143,8 @@ public class ElementLibrary implements Iterable .add(Keyboard.DESCRIPTION) .add(Terminal.DESCRIPTION) .add(VGA.DESCRIPTION) - .add(MIDI.DESCRIPTION))) + .add(MIDI.DESCRIPTION) + .add(PinControl.DESCRIPTION))) .add(new LibraryNode(Lang.get("lib_wires")) .add(Ground.DESCRIPTION) .add(VDD.DESCRIPTION) diff --git a/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java b/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java new file mode 100644 index 000000000..4b8bb9649 --- /dev/null +++ b/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019 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.draw.shapes; + +import de.neemann.digital.core.Observer; +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.PinDescriptions; +import de.neemann.digital.draw.elements.IOState; +import de.neemann.digital.draw.elements.Pin; +import de.neemann.digital.draw.elements.Pins; +import de.neemann.digital.draw.graphics.Graphic; +import de.neemann.digital.draw.graphics.Style; +import de.neemann.digital.draw.graphics.Vector; + +import static de.neemann.digital.draw.shapes.GenericShape.SIZE; + +/** + * The shape for the pin control logic + */ +public class PinControlShape implements Shape { + private final PinDescriptions in; + private final PinDescriptions out; + + /** + * Creates a new instance + * + * @param attr the elements attributes + * @param in the inputs + * @param out the outputs + */ + public PinControlShape(ElementAttributes attr, PinDescriptions in, PinDescriptions out) { + this.in = in; + this.out = out; + } + + @Override + public Pins getPins() { + return new Pins() + .add(new Pin(new Vector(0, -SIZE), in.get(0))) + .add(new Pin(new Vector(0, 0), out.get(0))) + .add(new Pin(new Vector(0, +SIZE), in.get(1))) + .add(new Pin(new Vector(SIZE * 2, 0), out.get(1))); + } + + @Override + public InteractorInterface applyStateMonitor(IOState ioState, Observer guiObserver) { + return null; + } + + @Override + public void drawTo(Graphic graphic, Style highLight) { + graphic.drawLine(new Vector(0, -SIZE), new Vector(SIZE, 0), Style.NORMAL); + graphic.drawLine(new Vector(0, 0), new Vector(SIZE, 0), Style.NORMAL); + graphic.drawLine(new Vector(0, SIZE), new Vector(SIZE, 0), Style.NORMAL); + graphic.drawLine(new Vector(SIZE, 0), new Vector(SIZE * 2, 0), Style.NORMAL); + } +} diff --git a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java index 6081000f8..5baafa7d8 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java +++ b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java @@ -163,6 +163,7 @@ public final class ShapeFactory { map.put(DiodeBackward.DESCRIPTION.getName(), DiodeBackwardShape::new); map.put(PullUp.DESCRIPTION.getName(), PullUpShape::new); map.put(PullDown.DESCRIPTION.getName(), PullDownShape::new); + map.put(PinControl.DESCRIPTION.getName(), PinControlShape::new); // disables string formatting for external components, see #272 map.put(External.DESCRIPTION.getName(), diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 2a60b4b96..76112b696 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -338,25 +338,45 @@ Eingang zum Steuern des Treibers. Ist dieser Eingang auf 1 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 0, ist der Ausgang hochohmig. Treiber, invertierte Auswahl - Ein Treiber kann dazu verwendet werden, ein Datenwort nur unter speziellen Voraussetzungen auf eine andere Leitung weiterzureichen. + Ein Treiber kann dazu verwendet werden, ein Datenwort nur unter speziellen + Voraussetzungen auf eine andere Leitung weiterzureichen. Gesteuert wird der Treiber durch den sel Eingang. Ist der sel Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 1, ist der Ausgang hochohmig. Das Eingangssignal des Treibers. Eingang zum Steuern des Treibers. - Ist dieser Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 1, ist der Ausgang hochohmig. - Gibt den am Eingang anliegenden Wert aus, wenn der Selection Eingang auf 0 gesetzt ist. + Ist dieser Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 1, + ist der Ausgang hochohmig. + + Gibt den am Eingang anliegenden Wert aus, wenn der Selection Eingang auf 0 + gesetzt ist. + + Pinsteuerung + Steuerlogik für einen bidirektionalen Pin. + Nur im Rahmen der VHDL- oder Verilog-Generierung erforderlich! + Diese Komponente ist notwendig, um einen bidirektionalen HDL-Port zu erstellen! + Wenn Sie keinen bidirektionalen IO-Port auf einem FPGA verwenden wollen, verwenden Sie diese Komponente nicht! + + Die auszugebenden Daten + Aktiviert die Ausgabe + Die zu lesenden Daten. + Der Anschluss für den eigentlichen Pin. Hier sollte nur noch ein einzelner + Eingang angeschlossen werden. + Multiplexer Ein Baustein, welcher den Wert eines der Eingänge am Ausgang ausgibt. - Über den sel-Eingang wird ausgewählt, welcher der Eingänge ausgegeben werden soll. + Über den sel-Eingang wird ausgewählt, welcher der Eingänge ausgegeben werden soll. + Der {0}. Dateneingang des Multiplexers. Ausgeben wird der Wert, der am gewählten Dateneingang anliegt. - Mit dieser Leitung wird der Dateneingang ausgewählt, welcher am Ausgang ausgegeben werden soll. + Mit dieser Leitung wird der Dateneingang ausgewählt, welcher am Ausgang + ausgegeben werden soll. + Demultiplexer Ein Baustein, welcher einen Eingangswert auf verschiedene Ausgänge ausgeben kann. Gibt das Eingangssignal auf einem wählbaren Ausgang aus. Die anderen Ausgänge werden auf den Vorgabewert gesetzt. diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 9084ba4f8..cac2712ec 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -363,11 +363,24 @@ If the sel input is 1, this output is in high z state. + Pin Control + Control logic for a bi-directional pin. Only needed in the context of VHDL or + Verilog generation! This component is necessary to create a bi-directional HDL port! If you don't want + to use a di-directional IO-port on an FPGA, don't use this component! + + The data to be output. + Activates the output. + The data to be read. + The connector for the actual pin. Only a single input should be connected + here. + Multiplexer - A component which uses the value of the sel pin to decide which input value is set to the output. + A component which uses the value of the sel pin to decide which input value is + set to the output. + The {0}. data input of the multiplexer. The value of the selected input. This input is used to select the data input which is output. diff --git a/src/test/resources/dig/backtrack/AllComponents.dig b/src/test/resources/dig/backtrack/AllComponents.dig index 3c5cbab72..d9fab394c 100644 --- a/src/test/resources/dig/backtrack/AllComponents.dig +++ b/src/test/resources/dig/backtrack/AllComponents.dig @@ -614,6 +614,30 @@ + + PinControl + + + Bits + 8 + + + + + + Tunnel + + + rotation + + + + NetName + zz + + + + @@ -716,6 +740,10 @@ + + + + @@ -856,6 +884,10 @@ + + + + @@ -1060,6 +1092,14 @@ + + + + + + + + @@ -1330,7 +1370,7 @@ - + @@ -1340,6 +1380,10 @@ + + + + @@ -1460,6 +1504,10 @@ + + + + @@ -1788,6 +1836,10 @@ + + + + @@ -1888,6 +1940,10 @@ + + + + From 373c8bd4a4f3721dc7e7e4badf0be23691e8836c Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 14 Dec 2019 20:27:32 +0100 Subject: [PATCH 02/11] first vhdl inout test has passed, see #394 --- .../neemann/digital/core/io/PinControl.java | 5 +- .../neemann/digital/hdl/model2/HDLModel.java | 15 +- .../de/neemann/digital/hdl/model2/HDLNet.java | 71 +++++-- .../neemann/digital/hdl/model2/HDLNode.java | 31 ++- .../neemann/digital/hdl/model2/HDLPort.java | 6 +- .../digital/hdl/vhdl2/VHDLCreator.java | 5 + src/main/resources/lang/lang_de.xml | 2 +- src/main/resources/lang/lang_en.xml | 2 +- src/main/resources/vhdl/DIG_PinControl.tem | 64 ++++++ .../digital/hdl/vhdl2/VHDLSimulatorTest.java | 5 +- .../digital/integration/TestExamples.java | 4 +- .../resources/dig/test/pinControl/simple.dig | 182 ++++++++++++++++++ 12 files changed, 357 insertions(+), 35 deletions(-) create mode 100644 src/main/resources/vhdl/DIG_PinControl.tem create mode 100644 src/test/resources/dig/test/pinControl/simple.dig diff --git a/src/main/java/de/neemann/digital/core/io/PinControl.java b/src/main/java/de/neemann/digital/core/io/PinControl.java index be9b3f3de..040e56984 100644 --- a/src/main/java/de/neemann/digital/core/io/PinControl.java +++ b/src/main/java/de/neemann/digital/core/io/PinControl.java @@ -26,7 +26,8 @@ public class PinControl extends Node implements Element { */ public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(PinControl.class, input("wr"), input("oe")) .addAttribute(Keys.ROTATE) - .addAttribute(Keys.BITS); + .addAttribute(Keys.BITS) + .addAttribute(Keys.MIRROR); private final int bits; private final ObservableValue rdValue; @@ -46,7 +47,7 @@ public class PinControl extends Node implements Element { public PinControl(ElementAttributes attr) { bits = attr.getBits(); rdValue = new ObservableValue("rd", bits).setPinDescription(DESCRIPTION); - outWriteValue = new ObservableValue("out", bits).setPinDescription(DESCRIPTION).setBidirectional(); + outWriteValue = new ObservableValue("pin", bits).setPinDescription(DESCRIPTION).setBidirectional(); } @Override 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 5dd57e3ef..59d294d05 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java @@ -180,10 +180,17 @@ public class HDLModel implements Iterable { private 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.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0)); - else - node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); + switch (p.getDirection()) { + case input: + node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0)); + break; + case output: + node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); + break; + case both: + node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.INOUT, node.getBits(p.getName()))); + break; + } } return node; } 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 67ccd90e3..4a1ae5253 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java @@ -7,6 +7,7 @@ package de.neemann.digital.hdl.model2; import de.neemann.digital.hdl.model2.expression.ExprConstant; import de.neemann.digital.hdl.printer.CodePrinter; +import de.neemann.digital.hdl.vhdl2.VHDLTestBenchCreator; import de.neemann.digital.lang.Lang; import java.io.IOException; @@ -18,8 +19,9 @@ import java.util.ArrayList; */ public class HDLNet implements Printable, HasName { private final boolean userNamed; + private final ArrayList inputs; + private final ArrayList inOutputs; private String name; - private ArrayList inputs; private HDLPort output; private boolean needsVariable = true; private boolean isInput; @@ -32,6 +34,7 @@ public class HDLNet implements Printable, HasName { public HDLNet(String name) { this.name = name; inputs = new ArrayList<>(); + inOutputs = new ArrayList<>(); userNamed = name != null; } @@ -49,16 +52,24 @@ public class HDLNet implements Printable, HasName { * @throws HDLException HDLException */ public void addPort(HDLPort hdlPort) throws HDLException { - if (hdlPort.getDirection().equals(HDLPort.Direction.OUT)) { - if (output != null) { - String netName = name; - if (netName == null) - netName = Lang.get("err_unnamedNet"); - throw new HDLException(Lang.get("err_hdlMultipleOutputsConnectedToNet_N_N_N", netName, output, hdlPort)); - } - output = hdlPort; - } else - inputs.add(hdlPort); + switch (hdlPort.getDirection()) { + case OUT: + if (output != null) { + String netName = name; + if (netName == null) + netName = Lang.get("err_unnamedNet"); + throw new HDLException(Lang.get("err_hdlMultipleOutputsConnectedToNet_N_N_N", netName, output, hdlPort)); + } + output = hdlPort; + break; + case IN: + inputs.add(hdlPort); + break; + case INOUT: + inOutputs.add(hdlPort); + break; + + } } /** @@ -81,11 +92,25 @@ public class HDLNet implements Printable, HasName { } void fixBits() throws HDLException { - if (output == null) - throw new HDLException("no output connected to net"); - final int bits = output.getBits(); - if (bits == 0) - throw new HDLException("no bit number set for output " + output.getName()); + int bits = 0; + if (output == null) { + if (inOutputs.isEmpty()) + throw new HDLException("no output connected to net"); + else { + for (HDLPort p : inOutputs) { + if (p.getBits() > 0) { + bits = p.getBits(); + break; + } + } + if (bits == 0) + throw new HDLException("no bit number set for inOutputs " + inOutputs); + } + } else { + bits = output.getBits(); + if (bits == 0) + throw new HDLException("no bit number set for output " + output.getName()); + } for (HDLPort i : inputs) i.setBits(bits); @@ -96,6 +121,8 @@ public class HDLNet implements Printable, HasName { * @return the constant if this net is a constant, null otherwise */ public ExprConstant isConstant() { + if (output == null) + return null; return ExprConstant.isConstant(output.getParent()); } @@ -161,8 +188,16 @@ public class HDLNet implements Printable, HasName { /** * @return the number of bits on this net */ - public int getBits() { - return output.getBits(); + public int getBits() throws HDLException { + if (output != null) + return output.getBits(); + + for (HDLPort p : inOutputs) { + if (p.getBits() > 0) { + return p.getBits(); + } + } + throw new HDLException("no bit number set for inOutputs " + inOutputs); } /** 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 d1b343274..b0b625140 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNode.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNode.java @@ -9,6 +9,7 @@ import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.hdl.model2.expression.Expression; import de.neemann.digital.hdl.model2.expression.Visitor; import de.neemann.digital.hdl.printer.CodePrinter; +import de.neemann.digital.hdl.vhdl2.VHDLTestBenchCreator; import java.io.IOException; import java.util.ArrayList; @@ -22,6 +23,7 @@ public abstract class HDLNode { private final HDLModel.BitProvider bitProvider; private final ArrayList inputs; private final ArrayList outputs; + private final ArrayList inOutputs; private String hdlEntityName; /** @@ -37,6 +39,7 @@ public abstract class HDLNode { this.bitProvider = bitProvider; inputs = new ArrayList<>(); outputs = new ArrayList<>(); + inOutputs = new ArrayList<>(); } /** @@ -46,10 +49,17 @@ public abstract class HDLNode { * @return this for chained calls */ public HDLNode addPort(HDLPort port) { - if (port.getDirection().equals(HDLPort.Direction.OUT)) - outputs.add(port); - else - inputs.add(port); + switch (port.getDirection()) { + case IN: + inputs.add(port); + break; + case OUT: + outputs.add(port); + break; + case INOUT: + inOutputs.add(port); + break; + } port.setParent(this); @@ -96,6 +106,13 @@ public abstract class HDLNode { return outputs; } + /** + * @return the list of inOutputs + */ + public ArrayList getInOutputs() { + return inOutputs; + } + int getBits(String name) { return bitProvider.getBits(name); } @@ -111,6 +128,10 @@ public abstract class HDLNode { printWithLocal(out, inputs); out.print("out"); printWithLocal(out, outputs); + if (!inOutputs.isEmpty()) { + out.print("inOut"); + printWithLocal(out, inOutputs); + } } private void printWithLocal(CodePrinter out, ArrayList ports) throws IOException { @@ -177,6 +198,8 @@ public abstract class HDLNode { p.rename(renaming); for (HDLPort p : inputs) p.rename(renaming); + for (HDLPort p : inOutputs) + p.rename(renaming); } /** 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 3e64b16d3..22b8dd391 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java @@ -30,7 +30,11 @@ public class HDLPort implements Printable, HasName { * Caution: a circuits input components port has type OUT because it defines a value, * seen from inside the node. */ - OUT + OUT, + /** + * Bidirectional port + */ + INOUT } private String name; 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 aa6519012..3af1433d1 100644 --- a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java @@ -250,6 +250,11 @@ public class VHDLCreator { sep.check(); out.print(o.getName()).print(" => ").print(o.getNet().getName()); } + for (HDLPort o : node.getInOutputs()) + if (o.getNet() != null) { + sep.check(); + out.print(o.getName()).print(" => ").print(o.getNet().getName()); + } out.println(");").dec().dec(); } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 76112b696..9ec4fa634 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -362,7 +362,7 @@ Die auszugebenden Daten Aktiviert die Ausgabe Die zu lesenden Daten. - Der Anschluss für den eigentlichen Pin. Hier sollte nur noch ein einzelner + Der Anschluss für den eigentlichen Pin. Hier sollte nur noch ein einzelner Eingang angeschlossen werden. diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index cac2712ec..76791481c 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -371,7 +371,7 @@ The data to be output. Activates the output. The data to be read. - The connector for the actual pin. Only a single input should be connected + The connector for the actual pin. Only a single input should be connected here. diff --git a/src/main/resources/vhdl/DIG_PinControl.tem b/src/main/resources/vhdl/DIG_PinControl.tem new file mode 100644 index 000000000..8d0b84cc6 --- /dev/null +++ b/src/main/resources/vhdl/DIG_PinControl.tem @@ -0,0 +1,64 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +ENTITY PinControl IS + PORT( + pin : INOUT STD_LOGIC; + oe : IN STD_LOGIC; + wr : IN STD_LOGIC; + rd : OUT STD_LOGIC); +END PinControl; + +ARCHITECTURE Behavioral OF PinControl IS +BEGIN + PROCESS (oe, pin, wr) -- Behavioral representation + BEGIN -- of tri-states. + IF( oe = '0') THEN + pin <= 'Z'; + rd <= pin; + ELSE + pin <= wr; + rd <= wr; + END IF; + END PROCESS; +END Behavioral; + + + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +ENTITY PinControl_BUS IS + GENERIC ( + Bits: integer ); + PORT( + pin : INOUT std_logic_vector((Bits-1) downto 0); + oe : IN STD_LOGIC; + wr : IN std_logic_vector((Bits-1) downto 0); + rd : OUT std_logic_vector((Bits-1) downto 0)); +END PinControl_BUS; + +ARCHITECTURE Behavioral OF PinControl_BUS IS +BEGIN + PROCESS (oe, pin, wr) -- Behavioral representation + BEGIN -- of tri-states. + IF( oe = '0') THEN + pin <= (others => 'Z'); + rd <= pin; + ELSE + pin <= wr; + rd <= wr; + END IF; + END PROCESS; +END Behavioral; + + 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 a3ebabaf3..e04f3e47b 100644 --- a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java @@ -14,6 +14,7 @@ import de.neemann.digital.draw.library.ElementNotFoundException; import de.neemann.digital.gui.Settings; import de.neemann.digital.hdl.model2.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.TestExamples; @@ -32,9 +33,9 @@ public class VHDLSimulatorTest extends TestCase { private static final String GHDL = System.getProperty("ghdl", "ghdl"); private int testBenches; - /* + //* public void testDebug() throws Exception { - File file = new File(Resources.getRoot(), "dig/test/vhdl/lut2.dig"); + File file = new File(Resources.getRoot(), "/dig/test/pinControl/simple.dig"); ToBreakRunner br = new ToBreakRunner(file); System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit())); diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index 2c9a374e8..d043be59c 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -43,8 +43,8 @@ public class TestExamples extends TestCase { */ public void testTestExamples() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test"); - assertEquals(184, new FileScanner(this::check).scan(examples)); - assertEquals(172, testCasesInFiles); + assertEquals(185, new FileScanner(this::check).scan(examples)); + assertEquals(173, testCasesInFiles); } /** diff --git a/src/test/resources/dig/test/pinControl/simple.dig b/src/test/resources/dig/test/pinControl/simple.dig new file mode 100644 index 000000000..77048e635 --- /dev/null +++ b/src/test/resources/dig/test/pinControl/simple.dig @@ -0,0 +1,182 @@ + + + 1 + + + + In + + + Label + wr_0 + + + Bits + 4 + + + + + + In + + + Label + oe + + + + + + PinControl + + + Bits + 4 + + + + + + Out + + + rotation + + + + Label + rd_0 + + + Bits + 4 + + + + + + In + + + rotation + + + + Label + wr_1 + + + Bits + 4 + + + + + + PinControl + + + mirror + true + + + rotation + + + + Bits + 4 + + + + + + Out + + + Label + rd_1 + + + Bits + 4 + + + + + + Not + + + + + Testcase + + + Testdata + + oe wr_0 rd_0 wr_1 rd_1 +1 1 x x 1 +1 2 x x 2 +0 x 1 1 x +0 x 2 2 x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 8bc683366f9737fabd69ed09de72ee86e05e5eaf Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 14 Dec 2019 20:30:50 +0100 Subject: [PATCH 03/11] fixed some checkstyle issues --- src/main/java/de/neemann/digital/hdl/model2/HDLModel.java | 1 - src/main/java/de/neemann/digital/hdl/model2/HDLNet.java | 2 +- src/main/java/de/neemann/digital/hdl/model2/HDLNode.java | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) 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 59d294d05..ed6dffe16 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java @@ -10,7 +10,6 @@ import de.neemann.digital.core.ObservableValues; 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.core.io.DipSwitch; import de.neemann.digital.core.io.Ground; 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 4a1ae5253..887aee56e 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java @@ -7,7 +7,6 @@ package de.neemann.digital.hdl.model2; import de.neemann.digital.hdl.model2.expression.ExprConstant; import de.neemann.digital.hdl.printer.CodePrinter; -import de.neemann.digital.hdl.vhdl2.VHDLTestBenchCreator; import de.neemann.digital.lang.Lang; import java.io.IOException; @@ -187,6 +186,7 @@ public class HDLNet implements Printable, HasName { /** * @return the number of bits on this net + * @throws HDLException HDLException */ public int getBits() throws HDLException { if (output != null) 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 b0b625140..078a543c8 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNode.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNode.java @@ -9,7 +9,6 @@ import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.hdl.model2.expression.Expression; import de.neemann.digital.hdl.model2.expression.Visitor; import de.neemann.digital.hdl.printer.CodePrinter; -import de.neemann.digital.hdl.vhdl2.VHDLTestBenchCreator; import java.io.IOException; import java.util.ArrayList; From a78fa95764bf91898136235e4454e48851d84282 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 14 Dec 2019 21:30:53 +0100 Subject: [PATCH 04/11] inout inheritance is working, see #394 --- .../de/neemann/digital/hdl/model2/HDLCircuit.java | 10 ++++++++-- .../java/de/neemann/digital/hdl/model2/HDLModel.java | 11 +++++------ .../java/de/neemann/digital/hdl/model2/HDLNet.java | 8 +++++++- .../java/de/neemann/digital/hdl/model2/HDLPort.java | 9 ++++++++- .../de/neemann/digital/hdl/vhdl2/VHDLCreator.java | 10 ++++++++-- 5 files changed, 36 insertions(+), 12 deletions(-) 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 df21f0d4b..7124ef119 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java @@ -154,12 +154,18 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin nodes.addAll(newNodes); for (HDLPort i : inputs) - if (i.getNet() != null) + if (i.getNet() != null) { i.getNet().setIsInput(i.getName()); + if (i.getNet().isInOutNet()) + i.setInOut(); + } - for (HDLPort o : outputs) + for (HDLPort o : outputs) { if (o.getNet().needsVariable()) o.getNet().setIsOutput(o.getName(), o.getNet().getInputs().size() == 1); + if (o.getNet().isInOutNet()) + o.setInOut(); + } } 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 ed6dffe16..c550f7da7 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java @@ -10,10 +10,7 @@ import de.neemann.digital.core.ObservableValues; 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.io.Const; -import de.neemann.digital.core.io.DipSwitch; -import de.neemann.digital.core.io.Ground; -import de.neemann.digital.core.io.VDD; +import de.neemann.digital.core.io.*; import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Pin; import de.neemann.digital.draw.elements.PinException; @@ -150,7 +147,6 @@ public class HDLModel implements Iterable { td.createElement(v.getElementAttributes()).getOutputs())), v, parent).createExpressions(); - } catch (ElementNotFoundException | PinException | NodeException e) { throw new HDLException("error creating node", e); } @@ -187,7 +183,10 @@ public class HDLModel implements Iterable { node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); break; case both: - node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.INOUT, node.getBits(p.getName()))); + if (v.equalsDescription(PinControl.DESCRIPTION)) + node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.INOUT, node.getBits(p.getName()))); + else + node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); break; } } 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 887aee56e..0290aa473 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLNet.java @@ -67,7 +67,6 @@ public class HDLNet implements Printable, HasName { case INOUT: inOutputs.add(hdlPort); break; - } } @@ -225,4 +224,11 @@ public class HDLNet implements Printable, HasName { name = renaming.checkName(name); } + /** + * @return true if this is a inOut net + */ + public boolean isInOutNet() { + return !inOutputs.isEmpty(); + } + } 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 22b8dd391..834a7c6b9 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLPort.java @@ -38,7 +38,7 @@ public class HDLPort implements Printable, HasName { } private String name; - private final Direction direction; + private Direction direction; private int bits; private String description; private boolean isClock; @@ -217,4 +217,11 @@ public class HDLPort implements Printable, HasName { name = renaming.checkName(name); } + /** + * Sets this port to a inOut mode port + */ + public void setInOut() { + direction = Direction.INOUT; + } + } 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 3af1433d1..06ca69510 100644 --- a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLCreator.java @@ -178,18 +178,24 @@ public class VHDLCreator { for (HDLPort i : circuit.getInputs()) { sep.check(); - out.print(i.getName()).print(": in ").print(getType(i.getBits())); + out.print(i.getName()).print(": ").print(getDir(i.getDirection(), "in")).print(" ").print(getType(i.getBits())); if (i.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", i.getDescription())); } for (HDLPort o : circuit.getOutputs()) { sep.check(); - out.print(o.getName()).print(": out ").print(getType(o.getBits())); + out.print(o.getName()).print(": ").print(getDir(o.getDirection(), "out")).print(" ").print(getType(o.getBits())); if (o.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" -- ", o.getDescription())); } sep.close(); out.println(");").dec(); } + private static String getDir(HDLPort.Direction direction, String def) { + if (direction == HDLPort.Direction.INOUT) + return "inout"; + return def; + } + private void printManyToOne(HDLNodeSplitterManyToOne node) throws IOException, HDLException { String target = node.getTargetSignal(); From ca6c9a97947b60c03f9bbc3bf30c8fd5a72b3d85 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 14 Dec 2019 22:45:38 +0100 Subject: [PATCH 05/11] first verilog inout test has passed, see #394 --- .../digital/hdl/verilog2/VerilogCreator.java | 21 +++- src/main/resources/verilog/DIG_PinControl.v | 26 +++++ .../hdl/verilog2/VerilogSimulatorTest.java | 18 +++- .../digital/hdl/vhdl2/VHDLSimulatorTest.java | 14 ++- .../digital/integration/TestExamples.java | 4 +- .../resources/dig/test/pinControl/uniTest.dig | 98 +++++++++++++++++++ 6 files changed, 170 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/verilog/DIG_PinControl.v create mode 100644 src/test/resources/dig/test/pinControl/uniTest.dig 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 78d8a118c..1020815ee 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog2/VerilogCreator.java +++ b/src/main/java/de/neemann/digital/hdl/verilog2/VerilogCreator.java @@ -56,12 +56,17 @@ public class VerilogCreator { /** * Returns the verilog type for a signal * - * @param dir the signal type (input or output) + * @param def the signal type (input or output) used if dir is not "inout" + * @param dir used to check if direction is "inout" * @param bits the number of bits * @return the verilog signal type */ - public static String getType(HDLPort.Direction dir, int bits) { - String result = (dir == HDLPort.Direction.IN) ? "input" : "output"; + public static String getType(HDLPort.Direction def, HDLPort.Direction dir, int bits) { + String result; + if (dir == HDLPort.Direction.INOUT) + result = "inout"; + else + result = (def == HDLPort.Direction.IN) ? "input" : "output"; if (bits > 1) { result += " [" + (bits - 1) + ":0]"; @@ -181,12 +186,12 @@ public class VerilogCreator { for (HDLPort i : circuit.getInputs()) { sep.check(); - out.print(getType(HDLPort.Direction.IN, i.getBits())).print(" ").print(i.getName()); + out.print(getType(HDLPort.Direction.IN, i.getDirection(), i.getBits())).print(" ").print(i.getName()); if (i.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" // ", i.getDescription())); } for (HDLPort o : circuit.getOutputs()) { sep.check(); - out.print(getType(HDLPort.Direction.OUT, o.getBits())).print(" ").print(o.getName()); + out.print(getType(HDLPort.Direction.OUT, o.getDirection(), o.getBits())).print(" ").print(o.getName()); if (o.hasDescription()) sep.setLineFinalizer(ou -> ou.printComment(" // ", o.getDescription())); } sep.close(); @@ -260,6 +265,12 @@ public class VerilogCreator { sep.check(); out.print(".").print(o.getName()).print("( ").print(o.getNet().getName()).print(" )"); } + + for (HDLPort o : node.getInOutputs()) + if (o.getNet() != null) { + sep.check(); + out.print(".").print(o.getName()).print("( ").print(o.getNet().getName()).print(" )"); + } out.dec(); out.println().println(");"); } diff --git a/src/main/resources/verilog/DIG_PinControl.v b/src/main/resources/verilog/DIG_PinControl.v new file mode 100644 index 000000000..7c3ad712e --- /dev/null +++ b/src/main/resources/verilog/DIG_PinControl.v @@ -0,0 +1,26 @@ + 1) { + generics[0] := "Bits"; + export bitRange := "[(Bits-1):0] "; + export zval := "{Bits{1'bz}}"; + } + else { + moduleName = moduleName+"_BUS"; + export bitRange := ""; + export zval := "1'bz"; + } +?>module 1) { ?> +#( + parameter Bits = 2 +) +( + inout pin, + input oe, + input wr, + output rd +); + + assign pin = oe ? wr : ; + assign rd = oe ? wr : pin ; +endmodule 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 ab0840518..52e685038 100644 --- a/src/test/java/de/neemann/digital/hdl/verilog2/VerilogSimulatorTest.java +++ b/src/test/java/de/neemann/digital/hdl/verilog2/VerilogSimulatorTest.java @@ -14,6 +14,7 @@ import de.neemann.digital.draw.library.ElementNotFoundException; import de.neemann.digital.gui.Settings; import de.neemann.digital.hdl.model2.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.TestExamples; @@ -42,13 +43,13 @@ public class VerilogSimulatorTest extends TestCase { /* public void testDebug() throws Exception { - File file = new File(Resources.getRoot(), "dig/test/vhdl/lut.dig"); + File file = new File(Resources.getRoot(), "/dig/test/vhdl/pinControl/simple.dig"); ToBreakRunner br = new ToBreakRunner(file); System.out.println(new VerilogGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit())); checkVerilogExport(file); - }*/ + }/**/ public void testInSimulator() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test/vhdl"); @@ -71,6 +72,19 @@ public class VerilogSimulatorTest extends TestCase { } } + /* + public void testInSimulatorInOut() throws Exception { + File examples = new File(Resources.getRoot(), "/dig/test/pinControl"); + try { + int tested = new FileScanner(this::checkVerilogExport).noOutput().scan(examples); + assertEquals(2, tested); + assertEquals(2, testBenches); + } catch (FileScanner.SkipAllException e) { + // if iverilog is not installed its also ok + } + }/**/ + + public void testDistributedInSimulator() throws Exception { File examples = new File(Resources.getRoot(), "../../main/dig/hdl"); try { 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 e04f3e47b..6692d588b 100644 --- a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java @@ -14,7 +14,6 @@ import de.neemann.digital.draw.library.ElementNotFoundException; import de.neemann.digital.gui.Settings; import de.neemann.digital.hdl.model2.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.TestExamples; @@ -33,7 +32,7 @@ public class VHDLSimulatorTest extends TestCase { private static final String GHDL = System.getProperty("ghdl", "ghdl"); private int testBenches; - //* + /* public void testDebug() throws Exception { File file = new File(Resources.getRoot(), "/dig/test/pinControl/simple.dig"); @@ -64,6 +63,17 @@ public class VHDLSimulatorTest extends TestCase { } } + public void testInSimulatorInOut() throws Exception { + File examples = new File(Resources.getRoot(), "/dig/test/pinControl"); + try { + int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples); + assertEquals(2, tested); + assertEquals(2, testBenches); + } catch (FileScanner.SkipAllException e) { + // if ghdl is not installed its also ok + } + } + public void testDistributedInSimulator() throws Exception { File examples = new File(Resources.getRoot(), "../../main/dig/hdl"); try { diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index d043be59c..569da6b51 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -43,8 +43,8 @@ public class TestExamples extends TestCase { */ public void testTestExamples() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test"); - assertEquals(185, new FileScanner(this::check).scan(examples)); - assertEquals(173, testCasesInFiles); + assertEquals(186, new FileScanner(this::check).scan(examples)); + assertEquals(174, testCasesInFiles); } /** diff --git a/src/test/resources/dig/test/pinControl/uniTest.dig b/src/test/resources/dig/test/pinControl/uniTest.dig new file mode 100644 index 000000000..9aeac3ea6 --- /dev/null +++ b/src/test/resources/dig/test/pinControl/uniTest.dig @@ -0,0 +1,98 @@ + + + 1 + + + + In + + + Label + wr + + + + + + In + + + Label + oe + + + + + + PinControl + + + + + Out + + + rotation + + + + Label + rd + + + + + + Out + + + Label + pin + + + + + + Testcase + + + Testdata + + oe wr rd pin +1 0 0 0 +1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 660327e674c26c0d59ccb170054252f646f90650 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 15 Dec 2019 09:31:30 +0100 Subject: [PATCH 06/11] adds a error message if PinControl is used in a embedded circuit, see #394 --- .../neemann/digital/hdl/model2/HDLCircuit.java | 17 ++++++++++++++--- .../de/neemann/digital/hdl/model2/HDLModel.java | 12 +++++++----- .../digital/hdl/model2/HDLModelTest.java | 2 +- .../digital/hdl/verilog2/DescriptionTest.java | 2 +- .../de/neemann/digital/hdl/vhdl2/ClockTest.java | 2 +- .../digital/hdl/vhdl2/DescriptionTest.java | 2 +- .../digital/hdl/vhdl2/VHDLSimulatorTest.java | 2 +- 7 files changed, 26 insertions(+), 13 deletions(-) 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 7124ef119..31ad3934a 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java @@ -44,6 +44,7 @@ import java.util.*; */ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Printable { private final String elementName; + private final int depth; private final ArrayList outputs; private final ArrayList inputs; private final ArrayList listOfNets; @@ -61,12 +62,13 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin * @param circuit the circuit * @param elementName the name of the circuit * @param c the context to create the circuits + * @param depth the depth of this circuit in the circuits hierarchy * @throws PinException PinException * @throws HDLException HDLException * @throws NodeException NodeException */ - HDLCircuit(Circuit circuit, String elementName, HDLModel c) throws PinException, HDLException, NodeException { - this(circuit, elementName, c, null); + HDLCircuit(Circuit circuit, String elementName, HDLModel c, int depth) throws PinException, HDLException, NodeException { + this(circuit, elementName, c, depth, null); } /** @@ -75,13 +77,15 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin * @param circuit the circuit * @param elementName the name of the circuit * @param c the context to create the circuits + * @param depth the depth of this circuit in the circuits hierarchy * @param clockIntegrator the clock integrator * @throws PinException PinException * @throws HDLException HDLException * @throws NodeException NodeException */ - public HDLCircuit(Circuit circuit, String elementName, HDLModel c, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, NodeException { + public HDLCircuit(Circuit circuit, String elementName, HDLModel c, int depth, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, NodeException { this.elementName = elementName; + this.depth = depth; if (elementName.toLowerCase().endsWith(".dig")) hdlEntityName = elementName.substring(0, elementName.length() - 4); @@ -564,6 +568,13 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin return origin; } + /** + * @return the depth of this circuit in the circuits hierarchy + */ + public int getDepth() { + return depth; + } + /** * 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 c550f7da7..50741d2f7 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java @@ -73,7 +73,7 @@ public class HDLModel implements Iterable { if (c == null) { String elementName = v.getElementName(); elementName = cleanName(elementName.substring(0, elementName.length() - 4) + "_gen" + cache.getNum() + ".dig"); - c = new HDLCircuit(holder.getCircuit(), elementName, this); + c = new HDLCircuit(holder.getCircuit(), elementName, this, parent.getDepth() + 1); cache.addHDLCircuit(c, holder.getArgs()); circuitMap.put(holder.getCircuit(), c); } @@ -86,7 +86,7 @@ public class HDLModel implements Iterable { HDLCircuit c = circuitMap.get(circuit); final String elementName = cleanName(v.getElementName()); if (c == null) { - c = new HDLCircuit(circuit, elementName, this); + c = new HDLCircuit(circuit, elementName, this, parent.getDepth() + 1); circuitMap.put(circuit, c); } @@ -183,9 +183,11 @@ public class HDLModel implements Iterable { node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); break; case both: - if (v.equalsDescription(PinControl.DESCRIPTION)) + if (v.equalsDescription(PinControl.DESCRIPTION)) { + if (c.getDepth() != 0) + throw new HDLException("PinControl component is allowed only in the top level circuit"); node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.INOUT, node.getBits(p.getName()))); - else + } else node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.OUT, node.getBits(p.getName()))); break; } @@ -210,7 +212,7 @@ public class HDLModel implements Iterable { * @throws NodeException NodeException */ public HDLModel create(Circuit circuit, HDLClockIntegrator clockIntegrator) throws PinException, HDLException, NodeException { - main = new HDLCircuit(circuit, "main", this, clockIntegrator); + main = new HDLCircuit(circuit, "main", this, 0, clockIntegrator); circuitMap.put(circuit, main); return this; } diff --git a/src/test/java/de/neemann/digital/hdl/model2/HDLModelTest.java b/src/test/java/de/neemann/digital/hdl/model2/HDLModelTest.java index 79b98c976..46ef1ad70 100644 --- a/src/test/java/de/neemann/digital/hdl/model2/HDLModelTest.java +++ b/src/test/java/de/neemann/digital/hdl/model2/HDLModelTest.java @@ -21,7 +21,7 @@ public class HDLModelTest extends TestCase { private HDLCircuit getCircuit(String filename, HDLClockIntegrator ci) throws IOException, PinException, HDLException, NodeException, ElementNotFoundException { ToBreakRunner br = new ToBreakRunner(filename); - return new HDLCircuit(br.getCircuit(), "main", new HDLModel(br.getLibrary()), ci); + return new HDLCircuit(br.getCircuit(), "main", new HDLModel(br.getLibrary()), 0, ci); } public void testSimple() throws IOException, PinException, HDLException, NodeException, ElementNotFoundException { diff --git a/src/test/java/de/neemann/digital/hdl/verilog2/DescriptionTest.java b/src/test/java/de/neemann/digital/hdl/verilog2/DescriptionTest.java index d1511b46c..776e3ea0e 100644 --- a/src/test/java/de/neemann/digital/hdl/verilog2/DescriptionTest.java +++ b/src/test/java/de/neemann/digital/hdl/verilog2/DescriptionTest.java @@ -26,7 +26,7 @@ public class DescriptionTest extends TestCase { br.getCircuit(), "main" , new HDLModel(br.getLibrary()), - null) + 0, null) .applyDefaultOptimizations(); CodePrinterStr out = new CodePrinterStr(); new VerilogCreator(out, br.getLibrary()).printHDLCircuit(circuit, "naming"); diff --git a/src/test/java/de/neemann/digital/hdl/vhdl2/ClockTest.java b/src/test/java/de/neemann/digital/hdl/vhdl2/ClockTest.java index 020063f03..c16f21e15 100644 --- a/src/test/java/de/neemann/digital/hdl/vhdl2/ClockTest.java +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/ClockTest.java @@ -123,7 +123,7 @@ public class ClockTest extends TestCase { HDLCircuit c = new HDLCircuit( br.getCircuit(), "main", new HDLModel(br.getLibrary()), - ci); + 0, ci); c.applyDefaultOptimizations(); diff --git a/src/test/java/de/neemann/digital/hdl/vhdl2/DescriptionTest.java b/src/test/java/de/neemann/digital/hdl/vhdl2/DescriptionTest.java index f022dc1c3..ee049a61c 100644 --- a/src/test/java/de/neemann/digital/hdl/vhdl2/DescriptionTest.java +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/DescriptionTest.java @@ -26,7 +26,7 @@ public class DescriptionTest extends TestCase { br.getCircuit(), "main" , new HDLModel(br.getLibrary()), - null) + 0, null) .applyDefaultOptimizations(); CodePrinterStr out = new CodePrinterStr(); new VHDLCreator(out, br.getLibrary()).printHDLCircuit(circuit); 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 6692d588b..6bd1c1e3e 100644 --- a/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java +++ b/src/test/java/de/neemann/digital/hdl/vhdl2/VHDLSimulatorTest.java @@ -34,7 +34,7 @@ public class VHDLSimulatorTest extends TestCase { /* public void testDebug() throws Exception { - File file = new File(Resources.getRoot(), "/dig/test/pinControl/simple.dig"); + File file = new File(Resources.getRoot(), "/dig/test/pinControl/nesting.dig"); ToBreakRunner br = new ToBreakRunner(file); System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit())); From a4a3ff5d605b07d6a9064906522b524d160dfd2a Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 15 Dec 2019 09:39:57 +0100 Subject: [PATCH 07/11] Added some explanations, see #394 --- .../java/de/neemann/digital/draw/shapes/PinControlShape.java | 3 +-- src/main/resources/lang/lang_de.xml | 2 ++ src/main/resources/lang/lang_en.xml | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java b/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java index 4b8bb9649..2ce2519c2 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java +++ b/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java @@ -53,8 +53,7 @@ public class PinControlShape implements Shape { @Override public void drawTo(Graphic graphic, Style highLight) { graphic.drawLine(new Vector(0, -SIZE), new Vector(SIZE, 0), Style.NORMAL); - graphic.drawLine(new Vector(0, 0), new Vector(SIZE, 0), Style.NORMAL); + graphic.drawLine(new Vector(0, 0), new Vector(SIZE * 2, 0), Style.NORMAL); graphic.drawLine(new Vector(0, SIZE), new Vector(SIZE, 0), Style.NORMAL); - graphic.drawLine(new Vector(SIZE, 0), new Vector(SIZE * 2, 0), Style.NORMAL); } } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 9ec4fa634..19112d5db 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -358,6 +358,8 @@ Nur im Rahmen der VHDL- oder Verilog-Generierung erforderlich! Diese Komponente ist notwendig, um einen bidirektionalen HDL-Port zu erstellen! Wenn Sie keinen bidirektionalen IO-Port auf einem FPGA verwenden wollen, verwenden Sie diese Komponente nicht! + Die Pinsteuerung kann nicht in einer eingebetteten Schaltung verwendet werden! Sie ist nur auf der obersten + Schaltungsebene erlaubt! Die auszugebenden Daten Aktiviert die Ausgabe diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 76791481c..57884bd41 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -367,6 +367,7 @@ Control logic for a bi-directional pin. Only needed in the context of VHDL or Verilog generation! This component is necessary to create a bi-directional HDL port! If you don't want to use a di-directional IO-port on an FPGA, don't use this component! + The PinControl component cannot be used in an embedded circuit! It is only allowed at the top level circuit! The data to be output. Activates the output. From 13c555fbd1639d1156976df23dc7a95a69dac7e3 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 15 Dec 2019 13:46:29 +0100 Subject: [PATCH 08/11] enables at least one verilog test, see #394 --- .../digital/hdl/verilog2/VerilogSimulatorTest.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 52e685038..de4f7be28 100644 --- a/src/test/java/de/neemann/digital/hdl/verilog2/VerilogSimulatorTest.java +++ b/src/test/java/de/neemann/digital/hdl/verilog2/VerilogSimulatorTest.java @@ -72,17 +72,19 @@ public class VerilogSimulatorTest extends TestCase { } } - /* public void testInSimulatorInOut() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test/pinControl"); try { - int tested = new FileScanner(this::checkVerilogExport).noOutput().scan(examples); + int tested = new FileScanner(f -> { + if (!f.getName().equals("uniTest.dig")) + checkVerilogExport(f); + }).noOutput().scan(examples); assertEquals(2, tested); - assertEquals(2, testBenches); + assertEquals(1, testBenches); } catch (FileScanner.SkipAllException e) { // if iverilog is not installed its also ok } - }/**/ + } public void testDistributedInSimulator() throws Exception { @@ -142,7 +144,7 @@ public class VerilogSimulatorTest extends TestCase { try { File srcFile = new File(dir, file.getName() .replace('.', '_') - .replace('-', '_')+ ".v"); + .replace('-', '_') + ".v"); CodePrinter out = new CodePrinter(srcFile); try (VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out)) { gen.export(br.getCircuit()); From 1108e9c4d11777331f2dd4c20289d19a67ce7ff8 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 15 Dec 2019 13:58:45 +0100 Subject: [PATCH 09/11] typos, see #394 --- src/main/resources/lang/lang_de.xml | 2 +- src/main/resources/lang/lang_en.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 19112d5db..9f3502d33 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -365,7 +365,7 @@ Aktiviert die Ausgabe Die zu lesenden Daten. Der Anschluss für den eigentlichen Pin. Hier sollte nur noch ein einzelner - Eingang angeschlossen werden. + Ausgang angeschlossen werden. diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 57884bd41..a79b28cd7 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -372,7 +372,7 @@ The data to be output. Activates the output. The data to be read. - The connector for the actual pin. Only a single input should be connected + The connector for the actual pin. Only a single output should be connected here. From 98694a92cc766133774ad3ea146da8ba9b745455 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 15 Dec 2019 21:46:46 +0100 Subject: [PATCH 10/11] new PinControl shape, see #394 --- .../digital/draw/shapes/PinControlShape.java | 29 ++++--- .../resources/dig/backtrack/AllComponents.dig | 86 +++++++++++-------- .../resources/dig/test/pinControl/simple.dig | 72 ++++++++-------- .../resources/dig/test/pinControl/uniTest.dig | 40 ++++----- 4 files changed, 123 insertions(+), 104 deletions(-) diff --git a/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java b/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java index 2ce2519c2..35c4851ec 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java +++ b/src/main/java/de/neemann/digital/draw/shapes/PinControlShape.java @@ -11,11 +11,10 @@ import de.neemann.digital.core.element.PinDescriptions; import de.neemann.digital.draw.elements.IOState; import de.neemann.digital.draw.elements.Pin; import de.neemann.digital.draw.elements.Pins; -import de.neemann.digital.draw.graphics.Graphic; -import de.neemann.digital.draw.graphics.Style; -import de.neemann.digital.draw.graphics.Vector; +import de.neemann.digital.draw.graphics.*; import static de.neemann.digital.draw.shapes.GenericShape.SIZE; +import static de.neemann.digital.draw.shapes.GenericShape.SIZE2; /** * The shape for the pin control logic @@ -23,6 +22,7 @@ import static de.neemann.digital.draw.shapes.GenericShape.SIZE; public class PinControlShape implements Shape { private final PinDescriptions in; private final PinDescriptions out; + private Pins pins; /** * Creates a new instance @@ -38,11 +38,13 @@ public class PinControlShape implements Shape { @Override public Pins getPins() { - return new Pins() - .add(new Pin(new Vector(0, -SIZE), in.get(0))) - .add(new Pin(new Vector(0, 0), out.get(0))) - .add(new Pin(new Vector(0, +SIZE), in.get(1))) - .add(new Pin(new Vector(SIZE * 2, 0), out.get(1))); + if (pins == null) + pins = new Pins() + .add(new Pin(new Vector(0, 0), in.get(0))) + .add(new Pin(new Vector(SIZE, -SIZE), in.get(1))) + .add(new Pin(new Vector(SIZE * 2, SIZE), out.get(0))) + .add(new Pin(new Vector(SIZE * 3, 0), out.get(1))); + return pins; } @Override @@ -52,8 +54,13 @@ public class PinControlShape implements Shape { @Override public void drawTo(Graphic graphic, Style highLight) { - graphic.drawLine(new Vector(0, -SIZE), new Vector(SIZE, 0), Style.NORMAL); - graphic.drawLine(new Vector(0, 0), new Vector(SIZE * 2, 0), Style.NORMAL); - graphic.drawLine(new Vector(0, SIZE), new Vector(SIZE, 0), Style.NORMAL); + graphic.drawLine(new Vector(0, 0), new Vector(SIZE2, 0), Style.NORMAL); + graphic.drawLine(new Vector(SIZE + SIZE2, 0), new Vector(SIZE * 3, 0), Style.NORMAL); + graphic.drawLine(new Vector(SIZE * 2, 0), new Vector(SIZE * 2, SIZE), Style.NORMAL); + graphic.drawPolygon(new Polygon() + .add(SIZE2, SIZE2) + .add(SIZE2, -SIZE2) + .add(SIZE + SIZE2, 0), Style.NORMAL); + graphic.drawLine(new Vector(SIZE, -SIZE), new Vector(SIZE, -6), Style.NORMAL); } } diff --git a/src/test/resources/dig/backtrack/AllComponents.dig b/src/test/resources/dig/backtrack/AllComponents.dig index d9fab394c..3c8f6a624 100644 --- a/src/test/resources/dig/backtrack/AllComponents.dig +++ b/src/test/resources/dig/backtrack/AllComponents.dig @@ -636,7 +636,7 @@ zz - + @@ -692,6 +692,14 @@ + + + + + + + + @@ -742,7 +750,7 @@ - + @@ -885,7 +893,7 @@ - + @@ -1092,14 +1100,6 @@ - - - - - - - - @@ -1288,6 +1288,22 @@ + + + + + + + + + + + + + + + + @@ -1312,14 +1328,6 @@ - - - - - - - - @@ -1496,6 +1504,10 @@ + + + + @@ -1504,10 +1516,6 @@ - - - - @@ -1688,6 +1696,10 @@ + + + + @@ -1837,16 +1849,8 @@ - - - - - - - - - - + + @@ -1864,6 +1868,18 @@ + + + + + + + + + + + + @@ -1940,10 +1956,6 @@ - - - - diff --git a/src/test/resources/dig/test/pinControl/simple.dig b/src/test/resources/dig/test/pinControl/simple.dig index 77048e635..af8563a7d 100644 --- a/src/test/resources/dig/test/pinControl/simple.dig +++ b/src/test/resources/dig/test/pinControl/simple.dig @@ -15,7 +15,7 @@ 4 - + In @@ -25,7 +25,7 @@ oe - + PinControl @@ -53,7 +53,7 @@ 4 - + In @@ -71,7 +71,7 @@ 4 - + PinControl @@ -89,7 +89,7 @@ 4 - + Out @@ -103,12 +103,12 @@ 4 - + Not - + Testcase @@ -125,58 +125,58 @@ - + - - + + - - - - - - - - - - - - - + - - + + - - + + - - + + + + + + - + - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/dig/test/pinControl/uniTest.dig b/src/test/resources/dig/test/pinControl/uniTest.dig index 9aeac3ea6..8d6b24e6e 100644 --- a/src/test/resources/dig/test/pinControl/uniTest.dig +++ b/src/test/resources/dig/test/pinControl/uniTest.dig @@ -11,7 +11,7 @@ wr - + In @@ -21,7 +21,7 @@ oe - + PinControl @@ -40,7 +40,7 @@ rd - + Out @@ -50,7 +50,7 @@ pin - + Testcase @@ -69,30 +69,30 @@ - - - - - + - - + + - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file From 195550444532d2b81058804561dc604897dc56e2 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 15 Dec 2019 22:02:12 +0100 Subject: [PATCH 11/11] typos, see #394 --- src/main/resources/lang/lang_de.xml | 4 ++-- src/main/resources/lang/lang_en.xml | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 9f3502d33..64438a90e 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -355,8 +355,8 @@ Pinsteuerung Steuerlogik für einen bidirektionalen Pin. - Nur im Rahmen der VHDL- oder Verilog-Generierung erforderlich! - Diese Komponente ist notwendig, um einen bidirektionalen HDL-Port zu erstellen! + Diese ist nur im Rahmen der VHDL- oder Verilog-Generierung erforderlich, um einen bidirektionalen HDL-Port zu + erstellen! Wenn Sie keinen bidirektionalen IO-Port auf einem FPGA verwenden wollen, verwenden Sie diese Komponente nicht! Die Pinsteuerung kann nicht in einer eingebetteten Schaltung verwendet werden! Sie ist nur auf der obersten Schaltungsebene erlaubt! diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index a79b28cd7..6f275f8f8 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -364,9 +364,10 @@ Pin Control - Control logic for a bi-directional pin. Only needed in the context of VHDL or - Verilog generation! This component is necessary to create a bi-directional HDL port! If you don't want - to use a di-directional IO-port on an FPGA, don't use this component! + Control logic for a bi-directional pin. + This component is necessary only in the context of VHDL or Verilog generation, in order to create a + bi-directional HDL port! + If you don't want to use a bi-directional IO-port on an FPGA, don't use this component! The PinControl component cannot be used in an embedded circuit! It is only allowed at the top level circuit! The data to be output.