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