From 55b7ba5b2736f877e1ce222101249c1387f4af94 Mon Sep 17 00:00:00 2001 From: hneemann Date: Tue, 20 Feb 2018 12:55:43 +0100 Subject: [PATCH] allows testing of circuits using high-z inputs which are bidirectional. --- .../java/de/neemann/digital/core/Signal.java | 19 +++ .../java/de/neemann/digital/core/io/In.java | 7 +- .../neemann/digital/testing/TestExecutor.java | 12 +- src/main/resources/lang/lang_de.xml | 19 ++- src/main/resources/lang/lang_en.xml | 15 +++ .../digital/integration/TestExamples.java | 4 +- src/test/resources/dig/test/inAsOutTest.dig | 123 ++++++++++++++++++ 7 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 src/test/resources/dig/test/inAsOutTest.dig diff --git a/src/main/java/de/neemann/digital/core/Signal.java b/src/main/java/de/neemann/digital/core/Signal.java index 042c042f5..500dc396c 100644 --- a/src/main/java/de/neemann/digital/core/Signal.java +++ b/src/main/java/de/neemann/digital/core/Signal.java @@ -9,6 +9,7 @@ public final class Signal implements Comparable { private final Setter setter; private IntFormat format = IntFormat.def; private String pinNumber; + private ObservableValue bidirectionalReader; /** * Creates a new Instance @@ -138,6 +139,24 @@ public final class Signal implements Comparable { return setter; } + /** + * If a signal is bidirectional the input is set. + * + * @param bidirectionalReader the corresponding input value + * @return this for chained calls + */ + public Signal setBidirectionalReader(ObservableValue bidirectionalReader) { + this.bidirectionalReader = bidirectionalReader; + return this; + } + + /** + * @return the bidirectional reader, maybe null + */ + public ObservableValue getBidirectionalReader() { + return bidirectionalReader; + } + /** * Setter interface to set a value */ diff --git a/src/main/java/de/neemann/digital/core/io/In.java b/src/main/java/de/neemann/digital/core/io/In.java index a98aeb057..5c1046f97 100644 --- a/src/main/java/de/neemann/digital/core/io/In.java +++ b/src/main/java/de/neemann/digital/core/io/In.java @@ -5,7 +5,6 @@ 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 de.neemann.digital.lang.Lang; /** * The Input @@ -41,6 +40,7 @@ public class In implements Element { private final String pinNumber; private final IntFormat format; private Model model; + private ObservableValue input; /** * Create a new instance @@ -53,13 +53,15 @@ public class In implements Element { pinNumber = attributes.get(Keys.PINNUMBER); output = new ObservableValue("out", attributes.get(Keys.BITS), highZ).setPinDescription(DESCRIPTION).setPinNumber(pinNumber); output.set(value.getValue(), value.isHighZ()); + if (highZ) output.setBidirectional(); label = attributes.getCleanLabel(); format = attributes.get(Keys.INT_FORMAT); } @Override public void setInputs(ObservableValues inputs) throws NodeException { - throw new NodeException(Lang.get("err_noInputsAvailable")); + // if input is bidirectional the value is given to read the pins state! + input = inputs.get(0); } @Override @@ -71,6 +73,7 @@ public class In implements Element { public void registerNodes(Model model) { model.addInput(new Signal(label, output, output::set) .setPinNumber(pinNumber) + .setBidirectionalReader(input) .setFormat(format)); this.model = model; } diff --git a/src/main/java/de/neemann/digital/testing/TestExecutor.java b/src/main/java/de/neemann/digital/testing/TestExecutor.java index 5031e0275..6aa4eb0ec 100644 --- a/src/main/java/de/neemann/digital/testing/TestExecutor.java +++ b/src/main/java/de/neemann/digital/testing/TestExecutor.java @@ -59,13 +59,24 @@ public class TestExecutor { HashSet usedSignals = new HashSet<>(); inputs = new ArrayList<>(); + outputs = new ArrayList<>(); for (Signal s : model.getInputs()) { final int index = getIndexOf(s.getName()); if (index >= 0) { inputs.add(new TestSignal(index, s.getValue())); addTo(usedSignals, s.getName()); } + ObservableValue outValue = s.getBidirectionalReader(); + if (outValue != null) { + final String outName = s.getName() + "_out"; + final int inIndex = getIndexOf(outName); + if (inIndex >= 0) { + outputs.add(new TestSignal(inIndex, outValue)); + addTo(usedSignals, outName); + } + } } + for (Clock c : model.getClocks()) { final int index = getIndexOf(c.getLabel()); if (index >= 0) { @@ -74,7 +85,6 @@ public class TestExecutor { } } - outputs = new ArrayList<>(); for (Signal s : model.getOutputs()) { final int index = getIndexOf(s.getName()); if (index >= 0) { diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index a58bd3371..b2a946469 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1360,7 +1360,8 @@ werden: "let U=A+B, let V=A*B"

Die erste Zeile muss, durch ein Leerzeichen getrennt, die -Ein- und Ausgänge auflisten. In den folgenden Zeilen stehen dann die Sollwerte. +Ein- und Ausgänge auflisten, die verwendet werden sollen. +In den folgenden Zeilen stehen dann die Sollwerte. Dabei steht ein 'X' für Don't Care, und ein 'Z' für hochohmig. Wird der Wert 'C' verwendet, werden zunächst alle anderen Werte gesetzt, dann wird ein Taktzyklus durchgeführt, und erst daran anschließend werden die Werte verglichen. @@ -1413,6 +1414,22 @@ loop(a,16) end loop +

Ein Eingang, welcher hochhomige Werte erlaubt, kann auch als Testausgang verwendet werden. +In diesem Fall kann der Signalname mit einem nachgestellten '_out' verwendet werden, um den +aktuellen Wert zurückzulesen und zu überprüfen. Dazu muss der entsprechende Eingang auf +hochohmig ('Z') gesetzt sein.

+ +
OE CLK D D_out
+0   0  0 0
+0   C  1 1
+1   0  z 1
+0   C  0 0
+1   0  z 0
+
+ +

Die Schaltung zu diesem Test hat nur einen Eingang 'D', welcher aber hochohmig sein kann. +Daher steht auch das Signal 'D_out' zur Verfügung, um in diesem Fall den Wert zu prüfen.

+ ]]> diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 3ac990e5c..5151b0e07 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -1400,6 +1400,21 @@ loop(a,16) end loop +

An input that allows high impedance as a value can also be used as a test output. +In this case, the signal name can be used with a trailing "_out" to read back and check the current value. +For this, the corresponding input must be set to high impedance ('Z').

+ +
OE CLK D D_out
+0   0  0 0
+0   C  1 1
+1   0  z 1
+0   C  0 0
+1   0  z 0
+
+ +

The circuit for this test has only one input 'D', but which can be high impedance state. +Therefore, the signal 'D_out' is also available to check the value in this case.

+ ]]> \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index 01efb76f7..c468acc92 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -40,8 +40,8 @@ public class TestExamples extends TestCase { */ public void testTestExamples() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test"); - assertEquals(121, new FileScanner(this::check).scan(examples)); - assertEquals(110, testCasesInFiles); + assertEquals(122, new FileScanner(this::check).scan(examples)); + assertEquals(111, testCasesInFiles); } diff --git a/src/test/resources/dig/test/inAsOutTest.dig b/src/test/resources/dig/test/inAsOutTest.dig new file mode 100644 index 000000000..14eb07129 --- /dev/null +++ b/src/test/resources/dig/test/inAsOutTest.dig @@ -0,0 +1,123 @@ + + + 1 + + + + D_FF + + + + + In + + + Label + D + + + isHighZ + true + + + + + + Driver + + + rotation + + + + flipSelPos + true + + + + + + In + + + Label + OE + + + + + + Clock + + + Label + CLK + + + + + + Testcase + + + Testdata + + OE CLK D D_out +0 0 0 0 +0 C 1 1 +1 0 z 1 +0 C 0 0 +1 0 z 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file