diff --git a/src/main/java/de/neemann/digital/core/ObservableValue.java b/src/main/java/de/neemann/digital/core/ObservableValue.java index 56cb85336..4cd0000bc 100644 --- a/src/main/java/de/neemann/digital/core/ObservableValue.java +++ b/src/main/java/de/neemann/digital/core/ObservableValue.java @@ -16,6 +16,7 @@ public class ObservableValue extends Observable implements PinDescription { private long value; private boolean highZ; private boolean bidirectional; + private boolean isConstant = false; private String description; /** @@ -47,43 +48,52 @@ public class ObservableValue extends Observable implements PinDescription { supportsHighZ = highZ; } + /** - * Sets the value and fires a event if value has changed. + * Makes this value a constant value + */ + public void setConstant() { + isConstant = true; + } + + /** + * @return true if this value is a constant + */ + public boolean isConstant() { + return isConstant; + } + + /** + * Sets the value and fires an event if value has changed. + * Also sets this value to low Z * * @param value the new value * @return this for chained calls */ public ObservableValue setValue(long value) { - value = getValueBits(value); - if (this.value != value) { - this.value = value; - if (!highZ) - fireHasChanged(); - } + set(value, false); return this; } /** - * Sets the highZ state of this value - * - * @param highZ the new highZ state - */ - public void setHighZ(boolean highZ) { - if (this.highZ != highZ) { - this.highZ = highZ; - fireHasChanged(); - } - } - - /** - * Sets the value and highZ state + * Sets the value and highZ state and fires an event if value has changed. * * @param value the value * @param highZ highZ state + * @return this for chained calls */ - public void set(long value, boolean highZ) { - setValue(value); - setHighZ(highZ); + public ObservableValue set(long value, boolean highZ) { + value = getValueBits(value); + if (highZ != this.highZ || (!highZ && (value != this.value))) { + + if (isConstant) + throw new RuntimeException("tried to modify a constant value!"); + + this.highZ = highZ; + this.value = value; + fireHasChanged(); + } + return this; } /** @@ -243,21 +253,13 @@ public class ObservableValue extends Observable implements PinDescription { /** * Makes this value a bidirectional value. * - * @param bidirectional true if value is bidirectional * @return this for chained calls */ - public ObservableValue setBidirectional(boolean bidirectional) { - this.bidirectional = bidirectional; + public ObservableValue setBidirectional() { + this.bidirectional = true; return this; } - /** - * @return true if value is bidirectional - */ - public boolean isBidirectional() { - return bidirectional; - } - @Override public String getDescription() { if (description != null) diff --git a/src/main/java/de/neemann/digital/core/io/Const.java b/src/main/java/de/neemann/digital/core/io/Const.java index 1940f02f8..e4920dffb 100644 --- a/src/main/java/de/neemann/digital/core/io/Const.java +++ b/src/main/java/de/neemann/digital/core/io/Const.java @@ -35,6 +35,7 @@ public class Const implements Element { public Const(ElementAttributes attributes) { output = new ObservableValue("out", attributes.get(Keys.BITS)).setPinDescription(DESCRIPTION); output.setValue(attributes.get(Keys.VALUE)); + output.setConstant(); } @Override diff --git a/src/main/java/de/neemann/digital/core/io/Ground.java b/src/main/java/de/neemann/digital/core/io/Ground.java index 7a561c14e..f12ba5a41 100644 --- a/src/main/java/de/neemann/digital/core/io/Ground.java +++ b/src/main/java/de/neemann/digital/core/io/Ground.java @@ -34,6 +34,7 @@ public class Ground implements Element { public Ground(ElementAttributes attributes) { output = new ObservableValue("out", attributes.get(Keys.BITS)).setPinDescription(DESCRIPTION); output.setValue(0); + output.setConstant(); } @Override diff --git a/src/main/java/de/neemann/digital/core/io/VDD.java b/src/main/java/de/neemann/digital/core/io/VDD.java index d9f6a1d48..c17be10e9 100644 --- a/src/main/java/de/neemann/digital/core/io/VDD.java +++ b/src/main/java/de/neemann/digital/core/io/VDD.java @@ -34,6 +34,7 @@ public class VDD implements Element { public VDD(ElementAttributes attributes) { output = new ObservableValue("out", attributes.get(Keys.BITS)).setPinDescription(DESCRIPTION); output.setValue(-1); + output.setConstant(); } @Override diff --git a/src/main/java/de/neemann/digital/core/memory/RAMDualPort.java b/src/main/java/de/neemann/digital/core/memory/RAMDualPort.java index 655f29f16..1d26edcd8 100644 --- a/src/main/java/de/neemann/digital/core/memory/RAMDualPort.java +++ b/src/main/java/de/neemann/digital/core/memory/RAMDualPort.java @@ -158,7 +158,7 @@ public class RAMDualPort extends Node implements Element, RAMInterface { if (ld) { output.set(memory.getDataWord(addr), false); } else { - output.setHighZ(true); + output.set(0, true); } } diff --git a/src/main/java/de/neemann/digital/core/memory/RAMSinglePort.java b/src/main/java/de/neemann/digital/core/memory/RAMSinglePort.java index 372c4a78d..b13f4c974 100644 --- a/src/main/java/de/neemann/digital/core/memory/RAMSinglePort.java +++ b/src/main/java/de/neemann/digital/core/memory/RAMSinglePort.java @@ -48,7 +48,7 @@ public class RAMSinglePort extends RAMDualPort { @Override protected ObservableValue createOutput() { return super.createOutput() - .setBidirectional(true) + .setBidirectional() .setPinDescription(DESCRIPTION); } diff --git a/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java b/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java index 21e52f51d..c3c4ad4ad 100644 --- a/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java +++ b/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java @@ -62,7 +62,7 @@ public class RAMSinglePortSel extends Node implements Element, RAMInterface { size = 1 << addrBits; memory = new DataField(size); label = attr.getCleanLabel(); - dataOut = new ObservableValue("D", bits, true).setPinDescription(DESCRIPTION).setBidirectional(true); + dataOut = new ObservableValue("D", bits, true).setPinDescription(DESCRIPTION).setBidirectional(); } @Override @@ -92,7 +92,7 @@ public class RAMSinglePortSel extends Node implements Element, RAMInterface { if (cs && oe) { dataOut.set(memory.getDataWord(addr), false); } else { - dataOut.setHighZ(true); + dataOut.set(0, true); } } diff --git a/src/main/java/de/neemann/digital/core/pld/Diode.java b/src/main/java/de/neemann/digital/core/pld/Diode.java index 93425083d..085f3ed0b 100644 --- a/src/main/java/de/neemann/digital/core/pld/Diode.java +++ b/src/main/java/de/neemann/digital/core/pld/Diode.java @@ -31,8 +31,8 @@ public class Diode implements Element, Observer { * @param attr the elements attributes */ public Diode(ElementAttributes attr) { - cathode = new ObservableValue("cathode", 1, true).setBidirectional(true); - anode = new ObservableValue("anode", 1, true).setBidirectional(true); + cathode = new ObservableValue("cathode", 1, true).setBidirectional(); + anode = new ObservableValue("anode", 1, true).setBidirectional(); blown = attr.get(Keys.BLOWN); } diff --git a/src/main/java/de/neemann/digital/core/switching/Switch.java b/src/main/java/de/neemann/digital/core/switching/Switch.java index 23ef7d1ae..2ed592b72 100644 --- a/src/main/java/de/neemann/digital/core/switching/Switch.java +++ b/src/main/java/de/neemann/digital/core/switching/Switch.java @@ -47,10 +47,8 @@ public class Switch implements Element, Observer { public Switch(ElementAttributes attr, boolean closed) { bits = attr.getBits(); this.closed = closed; - output1 = new ObservableValue("out1", bits, true).setPinDescription(DESCRIPTION).setBidirectional(true); - output2 = new ObservableValue("out2", bits, true).setPinDescription(DESCRIPTION).setBidirectional(true); - output1.set(0, true); - output2.set(0, true); + output1 = new ObservableValue("out1", bits, true).setPinDescription(DESCRIPTION).setBidirectional().set(0, true); + output2 = new ObservableValue("out2", bits, true).setPinDescription(DESCRIPTION).setBidirectional().set(0, true); } @Override @@ -59,7 +57,18 @@ public class Switch implements Element, Observer { ObservableValue input2 = inputs.get(1).addObserverToValue(this).checkBits(bits, null); if (input1 instanceof CommonBusValue) { if (input2 instanceof CommonBusValue) { - switchModel = new RealSwitch((CommonBusValue) input1, (CommonBusValue) input2); + final CommonBusValue in1 = (CommonBusValue) input1; + final CommonBusValue in2 = (CommonBusValue) input2; + ObservableValue constant = in1.searchConstant(); + if (constant != null) + switchModel = new SimpleSwitch(constant, output2); + else { + constant = in2.searchConstant(); + if (constant != null) + switchModel = new SimpleSwitch(constant, output1); + else + switchModel = new RealSwitch(in1, in2); + } } else { switchModel = new SimpleSwitch(input1, output2); } @@ -116,14 +125,14 @@ public class Switch implements Element, Observer { /** * @return output 1 */ - public ObservableValue getOutput1() { + ObservableValue getOutput1() { return output1; } /** * @return output 2 */ - public ObservableValue getOutput2() { + ObservableValue getOutput2() { return output2; } diff --git a/src/main/java/de/neemann/digital/core/wiring/bus/CommonBusValue.java b/src/main/java/de/neemann/digital/core/wiring/bus/CommonBusValue.java index 9639da1ec..c3cd68d67 100644 --- a/src/main/java/de/neemann/digital/core/wiring/bus/CommonBusValue.java +++ b/src/main/java/de/neemann/digital/core/wiring/bus/CommonBusValue.java @@ -30,14 +30,14 @@ public final class CommonBusValue extends ObservableValue implements Observer { * * @param handler the handler */ - public void setHandler(AbstractBusHandler handler) { + void setHandler(AbstractBusHandler handler) { this.handler = handler; } /** - * Resets the handler. SO this net is isolated to a single simple net. + * Resets the handler. So this net is isolated to a single simple net. */ - public void resetHandler() { + void resetHandler() { setHandler(new SingleBusHandler(obs, this, resistor, inputs)); hasChanged(); } @@ -55,4 +55,16 @@ public final class CommonBusValue extends ObservableValue implements Observer { public ObservableValue[] getInputs() { return inputs; } + + /** + * Returns true if this net is a constant + * + * @return true if this is a constant + */ + public ObservableValue searchConstant() { + for (ObservableValue i : inputs) + if (i.isConstant()) + return i; + return null; + } } diff --git a/src/main/java/de/neemann/digital/gui/components/SingleValueDialog.java b/src/main/java/de/neemann/digital/gui/components/SingleValueDialog.java index 114b6057f..29911cfdb 100644 --- a/src/main/java/de/neemann/digital/gui/components/SingleValueDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/SingleValueDialog.java @@ -218,7 +218,7 @@ public final class SingleValueDialog extends JDialog { SingleValueDialog svd = new SingleValueDialog(pos, value); if (svd.showDialog()) { if (svd.getSelectedFormat().equals(InMode.HIGHZ)) { - modelSync.access(() -> value.setHighZ(true)); + modelSync.access(() -> value.set(0, true)); } else { modelSync.access(() -> value.set(svd.editValue, false)); } diff --git a/src/main/java/de/neemann/digital/gui/components/graphics/GraphicCard.java b/src/main/java/de/neemann/digital/gui/components/graphics/GraphicCard.java index 352623ed4..ce316c072 100644 --- a/src/main/java/de/neemann/digital/gui/components/graphics/GraphicCard.java +++ b/src/main/java/de/neemann/digital/gui/components/graphics/GraphicCard.java @@ -80,7 +80,7 @@ public class GraphicCard extends Node implements Element, RAMInterface { dataOut = new ObservableValue("D", bits, true) .setPinDescription(DESCRIPTION) - .setBidirectional(true); + .setBidirectional(); } @Override @@ -135,7 +135,7 @@ public class GraphicCard extends Node implements Element, RAMInterface { if (ld) { dataOut.set(memory.getDataWord(addr), false); } else { - dataOut.setHighZ(true); + dataOut.set(0, true); } }