added better multipla output detection, added support for bidirectional pins

This commit is contained in:
hneemann 2016-03-27 10:48:41 +02:00
parent aef075ca00
commit ed015c16af
16 changed files with 277 additions and 119 deletions

View File

@ -20,7 +20,7 @@
<string>Z_1</string>
</entry>
</elementAttributes>
<pos x="240" y="140"/>
<pos x="240" y="130"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -100,23 +100,31 @@
</visualElements>
<wires>
<wire>
<p1 x="230" y="160"/>
<p2 x="240" y="160"/>
<p1 x="210" y="210"/>
<p2 x="230" y="210"/>
</wire>
<wire>
<p1 x="230" y="210"/>
<p2 x="240" y="210"/>
</wire>
<wire>
<p1 x="230" y="130"/>
<p2 x="240" y="130"/>
</wire>
<wire>
<p1 x="270" y="130"/>
<p2 x="290" y="130"/>
</wire>
<wire>
<p1 x="290" y="180"/>
<p2 x="300" y="180"/>
</wire>
<wire>
<p1 x="220" y="150"/>
<p1 x="230" y="150"/>
<p2 x="240" y="150"/>
</wire>
<wire>
<p1 x="270" y="150"/>
<p1 x="280" y="150"/>
<p2 x="350" y="150"/>
</wire>
<wire>
@ -140,16 +148,12 @@
<p2 x="350" y="170"/>
</wire>
<wire>
<p1 x="210" y="210"/>
<p2 x="230" y="210"/>
</wire>
<wire>
<p1 x="230" y="140"/>
<p1 x="220" y="140"/>
<p2 x="240" y="140"/>
</wire>
<wire>
<p1 x="270" y="140"/>
<p2 x="290" y="140"/>
<p2 x="280" y="140"/>
</wire>
<wire>
<p1 x="230" y="190"/>
@ -164,7 +168,7 @@
<p2 x="350" y="190"/>
</wire>
<wire>
<p1 x="290" y="140"/>
<p1 x="290" y="130"/>
<p2 x="290" y="180"/>
</wire>
<wire>
@ -172,15 +176,11 @@
<p2 x="230" y="210"/>
</wire>
<wire>
<p1 x="230" y="140"/>
<p2 x="230" y="160"/>
<p1 x="230" y="130"/>
<p2 x="230" y="150"/>
</wire>
<wire>
<p1 x="230" y="210"/>
<p2 x="230" y="210"/>
</wire>
<wire>
<p1 x="230" y="160"/>
<p1 x="230" y="150"/>
<p2 x="230" y="170"/>
</wire>
<wire>
@ -188,7 +188,11 @@
<p2 x="280" y="190"/>
</wire>
<wire>
<p1 x="220" y="150"/>
<p1 x="280" y="140"/>
<p2 x="280" y="150"/>
</wire>
<wire>
<p1 x="220" y="140"/>
<p2 x="220" y="170"/>
</wire>
<wire>

View File

