if high-z values are used, random bits are created

This commit is contained in:
hneemann 2020-11-17 20:51:49 +01:00
parent f7b1113a3f
commit 8ee40a3d49
7 changed files with 55 additions and 23 deletions

View File

@ -519,9 +519,9 @@ in der Speichermatrix gespeichert.}}</string>
# 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

View File

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

View File

@ -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()) {

View File

@ -336,8 +336,7 @@
<string name="elem_VDD_pin_out">Dieser Ausgang gibt immer 1 aus.</string>
<string name="elem_NotConnected">Nicht verbunden</string>
<string name="elem_NotConnected_tt">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.</string>

View File

@ -333,7 +333,7 @@
<string name="elem_VDD_pin_out">This output always returns 1.</string>
<string name="elem_NotConnected">Not Connected</string>
<string name="elem_NotConnected_tt">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.</string>

View File

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

View File

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