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"))
.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

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 {
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;
}

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.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<HDLPort> inputs;
private final ArrayList<HDLPort> inOutputs;
private String name;
private ArrayList<HDLPort> 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);
}
/**

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.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<HDLPort> inputs;
private final ArrayList<HDLPort> outputs;
private final ArrayList<HDLPort> 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<HDLPort> 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<HDLPort> 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);
}
/**

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,
* seen from inside the node.
*/
OUT
OUT,
/**
* Bidirectional port
*/
INOUT
}
private String name;

View File

@ -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();
}

View File

@ -362,7 +362,7 @@
<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_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.
</string>

View File

@ -371,7 +371,7 @@
<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_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.
</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.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()));

View File

@ -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);
}
/**

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>