@ -10,7 +10,7 @@
<visualElement>
<elementName>Const</elementName>
<elementAttributes/>
<pos x="210" y="210"/>
<pos x="220" y="210"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -72,19 +72,19 @@
<string>Clock</string>
</entry>
</elementAttributes>
<pos x="200" y="150"/>
<pos x="130" y="140"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Or</elementName>
<elementAttributes/>
<pos x="150" y="180"/>
<pos x="170" y="180"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Not</elementName>
<elementAttributes/>
<pos x="120" y="200"/>
<pos x="140" y="200"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -95,13 +95,13 @@
<string>Feuer</string>
</entry>
</elementAttributes>
<pos x="110" y="200"/>
<pos x="130" y="200"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>MS-JK.dig</elementName>
<elementAttributes/>
<pos x="240" y="140"/>
<pos x="240" y="130"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -113,37 +113,37 @@
</visualElements>
<wires>
<wire>
<p1 x="230" y="160"/>
<p2 x="240" y="160"/>
</wire>
<wire>
<p1 x="210" y="210"/>
<p1 x="220" y="210"/>
<p2 x="240" y="210"/>
</wire>
<wire>
<p1 x="200" y="180"/>
<p1 x="230" y="130"/>
<p2 x="240" y="130"/>
</wire>
<wire>
<p1 x="270" y="130"/>
<p2 x="290" y="130"/>
</wire>
<wire>
<p1 x="210" y="180"/>
<p2 x="290" y="180"/>
</wire>
<wire>
<p1 x="140" y="180"/>
<p2 x="150" y="180"/>
<p1 x="160" y="180"/>
<p2 x="170" y="180"/>
</wire>
<wire>
<p1 x="290" y="180"/>
<p2 x="300" y="180"/>
</wire>
<wire>
<p1 x="200" y="150"/>
<p2 x="220" y="150"/>
</wire>
<wire>
<p1 x="270" y="150"/>
<p2 x="350" y="150"/>
</wire>
<wire>
<p1 x="220" y="150"/>
<p1 x="230" y="150"/>
<p2 x="240" y="150"/>
</wire>
<wire>
<p1 x="280" y="150"/>
<p2 x="350" y="150"/>
</wire>
<wire>
<p1 x="270" y="200"/>
<p2 x="300" y="200"/>
@ -153,32 +153,36 @@
<p2 x="240" y="200"/>
</wire>
<wire>
<p1 x="110" y="200"/>
<p2 x="120" y="200"/>
<p1 x="130" y="200"/>
<p2 x="140" y="200"/>
</wire>
<wire>
<p1 x="140" y="200"/>
<p2 x="150" y="200"/>
<p1 x="160" y="200"/>
<p2 x="170" y="200"/>
</wire>
<wire>
<p1 x="230" y="170"/>
<p2 x="280" y="170"/>
</wire>
<wire>
<p1 x="140" y="170"/>
<p2 x="200" y="170"/>
<p1 x="160" y="170"/>
<p2 x="210" y="170"/>
</wire>
<wire>
<p1 x="280" y="170"/>
<p2 x="350" y="170"/>
</wire>
<wire>
<p1 x="230" y="140"/>
<p2 x="240" y="140"/>
<p1 x="130" y="140"/>
<p2 x="220" y="140"/>
</wire>
<wire>
<p1 x="270" y="140"/>
<p2 x="290" y="140"/>
<p2 x="280" y="140"/>
</wire>
<wire>
<p1 x="220" y="140"/>
<p2 x="240" y="140"/>
</wire>
<wire>
<p1 x="270" y="190"/>
@ -189,19 +193,19 @@
<p2 x="350" y="190"/>
</wire>
<wire>
<p1 x="180" y="190"/>
<p1 x="200" y="190"/>
<p2 x="240" y="190"/>
</wire>
<wire>
<p1 x="290" y="140"/>
<p1 x="290" y="130"/>
<p2 x="290" y="180"/>
</wire>
<wire>
<p1 x="230" y="140"/>
<p2 x="230" y="160"/>
<p1 x="230" y="130"/>
<p2 x="230" y="150"/>
</wire>
<wire>
<p1 x="230" y="160"/>
<p1 x="230" y="150"/>
<p2 x="230" y="170"/>
</wire>
<wire>
@ -209,16 +213,20 @@
<p2 x="280" y="190"/>
</wire>
<wire>
<p1 x="200" y="170"/>
<p2 x="200" y="180"/>
<p1 x="280" y="140"/>
<p2 x="280" y="150"/>
</wire>
<wire>
<p1 x="220" y="150"/>
<p1 x="210" y="170"/>
<p2 x="210" y="180"/>
</wire>
<wire>
<p1 x="220" y="140"/>
<p2 x="220" y="200"/>
</wire>
<wire>
<p1 x="140" y="170"/>
<p2 x="140" y="180"/>
<p1 x="160" y="170"/>
<p2 x="160" y="180"/>
</wire>
</wires>
</circuit>

View File

