first vhdl inout test has passed, see #394

This commit is contained in:
hneemann 2019-12-14 20:27:32 +01:00
parent a4d65b9d02
commit 373c8bd4a4
12 changed files with 357 additions and 35 deletions

View File

@ -26,7 +26,8 @@ public class PinControl extends Node implements Element {
*/ */
public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(PinControl.class, input("wr"), input("oe")) public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(PinControl.class, input("wr"), input("oe"))
.addAttribute(Keys.ROTATE) .addAttribute(Keys.ROTATE)
.addAttribute(Keys.BITS); .addAttribute(Keys.BITS)
.addAttribute(Keys.MIRROR);
private final int bits; private final int bits;
private final ObservableValue rdValue; private final ObservableValue rdValue;
@ -46,7 +47,7 @@ public class PinControl extends Node implements Element {
public PinControl(ElementAttributes attr) { public PinControl(ElementAttributes attr) {
bits = attr.getBits(); bits = attr.getBits();
rdValue = new ObservableValue("rd", bits).setPinDescription(DESCRIPTION); rdValue = new ObservableValue("rd", bits).setPinDescription(DESCRIPTION);
outWriteValue = new ObservableValue("out", bits).setPinDescription(DESCRIPTION).setBidirectional(); outWriteValue = new ObservableValue("pin", bits).setPinDescription(DESCRIPTION).setBidirectional();
} }
@Override @Override

View File

@ -180,10 +180,17 @@ public class HDLModel implements Iterable<HDLCircuit> {
private <N extends HDLNode> N addInputsOutputs(N node, VisualElement v, HDLCircuit c) throws HDLException { private <N extends HDLNode> N addInputsOutputs(N node, VisualElement v, HDLCircuit c) throws HDLException {
for (Pin p : v.getPins()) { for (Pin p : v.getPins()) {
HDLNet net = c.getNetOfPin(p); HDLNet net = c.getNetOfPin(p);
if (p.getDirection().equals(PinDescription.Direction.input)) switch (p.getDirection()) {
case input:
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0)); node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.IN, 0));
else break;
case output:
node.addPort(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())));
break;
case both:
node.addPort(new HDLPort(p.getName(), net, HDLPort.Direction.INOUT, node.getBits(p.getName())));
break;
}
} }
return node; return node;
} }

View File

