mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-12 06:15:32 -04:00
first vhdl inout test has passed, see #394
This commit is contained in:
parent
a4d65b9d02
commit
373c8bd4a4
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
64
src/main/resources/vhdl/DIG_PinControl.tem
Normal file
64
src/main/resources/vhdl/DIG_PinControl.tem
Normal 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;
|
||||
|
||||
<?
|
||||
}
|
||||
?>
|
@ -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()));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
182
src/test/resources/dig/test/pinControl/simple.dig
Normal file
182
src/test/resources/dig/test/pinControl/simple.dig
Normal 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>
|
Loading…
x
Reference in New Issue
Block a user