@ -10,7 +10,7 @@
<visualElement>
<elementName>Const</elementName>
<elementAttributes/>
<pos x="210" y="210"/>
<pos x="220" y="210"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -72,19 +72,19 @@
<string>Clock</string>
</entry>
</elementAttributes>
<pos x="200" y="150"/>
<pos x="200" y="140"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Or</elementName>
<elementAttributes/>
<pos x="150" y="180"/>
<pos x="170" y="180"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Not</elementName>
<elementAttributes/>
<pos x="120" y="200"/>
<pos x="140" y="200"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -95,13 +95,13 @@
<string>Feuer</string>
</entry>
</elementAttributes>
<pos x="110" y="200"/>
<pos x="130" y="200"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>T-JK.dig</elementName>
<elementAttributes/>
<pos x="240" y="140"/>
<pos x="240" y="130"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -113,37 +113,37 @@
</visualElements>
<wires>
<wire>
<p1 x="230" y="160"/>
<p2 x="240" y="160"/>
</wire>
<wire>
<p1 x="210" y="210"/>
<p1 x="220" y="210"/>
<p2 x="240" y="210"/>
</wire>
<wire>
<p1 x="200" y="180"/>
<p1 x="230" y="130"/>
<p2 x="240" y="130"/>
</wire>
<wire>
<p1 x="270" y="130"/>
<p2 x="290" y="130"/>
</wire>
<wire>
<p1 x="210" y="180"/>
<p2 x="290" y="180"/>
</wire>
<wire>
<p1 x="140" y="180"/>
<p2 x="150" y="180"/>
<p1 x="160" y="180"/>
<p2 x="170" y="180"/>
</wire>
<wire>
<p1 x="290" y="180"/>
<p2 x="300" y="180"/>
</wire>
<wire>
<p1 x="200" y="150"/>
<p2 x="220" y="150"/>
</wire>
<wire>
<p1 x="270" y="150"/>
<p2 x="350" y="150"/>
</wire>
<wire>
<p1 x="220" y="150"/>
<p1 x="230" y="150"/>
<p2 x="240" y="150"/>
</wire>
<wire>
<p1 x="280" y="150"/>
<p2 x="350" y="150"/>
</wire>
<wire>
<p1 x="270" y="200"/>
<p2 x="300" y="200"/>
@ -153,32 +153,36 @@
<p2 x="240" y="200"/>
</wire>
<wire>
<p1 x="110" y="200"/>
<p2 x="120" y="200"/>
<p1 x="130" y="200"/>
<p2 x="140" y="200"/>
</wire>
<wire>
<p1 x="140" y="200"/>
<p2 x="150" y="200"/>
<p1 x="160" y="200"/>
<p2 x="170" y="200"/>
</wire>
<wire>
<p1 x="230" y="170"/>
<p2 x="280" y="170"/>
</wire>
<wire>
<p1 x="140" y="170"/>
<p2 x="200" y="170"/>
<p1 x="160" y="170"/>
<p2 x="210" y="170"/>
</wire>
<wire>
<p1 x="280" y="170"/>
<p2 x="350" y="170"/>
</wire>
<wire>
<p1 x="230" y="140"/>
<p2 x="240" y="140"/>
<p1 x="200" y="140"/>
<p2 x="220" y="140"/>
</wire>
<wire>
<p1 x="270" y="140"/>
<p2 x="290" y="140"/>
<p2 x="280" y="140"/>
</wire>
<wire>
<p1 x="220" y="140"/>
<p2 x="240" y="140"/>
</wire>
<wire>
<p1 x="270" y="190"/>
@ -189,19 +193,27 @@
<p2 x="350" y="190"/>
</wire>
<wire>
<p1 x="180" y="190"/>
<p1 x="200" y="190"/>
<p2 x="240" y="190"/>
</wire>
<wire>
<p1 x="290" y="140"/>
<p1 x="160" y="170"/>
<p2 x="160" y="180"/>
</wire>
<wire>
<p1 x="290" y="130"/>
<p2 x="290" y="180"/>
</wire>
<wire>
<p1 x="230" y="140"/>
<p2 x="230" y="160"/>
<p1 x="210" y="170"/>
<p2 x="210" y="180"/>
</wire>
<wire>
<p1 x="230" y="160"/>
<p1 x="230" y="130"/>
<p2 x="230" y="150"/>
</wire>
<wire>
<p1 x="230" y="150"/>
<p2 x="230" y="170"/>
</wire>
<wire>
@ -209,16 +221,12 @@
<p2 x="280" y="190"/>
</wire>
<wire>
<p1 x="200" y="170"/>
<p2 x="200" y="180"/>
<p1 x="280" y="140"/>
<p2 x="280" y="150"/>
</wire>
<wire>
<p1 x="220" y="150"/>
<p1 x="220" y="140"/>
<p2 x="220" y="200"/>
</wire>
<wire>
<p1 x="140" y="170"/>
<p2 x="140" y="180"/>
</wire>
</wires>
</circuit>

View File

@ -12,6 +12,7 @@ public class ObservableValue extends Value {
private final ArrayList<Observer> 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;
}
}

View File

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

View File

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

View File

@ -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}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -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
}
}