@ -7,6 +7,7 @@ package de.neemann.digital.hdl.model2;
import de.neemann.digital.hdl.model2.expression.ExprConstant; import de.neemann.digital.hdl.model2.expression.ExprConstant;
import de.neemann.digital.hdl.printer.CodePrinter; import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.hdl.vhdl2.VHDLTestBenchCreator;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
import java.io.IOException; import java.io.IOException;
@ -18,8 +19,9 @@ import java.util.ArrayList;
*/ */
public class HDLNet implements Printable, HasName { public class HDLNet implements Printable, HasName {
private final boolean userNamed; private final boolean userNamed;
private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLPort> inOutputs;
private String name; private String name;
private ArrayList<HDLPort> inputs;
private HDLPort output; private HDLPort output;
private boolean needsVariable = true; private boolean needsVariable = true;
private boolean isInput; private boolean isInput;
@ -32,6 +34,7 @@ public class HDLNet implements Printable, HasName {
public HDLNet(String name) { public HDLNet(String name) {
this.name = name; this.name = name;
inputs = new ArrayList<>(); inputs = new ArrayList<>();
inOutputs = new ArrayList<>();
userNamed = name != null; userNamed = name != null;
} }
@ -49,7 +52,8 @@ public class HDLNet implements Printable, HasName {
* @throws HDLException HDLException * @throws HDLException HDLException
*/ */
public void addPort(HDLPort hdlPort) throws HDLException { public void addPort(HDLPort hdlPort) throws HDLException {
if (hdlPort.getDirection().equals(HDLPort.Direction.OUT)) { switch (hdlPort.getDirection()) {
case OUT:
if (output != null) { if (output != null) {
String netName = name; String netName = name;
if (netName == null) if (netName == null)
@ -57,8 +61,15 @@ public class HDLNet implements Printable, HasName {
throw new HDLException(Lang.get("err_hdlMultipleOutputsConnectedToNet_N_N_N", netName, output, hdlPort)); throw new HDLException(Lang.get("err_hdlMultipleOutputsConnectedToNet_N_N_N", netName, output, hdlPort));
} }
output = hdlPort; output = hdlPort;
} else break;
case IN:
inputs.add(hdlPort); inputs.add(hdlPort);
break;
case INOUT:
inOutputs.add(hdlPort);
break;
}
} }
/** /**
@ -81,11 +92,25 @@ public class HDLNet implements Printable, HasName {
} }
void fixBits() throws HDLException { void fixBits() throws HDLException {
if (output == null) int bits = 0;
if (output == null) {
if (inOutputs.isEmpty())
throw new HDLException("no output connected to net"); throw new HDLException("no output connected to net");
final int bits = output.getBits(); 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) if (bits == 0)
throw new HDLException("no bit number set for output " + output.getName()); throw new HDLException("no bit number set for output " + output.getName());
}
for (HDLPort i : inputs) for (HDLPort i : inputs)
i.setBits(bits); i.setBits(bits);
@ -96,6 +121,8 @@ public class HDLNet implements Printable, HasName {
* @return the constant if this net is a constant, null otherwise * @return the constant if this net is a constant, null otherwise
*/ */
public ExprConstant isConstant() { public ExprConstant isConstant() {
if (output == null)
return null;
return ExprConstant.isConstant(output.getParent()); return ExprConstant.isConstant(output.getParent());
} }
@ -161,8 +188,16 @@ public class HDLNet implements Printable, HasName {
/** /**
* @return the number of bits on this net * @return the number of bits on this net
*/ */
public int getBits() { public int getBits() throws HDLException {
if (output != null)
return output.getBits(); return output.getBits();
for (HDLPort p : inOutputs) {
if (p.getBits() > 0) {
return p.getBits();
}
}
throw new HDLException("no bit number set for inOutputs " + inOutputs);
} }
/** /**

View File

@ -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.Expression;
import de.neemann.digital.hdl.model2.expression.Visitor; import de.neemann.digital.hdl.model2.expression.Visitor;
import de.neemann.digital.hdl.printer.CodePrinter; import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.hdl.vhdl2.VHDLTestBenchCreator;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -22,6 +23,7 @@ public abstract class HDLNode {
private final HDLModel.BitProvider bitProvider; private final HDLModel.BitProvider bitProvider;
private final ArrayList<HDLPort> inputs; private final ArrayList<HDLPort> inputs;
private final ArrayList<HDLPort> outputs; private final ArrayList<HDLPort> outputs;
private final ArrayList<HDLPort> inOutputs;
private String hdlEntityName; private String hdlEntityName;
/** /**
@ -37,6 +39,7 @@ public abstract class HDLNode {
this.bitProvider = bitProvider; this.bitProvider = bitProvider;
inputs = new ArrayList<>(); inputs = new ArrayList<>();
outputs = new ArrayList<>(); outputs = new ArrayList<>();
inOutputs = new ArrayList<>();
} }
/** /**
@ -46,10 +49,17 @@ public abstract class HDLNode {
* @return this for chained calls * @return this for chained calls
*/ */
public HDLNode addPort(HDLPort port) { public HDLNode addPort(HDLPort port) {
if (port.getDirection().equals(HDLPort.Direction.OUT)) switch (port.getDirection()) {
outputs.add(port); case IN:
else
inputs.add(port); inputs.add(port);
break;
case OUT:
outputs.add(port);
break;
case INOUT:
inOutputs.add(port);
break;
}
port.setParent(this); port.setParent(this);
@ -96,6 +106,13 @@ public abstract class HDLNode {
return outputs; return outputs;
} }
/**
* @return the list of inOutputs
*/
public ArrayList<HDLPort> getInOutputs() {
return inOutputs;
}
int getBits(String name) { int getBits(String name) {
return bitProvider.getBits(name); return bitProvider.getBits(name);
} }
@ -111,6 +128,10 @@ public abstract class HDLNode {
printWithLocal(out, inputs); printWithLocal(out, inputs);
out.print("out"); out.print("out");
printWithLocal(out, outputs); printWithLocal(out, outputs);
if (!inOutputs.isEmpty()) {
out.print("inOut");
printWithLocal(out, inOutputs);
}
} }
private void printWithLocal(CodePrinter out, ArrayList<HDLPort> ports) throws IOException { private void printWithLocal(CodePrinter out, ArrayList<HDLPort> ports) throws IOException {
@ -177,6 +198,8 @@ public abstract class HDLNode {
p.rename(renaming); p.rename(renaming);
for (HDLPort p : inputs) for (HDLPort p : inputs)
p.rename(renaming); p.rename(renaming);
for (HDLPort p : inOutputs)
p.rename(renaming);
} }
/** /**

View File

@ -30,7 +30,11 @@ public class HDLPort implements Printable, HasName {
* Caution: a circuits input components port has type OUT because it defines a value, * Caution: a circuits input components port has type OUT because it defines a value,
* seen from inside the node. * seen from inside the node.
*/ */
OUT OUT,
/**
* Bidirectional port
*/
INOUT
} }
private String name; private String name;

View File

@ -250,6 +250,11 @@ public class VHDLCreator {
sep.check(); sep.check();
out.print(o.getName()).print(" => ").print(o.getNet().getName()); 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(); out.println(");").dec().dec();
} }

View File

@ -362,7 +362,7 @@
<string name="elem_PinControl_pin_wr">Die auszugebenden Daten</string> <string name="elem_PinControl_pin_wr">Die auszugebenden Daten</string>
<string name="elem_PinControl_pin_oe">Aktiviert die Ausgabe</string> <string name="elem_PinControl_pin_oe">Aktiviert die Ausgabe</string>
<string name="elem_PinControl_pin_rd">Die zu lesenden Daten.</string> <string name="elem_PinControl_pin_rd">Die zu lesenden Daten.</string>
<string name="elem_PinControl_pin_out">Der Anschluss für den eigentlichen Pin. Hier sollte nur noch ein einzelner <string name="elem_PinControl_pin_pin">Der Anschluss für den eigentlichen Pin. Hier sollte nur noch ein einzelner
Eingang angeschlossen werden. Eingang angeschlossen werden.
</string> </string>

View File

@ -371,7 +371,7 @@
<string name="elem_PinControl_pin_wr">The data to be output.</string> <string name="elem_PinControl_pin_wr">The data to be output.</string>
<string name="elem_PinControl_pin_oe">Activates the output.</string> <string name="elem_PinControl_pin_oe">Activates the output.</string>
<string name="elem_PinControl_pin_rd">The data to be read.</string> <string name="elem_PinControl_pin_rd">The data to be read.</string>
<string name="elem_PinControl_pin_out">The connector for the actual pin. Only a single input should be connected <string name="elem_PinControl_pin_pin">The connector for the actual pin. Only a single input should be connected
here. here.
</string> </string>

View File

@ -0,0 +1,64 @@
LIBRARY ieee;
USE ieee.std_logic_1164.all;
<?
if (elem.Bits=1) {
export entityName:="PinControl"; ?>
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;
<? } else {
export entityName:="PinControl_BUS"; ?>
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY PinControl_BUS IS
GENERIC (
Bits: integer );<? vhdl.registerGeneric("Bits"); ?>
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;
<?
}
?>

View File

@ -14,6 +14,7 @@ import de.neemann.digital.draw.library.ElementNotFoundException;
import de.neemann.digital.gui.Settings; import de.neemann.digital.gui.Settings;
import de.neemann.digital.hdl.model2.HDLException; import de.neemann.digital.hdl.model2.HDLException;
import de.neemann.digital.hdl.printer.CodePrinter; import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.hdl.printer.CodePrinterStr;
import de.neemann.digital.integration.FileScanner; import de.neemann.digital.integration.FileScanner;
import de.neemann.digital.integration.Resources; import de.neemann.digital.integration.Resources;
import de.neemann.digital.integration.TestExamples; 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 static final String GHDL = System.getProperty("ghdl", "ghdl");
private int testBenches; private int testBenches;
/* //*
public void testDebug() throws Exception { 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); ToBreakRunner br = new ToBreakRunner(file);
System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit())); System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit()));

View File

@ -43,8 +43,8 @@ public class TestExamples extends TestCase {
*/ */
public void testTestExamples() throws Exception { public void testTestExamples() throws Exception {
File examples = new File(Resources.getRoot(), "/dig/test"); File examples = new File(Resources.getRoot(), "/dig/test");
assertEquals(184, new FileScanner(this::check).scan(examples)); assertEquals(185, new FileScanner(this::check).scan(examples));
assertEquals(172, testCasesInFiles); assertEquals(173, testCasesInFiles);
} }
/** /**

View File

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>1</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>wr_0</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="340" y="140"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>oe</string>
</entry>
</elementAttributes>
<pos x="340" y="220"/>
</visualElement>
<visualElement>
<elementName>PinControl</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="380" y="180"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>Label</string>
<string>rd_0</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="340" y="180"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>Label</string>
<string>wr_1</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="520" y="140"/>
</visualElement>
<visualElement>
<elementName>PinControl</elementName>
<elementAttributes>
<entry>
<string>mirror</string>
<boolean>true</boolean>
</entry>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="480" y="180"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>rd_1</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="520" y="180"/>
</visualElement>
<visualElement>
<elementName>Not</elementName>
<elementAttributes/>
<pos x="400" y="220"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Testdata</string>
<testData>
<dataString>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
</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="380" y="80"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="360" y="220"/>
<p2 x="380" y="200"/>
</wire>
<wire>
<p1 x="500" y="140"/>
<p2 x="480" y="160"/>
</wire>
<wire>
<p1 x="360" y="140"/>
<p2 x="380" y="160"/>
</wire>
<wire>
<p1 x="420" y="180"/>
<p2 x="440" y="180"/>
</wire>
<wire>
<p1 x="340" y="180"/>
<p2 x="380" y="180"/>
</wire>
<wire>
<p1 x="480" y="180"/>
<p2 x="520" y="180"/>
</wire>
<wire>
<p1 x="440" y="220"/>
<p2 x="480" y="220"/>
</wire>
<wire>
<p1 x="340" y="220"/>
<p2 x="360" y="220"/>
</wire>
<wire>
<p1 x="360" y="220"/>
<p2 x="400" y="220"/>
</wire>
<wire>
<p1 x="500" y="140"/>
<p2 x="520" y="140"/>
</wire>
<wire>
<p1 x="340" y="140"/>
<p2 x="360" y="140"/>
</wire>
<wire>
<p1 x="480" y="200"/>
<p2 x="480" y="220"/>
</wire>
</wires>
<measurementOrdering/>
</circuit>