From ed015c16af5bd57c2007e1ce662a7b8227d4ba69 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 27 Mar 2016 10:48:41 +0200 Subject: [PATCH] added better multipla output detection, added support for bidirectional pins --- src/main/dig/Ampel_Einfach.dig | 44 +++++---- src/main/dig/Ampel_MSJK.dig | 92 ++++++++++-------- src/main/dig/Ampel_TJK.dig | 96 ++++++++++--------- .../neemann/digital/core/ObservableValue.java | 14 +++ .../digital/core/memory/DataField.java | 11 ++- .../neemann/digital/core/wiring/DataBus.java | 2 + .../digital/gui/draw/elements/Pin.java | 9 ++ .../digital/gui/draw/graphics/Style.java | 4 +- .../digital/gui/draw/model/ModelEntry.java | 14 +++ .../neemann/digital/gui/draw/model/Net.java | 3 + .../digital/gui/draw/shapes/DemuxerShape.java | 10 +- src/main/resources/lang/lang_de.properties | 7 +- src/main/resources/lang/lang_en.properties | 1 + .../digital/core/memory/CounterTest.java | 36 +++++++ .../digital/core/memory/DataFieldTest.java | 11 +++ .../digital/core/memory/RAMDualPortTest.java | 42 ++++++++ 16 files changed, 277 insertions(+), 119 deletions(-) create mode 100644 src/test/java/de/neemann/digital/core/memory/CounterTest.java create mode 100644 src/test/java/de/neemann/digital/core/memory/RAMDualPortTest.java diff --git a/src/main/dig/Ampel_Einfach.dig b/src/main/dig/Ampel_Einfach.dig index 9fd767583..d9ff8bde4 100644 --- a/src/main/dig/Ampel_Einfach.dig +++ b/src/main/dig/Ampel_Einfach.dig @@ -20,7 +20,7 @@ Z_1 - + 0 @@ -100,23 +100,31 @@ - - + + + + + + + + + + - + - + @@ -140,16 +148,12 @@ - - - - - + - + @@ -164,7 +168,7 @@ - + @@ -172,15 +176,11 @@ - - + + - - - - - + @@ -188,7 +188,11 @@ - + + + + + diff --git a/src/main/dig/Ampel_MSJK.dig b/src/main/dig/Ampel_MSJK.dig index 8cc03d444..beb22404f 100644 --- a/src/main/dig/Ampel_MSJK.dig +++ b/src/main/dig/Ampel_MSJK.dig @@ -10,7 +10,7 @@ Const - + 0 @@ -72,19 +72,19 @@ Clock - + 0 Or - + 0 Not - + 0 @@ -95,13 +95,13 @@ Feuer - + 0 MS-JK.dig - + 0 @@ -113,37 +113,37 @@ - - - - - + - + + + + + + + + + - - + + - - - - - - - - - + + + + + @@ -153,32 +153,36 @@ - - + + - - + + - - + + - - + + - + + + + + @@ -189,19 +193,19 @@ - + - + - - + + - + @@ -209,16 +213,20 @@ - - + + - + + + + + - - + + \ No newline at end of file diff --git a/src/main/dig/Ampel_TJK.dig b/src/main/dig/Ampel_TJK.dig index 21f802292..0393bb55f 100644 --- a/src/main/dig/Ampel_TJK.dig +++ b/src/main/dig/Ampel_TJK.dig @@ -10,7 +10,7 @@ Const - + 0 @@ -72,19 +72,19 @@ Clock - + 0 Or - + 0 Not - + 0 @@ -95,13 +95,13 @@ Feuer - + 0 T-JK.dig - + 0 @@ -113,37 +113,37 @@ - - - - - + - + + + + + + + + + - - + + - - - - - - - - - + + + + + @@ -153,32 +153,36 @@ - - + + - - + + - - + + - - + + - + + + + + @@ -189,19 +193,27 @@ - + - + + + + + - - + + - + + + + + @@ -209,16 +221,12 @@ - - + + - + - - - - \ No newline at end of file diff --git a/src/main/java/de/neemann/digital/core/ObservableValue.java b/src/main/java/de/neemann/digital/core/ObservableValue.java index f1385047e..0240d277f 100644 --- a/src/main/java/de/neemann/digital/core/ObservableValue.java +++ b/src/main/java/de/neemann/digital/core/ObservableValue.java @@ -12,6 +12,7 @@ public class ObservableValue extends Value { private final ArrayList observers; private final String name; private final long mask; + private final boolean supportsHighZ; public ObservableValue(String name, int bits) { this(name, bits, false); @@ -22,6 +23,7 @@ public class ObservableValue extends Value { mask = (1L << bits) - 1; this.name = name; observers = new ArrayList<>(); + supportsHighZ = highZ; } public ObservableValue addObserver(Observer observer) { @@ -137,4 +139,16 @@ public class ObservableValue extends Value { public int observerCount() { return observers.size(); } + + public boolean supportsHighZ() { + return supportsHighZ; + } + + public boolean isHighZIgnoreBurn() { + return highZ; + } + + public long getValueIgnoreBurn() { + return value; + } } diff --git a/src/main/java/de/neemann/digital/core/memory/DataField.java b/src/main/java/de/neemann/digital/core/memory/DataField.java index f7c45d80f..aad49c1e0 100644 --- a/src/main/java/de/neemann/digital/core/memory/DataField.java +++ b/src/main/java/de/neemann/digital/core/memory/DataField.java @@ -2,10 +2,7 @@ package de.neemann.digital.core.memory; import de.neemann.digital.lang.Lang; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; +import java.io.*; import java.util.Arrays; /** @@ -32,7 +29,11 @@ public class DataField { } public DataField(File file) throws IOException { - try (BufferedReader br = new BufferedReader(new FileReader(file))) { + this(new FileReader(file)); + } + + public DataField(Reader reader) throws IOException { + try (BufferedReader br = new BufferedReader(reader)) { data = new long[1024]; String header = br.readLine(); if (header == null || !header.equals("v2.0 raw")) diff --git a/src/main/java/de/neemann/digital/core/wiring/DataBus.java b/src/main/java/de/neemann/digital/core/wiring/DataBus.java index 4254f0bf1..4864d1bf7 100644 --- a/src/main/java/de/neemann/digital/core/wiring/DataBus.java +++ b/src/main/java/de/neemann/digital/core/wiring/DataBus.java @@ -36,6 +36,8 @@ public class DataBus { if (bits != b) throw new PinException(Lang.get("err_notAllOutputsSameBits"), net); } + if (!o.supportsHighZ()) + throw new PinException(Lang.get("err_notAllOutputsSupportHighZ"), net); } commonOut = new CommonObservableValue(bits); diff --git a/src/main/java/de/neemann/digital/gui/draw/elements/Pin.java b/src/main/java/de/neemann/digital/gui/draw/elements/Pin.java index 8e8fd0f7e..a41771e93 100644 --- a/src/main/java/de/neemann/digital/gui/draw/elements/Pin.java +++ b/src/main/java/de/neemann/digital/gui/draw/elements/Pin.java @@ -13,6 +13,7 @@ public class Pin { private final String name; private final Direction direction; private ObservableValue value; + private ObservableValue readerValue; // reader for bidirectional pins public Pin(Vector pos, Pin pin) { this(pos, pin.name, pin.direction); @@ -44,5 +45,13 @@ public class Pin { this.value = value; } + public ObservableValue getReaderValue() { + return readerValue; + } + + public void setReaderValue(ObservableValue readerValue) { + this.readerValue = readerValue; + } + public enum Direction {input, output, both} } diff --git a/src/main/java/de/neemann/digital/gui/draw/graphics/Style.java b/src/main/java/de/neemann/digital/gui/draw/graphics/Style.java index ec04c79d5..aa031fdff 100644 --- a/src/main/java/de/neemann/digital/gui/draw/graphics/Style.java +++ b/src/main/java/de/neemann/digital/gui/draw/graphics/Style.java @@ -67,9 +67,9 @@ public class Style { public static Style getWireStyle(ObservableValue value) { if (value == null || value.getBits() > 1) return WIRE; - if (value.isHighZ()) return WIRE_HIGHZ; + if (value.isHighZIgnoreBurn()) return WIRE_HIGHZ; - if (value.getValue() == 1) return WIRE_HIGH; + if (value.getValueIgnoreBurn() == 1) return WIRE_HIGH; else return WIRE_LOW; } } diff --git a/src/main/java/de/neemann/digital/gui/draw/model/ModelEntry.java b/src/main/java/de/neemann/digital/gui/draw/model/ModelEntry.java index 1f72ac121..bd06beec6 100644 --- a/src/main/java/de/neemann/digital/gui/draw/model/ModelEntry.java +++ b/src/main/java/de/neemann/digital/gui/draw/model/ModelEntry.java @@ -4,9 +4,11 @@ import de.neemann.digital.core.NodeException; import de.neemann.digital.core.ObservableValue; import de.neemann.digital.core.Observer; import de.neemann.digital.core.element.Element; +import de.neemann.digital.core.wiring.Splitter; import de.neemann.digital.gui.draw.elements.*; import de.neemann.digital.lang.Lang; +import java.util.ArrayList; import java.util.HashMap; /** @@ -48,6 +50,18 @@ public class ModelEntry { inputs[i] = value; } + + ArrayList bidirect = null; + for (Pin p : pins) { + if (p.getDirection() == Pin.Direction.both) { + if (bidirect == null) + bidirect = new ArrayList<>(); + bidirect.add(p.getReaderValue()); + } + } + if (bidirect != null) + inputs = Splitter.combine(inputs, bidirect.toArray(new ObservableValue[bidirect.size()])); + element.setInputs(inputs); } ioState = new IOState(inputs, element.getOutputs()); diff --git a/src/main/java/de/neemann/digital/gui/draw/model/Net.java b/src/main/java/de/neemann/digital/gui/draw/model/Net.java index 380cd0bf3..c767337d0 100644 --- a/src/main/java/de/neemann/digital/gui/draw/model/Net.java +++ b/src/main/java/de/neemann/digital/gui/draw/model/Net.java @@ -97,6 +97,9 @@ public class Net { for (Pin i : inputs) i.setValue(value); + for (Pin o : outputs) // set also the reader for bidirectional pins + o.setReaderValue(value); + if (bindWiresToValues && wires != null) for (Wire w : wires) w.setValue(value); diff --git a/src/main/java/de/neemann/digital/gui/draw/shapes/DemuxerShape.java b/src/main/java/de/neemann/digital/gui/draw/shapes/DemuxerShape.java index 05c4434ab..671da713d 100644 --- a/src/main/java/de/neemann/digital/gui/draw/shapes/DemuxerShape.java +++ b/src/main/java/de/neemann/digital/gui/draw/shapes/DemuxerShape.java @@ -18,19 +18,21 @@ public class DemuxerShape implements Shape { private final int outputCount; private final boolean hasInput; private final boolean flip; + private final int height; private Pins pins; public DemuxerShape(int selectorBits, boolean hasInput, boolean flip) { this.hasInput = hasInput; this.flip = flip; - this.outputCount = 1 << selectorBits; + outputCount = 1 << selectorBits; + height = hasInput || (outputCount <= 2) ? outputCount * SIZE : (outputCount - 1) * SIZE; } @Override public Pins getPins() { if (pins == null) { pins = new Pins(); - pins.add(new Pin(new Vector(SIZE, flip ? 0 : outputCount * SIZE), "sel", Pin.Direction.input)); + pins.add(new Pin(new Vector(SIZE, flip ? 0 : height), "sel", Pin.Direction.input)); if (outputCount == 2) { pins.add(new Pin(new Vector(SIZE * 2, 0 * SIZE), "out_0", Pin.Direction.output)); pins.add(new Pin(new Vector(SIZE * 2, 2 * SIZE), "out_1", Pin.Direction.output)); @@ -54,7 +56,7 @@ public class DemuxerShape implements Shape { graphic.drawPolygon(new Polygon(true) .add(2, 3) .add(SIZE * 2 - 2, -2) - .add(SIZE * 2 - 2, outputCount * SIZE + 2) - .add(2, outputCount * SIZE - 3), Style.NORMAL); + .add(SIZE * 2 - 2, height + 2) + .add(2, height - 3), Style.NORMAL); } } diff --git a/src/main/resources/lang/lang_de.properties b/src/main/resources/lang/lang_de.properties index dffeb4155..d00375758 100644 --- a/src/main/resources/lang/lang_de.properties +++ b/src/main/resources/lang/lang_de.properties @@ -50,12 +50,15 @@ err_duplicateElement_N=Doppeltes Element {0} err_element_N_notFound=Element {0} nicht gefunden err_spitterDefSyntaxError=Fehler in der Definition {0} eines Splitters err_noShapeFoundFor_N=Es wurde kein Diagramm für {0} gefunden. +err_invalidFileFormat=Ung\u00FCltiges Dateiformat err_readOfHighZ=Lesen einer hochohmigen Leitung +err_notAllOutputsSameBits=Es haben nicht alle Ausg\u00E4nge die gleiche Bitbreite +err_notAllOutputsSupportHighZ=Wenn mehrere Ausg\u00E4nge verbunden sind, m\u00FCssen alle Tri-State Ausg\u00E4nge sein attr_dialogTitle=Eigenschaften msg_errorEditingValue=Fehler bei der Eingabe eines Wertes msg_color=Farbe -msg_errorImportingModel=Fehler beim Import eins Modells -msg_errorCreatingModel=Fehler beim Erzeugen eines Modells +msg_errorImportingModel=Fehler beim Import eines Modells +msg_errorCreatingModel=Fehler beim Erzeugen des Modells msg_errorWritingFile=Fehler beim Schreiben einer Datei msg_errorReadingFile=Fehler beim Lesen einer Datei msg_errorCalculatingStep=Fehler beim Berechnen eines Schrittes diff --git a/src/main/resources/lang/lang_en.properties b/src/main/resources/lang/lang_en.properties index 6ec628f90..40fdda999 100644 --- a/src/main/resources/lang/lang_en.properties +++ b/src/main/resources/lang/lang_en.properties @@ -53,6 +53,7 @@ err_noShapeFoundFor_N=No shape found for Element {0} err_invalidFileFormat=Invalid file format err_readOfHighZ=Read of high Z value err_notAllOutputsSameBits=Not all connected outputs have the same bit count +err_notAllOutputsSupportHighZ=If multiple outputs are connected together, all of them have to be three-state outputs attr_dialogTitle=Attributes msg_errorEditingValue=Error editing a atribute value msg_color=Color diff --git a/src/test/java/de/neemann/digital/core/memory/CounterTest.java b/src/test/java/de/neemann/digital/core/memory/CounterTest.java new file mode 100644 index 000000000..db93f07cd --- /dev/null +++ b/src/test/java/de/neemann/digital/core/memory/CounterTest.java @@ -0,0 +1,36 @@ +package de.neemann.digital.core.memory; + +import de.neemann.digital.TestExecuter; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.element.ElementAttributes; +import junit.framework.TestCase; + +/** + * @author hneemann + */ +public class CounterTest extends TestCase { + + public void testCounter() throws Exception { + ObservableValue clk = new ObservableValue("clk", 1); + ObservableValue clr = new ObservableValue("clr", 1); + + Model model = new Model(); + Counter out = model.add(new Counter( + new ElementAttributes() + .setBits(8))); + out.setInputs(clk, clr); + + TestExecuter sc = new TestExecuter(model).setInputs(clk, clr).setOutputs(out.getOutputs()); + sc.check(0, 0, 0); + sc.check(1, 0, 1); + sc.check(0, 0, 1); + sc.check(1, 0, 2); + sc.check(0, 0, 2); + sc.check(1, 0, 3); + sc.check(0, 0, 3); + sc.check(0, 1, 0); + } + + +} \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/core/memory/DataFieldTest.java b/src/test/java/de/neemann/digital/core/memory/DataFieldTest.java index 34d960ded..87c87ddb0 100644 --- a/src/test/java/de/neemann/digital/core/memory/DataFieldTest.java +++ b/src/test/java/de/neemann/digital/core/memory/DataFieldTest.java @@ -2,6 +2,8 @@ package de.neemann.digital.core.memory; import junit.framework.TestCase; +import java.io.StringReader; + /** * @author hneemann */ @@ -25,4 +27,13 @@ public class DataFieldTest extends TestCase { assertEquals(1, data.getData(30)); } + public void testLoad() throws Exception { + String data = "v2.0 raw\n0\n10\nAA\nFF"; + DataField df = new DataField(new StringReader(data)); + assertEquals(4, df.size()); + assertEquals(0x00, df.getData(0)); + assertEquals(0x10, df.getData(1)); + assertEquals(0xAA, df.getData(2)); + assertEquals(0xFF, df.getData(3)); + } } \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/core/memory/RAMDualPortTest.java b/src/test/java/de/neemann/digital/core/memory/RAMDualPortTest.java new file mode 100644 index 000000000..4846fcd4b --- /dev/null +++ b/src/test/java/de/neemann/digital/core/memory/RAMDualPortTest.java @@ -0,0 +1,42 @@ +package de.neemann.digital.core.memory; + +import de.neemann.digital.TestExecuter; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.element.AttributeKey; +import de.neemann.digital.core.element.ElementAttributes; +import junit.framework.TestCase; + +import static de.neemann.digital.TestExecuter.HIGHZ; + +/** + * @author hneemann + */ +public class RAMDualPortTest extends TestCase { + + public void testRAM() throws Exception { + ObservableValue a = new ObservableValue("a", 4); + ObservableValue d = new ObservableValue("d", 4); + ObservableValue str = new ObservableValue("str", 1); + ObservableValue clk = new ObservableValue("clk", 1); + ObservableValue ld = new ObservableValue("ld", 1); + + Model model = new Model(); + RAMDualPort out = model.add(new RAMDualPort( + new ElementAttributes() + .set(AttributeKey.AddrBits, 4) + .setBits(4))); + out.setInputs(a, d, str, clk, ld); + + TestExecuter sc = new TestExecuter(model).setInputs(a, d, str, clk, ld).setOutputs(out.getOutputs()); + // A D ST C LD + sc.check(0, 0, 0, 0, 0, HIGHZ); // def + sc.check(0, 5, 1, 1, 0, HIGHZ); // st 0->5 + sc.check(0, 0, 0, 0, 0, HIGHZ); // def + sc.check(1, 9, 1, 1, 0, HIGHZ); // st 1->9 + sc.check(0, 0, 0, 0, 1, 5); // rd 5 + sc.check(1, 0, 0, 0, 1, 9); // rd 5 + } + + +} \ No newline at end of file