diff --git a/src/main/dig/cmos/sram.dig b/src/main/dig/cmos/sram.dig
index 43c62188b..0b8fd8a8a 100644
--- a/src/main/dig/cmos/sram.dig
+++ b/src/main/dig/cmos/sram.dig
@@ -519,9 +519,9 @@ in der Speichermatrix gespeichert.}}
# write all cells to one
loop(n,16)
-bits(4,n) 0 1 0
-bits(4,n) 1 1 1
-bits(4,n) 0 1 1
+bits(4,n) 0 1 x
+bits(4,n) 1 1 x
+bits(4,n) 0 1 x
end loop
# check all cells are one
diff --git a/src/main/java/de/neemann/digital/core/ObservableValue.java b/src/main/java/de/neemann/digital/core/ObservableValue.java
index f6f2bbf52..59828cc59 100644
--- a/src/main/java/de/neemann/digital/core/ObservableValue.java
+++ b/src/main/java/de/neemann/digital/core/ObservableValue.java
@@ -9,6 +9,8 @@ import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.PinDescription;
import de.neemann.digital.lang.Lang;
+import java.util.Random;
+
/**
* Represents all signal values in the simulator.
* There are some setters to set the value. Each bit of a value can be set to high z state.
@@ -29,6 +31,8 @@ public class ObservableValue extends Observable implements PinDescription {
private String description;
private String pinNumber;
private boolean isSwitchPin;
+ // used to create random bits if high-z values are read
+ private Random random;
/**
* Creates a new instance.
@@ -122,11 +126,27 @@ public class ObservableValue extends Observable implements PinDescription {
}
/**
- * returns the actual value
+ * Returns the current value.
+ * The high-z bits are set to a random value.
*
* @return the value
*/
public long getValue() {
+ if (highZ != 0) {
+ if (random == null)
+ random = new Random();
+ return value | (random.nextLong() & highZ);
+ } else
+ return value;
+ }
+
+ /**
+ * Returns the current value
+ * The high-z bits are set to zero
+ *
+ * @return the value
+ */
+ public long getValueHighZIsZero() {
return value;
}
diff --git a/src/main/java/de/neemann/digital/core/wiring/bus/AbstractBusHandler.java b/src/main/java/de/neemann/digital/core/wiring/bus/AbstractBusHandler.java
index ec8720160..430054642 100644
--- a/src/main/java/de/neemann/digital/core/wiring/bus/AbstractBusHandler.java
+++ b/src/main/java/de/neemann/digital/core/wiring/bus/AbstractBusHandler.java
@@ -81,14 +81,16 @@ public abstract class AbstractBusHandler {
long highz = -1;
for (ObservableValue input : getInputs()) {
highz &= input.getHighZ();
- value |= input.getValue();
+ value |= input.getValueHighZIsZero();
}
// check for a burn condition!
for (ObservableValue input : getInputs()) {
long bothDefine = ~(highz | input.getHighZ());
- if ((value & bothDefine) != (input.getValue() & bothDefine))
+ if ((value & bothDefine) != (input.getValueHighZIsZero() & bothDefine)) {
burn = State.burn;
+ break;
+ }
}
switch (getResistor()) {
diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml
index 6a67af8c6..3ad04bfb4 100644
--- a/src/main/resources/lang/lang_de.xml
+++ b/src/main/resources/lang/lang_de.xml
@@ -336,8 +336,7 @@
Dieser Ausgang gibt immer 1 aus.
Nicht verbunden
Dieses Element kann verwendet werden, um eine Leitung auf High-Z zu
- legen. Wird ein Eingang eines Gatters auf High-Z gesetzt, wird dieser Wert vom Simulator wie Null
- interpretiert.
+ legen. Wird ein Eingang eines logischen Gatters auf High-Z gesetzt, ist der gelesene Wert undefiniert.
Zu beachten ist, dass es in der Realität in vielen Fällen zu überhöhter Stromaufnahme und gar zu
Beschädigungen kommen kann, wenn ein Digitaleingang nicht auf Null oder Eins gesetzt wird, sondern
unbeschaltet bleibt. Daher sollte dies Element mit Bedacht eingesetzt werden.
diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml
index 0b9ea195a..bacd3ea54 100644
--- a/src/main/resources/lang/lang_en.xml
+++ b/src/main/resources/lang/lang_en.xml
@@ -333,7 +333,7 @@
This output always returns 1.
Not Connected
This component can be used to set a line to High-Z.
- If an input of a gate is set to High-Z, the simulator interprets this value as zero.
+ If an input of a logical gate is set to high-Z, the read value is undefined.
Note that in reality in many cases excessive current consumption and even damage can
occur if a digital input is not set to zero or one but remains unconnected.
Therefore this element should be used with care.
diff --git a/src/test/java/de/neemann/digital/core/ObservableValueTest.java b/src/test/java/de/neemann/digital/core/ObservableValueTest.java
index c28956e0d..1fb975f2f 100644
--- a/src/test/java/de/neemann/digital/core/ObservableValueTest.java
+++ b/src/test/java/de/neemann/digital/core/ObservableValueTest.java
@@ -9,6 +9,7 @@ import junit.framework.Assert;
import junit.framework.TestCase;
/**
+ *
*/
public class ObservableValueTest extends TestCase {
@@ -52,13 +53,22 @@ public class ObservableValueTest extends TestCase {
public void testHighZ() {
ObservableValue v = new ObservableValue("z", 4);
- check(0, 15, v.set(15, 15));
check(14, 1, v.set(15, 1));
check(12, 3, v.set(15, 3));
+
+ v.set(15, 15);
+ long min = 15;
+ long max = 0;
+ for (int i = 0; i < 100; i++) {
+ long val = v.getValue();
+ if (val < min) min = val;
+ if (val > max) max = val;
+ }
+ assertTrue(max - min > 8);
}
private void check(long val, long z, ObservableValue v) {
- assertEquals(val, v.getValue());
+ assertEquals(val, v.getValue() & ~z);
assertEquals(z, v.getHighZ());
}
@@ -66,10 +76,10 @@ public class ObservableValueTest extends TestCase {
ObservableValue v = new ObservableValue("z", 4)
.setToHighZ()
.addObserverToValue(Assert::fail);
- v.set(0,15);
- v.set(1,15);
- v.set(2,15);
- v.set(3,15);
+ v.set(0, 15);
+ v.set(1, 15);
+ v.set(2, 15);
+ v.set(3, 15);
}
public void testChange() {
@@ -91,12 +101,12 @@ public class ObservableValueTest extends TestCase {
@Override
public void hasChanged() {
- changed=true;
+ changed = true;
}
private boolean isChanged() {
final boolean c = changed;
- changed=false;
+ changed = false;
return c;
}
}
diff --git a/src/test/java/de/neemann/digital/core/wiring/BusSplitterTest.java b/src/test/java/de/neemann/digital/core/wiring/BusSplitterTest.java
index e680ba954..f031c18a1 100644
--- a/src/test/java/de/neemann/digital/core/wiring/BusSplitterTest.java
+++ b/src/test/java/de/neemann/digital/core/wiring/BusSplitterTest.java
@@ -11,6 +11,7 @@ import de.neemann.digital.core.ObservableValue;
import de.neemann.digital.core.element.ElementAttributes;
import junit.framework.TestCase;
+import static de.neemann.digital.TestExecuter.IGNORE;
import static de.neemann.digital.core.ObservableValues.ovs;
public class BusSplitterTest extends TestCase {
@@ -30,12 +31,12 @@ public class BusSplitterTest extends TestCase {
TestExecuter te = new TestExecuter(model).setInputs(oe, d, d0, d1, d2, d3).setOutputs(out.getOutputs());
- te.check(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- te.check(1, 5, 0, 0, 0, 0, 0, 1, 0, 1, 0);
- te.check(1, 15, 0, 0, 0, 0, 0, 1, 1, 1, 1);
- te.check(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- te.check(0, 0, 1, 0, 1, 0, 5, 0, 0, 0, 0);
- te.check(0, 0, 1, 1, 1, 1, 15, 0, 0, 0, 0);
+ te.checkZ(1, 0, 0, 0, 0, 0, IGNORE, 0, 0, 0, 0);
+ te.checkZ(1, 5, 0, 0, 0, 0, IGNORE, 1, 0, 1, 0);
+ te.checkZ(1, 15, 0, 0, 0, 0, IGNORE, 1, 1, 1, 1);
+ te.checkZ(0, 0, 0, 0, 0, 0, 0, IGNORE, IGNORE, IGNORE, IGNORE);
+ te.checkZ(0, 0, 1, 0, 1, 0, 5, IGNORE, IGNORE, IGNORE, IGNORE);
+ te.checkZ(0, 0, 1, 1, 1, 1, 15, IGNORE, IGNORE, IGNORE, IGNORE);
}
}