Generalized WireObserver to LogicObserver
authorFabian Stemmler <stemmler@in.tum.de>
Sun, 2 Jun 2019 09:33:57 +0000 (11:33 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Sun, 2 Jun 2019 09:38:09 +0000 (11:38 +0200)
15 files changed:
net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObservable.java [new file with mode: 0644]
net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObserver.java [new file with mode: 0644]
net.mograsim.logic.core/src/net/mograsim/logic/core/components/BasicComponent.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/BitDisplay.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/Connector.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/Demux.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/Merger.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/Mux.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/Splitter.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/TriStateBuffer.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/gates/MultiInputGate.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/gates/NotGate.java
net.mograsim.logic.core/src/net/mograsim/logic/core/tests/ComponentTest.java
net.mograsim.logic.core/src/net/mograsim/logic/core/wires/Wire.java
net.mograsim.logic.core/src/net/mograsim/logic/core/wires/WireObserver.java [deleted file]

diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObservable.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObservable.java
new file mode 100644 (file)
index 0000000..ddfa070
--- /dev/null
@@ -0,0 +1,10 @@
+package net.mograsim.logic.core;\r
+\r
+public interface LogicObservable\r
+{\r
+       public void registerObserver(LogicObserver ob);\r
+\r
+       public void notifyObservers();\r
+\r
+//     public InnerState getInnerState();\r
+}\r
diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObserver.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObserver.java
new file mode 100644 (file)
index 0000000..9375004
--- /dev/null
@@ -0,0 +1,6 @@
+package net.mograsim.logic.core;\r
+\r
+public interface LogicObserver\r
+{\r
+       public void update(LogicObservable initiator);\r
+}\r
index 426c6a1..e2d2d65 100644 (file)
@@ -1,36 +1,35 @@
-package net.mograsim.logic.core.components;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.WireObserver;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-
-/**
- * A basic component that recomputes all outputs (with a delay), when it is updated.
- * 
- * @author Fabian Stemmler
- */
-public abstract class BasicComponent extends Component implements WireObserver
-{
-       private int processTime;
-
-       /**
-        * 
-        * @param processTime Amount of time this component takes to update its outputs. Must be more than 0, otherwise 1 is assumed.
-        * 
-        * @author Fabian Stemmler
-        */
-       public BasicComponent(Timeline timeline, int processTime)
-       {
-               super(timeline);
-               this.processTime = processTime > 0 ? processTime : 1;
-       }
-
-       @Override
-       public void update(ReadEnd initiator, BitVector oldValues)
-       {
-               timeline.addEvent(e -> compute(), processTime);
-       }
-
-       protected abstract void compute();
-}
+package net.mograsim.logic.core.components;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+\r
+/**\r
+ * A basic component that recomputes all outputs (with a delay), when it is updated.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+public abstract class BasicComponent extends Component implements LogicObserver\r
+{\r
+       private int processTime;\r
+\r
+       /**\r
+        * \r
+        * @param processTime Amount of time this component takes to update its outputs. Must be more than 0, otherwise 1 is assumed.\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       public BasicComponent(Timeline timeline, int processTime)\r
+       {\r
+               super(timeline);\r
+               this.processTime = processTime > 0 ? processTime : 1;\r
+       }\r
+\r
+       @Override\r
+       public void update(LogicObservable initiator)\r
+       {\r
+               timeline.addEvent(e -> compute(), processTime);\r
+       }\r
+\r
+       protected abstract void compute();\r
+}\r
index 268d157..af2fbc0 100644 (file)
@@ -1,51 +1,51 @@
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class BitDisplay extends BasicComponent
-{
-       private final ReadEnd in;
-       private BitVector displayedValue;
-
-       public BitDisplay(Timeline timeline, ReadEnd in)
-       {
-               super(timeline, 1);
-               this.in = in;
-               in.addObserver(this);
-               compute();
-       }
-
-       @Override
-       protected void compute()
-       {
-               displayedValue = in.getValues();
-       }
-
-       public BitVector getDisplayedValue()
-       {
-               return displayedValue;
-       }
-
-       public boolean isDisplaying(Bit... values)
-       {
-               return displayedValue.equals(BitVector.of(values));
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(in);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of();
-       }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.types.BitVector;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class BitDisplay extends BasicComponent\r
+{\r
+       private final ReadEnd in;\r
+       private BitVector displayedValue;\r
+\r
+       public BitDisplay(Timeline timeline, ReadEnd in)\r
+       {\r
+               super(timeline, 1);\r
+               this.in = in;\r
+               in.registerObserver(this);\r
+               compute();\r
+       }\r
+\r
+       @Override\r
+       protected void compute()\r
+       {\r
+               displayedValue = in.getValues();\r
+       }\r
+\r
+       public BitVector getDisplayedValue()\r
+       {\r
+               return displayedValue;\r
+       }\r
+\r
+       public boolean isDisplaying(Bit... values)\r
+       {\r
+               return displayedValue.equals(BitVector.of(values));\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of(in);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of();\r
+       }\r
+}\r
index 16b8e70..dc8490a 100644 (file)
@@ -1,76 +1,76 @@
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.WireObserver;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class Connector extends Component implements WireObserver
-{
-       private boolean connected;
-       private final ReadWriteEnd a;
-       private final ReadWriteEnd b;
-
-       public Connector(Timeline timeline, ReadWriteEnd a, ReadWriteEnd b)
-       {
-               super(timeline);
-               if (a.length() != b.length())
-                       throw new IllegalArgumentException(String.format("WireArray width does not match: %d, %d", a.length(), b.length()));
-               this.a = a;
-               this.b = b;
-               a.addObserver(this);
-               b.addObserver(this);
-       }
-
-       public void connect()
-       {
-               connected = true;
-               update(a);
-               update(b);
-       }
-
-       public void disconnect()
-       {
-               connected = false;
-               a.clearSignals();
-               b.clearSignals();
-       }
-
-       public void setConnection(boolean connected)
-       {
-               if (connected)
-                       connect();
-               else
-                       disconnect();
-       }
-
-       @Override
-       public void update(ReadEnd initiator, BitVector oldValues)
-       {
-               if (connected)
-                       timeline.addEvent(e -> update(initiator), 1);
-       }
-
-       private void update(ReadEnd initiator)
-       {
-               if (initiator == a)
-                       b.feedSignals(a.wireValuesExcludingMe());
-               else
-                       a.feedSignals(b.wireValuesExcludingMe());
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(a, b);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(a, b);
-       }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class Connector extends Component implements LogicObserver\r
+{\r
+       private boolean connected;\r
+       private final ReadWriteEnd a;\r
+       private final ReadWriteEnd b;\r
+\r
+       public Connector(Timeline timeline, ReadWriteEnd a, ReadWriteEnd b)\r
+       {\r
+               super(timeline);\r
+               if (a.length() != b.length())\r
+                       throw new IllegalArgumentException(String.format("WireArray width does not match: %d, %d", a.length(), b.length()));\r
+               this.a = a;\r
+               this.b = b;\r
+               a.registerObserver(this);\r
+               b.registerObserver(this);\r
+       }\r
+\r
+       public void connect()\r
+       {\r
+               connected = true;\r
+               update(a);\r
+               update(b);\r
+       }\r
+\r
+       public void disconnect()\r
+       {\r
+               connected = false;\r
+               a.clearSignals();\r
+               b.clearSignals();\r
+       }\r
+\r
+       public void setConnection(boolean connected)\r
+       {\r
+               if (connected)\r
+                       connect();\r
+               else\r
+                       disconnect();\r
+       }\r
+\r
+       @Override\r
+       public void update(LogicObservable initiator)\r
+       {\r
+               if (connected)\r
+                       timeline.addEvent(e -> innerUpdate(initiator), 1);\r
+       }\r
+\r
+       private void innerUpdate(LogicObservable initiator)\r
+       {\r
+               if (initiator == a)\r
+                       b.feedSignals(a.wireValuesExcludingMe());\r
+               else\r
+                       a.feedSignals(b.wireValuesExcludingMe());\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of(a, b);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(a, b);\r
+       }\r
+}\r
index 5da1bf6..e5b228d 100644 (file)
@@ -1,82 +1,82 @@
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.Wire;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-/**
- * Models a multiplexer. Takes an arbitrary amount of input {@link Wire}s, one of which, as determined by select, is put through to the
- * output.
- * 
- * @author Fabian Stemmler
- *
- */
-public class Demux extends BasicComponent
-{
-       private final ReadEnd select, in;
-       private final ReadWriteEnd[] outputs;
-       private final int outputSize;
-       private int selected = -1;
-
-       /**
-        * Output {@link Wire}s and in must be of uniform length
-        * 
-        * @param in      Must be of uniform length with all outputs.
-        * @param select  Indexes the output array to which the input is mapped. Must have enough bits to index all outputs.
-        * @param outputs One of these outputs receives the input signal, depending on the select bits
-        */
-       public Demux(Timeline timeline, int processTime, ReadEnd in, ReadEnd select, ReadWriteEnd... outputs)
-       {
-               super(timeline, processTime);
-               outputSize = in.length();
-
-               this.in = in;
-               this.outputs = outputs;
-               for (int i = 0; i < this.outputs.length; i++)
-               {
-                       if (outputs[i].length() != outputSize)
-                               throw new IllegalArgumentException("All DEMUX wire arrays must be of uniform length!");
-                       this.outputs[i] = outputs[i];
-               }
-
-               this.select = select;
-               select.addObserver(this);
-
-               int maxInputs = 1 << select.length();
-               if (this.outputs.length > maxInputs)
-                       throw new IllegalArgumentException("There are more outputs (" + this.outputs.length + ") to the DEMUX than supported by "
-                                       + select.length() + " select bits (" + maxInputs + ").");
-               in.addObserver(this);
-       }
-
-       @Override
-       public void compute()
-       {
-               int selectValue = select.hasNumericValue() ? (int) select.getUnsignedValue() : -1;
-               if (selectValue >= outputs.length)
-                       selectValue = -1;
-
-               if (selected != selectValue && selected != -1)
-                       outputs[selected].clearSignals();
-
-               selected = selectValue;
-
-               if (selectValue != -1)
-                       outputs[selectValue].feedSignals(in.getValues());
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(in, select);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(outputs);
-       }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.wires.Wire;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+/**\r
+ * Models a multiplexer. Takes an arbitrary amount of input {@link Wire}s, one of which, as determined by select, is put through to the\r
+ * output.\r
+ * \r
+ * @author Fabian Stemmler\r
+ *\r
+ */\r
+public class Demux extends BasicComponent\r
+{\r
+       private final ReadEnd select, in;\r
+       private final ReadWriteEnd[] outputs;\r
+       private final int outputSize;\r
+       private int selected = -1;\r
+\r
+       /**\r
+        * Output {@link Wire}s and in must be of uniform length\r
+        * \r
+        * @param in      Must be of uniform length with all outputs.\r
+        * @param select  Indexes the output array to which the input is mapped. Must have enough bits to index all outputs.\r
+        * @param outputs One of these outputs receives the input signal, depending on the select bits\r
+        */\r
+       public Demux(Timeline timeline, int processTime, ReadEnd in, ReadEnd select, ReadWriteEnd... outputs)\r
+       {\r
+               super(timeline, processTime);\r
+               outputSize = in.length();\r
+\r
+               this.in = in;\r
+               this.outputs = outputs;\r
+               for (int i = 0; i < this.outputs.length; i++)\r
+               {\r
+                       if (outputs[i].length() != outputSize)\r
+                               throw new IllegalArgumentException("All DEMUX wire arrays must be of uniform length!");\r
+                       this.outputs[i] = outputs[i];\r
+               }\r
+\r
+               this.select = select;\r
+               select.registerObserver(this);\r
+\r
+               int maxInputs = 1 << select.length();\r
+               if (this.outputs.length > maxInputs)\r
+                       throw new IllegalArgumentException("There are more outputs (" + this.outputs.length + ") to the DEMUX than supported by "\r
+                                       + select.length() + " select bits (" + maxInputs + ").");\r
+               in.registerObserver(this);\r
+       }\r
+\r
+       @Override\r
+       public void compute()\r
+       {\r
+               int selectValue = select.hasNumericValue() ? (int) select.getUnsignedValue() : -1;\r
+               if (selectValue >= outputs.length)\r
+                       selectValue = -1;\r
+\r
+               if (selected != selectValue && selected != -1)\r
+                       outputs[selected].clearSignals();\r
+\r
+               selected = selectValue;\r
+\r
+               if (selectValue != -1)\r
+                       outputs[selectValue].feedSignals(in.getValues());\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of(in, select);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(outputs);\r
+       }\r
+}\r
index c4c7170..06e064c 100644 (file)
@@ -1,85 +1,85 @@
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire;
-import net.mograsim.logic.core.wires.WireObserver;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class Merger extends Component implements WireObserver
-{
-       private ReadWriteEnd out;
-       private ReadEnd[] inputs;
-       private int[] beginningIndex;
-
-       /**
-        * 
-        * @param union  The output of merging n {@link Wire}s into one. Must have length = a1.length() + a2.length() + ... + an.length().
-        * @param inputs The inputs to be merged into the union
-        */
-       public Merger(Timeline timeline, ReadWriteEnd union, ReadEnd... inputs)
-       {
-               super(timeline);
-               this.inputs = inputs;
-               this.out = union;
-               this.beginningIndex = new int[inputs.length];
-
-               int length = 0;
-               for (int i = 0; i < inputs.length; i++)
-               {
-                       beginningIndex[i] = length;
-                       length += inputs[i].length();
-                       inputs[i].addObserver(this);
-               }
-
-               if (length != union.length())
-                       throw new IllegalArgumentException(
-                                       "The output of merging n WireArrays into one must have length = a1.length() + a2.length() + ... + an.length().");
-       }
-
-       public ReadEnd getInput(int index)
-       {
-               return inputs[index];
-       }
-
-       public ReadEnd getUnion()
-       {
-               return out;
-       }
-
-       @Override
-       public void update(ReadEnd initiator, BitVector oldValues)
-       {
-               int index = find(initiator);
-               int beginning = beginningIndex[index];
-               out.feedSignals(beginning, inputs[index].getValues());
-       }
-
-       private int find(ReadEnd r)
-       {
-               for (int i = 0; i < inputs.length; i++)
-                       if (inputs[i] == r)
-                               return i;
-               return -1;
-       }
-
-       public ReadEnd[] getInputs()
-       {
-               return inputs.clone();
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(inputs);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(out);
-       }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.wires.Wire;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class Merger extends Component implements LogicObserver\r
+{\r
+       private ReadWriteEnd out;\r
+       private ReadEnd[] inputs;\r
+       private int[] beginningIndex;\r
+\r
+       /**\r
+        * \r
+        * @param union  The output of merging n {@link Wire}s into one. Must have length = a1.length() + a2.length() + ... + an.length().\r
+        * @param inputs The inputs to be merged into the union\r
+        */\r
+       public Merger(Timeline timeline, ReadWriteEnd union, ReadEnd... inputs)\r
+       {\r
+               super(timeline);\r
+               this.inputs = inputs;\r
+               this.out = union;\r
+               this.beginningIndex = new int[inputs.length];\r
+\r
+               int length = 0;\r
+               for (int i = 0; i < inputs.length; i++)\r
+               {\r
+                       beginningIndex[i] = length;\r
+                       length += inputs[i].length();\r
+                       inputs[i].registerObserver(this);\r
+               }\r
+\r
+               if (length != union.length())\r
+                       throw new IllegalArgumentException(\r
+                                       "The output of merging n WireArrays into one must have length = a1.length() + a2.length() + ... + an.length().");\r
+       }\r
+\r
+       public ReadEnd getInput(int index)\r
+       {\r
+               return inputs[index];\r
+       }\r
+\r
+       public ReadEnd getUnion()\r
+       {\r
+               return out;\r
+       }\r
+\r
+       @Override\r
+       public void update(LogicObservable initiator)\r
+       {\r
+               int index = find(initiator);\r
+               int beginning = beginningIndex[index];\r
+               out.feedSignals(beginning, inputs[index].getValues());\r
+       }\r
+\r
+       private int find(LogicObservable r)\r
+       {\r
+               for (int i = 0; i < inputs.length; i++)\r
+                       if (inputs[i] == r)\r
+                               return i;\r
+               return -1;\r
+       }\r
+\r
+       public ReadEnd[] getInputs()\r
+       {\r
+               return inputs.clone();\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of(inputs);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(out);\r
+       }\r
+}\r
index bbb10f5..5e75f96 100644 (file)
@@ -41,11 +41,11 @@ public class Mux extends BasicComponent
                {
                        if (inputs[i].length() != outputSize)
                                throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");
-                       inputs[i].addObserver(this);
+                       inputs[i].registerObserver(this);
                }
 
                this.select = select;
-               select.addObserver(this);
+               select.registerObserver(this);
 
                int maxInputs = 1 << select.length();
                if (this.inputs.length > maxInputs)
index 9eb5b2c..a6165d9 100644 (file)
@@ -1,59 +1,60 @@
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.WireObserver;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class Splitter extends Component implements WireObserver
-{
-       private ReadEnd input;
-       private ReadWriteEnd[] outputs;
-
-       public Splitter(Timeline timeline, ReadEnd input, ReadWriteEnd... outputs)
-       {
-               super(timeline);
-               this.input = input;
-               this.outputs = outputs;
-               input.addObserver(this);
-               int length = 0;
-               for (ReadEnd out : outputs)
-                       length += out.length();
-
-               if (input.length() != length)
-                       throw new IllegalArgumentException(
-                                       "The input of splitting one into n WireArrays must have length = a1.length() + a2.length() + ... + an.length().");
-       }
-
-       protected void compute()
-       {
-               BitVector inputBits = input.getValues();
-               int startIndex = 0;
-               for (int i = 0; i < outputs.length; i++)
-               {
-                       outputs[i].feedSignals(inputBits.subVector(startIndex, startIndex + outputs[i].length()));
-                       startIndex += outputs[i].length();
-               }
-       }
-
-       @Override
-       public void update(ReadEnd initiator, BitVector oldValues)
-       {
-               compute();
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(input);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(outputs);
-       }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.BitVector;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class Splitter extends Component implements LogicObserver\r
+{\r
+       private ReadEnd input;\r
+       private ReadWriteEnd[] outputs;\r
+\r
+       public Splitter(Timeline timeline, ReadEnd input, ReadWriteEnd... outputs)\r
+       {\r
+               super(timeline);\r
+               this.input = input;\r
+               this.outputs = outputs;\r
+               input.registerObserver(this);\r
+               int length = 0;\r
+               for (ReadEnd out : outputs)\r
+                       length += out.length();\r
+\r
+               if (input.length() != length)\r
+                       throw new IllegalArgumentException(\r
+                                       "The input of splitting one into n WireArrays must have length = a1.length() + a2.length() + ... + an.length().");\r
+       }\r
+\r
+       protected void compute()\r
+       {\r
+               BitVector inputBits = input.getValues();\r
+               int startIndex = 0;\r
+               for (int i = 0; i < outputs.length; i++)\r
+               {\r
+                       outputs[i].feedSignals(inputBits.subVector(startIndex, startIndex + outputs[i].length()));\r
+                       startIndex += outputs[i].length();\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public void update(LogicObservable initiator)\r
+       {\r
+               compute();\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of(input);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(outputs);\r
+       }\r
+}\r
index f4f1b49..1f8f85a 100644 (file)
@@ -1,51 +1,51 @@
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class TriStateBuffer extends BasicComponent
-{
-       ReadEnd in, enable;
-       ReadWriteEnd out;
-
-       public TriStateBuffer(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out, ReadEnd enable)
-       {
-               super(timeline, processTime);
-               if (in.length() != out.length())
-                       throw new IllegalArgumentException(
-                                       "Tri-state output must have the same amount of bits as the input. Input: " + in.length() + " Output: " + out.length());
-               if (enable.length() != 1)
-                       throw new IllegalArgumentException("Tri-state enable must have exactly one bit, not " + enable.length() + ".");
-               this.in = in;
-               in.addObserver(this);
-               this.enable = enable;
-               enable.addObserver(this);
-               this.out = out;
-       }
-
-       @Override
-       protected void compute()
-       {
-               if (enable.getValue() == Bit.ONE)
-                       out.feedSignals(in.getValues());
-               else
-                       out.clearSignals();
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(in, enable);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(out);
-       }
-
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class TriStateBuffer extends BasicComponent\r
+{\r
+       ReadEnd in, enable;\r
+       ReadWriteEnd out;\r
+\r
+       public TriStateBuffer(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out, ReadEnd enable)\r
+       {\r
+               super(timeline, processTime);\r
+               if (in.length() != out.length())\r
+                       throw new IllegalArgumentException(\r
+                                       "Tri-state output must have the same amount of bits as the input. Input: " + in.length() + " Output: " + out.length());\r
+               if (enable.length() != 1)\r
+                       throw new IllegalArgumentException("Tri-state enable must have exactly one bit, not " + enable.length() + ".");\r
+               this.in = in;\r
+               in.registerObserver(this);\r
+               this.enable = enable;\r
+               enable.registerObserver(this);\r
+               this.out = out;\r
+       }\r
+\r
+       @Override\r
+       protected void compute()\r
+       {\r
+               if (enable.getValue() == Bit.ONE)\r
+                       out.feedSignals(in.getValues());\r
+               else\r
+                       out.clearSignals();\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of(in, enable);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(out);\r
+       }\r
+\r
+}\r
index afc8951..79a1df5 100644 (file)
@@ -1,56 +1,56 @@
-package net.mograsim.logic.core.components.gates;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.MutationOperation;
-import net.mograsim.logic.core.types.BitVector.BitVectorMutator;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public abstract class MultiInputGate extends BasicComponent
-{
-       protected ReadEnd[] in;
-       protected ReadWriteEnd out;
-       protected final int length;
-       protected MutationOperation op;
-
-       protected MultiInputGate(Timeline timeline, int processTime, MutationOperation op, ReadWriteEnd out, ReadEnd... in)
-       {
-               super(timeline, processTime);
-               this.op = op;
-               length = out.length();
-               this.in = in.clone();
-               if (in.length < 1)
-                       throw new IllegalArgumentException(String.format("Cannot create gate with %d wires.", in.length));
-               for (ReadEnd w : in)
-               {
-                       if (w.length() != length)
-                               throw new IllegalArgumentException("All wires connected to the gate must be of uniform length.");
-                       w.addObserver(this);
-               }
-               this.out = out;
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(in);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(out);
-       }
-
-       @Override
-       protected void compute()
-       {
-               BitVectorMutator mutator = BitVectorMutator.empty();
-               for (ReadEnd w : in)
-                       op.apply(mutator, w.getValues());
-               out.feedSignals(mutator.get());
-       }
-}
+package net.mograsim.logic.core.components.gates;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.components.BasicComponent;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.MutationOperation;\r
+import net.mograsim.logic.core.types.BitVector.BitVectorMutator;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public abstract class MultiInputGate extends BasicComponent\r
+{\r
+       protected ReadEnd[] in;\r
+       protected ReadWriteEnd out;\r
+       protected final int length;\r
+       protected MutationOperation op;\r
+\r
+       protected MultiInputGate(Timeline timeline, int processTime, MutationOperation op, ReadWriteEnd out, ReadEnd... in)\r
+       {\r
+               super(timeline, processTime);\r
+               this.op = op;\r
+               length = out.length();\r
+               this.in = in.clone();\r
+               if (in.length < 1)\r
+                       throw new IllegalArgumentException(String.format("Cannot create gate with %d wires.", in.length));\r
+               for (ReadEnd w : in)\r
+               {\r
+                       if (w.length() != length)\r
+                               throw new IllegalArgumentException("All wires connected to the gate must be of uniform length.");\r
+                       w.registerObserver(this);\r
+               }\r
+               this.out = out;\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of(in);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(out);\r
+       }\r
+\r
+       @Override\r
+       protected void compute()\r
+       {\r
+               BitVectorMutator mutator = BitVectorMutator.empty();\r
+               for (ReadEnd w : in)\r
+                       op.apply(mutator, w.getValues());\r
+               out.feedSignals(mutator.get());\r
+       }\r
+}\r
index b1cfefe..e1c0e60 100644 (file)
@@ -1,50 +1,50 @@
-package net.mograsim.logic.core.components.gates;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class NotGate extends BasicComponent
-{
-       private ReadEnd in;
-       private ReadWriteEnd out;
-
-       public NotGate(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out)
-       {
-               super(timeline, processTime);
-               this.in = in;
-               in.addObserver(this);
-               this.out = out;
-       }
-
-       @Override
-       protected void compute()
-       {
-               out.feedSignals(in.getValues().not());
-       }
-
-       public ReadEnd getIn()
-       {
-               return in;
-       }
-
-       public ReadEnd getOut()
-       {
-               return out;
-       }
-
-       @Override
-       public List<ReadEnd> getAllInputs()
-       {
-               return List.of(in);
-       }
-
-       @Override
-       public List<ReadWriteEnd> getAllOutputs()
-       {
-               return List.of(out);
-       }
-}
+package net.mograsim.logic.core.components.gates;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.components.BasicComponent;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class NotGate extends BasicComponent\r
+{\r
+       private ReadEnd in;\r
+       private ReadWriteEnd out;\r
+\r
+       public NotGate(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out)\r
+       {\r
+               super(timeline, processTime);\r
+               this.in = in;\r
+               in.registerObserver(this);\r
+               this.out = out;\r
+       }\r
+\r
+       @Override\r
+       protected void compute()\r
+       {\r
+               out.feedSignals(in.getValues().not());\r
+       }\r
+\r
+       public ReadEnd getIn()\r
+       {\r
+               return in;\r
+       }\r
+\r
+       public ReadEnd getOut()\r
+       {\r
+               return out;\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of(in);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(out);\r
+       }\r
+}\r
index a47f792..e97836b 100644 (file)
-package net.mograsim.logic.core.tests;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.util.function.LongConsumer;
-
-import org.junit.jupiter.api.Test;
-
-import net.mograsim.logic.core.components.Connector;
-import net.mograsim.logic.core.components.Demux;
-import net.mograsim.logic.core.components.Merger;
-import net.mograsim.logic.core.components.Mux;
-import net.mograsim.logic.core.components.Splitter;
-import net.mograsim.logic.core.components.TriStateBuffer;
-import net.mograsim.logic.core.components.gates.AndGate;
-import net.mograsim.logic.core.components.gates.NotGate;
-import net.mograsim.logic.core.components.gates.OrGate;
-import net.mograsim.logic.core.components.gates.XorGate;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-class ComponentTest
-{
-       private Timeline t = new Timeline(11);
-
-       @Test
-       void circuitExampleTest()
-       {
-               Wire a = new Wire(t, 1, 1), b = new Wire(t, 1, 1), c = new Wire(t, 1, 10), d = new Wire(t, 2, 1), e = new Wire(t, 1, 1),
-                               f = new Wire(t, 1, 1), g = new Wire(t, 1, 1), h = new Wire(t, 2, 1), i = new Wire(t, 2, 1), j = new Wire(t, 1, 1),
-                               k = new Wire(t, 1, 1);
-               new AndGate(t, 1, f.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
-               new NotGate(t, 1, f.createReadOnlyEnd(), g.createReadWriteEnd());
-               new Merger(t, h.createReadWriteEnd(), c.createReadOnlyEnd(), g.createReadOnlyEnd());
-               new Mux(t, 1, i.createReadWriteEnd(), e.createReadOnlyEnd(), h.createReadOnlyEnd(), d.createReadOnlyEnd());
-               new Splitter(t, i.createReadOnlyEnd(), k.createReadWriteEnd(), j.createReadWriteEnd());
-
-               a.createReadWriteEnd().feedSignals(Bit.ZERO);
-               b.createReadWriteEnd().feedSignals(Bit.ONE);
-               c.createReadWriteEnd().feedSignals(Bit.ZERO);
-               d.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE);
-               e.createReadWriteEnd().feedSignals(Bit.ZERO);
-
-               t.executeAll();
-
-               assertEquals(Bit.ONE, j.getValue());
-               assertEquals(Bit.ZERO, k.getValue());
-       }
-
-       @Test
-       void splitterTest()
-       {
-               t.reset();
-               Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), in = new Wire(t, 8, 1);
-               in.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-               new Splitter(t, in.createReadOnlyEnd(), a.createReadWriteEnd(), b.createReadWriteEnd(), c.createReadWriteEnd());
-
-               t.executeAll();
-
-               assertBitArrayEquals(a.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO);
-               assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO);
-               assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE);
-       }
-
-       @Test
-       void mergerTest()
-       {
-               t.reset();
-               Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), out = new Wire(t, 8, 1);
-               a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);
-               b.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO);
-               c.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               new Merger(t, out.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
-
-               t.executeAll();
-
-               assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-       }
-
-       @Test
-       void triStateBufferTest()
-       {
-               Wire a = new Wire(t, 1, 1), b = new Wire(t, 1, 1), en = new Wire(t, 1, 1), notEn = new Wire(t, 1, 1);
-               new NotGate(t, 1, en.createReadOnlyEnd(), notEn.createReadWriteEnd());
-               new TriStateBuffer(t, 1, a.createReadOnlyEnd(), b.createReadWriteEnd(), en.createReadOnlyEnd());
-               new TriStateBuffer(t, 1, b.createReadOnlyEnd(), a.createReadWriteEnd(), notEn.createReadOnlyEnd());
-
-               ReadWriteEnd enI = en.createReadWriteEnd(), aI = a.createReadWriteEnd(), bI = b.createReadWriteEnd();
-               enI.feedSignals(Bit.ONE);
-               aI.feedSignals(Bit.ONE);
-               bI.feedSignals(Bit.Z);
-
-               t.executeAll();
-
-               assertEquals(Bit.ONE, b.getValue());
-
-               bI.feedSignals(Bit.ZERO);
-
-               t.executeAll();
-
-               assertEquals(Bit.X, b.getValue());
-               assertEquals(Bit.ONE, a.getValue());
-
-               aI.clearSignals();
-               enI.feedSignals(Bit.ZERO);
-
-               t.executeAll();
-
-               assertEquals(Bit.ZERO, a.getValue());
-
-       }
-
-       @Test
-       void muxTest()
-       {
-               t.reset();
-               Wire a = new Wire(t, 4, 3), b = new Wire(t, 4, 6), c = new Wire(t, 4, 4), select = new Wire(t, 2, 5), out = new Wire(t, 4, 1);
-               ReadWriteEnd selectIn = select.createReadWriteEnd();
-
-               selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
-               a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-               c.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               new Mux(t, 1, out.createReadWriteEnd(), select.createReadOnlyEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(),
-                               c.createReadOnlyEnd());
-               t.executeAll();
-
-               assertBitArrayEquals(out.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-               selectIn.feedSignals(Bit.ZERO, Bit.ONE);
-               t.executeAll();
-
-               assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               selectIn.feedSignals(Bit.ONE, Bit.ONE);
-               t.executeAll();
-
-               assertBitArrayEquals(out.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
-
-       }
-
-       @Test
-       void demuxTest()
-       {
-               t.reset();
-               Wire a = new Wire(t, 4, 3), b = new Wire(t, 4, 6), c = new Wire(t, 4, 4), select = new Wire(t, 2, 5), in = new Wire(t, 4, 1);
-               ReadWriteEnd selectIn = select.createReadWriteEnd();
-
-               selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
-               in.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-
-               new Demux(t, 1, in.createReadOnlyEnd(), select.createReadOnlyEnd(), a.createReadWriteEnd(), b.createReadWriteEnd(),
-                               c.createReadWriteEnd());
-               t.executeAll();
-
-               assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-               assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);
-               assertBitArrayEquals(c.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);
-               selectIn.feedSignals(Bit.ZERO, Bit.ONE);
-               t.executeAll();
-
-               assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
-               assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);
-               assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-
-               selectIn.feedSignals(Bit.ONE, Bit.ONE);
-               t.executeAll();
-
-               assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
-               assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);
-               assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
-
-       }
-
-       @Test
-       void andTest()
-       {
-               t.reset();
-               Wire a = new Wire(t, 4, 1), b = new Wire(t, 4, 3), c = new Wire(t, 4, 1);
-               new AndGate(t, 1, c.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
-               a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
-               b.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               t.executeAll();
-
-               assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);
-       }
-
-       @Test
-       void orTest()
-       {
-               t.reset();
-               Wire a = new Wire(t, 4, 1), b = new Wire(t, 4, 3), c = new Wire(t, 4, 1);
-               new OrGate(t, 1, c.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
-               a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
-               b.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               t.executeAll();
-
-               assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);
-       }
-
-       @Test
-       void xorTest()
-       {
-               t.reset();
-               Wire a = new Wire(t, 3, 1), b = new Wire(t, 3, 2), c = new Wire(t, 3, 1), d = new Wire(t, 3, 1);
-               new XorGate(t, 1, d.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
-               a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
-               b.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-               c.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               t.executeAll();
-
-               assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);
-       }
-
-       @Test
-       void notTest()
-       {
-               t.reset();
-               Wire a = new Wire(t, 3, 1), b = new Wire(t, 3, 2);
-               new NotGate(t, 1, a.createReadOnlyEnd(), b.createReadWriteEnd());
-               a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
-
-               t.executeAll();
-
-               assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO, Bit.ZERO);
-       }
-
-       @Test
-       void rsLatchCircuitTest()
-       {
-               t.reset();
-               Wire r = new Wire(t, 1, 1), s = new Wire(t, 1, 1), t1 = new Wire(t, 1, 15), t2 = new Wire(t, 1, 1), q = new Wire(t, 1, 1),
-                               nq = new Wire(t, 1, 1);
-
-               new OrGate(t, 1, t2.createReadWriteEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd());
-               new OrGate(t, 1, t1.createReadWriteEnd(), s.createReadOnlyEnd(), q.createReadOnlyEnd());
-               new NotGate(t, 1, t2.createReadOnlyEnd(), q.createReadWriteEnd());
-               new NotGate(t, 1, t1.createReadOnlyEnd(), nq.createReadWriteEnd());
-
-               ReadWriteEnd sIn = s.createReadWriteEnd(), rIn = r.createReadWriteEnd();
-
-               sIn.feedSignals(Bit.ONE);
-               rIn.feedSignals(Bit.ZERO);
-
-               t.executeAll();
-
-               assertEquals(Bit.ONE, q.getValue());
-               assertEquals(Bit.ZERO, nq.getValue());
-
-               sIn.feedSignals(Bit.ZERO);
-
-               t.executeAll();
-               assertEquals(Bit.ONE, q.getValue());
-               assertEquals(Bit.ZERO, nq.getValue());
-
-               rIn.feedSignals(Bit.ONE);
-
-               t.executeAll();
-
-               assertEquals(Bit.ZERO, q.getValue());
-               assertEquals(Bit.ONE, nq.getValue());
-       }
-
-       @Test
-       void numericValueTest()
-       {
-               t.reset();
-
-               Wire a = new Wire(t, 4, 1);
-               a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);
-
-               t.executeAll();
-
-               assertEquals(15, a.getUnsignedValue());
-               assertEquals(-1, a.getSignedValue());
-       }
-
-       boolean flag = false;
-
-       @Test
-       void simpleTimelineTest()
-       {
-               Timeline t = new Timeline(3);
-               flag = false;
-               t.addEvent((e) ->
-               {
-                       if (!flag)
-                               fail();
-                       flag = false;
-               }, 15);
-               t.addEvent((e) ->
-               {
-                       if (flag)
-                               fail();
-                       flag = true;
-               }, 10);
-               t.addEvent((e) ->
-               {
-                       if (flag)
-                               fail();
-                       flag = true;
-               }, 20);
-               t.addEvent((e) ->
-               {
-                       fail("Only supposed to execute until timestamp 20, not 25");
-               }, 25);
-
-               t.executeUntil(t.laterThan(20), 100);
-
-               if (!flag)
-                       fail();
-       }
-
-       @Test
-       void multipleInputs()
-       {
-               t.reset();
-               Wire w = new Wire(t, 2, 1);
-               ReadWriteEnd wI1 = w.createReadWriteEnd(), wI2 = w.createReadWriteEnd();
-               wI1.feedSignals(Bit.ONE, Bit.Z);
-               wI2.feedSignals(Bit.Z, Bit.X);
-               t.executeAll();
-               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.X);
-
-               wI2.feedSignals(Bit.ZERO, Bit.Z);
-               t.executeAll();
-               assertBitArrayEquals(w.getValues(), Bit.X, Bit.Z);
-
-               wI2.feedSignals(Bit.Z, Bit.Z);
-               t.executeAll();
-               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
-
-               wI2.feedSignals(Bit.ONE, Bit.Z);
-               ReadEnd rE = w.createReadOnlyEnd();
-               rE.addObserver((i, oldValues) -> fail("WireEnd notified observer, although value did not change."));
-               t.executeAll();
-               rE.close();
-               wI1.feedSignals(Bit.X, Bit.X);
-               t.executeAll();
-               wI1.addObserver((i, oldValues) -> fail("WireEnd notified observer, although it was closed."));
-               wI1.close();
-               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
-       }
-
-       @Test
-       void wireConnections()
-       {
-               // Nur ein Experiment, was Ã¼ber mehrere 'passive' Bausteine hinweg passieren würde
-
-               t.reset();
-
-               Wire a = new Wire(t, 1, 2);
-               Wire b = new Wire(t, 1, 2);
-               Wire c = new Wire(t, 1, 2);
-               ReadWriteEnd aI = a.createReadWriteEnd();
-               ReadWriteEnd bI = b.createReadWriteEnd();
-               ReadWriteEnd cI = c.createReadWriteEnd();
-
-               TestBitDisplay test = new TestBitDisplay(t, c.createReadOnlyEnd());
-               TestBitDisplay test2 = new TestBitDisplay(t, a.createReadOnlyEnd());
-               LongConsumer print = time -> System.out.format("Time %2d\n   a: %s\n   b: %s\n   c: %s\n", time, a, b, c);
-
-               cI.feedSignals(Bit.ONE);
-               test.assertAfterSimulationIs(print, Bit.ONE);
-
-               cI.feedSignals(Bit.X);
-               test.assertAfterSimulationIs(print, Bit.X);
-
-               cI.feedSignals(Bit.X);
-               cI.feedSignals(Bit.Z);
-               test.assertAfterSimulationIs(print, Bit.Z);
-
-               new Connector(t, b.createReadWriteEnd(), c.createReadWriteEnd()).connect();
-               test.assertAfterSimulationIs(print, Bit.Z);
-               System.err.println("ONE");
-               bI.feedSignals(Bit.ONE);
-               test.assertAfterSimulationIs(print, Bit.ONE);
-               System.err.println("ZERO");
-               bI.feedSignals(Bit.ZERO);
-               test.assertAfterSimulationIs(print, Bit.ZERO);
-               System.err.println("Z");
-               bI.feedSignals(Bit.Z);
-               test.assertAfterSimulationIs(print, Bit.Z);
-
-               new Connector(t, a.createReadWriteEnd(), b.createReadWriteEnd()).connect();
-               System.err.println("Z 2");
-               aI.feedSignals(Bit.Z);
-               test.assertAfterSimulationIs(print, Bit.Z);
-               test2.assertAfterSimulationIs(Bit.Z);
-               System.err.println("ONE 2");
-               aI.feedSignals(Bit.ONE);
-               test.assertAfterSimulationIs(print, Bit.ONE);
-               test2.assertAfterSimulationIs(Bit.ONE);
-               System.err.println("ZERO 2");
-               aI.feedSignals(Bit.ZERO);
-               test.assertAfterSimulationIs(print, Bit.ZERO);
-               test2.assertAfterSimulationIs(Bit.ZERO);
-               System.err.println("Z 2 II");
-               aI.feedSignals(Bit.Z);
-               test.assertAfterSimulationIs(print, Bit.Z);
-               test2.assertAfterSimulationIs(Bit.Z);
-
-               System.err.println("No Conflict yet");
-               bI.feedSignals(Bit.ONE);
-               test.assertAfterSimulationIs(print, Bit.ONE);
-               test2.assertAfterSimulationIs(Bit.ONE);
-               aI.feedSignals(Bit.ONE);
-               test.assertAfterSimulationIs(print, Bit.ONE);
-               test2.assertAfterSimulationIs(Bit.ONE);
-               System.err.println("Conflict");
-               aI.feedSignals(Bit.ZERO);
-               test.assertAfterSimulationIs(print, Bit.X);
-               test2.assertAfterSimulationIs(Bit.X);
-               aI.feedSignals(Bit.ONE);
-               test.assertAfterSimulationIs(print, Bit.ONE);
-               test2.assertAfterSimulationIs(Bit.ONE);
-       }
-
-       private static void assertBitArrayEquals(BitVector actual, Bit... expected)
-       {
-               assertArrayEquals(expected, actual.getBits());
-       }
-}
+package net.mograsim.logic.core.tests;\r
+\r
+import static org.junit.Assert.assertTrue;\r
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;\r
+import static org.junit.jupiter.api.Assertions.assertEquals;\r
+import static org.junit.jupiter.api.Assertions.fail;\r
+\r
+import java.util.function.LongConsumer;\r
+\r
+import org.junit.jupiter.api.Test;\r
+\r
+import net.mograsim.logic.core.components.Connector;\r
+import net.mograsim.logic.core.components.Demux;\r
+import net.mograsim.logic.core.components.Merger;\r
+import net.mograsim.logic.core.components.Mux;\r
+import net.mograsim.logic.core.components.Splitter;\r
+import net.mograsim.logic.core.components.TriStateBuffer;\r
+import net.mograsim.logic.core.components.gates.AndGate;\r
+import net.mograsim.logic.core.components.gates.NotGate;\r
+import net.mograsim.logic.core.components.gates.OrGate;\r
+import net.mograsim.logic.core.components.gates.XorGate;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.types.BitVector;\r
+import net.mograsim.logic.core.wires.Wire;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+class ComponentTest\r
+{\r
+       private Timeline t = new Timeline(11);\r
+\r
+       @Test\r
+       void circuitExampleTest()\r
+       {\r
+               Wire a = new Wire(t, 1, 1), b = new Wire(t, 1, 1), c = new Wire(t, 1, 10), d = new Wire(t, 2, 1), e = new Wire(t, 1, 1),\r
+                               f = new Wire(t, 1, 1), g = new Wire(t, 1, 1), h = new Wire(t, 2, 1), i = new Wire(t, 2, 1), j = new Wire(t, 1, 1),\r
+                               k = new Wire(t, 1, 1);\r
+               new AndGate(t, 1, f.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+               new NotGate(t, 1, f.createReadOnlyEnd(), g.createReadWriteEnd());\r
+               new Merger(t, h.createReadWriteEnd(), c.createReadOnlyEnd(), g.createReadOnlyEnd());\r
+               new Mux(t, 1, i.createReadWriteEnd(), e.createReadOnlyEnd(), h.createReadOnlyEnd(), d.createReadOnlyEnd());\r
+               new Splitter(t, i.createReadOnlyEnd(), k.createReadWriteEnd(), j.createReadWriteEnd());\r
+\r
+               a.createReadWriteEnd().feedSignals(Bit.ZERO);\r
+               b.createReadWriteEnd().feedSignals(Bit.ONE);\r
+               c.createReadWriteEnd().feedSignals(Bit.ZERO);\r
+               d.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE);\r
+               e.createReadWriteEnd().feedSignals(Bit.ZERO);\r
+\r
+               t.executeAll();\r
+\r
+               assertEquals(Bit.ONE, j.getValue());\r
+               assertEquals(Bit.ZERO, k.getValue());\r
+       }\r
+\r
+       @Test\r
+       void splitterTest()\r
+       {\r
+               t.reset();\r
+               Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), in = new Wire(t, 8, 1);\r
+               in.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+               new Splitter(t, in.createReadOnlyEnd(), a.createReadWriteEnd(), b.createReadWriteEnd(), c.createReadWriteEnd());\r
+\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(a.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+               assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO);\r
+               assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE);\r
+       }\r
+\r
+       @Test\r
+       void mergerTest()\r
+       {\r
+               t.reset();\r
+               Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), out = new Wire(t, 8, 1);\r
+               a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+               b.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO);\r
+               c.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               new Merger(t, out.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+       }\r
+\r
+       @Test\r
+       void triStateBufferTest()\r
+       {\r
+               Wire a = new Wire(t, 1, 1), b = new Wire(t, 1, 1), en = new Wire(t, 1, 1), notEn = new Wire(t, 1, 1);\r
+               new NotGate(t, 1, en.createReadOnlyEnd(), notEn.createReadWriteEnd());\r
+               new TriStateBuffer(t, 1, a.createReadOnlyEnd(), b.createReadWriteEnd(), en.createReadOnlyEnd());\r
+               new TriStateBuffer(t, 1, b.createReadOnlyEnd(), a.createReadWriteEnd(), notEn.createReadOnlyEnd());\r
+\r
+               ReadWriteEnd enI = en.createReadWriteEnd(), aI = a.createReadWriteEnd(), bI = b.createReadWriteEnd();\r
+               enI.feedSignals(Bit.ONE);\r
+               aI.feedSignals(Bit.ONE);\r
+               bI.feedSignals(Bit.Z);\r
+\r
+               t.executeAll();\r
+\r
+               assertEquals(Bit.ONE, b.getValue());\r
+\r
+               bI.feedSignals(Bit.ZERO);\r
+\r
+               t.executeAll();\r
+\r
+               assertEquals(Bit.X, b.getValue());\r
+               assertEquals(Bit.ONE, a.getValue());\r
+\r
+               aI.clearSignals();\r
+               enI.feedSignals(Bit.ZERO);\r
+\r
+               t.executeAll();\r
+\r
+               assertEquals(Bit.ZERO, a.getValue());\r
+\r
+       }\r
+\r
+       @Test\r
+       void muxTest()\r
+       {\r
+               t.reset();\r
+               Wire a = new Wire(t, 4, 3), b = new Wire(t, 4, 6), c = new Wire(t, 4, 4), select = new Wire(t, 2, 5), out = new Wire(t, 4, 1);\r
+               ReadWriteEnd selectIn = select.createReadWriteEnd();\r
+\r
+               selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+               a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+               c.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               new Mux(t, 1, out.createReadWriteEnd(), select.createReadOnlyEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(),\r
+                               c.createReadOnlyEnd());\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(out.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+               selectIn.feedSignals(Bit.ZERO, Bit.ONE);\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               selectIn.feedSignals(Bit.ONE, Bit.ONE);\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(out.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+\r
+       }\r
+\r
+       @Test\r
+       void demuxTest()\r
+       {\r
+               t.reset();\r
+               Wire a = new Wire(t, 4, 3), b = new Wire(t, 4, 6), c = new Wire(t, 4, 4), select = new Wire(t, 2, 5), in = new Wire(t, 4, 1);\r
+               ReadWriteEnd selectIn = select.createReadWriteEnd();\r
+\r
+               selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+               in.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+\r
+               new Demux(t, 1, in.createReadOnlyEnd(), select.createReadOnlyEnd(), a.createReadWriteEnd(), b.createReadWriteEnd(),\r
+                               c.createReadWriteEnd());\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+               assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);\r
+               assertBitArrayEquals(c.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);\r
+               selectIn.feedSignals(Bit.ZERO, Bit.ONE);\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+               assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);\r
+               assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+\r
+               selectIn.feedSignals(Bit.ONE, Bit.ONE);\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+               assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);\r
+               assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+\r
+       }\r
+\r
+       @Test\r
+       void andTest()\r
+       {\r
+               t.reset();\r
+               Wire a = new Wire(t, 4, 1), b = new Wire(t, 4, 3), c = new Wire(t, 4, 1);\r
+               new AndGate(t, 1, c.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+               a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+               b.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+       }\r
+\r
+       @Test\r
+       void orTest()\r
+       {\r
+               t.reset();\r
+               Wire a = new Wire(t, 4, 1), b = new Wire(t, 4, 3), c = new Wire(t, 4, 1);\r
+               new OrGate(t, 1, c.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+               a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+               b.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+       }\r
+\r
+       @Test\r
+       void xorTest()\r
+       {\r
+               t.reset();\r
+               Wire a = new Wire(t, 3, 1), b = new Wire(t, 3, 2), c = new Wire(t, 3, 1), d = new Wire(t, 3, 1);\r
+               new XorGate(t, 1, d.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+               a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);\r
+               b.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+               c.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);\r
+       }\r
+\r
+       @Test\r
+       void notTest()\r
+       {\r
+               t.reset();\r
+               Wire a = new Wire(t, 3, 1), b = new Wire(t, 3, 2);\r
+               new NotGate(t, 1, a.createReadOnlyEnd(), b.createReadWriteEnd());\r
+               a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);\r
+\r
+               t.executeAll();\r
+\r
+               assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+       }\r
+\r
+       @Test\r
+       void rsLatchCircuitTest()\r
+       {\r
+               t.reset();\r
+               Wire r = new Wire(t, 1, 1), s = new Wire(t, 1, 1), t1 = new Wire(t, 1, 15), t2 = new Wire(t, 1, 1), q = new Wire(t, 1, 1),\r
+                               nq = new Wire(t, 1, 1);\r
+\r
+               new OrGate(t, 1, t2.createReadWriteEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd());\r
+               new OrGate(t, 1, t1.createReadWriteEnd(), s.createReadOnlyEnd(), q.createReadOnlyEnd());\r
+               new NotGate(t, 1, t2.createReadOnlyEnd(), q.createReadWriteEnd());\r
+               new NotGate(t, 1, t1.createReadOnlyEnd(), nq.createReadWriteEnd());\r
+\r
+               ReadWriteEnd sIn = s.createReadWriteEnd(), rIn = r.createReadWriteEnd();\r
+\r
+               sIn.feedSignals(Bit.ONE);\r
+               rIn.feedSignals(Bit.ZERO);\r
+\r
+               t.executeAll();\r
+\r
+               assertEquals(Bit.ONE, q.getValue());\r
+               assertEquals(Bit.ZERO, nq.getValue());\r
+\r
+               sIn.feedSignals(Bit.ZERO);\r
+\r
+               t.executeAll();\r
+               assertEquals(Bit.ONE, q.getValue());\r
+               assertEquals(Bit.ZERO, nq.getValue());\r
+\r
+               rIn.feedSignals(Bit.ONE);\r
+\r
+               t.executeAll();\r
+\r
+               assertEquals(Bit.ZERO, q.getValue());\r
+               assertEquals(Bit.ONE, nq.getValue());\r
+       }\r
+\r
+       @Test\r
+       void numericValueTest()\r
+       {\r
+               t.reset();\r
+\r
+               Wire a = new Wire(t, 4, 1);\r
+               a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);\r
+\r
+               t.executeAll();\r
+\r
+               assertEquals(15, a.getUnsignedValue());\r
+               assertEquals(-1, a.getSignedValue());\r
+       }\r
+\r
+       boolean flag = false;\r
+\r
+       @Test\r
+       void simpleTimelineTest()\r
+       {\r
+               Timeline t = new Timeline(3);\r
+               flag = false;\r
+               t.addEvent((e) ->\r
+               {\r
+                       if (!flag)\r
+                               fail("Events executed out of order!");\r
+                       flag = false;\r
+               }, 15);\r
+               t.addEvent((e) ->\r
+               {\r
+                       if (flag)\r
+                               fail("Events executed out of order!");\r
+                       flag = true;\r
+               }, 10);\r
+               t.addEvent((e) ->\r
+               {\r
+                       if (flag)\r
+                               fail("Events executed out of order!");\r
+                       flag = true;\r
+               }, 20);\r
+               t.addEvent((e) ->\r
+               {\r
+                       fail("Only supposed to execute until timestamp 20, not 25");\r
+               }, 25);\r
+\r
+               t.executeUntil(t.laterThan(20), 100);\r
+\r
+               if (!flag)\r
+                       fail("Not all events were executed in order!");\r
+       }\r
+\r
+       @Test\r
+       void multipleInputs()\r
+       {\r
+               t.reset();\r
+               Wire w = new Wire(t, 2, 1);\r
+               ReadWriteEnd wI1 = w.createReadWriteEnd(), wI2 = w.createReadWriteEnd();\r
+               wI1.feedSignals(Bit.ONE, Bit.Z);\r
+               wI2.feedSignals(Bit.Z, Bit.X);\r
+               t.executeAll();\r
+               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.X);\r
+\r
+               wI2.feedSignals(Bit.ZERO, Bit.Z);\r
+               t.executeAll();\r
+               assertBitArrayEquals(w.getValues(), Bit.X, Bit.Z);\r
+\r
+               wI2.feedSignals(Bit.Z, Bit.Z);\r
+               t.executeAll();\r
+               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);\r
+\r
+               wI2.feedSignals(Bit.ONE, Bit.Z);\r
+               ReadEnd rE = w.createReadOnlyEnd();\r
+               rE.registerObserver((i) -> fail("WireEnd notified observer, although value did not change."));\r
+               t.executeAll();\r
+               rE.close();\r
+               wI1.feedSignals(Bit.X, Bit.X);\r
+               t.executeAll();\r
+               wI1.registerObserver((i) -> fail("WireEnd notified observer, although it was closed."));\r
+               wI1.close();\r
+               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);\r
+       }\r
+\r
+       @Test\r
+       void wireConnections()\r
+       {\r
+               // Nur ein Experiment, was Ã¼ber mehrere 'passive' Bausteine hinweg passieren würde\r
+\r
+               t.reset();\r
+\r
+               Wire a = new Wire(t, 1, 2);\r
+               Wire b = new Wire(t, 1, 2);\r
+               Wire c = new Wire(t, 1, 2);\r
+               ReadWriteEnd aI = a.createReadWriteEnd();\r
+               ReadWriteEnd bI = b.createReadWriteEnd();\r
+               ReadWriteEnd cI = c.createReadWriteEnd();\r
+\r
+               TestBitDisplay test = new TestBitDisplay(t, c.createReadOnlyEnd());\r
+               TestBitDisplay test2 = new TestBitDisplay(t, a.createReadOnlyEnd());\r
+               LongConsumer print = time -> System.out.format("Time %2d\n   a: %s\n   b: %s\n   c: %s\n", time, a, b, c);\r
+\r
+               cI.feedSignals(Bit.ONE);\r
+               test.assertAfterSimulationIs(print, Bit.ONE);\r
+\r
+               cI.feedSignals(Bit.X);\r
+               test.assertAfterSimulationIs(print, Bit.X);\r
+\r
+               cI.feedSignals(Bit.X);\r
+               cI.feedSignals(Bit.Z);\r
+               test.assertAfterSimulationIs(print, Bit.Z);\r
+\r
+               new Connector(t, b.createReadWriteEnd(), c.createReadWriteEnd()).connect();\r
+               test.assertAfterSimulationIs(print, Bit.Z);\r
+               System.err.println("ONE");\r
+               bI.feedSignals(Bit.ONE);\r
+               test.assertAfterSimulationIs(print, Bit.ONE);\r
+               System.err.println("ZERO");\r
+               bI.feedSignals(Bit.ZERO);\r
+               test.assertAfterSimulationIs(print, Bit.ZERO);\r
+               System.err.println("Z");\r
+               bI.feedSignals(Bit.Z);\r
+               test.assertAfterSimulationIs(print, Bit.Z);\r
+\r
+               new Connector(t, a.createReadWriteEnd(), b.createReadWriteEnd()).connect();\r
+               System.err.println("Z 2");\r
+               aI.feedSignals(Bit.Z);\r
+               test.assertAfterSimulationIs(print, Bit.Z);\r
+               test2.assertAfterSimulationIs(Bit.Z);\r
+               System.err.println("ONE 2");\r
+               aI.feedSignals(Bit.ONE);\r
+               test.assertAfterSimulationIs(print, Bit.ONE);\r
+               test2.assertAfterSimulationIs(Bit.ONE);\r
+               System.err.println("ZERO 2");\r
+               aI.feedSignals(Bit.ZERO);\r
+               test.assertAfterSimulationIs(print, Bit.ZERO);\r
+               test2.assertAfterSimulationIs(Bit.ZERO);\r
+               System.err.println("Z 2 II");\r
+               aI.feedSignals(Bit.Z);\r
+               test.assertAfterSimulationIs(print, Bit.Z);\r
+               test2.assertAfterSimulationIs(Bit.Z);\r
+\r
+               System.err.println("No Conflict yet");\r
+               bI.feedSignals(Bit.ONE);\r
+               test.assertAfterSimulationIs(print, Bit.ONE);\r
+               test2.assertAfterSimulationIs(Bit.ONE);\r
+               aI.feedSignals(Bit.ONE);\r
+               test.assertAfterSimulationIs(print, Bit.ONE);\r
+               test2.assertAfterSimulationIs(Bit.ONE);\r
+               System.err.println("Conflict");\r
+               aI.feedSignals(Bit.ZERO);\r
+               test.assertAfterSimulationIs(print, Bit.X);\r
+               test2.assertAfterSimulationIs(Bit.X);\r
+               aI.feedSignals(Bit.ONE);\r
+               test.assertAfterSimulationIs(print, Bit.ONE);\r
+               test2.assertAfterSimulationIs(Bit.ONE);\r
+       }\r
+\r
+       private static void assertBitArrayEquals(BitVector actual, Bit... expected)\r
+       {\r
+               assertArrayEquals(expected, actual.getBits());\r
+       }\r
+}\r
index d73ee61..404aacd 100644 (file)
-package net.mograsim.logic.core.wires;
-
-import static net.mograsim.logic.core.types.Bit.U;
-import static net.mograsim.logic.core.types.Bit.Z;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.types.BitVector.BitVectorMutator;
-
-/**
- * Represents an array of wires that can store n bits of information.
- * 
- * @author Fabian Stemmler
- *
- */
-public class Wire
-{
-       private BitVector values;
-       public final int travelTime;
-       private List<ReadEnd> attached = new ArrayList<ReadEnd>();
-       public final int length;
-       private List<ReadWriteEnd> inputs = new ArrayList<ReadWriteEnd>();
-       private Timeline timeline;
-
-       public Wire(Timeline timeline, int length, int travelTime)
-       {
-               if (length < 1)
-                       throw new IllegalArgumentException(
-                                       String.format("Tried to create an array of wires with length %d, but a length of less than 1 makes no sense.", length));
-               this.timeline = timeline;
-               this.length = length;
-               this.travelTime = travelTime;
-               initValues();
-       }
-
-       private void initValues()
-       {
-               values = U.toVector(length);
-       }
-
-       private void recalculateSingleInput()
-       {
-               setNewValues(inputs.get(0).getInputValues());
-       }
-
-       private void recalculateMultipleInputs()
-       {
-               BitVectorMutator mutator = BitVectorMutator.empty();
-               for (ReadWriteEnd wireArrayEnd : inputs)
-                       mutator.join(wireArrayEnd.getInputValues());
-               setNewValues(mutator.get());
-       }
-
-       private void setNewValues(BitVector newValues)
-       {
-               if (values.equals(newValues))
-                       return;
-               BitVector oldValues = values;
-               values = newValues;
-               notifyObservers(oldValues);
-       }
-
-       private void recalculate()
-       {
-               switch (inputs.size())
-               {
-               case 0:
-                       return;
-               case 1:
-                       recalculateSingleInput();
-                       break;
-               default:
-                       recalculateMultipleInputs();
-               }
-       }
-
-       /**
-        * The {@link Wire} is interpreted as an unsigned integer with n bits.
-        * 
-        * @return <code>true</code> if all bits are either <code>Bit.ONE</code> or <code>Bit.ZERO</code> (they do not all have to have the same
-        *         value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is returned otherwise.
-        * 
-        * @author Fabian Stemmler
-        */
-       public boolean hasNumericValue()
-       {
-               for (Bit b : values)
-               {
-                       if (b != Bit.ZERO && b != Bit.ONE)
-                               return false;
-               }
-               return true;
-       }
-
-       /**
-        * The {@link Wire} is interpreted as an unsigned integer with n bits.
-        * 
-        * @return The unsigned value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
-        * 
-        * @author Fabian Stemmler
-        */
-       public long getUnsignedValue()
-       {
-               long val = 0;
-               long mask = 1;
-               for (Bit bit : values)
-               {
-                       switch (bit)
-                       {
-                       default:
-                       case Z:
-                       case X:
-                               return 0; // TODO: Proper handling for getUnsignedValue(), if not all bits are 1 or 0;
-                       case ONE:
-                               val |= mask;
-                               break;
-                       case ZERO:
-                       }
-                       mask = mask << 1;
-               }
-               return val;
-       }
-
-       /**
-        * The {@link Wire} is interpreted as a signed integer with n bits.
-        * 
-        * @return The signed value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
-        * 
-        * @author Fabian Stemmler
-        */
-       public long getSignedValue()
-       {
-               long val = getUnsignedValue();
-               long mask = 1 << (length - 1);
-               if ((mask & val) != 0)
-               {
-                       int shifts = 64 - length;
-                       return (val << shifts) >> shifts;
-               }
-               return val;
-       }
-
-       public Bit getValue()
-       {
-               return getValue(0);
-       }
-
-       public Bit getValue(int index)
-       {
-               return values.getBit(index);
-       }
-
-       public BitVector getValues(int start, int end)
-       {
-               return values.subVector(start, end);
-       }
-
-       public BitVector getValues()
-       {
-               return values;
-       }
-
-       /**
-        * Adds an {@link WireObserver}, who will be notified when the value of the {@link Wire} is updated.
-        * 
-        * @param ob The {@link WireObserver} to be notified of changes.
-        * @return true if the given {@link WireObserver} was not already registered, false otherwise
-        * 
-        * @author Fabian Stemmler
-        */
-       private void attachEnd(ReadEnd end)
-       {
-               attached.add(end);
-       }
-
-       private void detachEnd(ReadEnd end)
-       {
-               attached.remove(end);
-       }
-
-       private void notifyObservers(BitVector oldValues)
-       {
-               for (ReadEnd o : attached)
-                       o.update(oldValues);
-       }
-
-       /**
-        * Create and register a {@link ReadWriteEnd} object, which is tied to this {@link Wire}. This {@link ReadWriteEnd} can be written to.
-        */
-       public ReadWriteEnd createReadWriteEnd()
-       {
-               return new ReadWriteEnd();
-       }
-
-       /**
-        * Create a {@link ReadEnd} object, which is tied to this {@link Wire}. This {@link ReadEnd} cannot be written to.
-        */
-       public ReadEnd createReadOnlyEnd()
-       {
-               return new ReadEnd();
-       }
-
-       private void registerInput(ReadWriteEnd toRegister)
-       {
-               inputs.add(toRegister);
-       }
-
-       /**
-        * A {@link ReadEnd} feeds a constant signal into the {@link Wire} it is tied to. The combination of all inputs determines the
-        * {@link Wire}s final value. X dominates all other inputs Z does not affect the final value, unless there are no other inputs than Z 0
-        * and 1 turn into X when they are mixed
-        * 
-        * @author Fabian Stemmler
-        */
-       public class ReadEnd
-       {
-               private List<WireObserver> observers = new ArrayList<WireObserver>();
-
-               private ReadEnd()
-               {
-                       super();
-                       Wire.this.attachEnd(this);
-               }
-
-               public void update(BitVector oldValues)
-               {
-                       for (WireObserver ob : observers)
-                               ob.update(this, oldValues);
-               }
-
-               /**
-                * Included for convenient use on {@link Wire}s of length 1.
-                * 
-                * @return The value of bit 0.
-                * 
-                * @author Fabian Stemmler
-                */
-               public Bit getValue()
-               {
-                       return Wire.this.getValue();
-               }
-
-               /**
-                * @param index Index of the requested bit.
-                * @return The value of the indexed bit.
-                * 
-                * @author Fabian Stemmler
-                */
-               public Bit getValue(int index)
-               {
-                       return Wire.this.getValue(index);
-               }
-
-               /**
-                * @param index Index of the requested bit.
-                * @return The value of the indexed bit.
-                * 
-                * @author Fabian Stemmler
-                */
-               public BitVector getValues()
-               {
-                       return Wire.this.getValues();
-               }
-
-               /**
-                * @param start Start of the wanted segment. (inclusive)
-                * @param end   End of the wanted segment. (exclusive)
-                * @return The values of the segment of {@link Bit}s indexed.
-                * 
-                * @author Fabian Stemmler
-                */
-               public BitVector getValues(int start, int end)
-               {
-                       return Wire.this.getValues(start, end);
-               }
-
-               /**
-                * The {@link Wire} is interpreted as an unsigned integer with n bits.
-                * 
-                * @return <code>true</code> if all bits are either <code>Bit.ONE</code> or <code>Bit.ZERO</code> (they do not all have to have the
-                *         same value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is returned otherwise.
-                * 
-                * @author Fabian Stemmler
-                */
-               public boolean hasNumericValue()
-               {
-                       return Wire.this.hasNumericValue();
-               }
-
-               /**
-                * The {@link Wire} is interpreted as an unsigned integer with n bits.
-                * 
-                * @return The unsigned value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
-                * 
-                * @author Fabian Stemmler
-                */
-               public long getUnsignedValue()
-               {
-                       return Wire.this.getUnsignedValue();
-               }
-
-               /**
-                * The {@link Wire} is interpreted as a signed integer with n bits.
-                * 
-                * @return The signed value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
-                * 
-                * @author Fabian Stemmler
-                */
-               public long getSignedValue()
-               {
-                       return Wire.this.getSignedValue();
-               }
-
-               @Override
-               public String toString()
-               {
-                       return Wire.this.toString();
-               }
-
-               public void close()
-               {
-                       inputs.remove(this);
-                       detachEnd(this);
-                       recalculate();
-               }
-
-               public int length()
-               {
-                       return length;
-               }
-
-               public boolean addObserver(WireObserver ob)
-               {
-                       return observers.add(ob);
-               }
-
-               public Wire getWire()
-               {
-                       return Wire.this;
-               }
-       }
-
-       public class ReadWriteEnd extends ReadEnd
-       {
-               private boolean open;
-               private BitVector inputValues;
-
-               private ReadWriteEnd()
-               {
-                       super();
-                       open = true;
-                       initValues();
-                       registerInput(this);
-               }
-
-               private void initValues()
-               {
-                       inputValues = U.toVector(length);
-               }
-
-               /**
-                * Sets the wires values. This takes up time, as specified by the {@link Wire}s travel time.
-                * 
-                * @param newValues The new values the wires should take on.
-                * 
-                * @author Fabian Stemmler
-                */
-               public void feedSignals(Bit... newValues)
-               {
-                       feedSignals(BitVector.of(newValues));
-               }
-
-               public void feedSignals(BitVector newValues)
-               {
-                       if (newValues.length() != length)
-                               throw new IllegalArgumentException(
-                                               String.format("Attempted to input %d bits instead of %d bits.", newValues.length(), length));
-                       if (!open)
-                               throw new RuntimeException("Attempted to write to closed WireArrayEnd.");
-                       timeline.addEvent(e -> setValues(newValues), travelTime);
-               }
-
-               /**
-                * Sets values of a subarray of wires. This takes up time, as specified by the {@link Wire}s travel time.
-                * 
-                * @param bitVector   The new values the wires should take on.
-                * @param startingBit The first index of the subarray of wires.
-                * 
-                * @author Fabian Stemmler
-                */
-               public void feedSignals(int startingBit, BitVector bitVector)
-               {
-                       if (!open)
-                               throw new RuntimeException("Attempted to write to closed WireArrayEnd.");
-                       timeline.addEvent(e -> setValues(startingBit, bitVector), travelTime);
-               }
-
-               private void setValues(int startingBit, BitVector newValues)
-               {
-                       // index check covered in equals
-                       if (!inputValues.equalsWithOffset(newValues, startingBit))
-                       {
-                               Bit[] vals = inputValues.getBits();
-                               System.arraycopy(newValues.getBits(), 0, vals, startingBit, newValues.length());
-                               inputValues = BitVector.of(vals);
-                               Wire.this.recalculate();
-                       }
-               }
-
-               private void setValues(BitVector newValues)
-               {
-                       if (inputValues.equals(newValues))
-                               return;
-                       inputValues = newValues;
-                       Wire.this.recalculate();
-               }
-
-               /**
-                * @return The value (of bit 0) the {@link ReadEnd} is currently feeding into the associated {@link Wire}.
-                */
-               public Bit getInputValue()
-               {
-                       return getInputValue(0);
-               }
-
-               /**
-                * @return The value which the {@link ReadEnd} is currently feeding into the associated {@link Wire} at the indexed {@link Bit}.
-                */
-               public Bit getInputValue(int index)
-               {
-                       return inputValues.getBit(index);
-               }
-
-               /**
-                * @return A copy (safe to modify) of the values the {@link ReadEnd} is currently feeding into the associated {@link Wire}.
-                */
-               public BitVector getInputValues()
-               {
-                       return getInputValues(0, length);
-               }
-
-               public BitVector getInputValues(int start, int end)
-               {
-                       return inputValues.subVector(start, end);
-               }
-
-               /**
-                * {@link ReadEnd} now feeds Z into the associated {@link Wire}.
-                */
-               public void clearSignals()
-               {
-                       feedSignals(Z.toVector(length));
-               }
-
-               public BitVector wireValuesExcludingMe()
-               {
-                       BitVectorMutator mutator = BitVectorMutator.empty();
-                       for (ReadWriteEnd wireEnd : inputs)
-                       {
-                               if (wireEnd == this)
-                                       continue;
-                               mutator.join(wireEnd.inputValues);
-                       }
-                       return mutator.get();
-               }
-
-               @Override
-               public String toString()
-               {
-                       return inputValues.toString();
-               }
-       }
-
-       @Override
-       public String toString()
-       {
-               return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), values, inputs);
-               // Arrays.toString(values), inputs.stream().map(i -> Arrays.toString(i.inputValues)).reduce((s1, s2) -> s1 + s2)
-       }
-
-       public static ReadEnd[] extractEnds(Wire[] w)
-       {
-               ReadEnd[] inputs = new ReadEnd[w.length];
-               for (int i = 0; i < w.length; i++)
-                       inputs[i] = w[i].createReadWriteEnd();
-               return inputs;
-       }
+package net.mograsim.logic.core.wires;\r
+\r
+import static net.mograsim.logic.core.types.Bit.U;\r
+import static net.mograsim.logic.core.types.Bit.Z;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.types.BitVector;\r
+import net.mograsim.logic.core.types.BitVector.BitVectorMutator;\r
+\r
+/**\r
+ * Represents an array of wires that can store n bits of information.\r
+ * \r
+ * @author Fabian Stemmler\r
+ *\r
+ */\r
+public class Wire\r
+{\r
+       private BitVector values;\r
+       public final int travelTime;\r
+       private List<ReadEnd> attached = new ArrayList<ReadEnd>();\r
+       public final int length;\r
+       private List<ReadWriteEnd> inputs = new ArrayList<ReadWriteEnd>();\r
+       private Timeline timeline;\r
+\r
+       public Wire(Timeline timeline, int length, int travelTime)\r
+       {\r
+               if (length < 1)\r
+                       throw new IllegalArgumentException(\r
+                                       String.format("Tried to create an array of wires with length %d, but a length of less than 1 makes no sense.", length));\r
+               this.timeline = timeline;\r
+               this.length = length;\r
+               this.travelTime = travelTime;\r
+               initValues();\r
+       }\r
+\r
+       private void initValues()\r
+       {\r
+               values = U.toVector(length);\r
+       }\r
+\r
+       private void recalculateSingleInput()\r
+       {\r
+               setNewValues(inputs.get(0).getInputValues());\r
+       }\r
+\r
+       private void recalculateMultipleInputs()\r
+       {\r
+               BitVectorMutator mutator = BitVectorMutator.empty();\r
+               for (ReadWriteEnd wireArrayEnd : inputs)\r
+                       mutator.join(wireArrayEnd.getInputValues());\r
+               setNewValues(mutator.get());\r
+       }\r
+\r
+       private void setNewValues(BitVector newValues)\r
+       {\r
+               if (values.equals(newValues))\r
+                       return;\r
+               BitVector oldValues = values;\r
+               values = newValues;\r
+               notifyObservers(oldValues);\r
+       }\r
+\r
+       private void recalculate()\r
+       {\r
+               switch (inputs.size())\r
+               {\r
+               case 0:\r
+                       return;\r
+               case 1:\r
+                       recalculateSingleInput();\r
+                       break;\r
+               default:\r
+                       recalculateMultipleInputs();\r
+               }\r
+       }\r
+\r
+       /**\r
+        * The {@link Wire} is interpreted as an unsigned integer with n bits.\r
+        * \r
+        * @return <code>true</code> if all bits are either <code>Bit.ONE</code> or <code>Bit.ZERO</code> (they do not all have to have the same\r
+        *         value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is returned otherwise.\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       public boolean hasNumericValue()\r
+       {\r
+               for (Bit b : values)\r
+               {\r
+                       if (b != Bit.ZERO && b != Bit.ONE)\r
+                               return false;\r
+               }\r
+               return true;\r
+       }\r
+\r
+       /**\r
+        * The {@link Wire} is interpreted as an unsigned integer with n bits.\r
+        * \r
+        * @return The unsigned value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       public long getUnsignedValue()\r
+       {\r
+               long val = 0;\r
+               long mask = 1;\r
+               for (Bit bit : values)\r
+               {\r
+                       switch (bit)\r
+                       {\r
+                       default:\r
+                       case Z:\r
+                       case X:\r
+                               return 0; // TODO: Proper handling for getUnsignedValue(), if not all bits are 1 or 0;\r
+                       case ONE:\r
+                               val |= mask;\r
+                               break;\r
+                       case ZERO:\r
+                       }\r
+                       mask = mask << 1;\r
+               }\r
+               return val;\r
+       }\r
+\r
+       /**\r
+        * The {@link Wire} is interpreted as a signed integer with n bits.\r
+        * \r
+        * @return The signed value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       public long getSignedValue()\r
+       {\r
+               long val = getUnsignedValue();\r
+               long mask = 1 << (length - 1);\r
+               if ((mask & val) != 0)\r
+               {\r
+                       int shifts = 64 - length;\r
+                       return (val << shifts) >> shifts;\r
+               }\r
+               return val;\r
+       }\r
+\r
+       public Bit getValue()\r
+       {\r
+               return getValue(0);\r
+       }\r
+\r
+       public Bit getValue(int index)\r
+       {\r
+               return values.getBit(index);\r
+       }\r
+\r
+       public BitVector getValues(int start, int end)\r
+       {\r
+               return values.subVector(start, end);\r
+       }\r
+\r
+       public BitVector getValues()\r
+       {\r
+               return values;\r
+       }\r
+\r
+       /**\r
+        * Adds an {@link LogicObserver}, who will be notified when the value of the {@link Wire} is updated.\r
+        * \r
+        * @param ob The {@link LogicObserver} to be notified of changes.\r
+        * @return true if the given {@link LogicObserver} was not already registered, false otherwise\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       private void attachEnd(ReadEnd end)\r
+       {\r
+               attached.add(end);\r
+       }\r
+\r
+       private void detachEnd(ReadEnd end)\r
+       {\r
+               attached.remove(end);\r
+       }\r
+\r
+       private void notifyObservers(BitVector oldValues)\r
+       {\r
+               for (ReadEnd o : attached)\r
+                       o.update(oldValues);\r
+       }\r
+\r
+       /**\r
+        * Create and register a {@link ReadWriteEnd} object, which is tied to this {@link Wire}. This {@link ReadWriteEnd} can be written to.\r
+        */\r
+       public ReadWriteEnd createReadWriteEnd()\r
+       {\r
+               return new ReadWriteEnd();\r
+       }\r
+\r
+       /**\r
+        * Create a {@link ReadEnd} object, which is tied to this {@link Wire}. This {@link ReadEnd} cannot be written to.\r
+        */\r
+       public ReadEnd createReadOnlyEnd()\r
+       {\r
+               return new ReadEnd();\r
+       }\r
+\r
+       private void registerInput(ReadWriteEnd toRegister)\r
+       {\r
+               inputs.add(toRegister);\r
+       }\r
+\r
+       /**\r
+        * A {@link ReadEnd} feeds a constant signal into the {@link Wire} it is tied to. The combination of all inputs determines the\r
+        * {@link Wire}s final value. X dominates all other inputs Z does not affect the final value, unless there are no other inputs than Z 0\r
+        * and 1 turn into X when they are mixed\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       public class ReadEnd implements LogicObservable\r
+       {\r
+               private List<LogicObserver> observers = new ArrayList<LogicObserver>();\r
+\r
+               private ReadEnd()\r
+               {\r
+                       super();\r
+                       Wire.this.attachEnd(this);\r
+               }\r
+\r
+               public void update(BitVector oldValues)\r
+               {\r
+                       notifyObservers();\r
+               }\r
+\r
+               /**\r
+                * Included for convenient use on {@link Wire}s of length 1.\r
+                * \r
+                * @return The value of bit 0.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public Bit getValue()\r
+               {\r
+                       return Wire.this.getValue();\r
+               }\r
+\r
+               /**\r
+                * @param index Index of the requested bit.\r
+                * @return The value of the indexed bit.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public Bit getValue(int index)\r
+               {\r
+                       return Wire.this.getValue(index);\r
+               }\r
+\r
+               /**\r
+                * @param index Index of the requested bit.\r
+                * @return The value of the indexed bit.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public BitVector getValues()\r
+               {\r
+                       return Wire.this.getValues();\r
+               }\r
+\r
+               /**\r
+                * @param start Start of the wanted segment. (inclusive)\r
+                * @param end   End of the wanted segment. (exclusive)\r
+                * @return The values of the segment of {@link Bit}s indexed.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public BitVector getValues(int start, int end)\r
+               {\r
+                       return Wire.this.getValues(start, end);\r
+               }\r
+\r
+               /**\r
+                * The {@link Wire} is interpreted as an unsigned integer with n bits.\r
+                * \r
+                * @return <code>true</code> if all bits are either <code>Bit.ONE</code> or <code>Bit.ZERO</code> (they do not all have to have the\r
+                *         same value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is returned otherwise.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public boolean hasNumericValue()\r
+               {\r
+                       return Wire.this.hasNumericValue();\r
+               }\r
+\r
+               /**\r
+                * The {@link Wire} is interpreted as an unsigned integer with n bits.\r
+                * \r
+                * @return The unsigned value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public long getUnsignedValue()\r
+               {\r
+                       return Wire.this.getUnsignedValue();\r
+               }\r
+\r
+               /**\r
+                * The {@link Wire} is interpreted as a signed integer with n bits.\r
+                * \r
+                * @return The signed value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public long getSignedValue()\r
+               {\r
+                       return Wire.this.getSignedValue();\r
+               }\r
+\r
+               @Override\r
+               public String toString()\r
+               {\r
+                       return Wire.this.toString();\r
+               }\r
+\r
+               public void close()\r
+               {\r
+                       inputs.remove(this);\r
+                       detachEnd(this);\r
+                       recalculate();\r
+               }\r
+\r
+               public int length()\r
+               {\r
+                       return length;\r
+               }\r
+\r
+               public Wire getWire()\r
+               {\r
+                       return Wire.this;\r
+               }\r
+\r
+               @Override\r
+               public void registerObserver(LogicObserver ob)\r
+               {\r
+                       observers.add(ob);\r
+               }\r
+\r
+               @Override\r
+               public void notifyObservers()\r
+               {\r
+                       for (LogicObserver ob : observers)\r
+                               ob.update(this);\r
+               }\r
+       }\r
+\r
+       public class ReadWriteEnd extends ReadEnd\r
+       {\r
+               private boolean open;\r
+               private BitVector inputValues;\r
+\r
+               private ReadWriteEnd()\r
+               {\r
+                       super();\r
+                       open = true;\r
+                       initValues();\r
+                       registerInput(this);\r
+               }\r
+\r
+               private void initValues()\r
+               {\r
+                       inputValues = U.toVector(length);\r
+               }\r
+\r
+               /**\r
+                * Sets the wires values. This takes up time, as specified by the {@link Wire}s travel time.\r
+                * \r
+                * @param newValues The new values the wires should take on.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public void feedSignals(Bit... newValues)\r
+               {\r
+                       feedSignals(BitVector.of(newValues));\r
+               }\r
+\r
+               public void feedSignals(BitVector newValues)\r
+               {\r
+                       if (newValues.length() != length)\r
+                               throw new IllegalArgumentException(\r
+                                               String.format("Attempted to input %d bits instead of %d bits.", newValues.length(), length));\r
+                       if (!open)\r
+                               throw new RuntimeException("Attempted to write to closed WireArrayEnd.");\r
+                       timeline.addEvent(e -> setValues(newValues), travelTime);\r
+               }\r
+\r
+               /**\r
+                * Sets values of a subarray of wires. This takes up time, as specified by the {@link Wire}s travel time.\r
+                * \r
+                * @param bitVector   The new values the wires should take on.\r
+                * @param startingBit The first index of the subarray of wires.\r
+                * \r
+                * @author Fabian Stemmler\r
+                */\r
+               public void feedSignals(int startingBit, BitVector bitVector)\r
+               {\r
+                       if (!open)\r
+                               throw new RuntimeException("Attempted to write to closed WireArrayEnd.");\r
+                       timeline.addEvent(e -> setValues(startingBit, bitVector), travelTime);\r
+               }\r
+\r
+               private void setValues(int startingBit, BitVector newValues)\r
+               {\r
+                       // index check covered in equals\r
+                       if (!inputValues.equalsWithOffset(newValues, startingBit))\r
+                       {\r
+                               Bit[] vals = inputValues.getBits();\r
+                               System.arraycopy(newValues.getBits(), 0, vals, startingBit, newValues.length());\r
+                               inputValues = BitVector.of(vals);\r
+                               Wire.this.recalculate();\r
+                       }\r
+               }\r
+\r
+               private void setValues(BitVector newValues)\r
+               {\r
+                       if (inputValues.equals(newValues))\r
+                               return;\r
+                       inputValues = newValues;\r
+                       Wire.this.recalculate();\r
+               }\r
+\r
+               /**\r
+                * @return The value (of bit 0) the {@link ReadEnd} is currently feeding into the associated {@link Wire}.\r
+                */\r
+               public Bit getInputValue()\r
+               {\r
+                       return getInputValue(0);\r
+               }\r
+\r
+               /**\r
+                * @return The value which the {@link ReadEnd} is currently feeding into the associated {@link Wire} at the indexed {@link Bit}.\r
+                */\r
+               public Bit getInputValue(int index)\r
+               {\r
+                       return inputValues.getBit(index);\r
+               }\r
+\r
+               /**\r
+                * @return A copy (safe to modify) of the values the {@link ReadEnd} is currently feeding into the associated {@link Wire}.\r
+                */\r
+               public BitVector getInputValues()\r
+               {\r
+                       return getInputValues(0, length);\r
+               }\r
+\r
+               public BitVector getInputValues(int start, int end)\r
+               {\r
+                       return inputValues.subVector(start, end);\r
+               }\r
+\r
+               /**\r
+                * {@link ReadEnd} now feeds Z into the associated {@link Wire}.\r
+                */\r
+               public void clearSignals()\r
+               {\r
+                       feedSignals(Z.toVector(length));\r
+               }\r
+\r
+               public BitVector wireValuesExcludingMe()\r
+               {\r
+                       BitVectorMutator mutator = BitVectorMutator.empty();\r
+                       for (ReadWriteEnd wireEnd : inputs)\r
+                       {\r
+                               if (wireEnd == this)\r
+                                       continue;\r
+                               mutator.join(wireEnd.inputValues);\r
+                       }\r
+                       return mutator.get();\r
+               }\r
+\r
+               @Override\r
+               public String toString()\r
+               {\r
+                       return inputValues.toString();\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public String toString()\r
+       {\r
+               return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), values, inputs);\r
+       }\r
+\r
+       public static ReadEnd[] extractEnds(Wire[] w)\r
+       {\r
+               ReadEnd[] inputs = new ReadEnd[w.length];\r
+               for (int i = 0; i < w.length; i++)\r
+                       inputs[i] = w[i].createReadWriteEnd();\r
+               return inputs;\r
+       }\r
 }
\ No newline at end of file
diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/wires/WireObserver.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/wires/WireObserver.java
deleted file mode 100644 (file)
index 66914b4..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-package net.mograsim.logic.core.wires;
-
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-
-public interface WireObserver
-{
-       public void update(ReadEnd initiator, BitVector oldValues);
-}