WireEnd functionality split into ReadEnd and ReadWriteEnd
authorFabian Stemmler <stemmler@in.tum.de>
Fri, 24 May 2019 22:12:15 +0000 (00:12 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Fri, 24 May 2019 22:12:15 +0000 (00:12 +0200)
20 files changed:
era.mi/src/era/mi/logic/components/BasicComponent.java
era.mi/src/era/mi/logic/components/BitDisplay.java
era.mi/src/era/mi/logic/components/Clock.java
era.mi/src/era/mi/logic/components/Component.java
era.mi/src/era/mi/logic/components/Connector.java
era.mi/src/era/mi/logic/components/Demux.java
era.mi/src/era/mi/logic/components/ManualSwitch.java
era.mi/src/era/mi/logic/components/Merger.java
era.mi/src/era/mi/logic/components/Mux.java
era.mi/src/era/mi/logic/components/Splitter.java
era.mi/src/era/mi/logic/components/TriStateBuffer.java
era.mi/src/era/mi/logic/components/gates/AndGate.java
era.mi/src/era/mi/logic/components/gates/MultiInputGate.java
era.mi/src/era/mi/logic/components/gates/NotGate.java
era.mi/src/era/mi/logic/components/gates/OrGate.java
era.mi/src/era/mi/logic/components/gates/XorGate.java
era.mi/src/era/mi/logic/tests/ComponentTest.java
era.mi/src/era/mi/logic/tests/TestBitDisplay.java
era.mi/src/era/mi/logic/wires/Wire.java
era.mi/src/era/mi/logic/wires/WireObserver.java

index e695283..f73e0f7 100644 (file)
@@ -1,35 +1,35 @@
-package era.mi.logic.components;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.WireObserver;
-
-/**
- * A basic component that recomputes all outputs (with a delay), when it is updated.
- * 
- * @author Fabian Stemmler
- */
-public abstract class BasicComponent implements WireObserver, Component
-{
-       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(int processTime)
-       {
-               this.processTime = processTime > 0 ? processTime : 1;
-       }
-
-       @Override
-       public void update(Wire initiator, BitVector oldValues)
-       {
-               Simulation.TIMELINE.addEvent(e -> compute(), processTime);
-       }
-
-       protected abstract void compute();
-}
+package era.mi.logic.components;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.WireObserver;\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 implements WireObserver, Component\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(int processTime)\r
+       {\r
+               this.processTime = processTime > 0 ? processTime : 1;\r
+       }\r
+\r
+       @Override\r
+       public void update(ReadEnd initiator, BitVector oldValues)\r
+       {\r
+               Simulation.TIMELINE.addEvent(e -> compute(), processTime);\r
+       }\r
+\r
+       protected abstract void compute();\r
+}\r
index 971eb7a..28b5165 100644 (file)
@@ -1,49 +1,50 @@
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.types.Bit;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class BitDisplay extends BasicComponent
-{
-       private final WireEnd in;
-       private BitVector displayedValue;
-
-       public BitDisplay(WireEnd in)
-       {
-               super(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<WireEnd> getAllInputs()
-       {
-               return List.of(in);
-       }
-
-       @Override
-       public List<WireEnd> getAllOutputs()
-       {
-               return List.of();
-       }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class BitDisplay extends BasicComponent\r
+{\r
+       private final ReadEnd in;\r
+       private BitVector displayedValue;\r
+\r
+       public BitDisplay(ReadEnd in)\r
+       {\r
+               super(1);\r
+               this.in = in;\r
+               in.addObserver(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 07419b4..b4528a4 100644 (file)
@@ -1,59 +1,60 @@
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.timeline.TimelineEvent;
-import era.mi.logic.timeline.TimelineEventHandler;
-import era.mi.logic.types.Bit;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class Clock implements TimelineEventHandler, Component
-{
-       private boolean toggle = false;
-       private WireEnd out;
-       private int delta;
-
-       /**
-        * 
-        * @param out   {@link Wire} the clock's impulses are fed into
-        * @param delta ticks between rising and falling edge
-        */
-       public Clock(WireEnd out, int delta)
-       {
-               this.delta = delta;
-               this.out = out;
-               addToTimeline();
-       }
-
-       @Override
-       public void handle(TimelineEvent e)
-       {
-               addToTimeline();
-               out.feedSignals(toggle ? Bit.ONE : Bit.ZERO);
-               toggle = !toggle;
-       }
-
-       public WireEnd getOut()
-       {
-               return out;
-       }
-
-       private void addToTimeline()
-       {
-               Simulation.TIMELINE.addEvent(this, delta);
-       }
-
-       @Override
-       public List<WireEnd> getAllInputs()
-       {
-               return List.of();
-       }
-
-       @Override
-       public List<WireEnd> getAllOutputs()
-       {
-               return List.of(out);
-       }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.timeline.TimelineEvent;\r
+import era.mi.logic.timeline.TimelineEventHandler;\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.wires.Wire;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class Clock implements TimelineEventHandler, Component\r
+{\r
+       private boolean toggle = false;\r
+       private ReadWriteEnd out;\r
+       private int delta;\r
+\r
+       /**\r
+        * \r
+        * @param out   {@link Wire} the clock's impulses are fed into\r
+        * @param delta ticks between rising and falling edge\r
+        */\r
+       public Clock(ReadWriteEnd out, int delta)\r
+       {\r
+               this.delta = delta;\r
+               this.out = out;\r
+               addToTimeline();\r
+       }\r
+\r
+       @Override\r
+       public void handle(TimelineEvent e)\r
+       {\r
+               addToTimeline();\r
+               out.feedSignals(toggle ? Bit.ONE : Bit.ZERO);\r
+               toggle = !toggle;\r
+       }\r
+\r
+       public ReadWriteEnd getOut()\r
+       {\r
+               return out;\r
+       }\r
+\r
+       private void addToTimeline()\r
+       {\r
+               Simulation.TIMELINE.addEvent(this, delta);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of();\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(out);\r
+       }\r
+}\r
index 5e994e3..d749a4b 100644 (file)
@@ -2,7 +2,8 @@ package era.mi.logic.components;
 \r
 import java.util.List;\r
 \r
 \r
 import java.util.List;\r
 \r
-import era.mi.logic.wires.Wire.WireEnd;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
 \r
 public interface Component\r
 {\r
 \r
 public interface Component\r
 {\r
@@ -11,10 +12,10 @@ public interface Component
         * Returns immutable list of all inputs to the {@link Component} (including e.g. the select bits to a MUX). Intended for visualization\r
         * in the UI.\r
         */\r
         * Returns immutable list of all inputs to the {@link Component} (including e.g. the select bits to a MUX). Intended for visualization\r
         * in the UI.\r
         */\r
-       public List<WireEnd> getAllInputs();\r
+       public List<ReadEnd> getAllInputs();\r
 \r
        /**\r
         * Returns immutable list of all outputs to the {@link Component}. Intended for visualization in the UI.\r
         */\r
 \r
        /**\r
         * Returns immutable list of all outputs to the {@link Component}. Intended for visualization in the UI.\r
         */\r
-       public List<WireEnd> getAllOutputs();\r
+       public List<ReadWriteEnd> getAllOutputs();\r
 }\r
 }\r
index 89fb96e..4f211bf 100644 (file)
@@ -1,75 +1,75 @@
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-import era.mi.logic.wires.WireObserver;
-
-public class Connector implements WireObserver, Component
-{
-       private boolean connected;
-       private final WireEnd a;
-       private final WireEnd b;
-
-       public Connector(WireEnd a, WireEnd b)
-       {
-               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.getWire());
-               update(b.getWire());
-       }
-
-       public void disconnect()
-       {
-               connected = false;
-               a.clearSignals();
-               b.clearSignals();
-       }
-
-       public void setConnection(boolean connected)
-       {
-               if (connected)
-                       connect();
-               else
-                       disconnect();
-       }
-
-       @Override
-       public void update(Wire initiator, BitVector oldValues)
-       {
-               if (connected)
-                       Simulation.TIMELINE.addEvent(e -> update(initiator), 1);
-       }
-
-       private void update(Wire initiator)
-       {
-               if (initiator == a.getWire())
-                       b.feedSignals(a.wireValuesExcludingMe());
-               else
-                       a.feedSignals(b.wireValuesExcludingMe());
-       }
-
-       @Override
-       public List<WireEnd> getAllInputs()
-       {
-               return List.of(a, b);
-       }
-
-       @Override
-       public List<WireEnd> getAllOutputs()
-       {
-               return List.of(a, b);
-       }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+import era.mi.logic.wires.WireObserver;\r
+\r
+public class Connector implements WireObserver, Component\r
+{\r
+       private boolean connected;\r
+       private final ReadWriteEnd a;\r
+       private final ReadWriteEnd b;\r
+\r
+       public Connector(ReadWriteEnd a, ReadWriteEnd b)\r
+       {\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.addObserver(this);\r
+               b.addObserver(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(ReadEnd initiator, BitVector oldValues)\r
+       {\r
+               if (connected)\r
+                       Simulation.TIMELINE.addEvent(e -> update(initiator), 1);\r
+       }\r
+\r
+       private void update(ReadEnd 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 ffc1bba..0a48cb9 100644 (file)
@@ -3,7 +3,8 @@ package era.mi.logic.components;
 import java.util.List;\r
 \r
 import era.mi.logic.wires.Wire;\r
 import java.util.List;\r
 \r
 import era.mi.logic.wires.Wire;\r
-import era.mi.logic.wires.Wire.WireEnd;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.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
 \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
@@ -14,8 +15,8 @@ import era.mi.logic.wires.Wire.WireEnd;
  */\r
 public class Demux extends BasicComponent\r
 {\r
  */\r
 public class Demux extends BasicComponent\r
 {\r
-       private final WireEnd select, in;\r
-       private final WireEnd[] outputs;\r
+       private final ReadEnd select, in;\r
+       private final ReadWriteEnd[] outputs;\r
        private final int outputSize;\r
        private int selected = -1;\r
 \r
        private final int outputSize;\r
        private int selected = -1;\r
 \r
@@ -26,7 +27,7 @@ public class Demux extends BasicComponent
         * @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
         * @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(int processTime, WireEnd in, WireEnd select, WireEnd... outputs)\r
+       public Demux(int processTime, ReadEnd in, ReadEnd select, ReadWriteEnd... outputs)\r
        {\r
                super(processTime);\r
                outputSize = in.length();\r
        {\r
                super(processTime);\r
                outputSize = in.length();\r
@@ -67,13 +68,13 @@ public class Demux extends BasicComponent
        }\r
 \r
        @Override\r
        }\r
 \r
        @Override\r
-       public List<WireEnd> getAllInputs()\r
+       public List<ReadEnd> getAllInputs()\r
        {\r
                return List.of(in, select);\r
        }\r
 \r
        @Override\r
        {\r
                return List.of(in, select);\r
        }\r
 \r
        @Override\r
-       public List<WireEnd> getAllOutputs()\r
+       public List<ReadWriteEnd> getAllOutputs()\r
        {\r
                return List.of(outputs);\r
        }\r
        {\r
                return List.of(outputs);\r
        }\r
index 0ad4a76..0b694a4 100644 (file)
@@ -1,71 +1,72 @@
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.types.Bit;
-import era.mi.logic.wires.Wire.WireEnd;
-
-/**
- * This class models a simple on/off (ONE/ZERO) switch for user interaction.
- *
- * @author Christian Femers
- *
- */
-public class ManualSwitch implements Component
-{
-       private WireEnd output;
-       private boolean isOn;
-
-       public ManualSwitch(WireEnd output)
-       {
-               if (output.length() != 1)
-                       throw new IllegalArgumentException("Switch output can be only a single wire");
-               this.output = output;
-       }
-
-       public void switchOn()
-       {
-               setState(true);
-       }
-
-       public void switchOff()
-       {
-               setState(false);
-       }
-
-       public void toggle()
-       {
-               setState(!isOn);
-       }
-
-       public void setState(boolean isOn)
-       {
-               if (this.isOn == isOn)
-                       return;
-               this.isOn = isOn;
-               output.feedSignals(getValue());
-       }
-
-       public boolean isOn()
-       {
-               return isOn;
-       }
-
-       public Bit getValue()
-       {
-               return isOn ? Bit.ONE : Bit.ZERO;
-       }
-
-       @Override
-       public List<WireEnd> getAllInputs()
-       {
-               return List.of();
-       }
-
-       @Override
-       public List<WireEnd> getAllOutputs()
-       {
-               return List.of(output);
-       }
-
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+/**\r
+ * This class models a simple on/off (ONE/ZERO) switch for user interaction.\r
+ *\r
+ * @author Christian Femers\r
+ *\r
+ */\r
+public class ManualSwitch implements Component\r
+{\r
+       private ReadWriteEnd output;\r
+       private boolean isOn;\r
+\r
+       public ManualSwitch(ReadWriteEnd output)\r
+       {\r
+               if (output.length() != 1)\r
+                       throw new IllegalArgumentException("Switch output can be only a single wire");\r
+               this.output = output;\r
+       }\r
+\r
+       public void switchOn()\r
+       {\r
+               setState(true);\r
+       }\r
+\r
+       public void switchOff()\r
+       {\r
+               setState(false);\r
+       }\r
+\r
+       public void toggle()\r
+       {\r
+               setState(!isOn);\r
+       }\r
+\r
+       public void setState(boolean isOn)\r
+       {\r
+               if (this.isOn == isOn)\r
+                       return;\r
+               this.isOn = isOn;\r
+               output.feedSignals(getValue());\r
+       }\r
+\r
+       public boolean isOn()\r
+       {\r
+               return isOn;\r
+       }\r
+\r
+       public Bit getValue()\r
+       {\r
+               return isOn ? Bit.ONE : Bit.ZERO;\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               return List.of();\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(output);\r
+       }\r
+\r
+}\r
index 34ba217..2c1ffcb 100644 (file)
@@ -1,82 +1,83 @@
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-import era.mi.logic.wires.WireObserver;
-
-public class Merger implements WireObserver, Component
-{
-       private WireEnd out;
-       private WireEnd[] 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(WireEnd union, WireEnd... inputs)
-       {
-               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 WireEnd getInput(int index)
-       {
-               return inputs[index];
-       }
-
-       public WireEnd getUnion()
-       {
-               return out;
-       }
-
-       @Override
-       public void update(Wire initiator, BitVector oldValues)
-       {
-               int index = find(initiator);
-               int beginning = beginningIndex[index];
-               out.feedSignals(beginning, inputs[index].getValues());
-       }
-
-       private int find(Wire w)
-       {
-               for (int i = 0; i < inputs.length; i++)
-                       if (inputs[i].getWire() == w)
-                               return i;
-               return -1;
-       }
-
-       public WireEnd[] getInputs()
-       {
-               return inputs.clone();
-       }
-
-       @Override
-       public List<WireEnd> getAllInputs()
-       {
-               return List.of(inputs);
-       }
-
-       @Override
-       public List<WireEnd> getAllOutputs()
-       {
-               return List.of(out);
-       }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+import era.mi.logic.wires.WireObserver;\r
+\r
+public class Merger implements WireObserver, Component\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(ReadWriteEnd union, ReadEnd... inputs)\r
+       {\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].addObserver(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(ReadEnd initiator, BitVector oldValues)\r
+       {\r
+               int index = find(initiator);\r
+               int beginning = beginningIndex[index];\r
+               out.feedSignals(beginning, inputs[index].getValues());\r
+       }\r
+\r
+       private int find(ReadEnd 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 aea7116..17ad0dd 100644 (file)
@@ -1,93 +1,94 @@
-package era.mi.logic.components;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-
-/**
- * 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 Mux extends BasicComponent
-{
-       private WireEnd select;
-       private WireEnd out;
-       private WireEnd[] inputs;
-       private final int outputSize;
-
-       /**
-        * Input {@link Wire}s and out must be of uniform length
-        * 
-        * @param out    Must be of uniform length with all inputs.
-        * @param select Indexes the input array which is to be mapped to the output. Must have enough bits to index all inputs.
-        * @param inputs One of these inputs is mapped to the output, depending on the select bits
-        */
-       public Mux(int processTime, WireEnd out, WireEnd select, WireEnd... inputs)
-       {
-               super(processTime);
-               outputSize = out.length();
-
-               this.inputs = inputs.clone();
-               for (int i = 0; i < this.inputs.length; i++)
-               {
-                       if (inputs[i].length() != outputSize)
-                               throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");
-                       inputs[i].addObserver(this);
-               }
-
-               this.select = select;
-               select.addObserver(this);
-
-               int maxInputs = 1 << select.length();
-               if (this.inputs.length > maxInputs)
-                       throw new IllegalArgumentException("There are more inputs (" + this.inputs.length + ") to the MUX than supported by "
-                                       + select.length() + " select bits (" + maxInputs + ").");
-
-               this.out = out;
-       }
-
-       public WireEnd getOut()
-       {
-               return out;
-       }
-
-       public WireEnd getSelect()
-       {
-               return select;
-       }
-
-       @Override
-       public void compute()
-       {
-               int selectValue;
-               if (!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) >= inputs.length)
-               {
-                       out.clearSignals();
-                       return;
-               }
-
-               WireEnd active = inputs[selectValue];
-               out.feedSignals(active.getValues());
-       }
-
-       @Override
-       public List<WireEnd> getAllInputs()
-       {
-               ArrayList<WireEnd> wires = new ArrayList<WireEnd>(Arrays.asList(inputs));
-               wires.add(select);
-               return Collections.unmodifiableList(wires);
-       }
-
-       @Override
-       public List<WireEnd> getAllOutputs()
-       {
-               return List.of(out);
-       }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import era.mi.logic.wires.Wire;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.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 Mux extends BasicComponent\r
+{\r
+       private ReadEnd select;\r
+       private ReadWriteEnd out;\r
+       private ReadEnd[] inputs;\r
+       private final int outputSize;\r
+\r
+       /**\r
+        * Input {@link Wire}s and out must be of uniform length\r
+        * \r
+        * @param out    Must be of uniform length with all inputs.\r
+        * @param select Indexes the input array which is to be mapped to the output. Must have enough bits to index all inputs.\r
+        * @param inputs One of these inputs is mapped to the output, depending on the select bits\r
+        */\r
+       public Mux(int processTime, ReadWriteEnd out, ReadEnd select, ReadEnd... inputs)\r
+       {\r
+               super(processTime);\r
+               outputSize = out.length();\r
+\r
+               this.inputs = inputs.clone();\r
+               for (int i = 0; i < this.inputs.length; i++)\r
+               {\r
+                       if (inputs[i].length() != outputSize)\r
+                               throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");\r
+                       inputs[i].addObserver(this);\r
+               }\r
+\r
+               this.select = select;\r
+               select.addObserver(this);\r
+\r
+               int maxInputs = 1 << select.length();\r
+               if (this.inputs.length > maxInputs)\r
+                       throw new IllegalArgumentException("There are more inputs (" + this.inputs.length + ") to the MUX than supported by "\r
+                                       + select.length() + " select bits (" + maxInputs + ").");\r
+\r
+               this.out = out;\r
+       }\r
+\r
+       public ReadEnd getOut()\r
+       {\r
+               return out;\r
+       }\r
+\r
+       public ReadEnd getSelect()\r
+       {\r
+               return select;\r
+       }\r
+\r
+       @Override\r
+       public void compute()\r
+       {\r
+               int selectValue;\r
+               if (!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) >= inputs.length)\r
+               {\r
+                       out.clearSignals();\r
+                       return;\r
+               }\r
+\r
+               ReadEnd active = inputs[selectValue];\r
+               out.feedSignals(active.getValues());\r
+       }\r
+\r
+       @Override\r
+       public List<ReadEnd> getAllInputs()\r
+       {\r
+               ArrayList<ReadEnd> wires = new ArrayList<ReadEnd>(Arrays.asList(inputs));\r
+               wires.add(select);\r
+               return Collections.unmodifiableList(wires);\r
+       }\r
+\r
+       @Override\r
+       public List<ReadWriteEnd> getAllOutputs()\r
+       {\r
+               return List.of(out);\r
+       }\r
+}\r
index 4764c27..530ad62 100644 (file)
@@ -1,43 +1,57 @@
-package era.mi.logic.components;
-
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-import era.mi.logic.wires.WireObserver;
-
-public class Splitter implements WireObserver
-{
-       private WireEnd input;
-       private WireEnd[] outputs;
-
-       public Splitter(WireEnd input, WireEnd... outputs)
-       {
-               this.input = input;
-               this.outputs = outputs;
-               input.addObserver(this);
-               int length = 0;
-               for (WireEnd 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(Wire initiator, BitVector oldValues)
-       {
-               compute();
-       }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+import era.mi.logic.wires.WireObserver;\r
+\r
+public class Splitter implements WireObserver, Component\r
+{\r
+       private ReadEnd input;\r
+       private ReadWriteEnd[] outputs;\r
+\r
+       public Splitter(ReadEnd input, ReadWriteEnd... outputs)\r
+       {\r
+               this.input = input;\r
+               this.outputs = outputs;\r
+               input.addObserver(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(ReadEnd initiator, BitVector oldValues)\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 0ab162f..7707232 100644 (file)
@@ -3,14 +3,15 @@ package era.mi.logic.components;
 import java.util.List;\r
 \r
 import era.mi.logic.types.Bit;\r
 import java.util.List;\r
 \r
 import era.mi.logic.types.Bit;\r
-import era.mi.logic.wires.Wire.WireEnd;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
 \r
 public class TriStateBuffer extends BasicComponent\r
 {\r
 \r
 public class TriStateBuffer extends BasicComponent\r
 {\r
-       WireEnd in, enable;\r
-       WireEnd out;\r
+       ReadEnd in, enable;\r
+       ReadWriteEnd out;\r
 \r
 \r
-       public TriStateBuffer(int processTime, WireEnd in, WireEnd out, WireEnd enable)\r
+       public TriStateBuffer(int processTime, ReadEnd in, ReadWriteEnd out, ReadEnd enable)\r
        {\r
                super(processTime);\r
                if (in.length() != out.length())\r
        {\r
                super(processTime);\r
                if (in.length() != out.length())\r
@@ -35,13 +36,13 @@ public class TriStateBuffer extends BasicComponent
        }\r
 \r
        @Override\r
        }\r
 \r
        @Override\r
-       public List<WireEnd> getAllInputs()\r
+       public List<ReadEnd> getAllInputs()\r
        {\r
                return List.of(in, enable);\r
        }\r
 \r
        @Override\r
        {\r
                return List.of(in, enable);\r
        }\r
 \r
        @Override\r
-       public List<WireEnd> getAllOutputs()\r
+       public List<ReadWriteEnd> getAllOutputs()\r
        {\r
                return List.of(out);\r
        }\r
        {\r
                return List.of(out);\r
        }\r
index 5da680e..4d0726e 100644 (file)
@@ -1,12 +1,13 @@
-package era.mi.logic.components.gates;
-
-import era.mi.logic.types.BitVector.BitVectorMutator;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class AndGate extends MultiInputGate
-{
-       public AndGate(int processTime, WireEnd out, WireEnd... in)
-       {
-               super(processTime, BitVectorMutator::and, out, in);
-       }
-}
+package era.mi.logic.components.gates;\r
+\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class AndGate extends MultiInputGate\r
+{\r
+       public AndGate(int processTime, ReadWriteEnd out, ReadEnd... in)\r
+       {\r
+               super(processTime, BitVectorMutator::and, out, in);\r
+       }\r
+}\r
index e76661d..4c985b4 100644 (file)
@@ -5,16 +5,17 @@ import java.util.List;
 import era.mi.logic.components.BasicComponent;\r
 import era.mi.logic.types.BitVector.BitVectorMutator;\r
 import era.mi.logic.types.MutationOperation;\r
 import era.mi.logic.components.BasicComponent;\r
 import era.mi.logic.types.BitVector.BitVectorMutator;\r
 import era.mi.logic.types.MutationOperation;\r
-import era.mi.logic.wires.Wire.WireEnd;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
 \r
 public abstract class MultiInputGate extends BasicComponent\r
 {\r
 \r
 public abstract class MultiInputGate extends BasicComponent\r
 {\r
-       protected WireEnd[] in;\r
-       protected WireEnd out;\r
+       protected ReadEnd[] in;\r
+       protected ReadWriteEnd out;\r
        protected final int length;\r
        protected MutationOperation op;\r
 \r
        protected final int length;\r
        protected MutationOperation op;\r
 \r
-       protected MultiInputGate(int processTime, MutationOperation op, WireEnd out, WireEnd... in)\r
+       protected MultiInputGate(int processTime, MutationOperation op, ReadWriteEnd out, ReadEnd... in)\r
        {\r
                super(processTime);\r
                this.op = op;\r
        {\r
                super(processTime);\r
                this.op = op;\r
@@ -22,7 +23,7 @@ public abstract class MultiInputGate extends BasicComponent
                this.in = in.clone();\r
                if (in.length < 1)\r
                        throw new IllegalArgumentException(String.format("Cannot create gate with %d wires.", in.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 (WireEnd w : in)\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
                {\r
                        if (w.length() != length)\r
                                throw new IllegalArgumentException("All wires connected to the gate must be of uniform length.");\r
@@ -32,13 +33,13 @@ public abstract class MultiInputGate extends BasicComponent
        }\r
 \r
        @Override\r
        }\r
 \r
        @Override\r
-       public List<WireEnd> getAllInputs()\r
+       public List<ReadEnd> getAllInputs()\r
        {\r
                return List.of(in);\r
        }\r
 \r
        @Override\r
        {\r
                return List.of(in);\r
        }\r
 \r
        @Override\r
-       public List<WireEnd> getAllOutputs()\r
+       public List<ReadWriteEnd> getAllOutputs()\r
        {\r
                return List.of(out);\r
        }\r
        {\r
                return List.of(out);\r
        }\r
@@ -47,7 +48,7 @@ public abstract class MultiInputGate extends BasicComponent
        protected void compute()\r
        {\r
                BitVectorMutator mutator = BitVectorMutator.empty();\r
        protected void compute()\r
        {\r
                BitVectorMutator mutator = BitVectorMutator.empty();\r
-               for (WireEnd w : in)\r
+               for (ReadEnd w : in)\r
                        op.apply(mutator, w.getValues());\r
                out.feedSignals(mutator.get());\r
        }\r
                        op.apply(mutator, w.getValues());\r
                out.feedSignals(mutator.get());\r
        }\r
index 1c0d833..ec1f816 100644 (file)
@@ -1,48 +1,49 @@
-package era.mi.logic.components.gates;
-
-import java.util.List;
-
-import era.mi.logic.components.BasicComponent;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class NotGate extends BasicComponent
-{
-       private WireEnd in;
-       private WireEnd out;
-
-       public NotGate(int processTime, WireEnd in, WireEnd out)
-       {
-               super(processTime);
-               this.in = in;
-               in.addObserver(this);
-               this.out = out;
-       }
-
-       @Override
-       protected void compute()
-       {
-               out.feedSignals(in.getValues().not());
-       }
-
-       public WireEnd getIn()
-       {
-               return in;
-       }
-
-       public WireEnd getOut()
-       {
-               return out;
-       }
-
-       @Override
-       public List<WireEnd> getAllInputs()
-       {
-               return List.of(in);
-       }
-
-       @Override
-       public List<WireEnd> getAllOutputs()
-       {
-               return List.of(out);
-       }
-}
+package era.mi.logic.components.gates;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.components.BasicComponent;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class NotGate extends BasicComponent\r
+{\r
+       private ReadEnd in;\r
+       private ReadWriteEnd out;\r
+\r
+       public NotGate(int processTime, ReadEnd in, ReadWriteEnd out)\r
+       {\r
+               super(processTime);\r
+               this.in = in;\r
+               in.addObserver(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 8c1775f..52dc921 100644 (file)
@@ -1,12 +1,13 @@
-package era.mi.logic.components.gates;
-
-import era.mi.logic.types.BitVector.BitVectorMutator;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class OrGate extends MultiInputGate
-{
-       public OrGate(int processTime, WireEnd out, WireEnd... in)
-       {
-               super(processTime, BitVectorMutator::or, out, in);
-       }
-}
+package era.mi.logic.components.gates;\r
+\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class OrGate extends MultiInputGate\r
+{\r
+       public OrGate(int processTime, ReadWriteEnd out, ReadEnd... in)\r
+       {\r
+               super(processTime, BitVectorMutator::or, out, in);\r
+       }\r
+}\r
index 73a2556..d241469 100644 (file)
@@ -1,18 +1,19 @@
-package era.mi.logic.components.gates;
-
-import era.mi.logic.types.BitVector.BitVectorMutator;
-import era.mi.logic.wires.Wire.WireEnd;
-
-/**
- * Outputs 1 when the number of 1 inputs is odd.
- * 
- * @author Fabian Stemmler
- */
-public class XorGate extends MultiInputGate
-{
-       public XorGate(int processTime, WireEnd out, WireEnd... in)
-       {
-               super(processTime, BitVectorMutator::xor, out, in);
-       }
-
-}
+package era.mi.logic.components.gates;\r
+\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+/**\r
+ * Outputs 1 when the number of 1 inputs is odd.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+public class XorGate extends MultiInputGate\r
+{\r
+       public XorGate(int processTime, ReadWriteEnd out, ReadEnd... in)\r
+       {\r
+               super(processTime, BitVectorMutator::xor, out, in);\r
+       }\r
+\r
+}\r
index 8a9bc5a..805d2e5 100644 (file)
-package era.mi.logic.tests;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.function.LongConsumer;
-
-import org.junit.jupiter.api.Test;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.components.Connector;
-import era.mi.logic.components.Demux;
-import era.mi.logic.components.Merger;
-import era.mi.logic.components.Mux;
-import era.mi.logic.components.Splitter;
-import era.mi.logic.components.TriStateBuffer;
-import era.mi.logic.components.gates.AndGate;
-import era.mi.logic.components.gates.NotGate;
-import era.mi.logic.components.gates.OrGate;
-import era.mi.logic.components.gates.XorGate;
-import era.mi.logic.types.Bit;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-
-@SuppressWarnings("unused")
-class ComponentTest
-{
-
-       @Test
-       void circuitExampleTest()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(1, 1), b = new Wire(1, 1), c = new Wire(1, 10), d = new Wire(2, 1), e = new Wire(1, 1), f = new Wire(1, 1),
-                               g = new Wire(1, 1), h = new Wire(2, 1), i = new Wire(2, 1), j = new Wire(1, 1), k = new Wire(1, 1);
-               new AndGate(1, f.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
-               new NotGate(1, f.createReadOnlyEnd(), g.createEnd());
-               new Merger(h.createEnd(), c.createReadOnlyEnd(), g.createReadOnlyEnd());
-               new Mux(1, i.createEnd(), e.createReadOnlyEnd(), h.createReadOnlyEnd(), d.createReadOnlyEnd());
-               new Splitter(i.createReadOnlyEnd(), k.createEnd(), j.createEnd());
-
-               a.createEnd().feedSignals(Bit.ZERO);
-               b.createEnd().feedSignals(Bit.ONE);
-               c.createEnd().feedSignals(Bit.ZERO);
-               d.createEnd().feedSignals(Bit.ONE, Bit.ONE);
-               e.createEnd().feedSignals(Bit.ZERO);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertEquals(Bit.ONE, j.getValue());
-               assertEquals(Bit.ZERO, k.getValue());
-       }
-
-       @Test
-       void splitterTest()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(3, 1), b = new Wire(2, 1), c = new Wire(3, 1), in = new Wire(8, 1);
-               in.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-               new Splitter(in.createReadOnlyEnd(), a.createEnd(), b.createEnd(), c.createEnd());
-
-               Simulation.TIMELINE.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()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(3, 1), b = new Wire(2, 1), c = new Wire(3, 1), out = new Wire(8, 1);
-               a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);
-               b.createEnd().feedSignals(Bit.ONE, Bit.ZERO);
-               c.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               new Merger(out.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
-
-               Simulation.TIMELINE.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(1, 1), b = new Wire(1, 1), en = new Wire(1, 1), notEn = new Wire(1, 1);
-               new NotGate(1, en.createReadOnlyEnd(), notEn.createEnd());
-               new TriStateBuffer(1, a.createReadOnlyEnd(), b.createEnd(), en.createReadOnlyEnd());
-               new TriStateBuffer(1, b.createReadOnlyEnd(), a.createEnd(), notEn.createReadOnlyEnd());
-
-               WireEnd enI = en.createEnd(), aI = a.createEnd(), bI = b.createEnd();
-               enI.feedSignals(Bit.ONE);
-               aI.feedSignals(Bit.ONE);
-               bI.feedSignals(Bit.Z);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertEquals(Bit.ONE, b.getValue());
-
-               bI.feedSignals(Bit.ZERO);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertEquals(Bit.X, b.getValue());
-               assertEquals(Bit.ONE, a.getValue());
-
-               aI.clearSignals();
-               enI.feedSignals(Bit.ZERO);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertEquals(Bit.ZERO, a.getValue());
-
-       }
-
-       @Test
-       void muxTest()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(4, 3), b = new Wire(4, 6), c = new Wire(4, 4), select = new Wire(2, 5), out = new Wire(4, 1);
-               WireEnd selectIn = select.createEnd();
-
-               selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
-               a.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-               c.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               new Mux(1, out.createEnd(), select.createReadOnlyEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
-               Simulation.TIMELINE.executeAll();
-
-               assertBitArrayEquals(out.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-               selectIn.feedSignals(Bit.ZERO, Bit.ONE);
-               Simulation.TIMELINE.executeAll();
-
-               assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               selectIn.feedSignals(Bit.ONE, Bit.ONE);
-               Simulation.TIMELINE.executeAll();
-
-               assertBitArrayEquals(out.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
-
-       }
-
-       @Test
-       void demuxTest()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(4, 3), b = new Wire(4, 6), c = new Wire(4, 4), select = new Wire(2, 5), in = new Wire(4, 1);
-               WireEnd selectIn = select.createEnd();
-
-               selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
-               in.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-
-               new Demux(1, in.createReadOnlyEnd(), select.createReadOnlyEnd(), a.createEnd(), b.createEnd(), c.createEnd());
-               Simulation.TIMELINE.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);
-               Simulation.TIMELINE.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);
-               Simulation.TIMELINE.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()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(4, 1), b = new Wire(4, 3), c = new Wire(4, 1);
-               new AndGate(1, c.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
-               a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
-               b.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);
-       }
-
-       @Test
-       void orTest()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(4, 1), b = new Wire(4, 3), c = new Wire(4, 1);
-               new OrGate(1, c.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
-               a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
-               b.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);
-       }
-
-       @Test
-       void xorTest()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(3, 1), b = new Wire(3, 2), c = new Wire(3, 1), d = new Wire(3, 1);
-               new XorGate(1, d.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
-               a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
-               b.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-               c.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);
-       }
-
-       @Test
-       void notTest()
-       {
-               Simulation.TIMELINE.reset();
-               Wire a = new Wire(3, 1), b = new Wire(3, 2);
-               new NotGate(1, a.createReadOnlyEnd(), b.createEnd());
-               a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO, Bit.ZERO);
-       }
-
-       @Test
-       void rsLatchCircuitTest()
-       {
-               Simulation.TIMELINE.reset();
-               Wire r = new Wire(1, 1), s = new Wire(1, 1), t1 = new Wire(1, 15), t2 = new Wire(1, 1), q = new Wire(1, 1), nq = new Wire(1, 1);
-
-               new OrGate(1, t2.createEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd());
-               new OrGate(1, t1.createEnd(), s.createReadOnlyEnd(), q.createReadOnlyEnd());
-               new NotGate(1, t2.createReadOnlyEnd(), q.createEnd());
-               new NotGate(1, t1.createReadOnlyEnd(), nq.createEnd());
-
-               WireEnd sIn = s.createEnd(), rIn = r.createEnd();
-
-               sIn.feedSignals(Bit.ONE);
-               rIn.feedSignals(Bit.ZERO);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertEquals(Bit.ONE, q.getValue());
-               assertEquals(Bit.ZERO, nq.getValue());
-
-               sIn.feedSignals(Bit.ZERO);
-
-               Simulation.TIMELINE.executeAll();
-               assertEquals(Bit.ONE, q.getValue());
-               assertEquals(Bit.ZERO, nq.getValue());
-
-               rIn.feedSignals(Bit.ONE);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertEquals(Bit.ZERO, q.getValue());
-               assertEquals(Bit.ONE, nq.getValue());
-       }
-
-       @Test
-       void numericValueTest()
-       {
-               Simulation.TIMELINE.reset();
-
-               Wire a = new Wire(4, 1);
-               a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);
-
-               Simulation.TIMELINE.executeAll();
-
-               assertEquals(15, a.getUnsignedValue());
-               assertEquals(-1, a.getSignedValue());
-       }
-
-       @Test
-       void multipleInputs()
-       {
-               Simulation.TIMELINE.reset();
-               Wire w = new Wire(2, 1);
-               WireEnd wI1 = w.createEnd(), wI2 = w.createEnd();
-               wI1.feedSignals(Bit.ONE, Bit.Z);
-               wI2.feedSignals(Bit.Z, Bit.X);
-               Simulation.TIMELINE.executeAll();
-               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.X);
-
-               wI2.feedSignals(Bit.ZERO, Bit.Z);
-               Simulation.TIMELINE.executeAll();
-               assertBitArrayEquals(w.getValues(), Bit.X, Bit.Z);
-
-               wI2.feedSignals(Bit.Z, Bit.Z);
-               Simulation.TIMELINE.executeAll();
-               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
-
-               wI2.feedSignals(Bit.ONE, Bit.Z);
-               w.addObserver((i, oldValues) -> fail("WireArray notified observer, although value did not change."));
-               Simulation.TIMELINE.executeAll();
-               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
-       }
-
-       @Test
-       void wireConnections()
-       {
-               // Nur ein Experiment, was Ã¼ber mehrere 'passive' Bausteine hinweg passieren würde
-
-               Simulation.TIMELINE.reset();
-
-               Wire a = new Wire(1, 2);
-               Wire b = new Wire(1, 2);
-               Wire c = new Wire(1, 2);
-               WireEnd aI = a.createEnd();
-               WireEnd bI = b.createEnd();
-               WireEnd cI = c.createEnd();
-
-               TestBitDisplay test = new TestBitDisplay(c.createReadOnlyEnd());
-               TestBitDisplay test2 = new TestBitDisplay(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(b.createEnd(), c.createEnd()).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(a.createEnd(), b.createEnd()).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 era.mi.logic.tests;\r
+\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 era.mi.logic.Simulation;\r
+import era.mi.logic.components.Connector;\r
+import era.mi.logic.components.Demux;\r
+import era.mi.logic.components.Merger;\r
+import era.mi.logic.components.Mux;\r
+import era.mi.logic.components.Splitter;\r
+import era.mi.logic.components.TriStateBuffer;\r
+import era.mi.logic.components.gates.AndGate;\r
+import era.mi.logic.components.gates.NotGate;\r
+import era.mi.logic.components.gates.OrGate;\r
+import era.mi.logic.components.gates.XorGate;\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+class ComponentTest\r
+{\r
+\r
+       @Test\r
+       void circuitExampleTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(1, 1), b = new Wire(1, 1), c = new Wire(1, 10), d = new Wire(2, 1), e = new Wire(1, 1), f = new Wire(1, 1),\r
+                               g = new Wire(1, 1), h = new Wire(2, 1), i = new Wire(2, 1), j = new Wire(1, 1), k = new Wire(1, 1);\r
+               new AndGate(1, f.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+               new NotGate(1, f.createReadOnlyEnd(), g.createEnd());\r
+               new Merger(h.createEnd(), c.createReadOnlyEnd(), g.createReadOnlyEnd());\r
+               new Mux(1, i.createEnd(), e.createReadOnlyEnd(), h.createReadOnlyEnd(), d.createReadOnlyEnd());\r
+               new Splitter(i.createReadOnlyEnd(), k.createEnd(), j.createEnd());\r
+\r
+               a.createEnd().feedSignals(Bit.ZERO);\r
+               b.createEnd().feedSignals(Bit.ONE);\r
+               c.createEnd().feedSignals(Bit.ZERO);\r
+               d.createEnd().feedSignals(Bit.ONE, Bit.ONE);\r
+               e.createEnd().feedSignals(Bit.ZERO);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertEquals(Bit.ONE, j.getValue());\r
+               assertEquals(Bit.ZERO, k.getValue());\r
+       }\r
+\r
+       @Test\r
+       void splitterTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(3, 1), b = new Wire(2, 1), c = new Wire(3, 1), in = new Wire(8, 1);\r
+               in.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+               new Splitter(in.createReadOnlyEnd(), a.createEnd(), b.createEnd(), c.createEnd());\r
+\r
+               Simulation.TIMELINE.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
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(3, 1), b = new Wire(2, 1), c = new Wire(3, 1), out = new Wire(8, 1);\r
+               a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+               b.createEnd().feedSignals(Bit.ONE, Bit.ZERO);\r
+               c.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               new Merger(out.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+\r
+               Simulation.TIMELINE.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(1, 1), b = new Wire(1, 1), en = new Wire(1, 1), notEn = new Wire(1, 1);\r
+               new NotGate(1, en.createReadOnlyEnd(), notEn.createEnd());\r
+               new TriStateBuffer(1, a.createReadOnlyEnd(), b.createEnd(), en.createReadOnlyEnd());\r
+               new TriStateBuffer(1, b.createReadOnlyEnd(), a.createEnd(), notEn.createReadOnlyEnd());\r
+\r
+               ReadWriteEnd enI = en.createEnd(), aI = a.createEnd(), bI = b.createEnd();\r
+               enI.feedSignals(Bit.ONE);\r
+               aI.feedSignals(Bit.ONE);\r
+               bI.feedSignals(Bit.Z);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertEquals(Bit.ONE, b.getValue());\r
+\r
+               bI.feedSignals(Bit.ZERO);\r
+\r
+               Simulation.TIMELINE.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
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertEquals(Bit.ZERO, a.getValue());\r
+\r
+       }\r
+\r
+       @Test\r
+       void muxTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(4, 3), b = new Wire(4, 6), c = new Wire(4, 4), select = new Wire(2, 5), out = new Wire(4, 1);\r
+               ReadWriteEnd selectIn = select.createEnd();\r
+\r
+               selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+               a.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+               c.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               new Mux(1, out.createEnd(), select.createReadOnlyEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertBitArrayEquals(out.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+               selectIn.feedSignals(Bit.ZERO, Bit.ONE);\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               selectIn.feedSignals(Bit.ONE, Bit.ONE);\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertBitArrayEquals(out.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+\r
+       }\r
+\r
+       @Test\r
+       void demuxTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(4, 3), b = new Wire(4, 6), c = new Wire(4, 4), select = new Wire(2, 5), in = new Wire(4, 1);\r
+               ReadWriteEnd selectIn = select.createEnd();\r
+\r
+               selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+               in.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+\r
+               new Demux(1, in.createReadOnlyEnd(), select.createReadOnlyEnd(), a.createEnd(), b.createEnd(), c.createEnd());\r
+               Simulation.TIMELINE.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
+               Simulation.TIMELINE.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
+               Simulation.TIMELINE.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
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(4, 1), b = new Wire(4, 3), c = new Wire(4, 1);\r
+               new AndGate(1, c.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+               a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+               b.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+       }\r
+\r
+       @Test\r
+       void orTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(4, 1), b = new Wire(4, 3), c = new Wire(4, 1);\r
+               new OrGate(1, c.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+               a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+               b.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+       }\r
+\r
+       @Test\r
+       void xorTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(3, 1), b = new Wire(3, 2), c = new Wire(3, 1), d = new Wire(3, 1);\r
+               new XorGate(1, d.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+               a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);\r
+               b.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+               c.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);\r
+       }\r
+\r
+       @Test\r
+       void notTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire a = new Wire(3, 1), b = new Wire(3, 2);\r
+               new NotGate(1, a.createReadOnlyEnd(), b.createEnd());\r
+               a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+       }\r
+\r
+       @Test\r
+       void rsLatchCircuitTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire r = new Wire(1, 1), s = new Wire(1, 1), t1 = new Wire(1, 15), t2 = new Wire(1, 1), q = new Wire(1, 1), nq = new Wire(1, 1);\r
+\r
+               new OrGate(1, t2.createEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd());\r
+               new OrGate(1, t1.createEnd(), s.createReadOnlyEnd(), q.createReadOnlyEnd());\r
+               new NotGate(1, t2.createReadOnlyEnd(), q.createEnd());\r
+               new NotGate(1, t1.createReadOnlyEnd(), nq.createEnd());\r
+\r
+               ReadWriteEnd sIn = s.createEnd(), rIn = r.createEnd();\r
+\r
+               sIn.feedSignals(Bit.ONE);\r
+               rIn.feedSignals(Bit.ZERO);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertEquals(Bit.ONE, q.getValue());\r
+               assertEquals(Bit.ZERO, nq.getValue());\r
+\r
+               sIn.feedSignals(Bit.ZERO);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+               assertEquals(Bit.ONE, q.getValue());\r
+               assertEquals(Bit.ZERO, nq.getValue());\r
+\r
+               rIn.feedSignals(Bit.ONE);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertEquals(Bit.ZERO, q.getValue());\r
+               assertEquals(Bit.ONE, nq.getValue());\r
+       }\r
+\r
+       @Test\r
+       void numericValueTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+\r
+               Wire a = new Wire(4, 1);\r
+               a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);\r
+\r
+               Simulation.TIMELINE.executeAll();\r
+\r
+               assertEquals(15, a.getUnsignedValue());\r
+               assertEquals(-1, a.getSignedValue());\r
+       }\r
+\r
+       @Test\r
+       void multipleInputs()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               Wire w = new Wire(2, 1);\r
+               ReadWriteEnd wI1 = w.createEnd(), wI2 = w.createEnd();\r
+               wI1.feedSignals(Bit.ONE, Bit.Z);\r
+               wI2.feedSignals(Bit.Z, Bit.X);\r
+               Simulation.TIMELINE.executeAll();\r
+               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.X);\r
+\r
+               wI2.feedSignals(Bit.ZERO, Bit.Z);\r
+               Simulation.TIMELINE.executeAll();\r
+               assertBitArrayEquals(w.getValues(), Bit.X, Bit.Z);\r
+\r
+               wI2.feedSignals(Bit.Z, Bit.Z);\r
+               Simulation.TIMELINE.executeAll();\r
+               assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);\r
+\r
+               wI2.feedSignals(Bit.ONE, Bit.Z);\r
+               ReadEnd rE = w.createReadOnlyEnd();\r
+               rE.addObserver((i, oldValues) -> fail("WireEnd notified observer, although value did not change."));\r
+               Simulation.TIMELINE.executeAll();\r
+               rE.close();\r
+               wI1.feedSignals(Bit.X, Bit.X);\r
+               Simulation.TIMELINE.executeAll();\r
+               wI1.addObserver((i, oldValues) -> 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
+               Simulation.TIMELINE.reset();\r
+\r
+               Wire a = new Wire(1, 2);\r
+               Wire b = new Wire(1, 2);\r
+               Wire c = new Wire(1, 2);\r
+               ReadWriteEnd aI = a.createEnd();\r
+               ReadWriteEnd bI = b.createEnd();\r
+               ReadWriteEnd cI = c.createEnd();\r
+\r
+               TestBitDisplay test = new TestBitDisplay(c.createReadOnlyEnd());\r
+               TestBitDisplay test2 = new TestBitDisplay(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(b.createEnd(), c.createEnd()).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(a.createEnd(), b.createEnd()).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 cb0494e..b9de0cc 100644 (file)
@@ -1,47 +1,47 @@
-package era.mi.logic.tests;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-
-import java.util.function.LongConsumer;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.components.BitDisplay;
-import era.mi.logic.types.Bit;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public final class TestBitDisplay extends BitDisplay
-{
-
-       public TestBitDisplay(WireEnd in)
-       {
-               super(in);
-       }
-
-       public void assertDisplays(Bit... expected)
-       {
-               assertArrayEquals(expected, getDisplayedValue().getBits());
-       }
-
-       public void assertAfterSimulationIs(Bit... expected)
-       {
-               Simulation.TIMELINE.executeAll();
-               assertDisplays(expected);
-       }
-
-       public void assertAfterSimulationIs(LongConsumer r, Bit... expected)
-       {
-               while (Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-                       r.accept(Simulation.TIMELINE.getSimulationTime());
-               }
-               assertDisplays(expected);
-       }
-
-       @Override
-       protected void compute()
-       {
-               super.compute();
-               System.out.println("update: value is " + getDisplayedValue());
-       }
-}
+package era.mi.logic.tests;\r
+\r
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;\r
+\r
+import java.util.function.LongConsumer;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.components.BitDisplay;\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+\r
+public final class TestBitDisplay extends BitDisplay\r
+{\r
+\r
+       public TestBitDisplay(ReadEnd in)\r
+       {\r
+               super(in);\r
+       }\r
+\r
+       public void assertDisplays(Bit... expected)\r
+       {\r
+               assertArrayEquals(expected, getDisplayedValue().getBits());\r
+       }\r
+\r
+       public void assertAfterSimulationIs(Bit... expected)\r
+       {\r
+               Simulation.TIMELINE.executeAll();\r
+               assertDisplays(expected);\r
+       }\r
+\r
+       public void assertAfterSimulationIs(LongConsumer r, Bit... expected)\r
+       {\r
+               while (Simulation.TIMELINE.hasNext())\r
+               {\r
+                       Simulation.TIMELINE.executeNext();\r
+                       r.accept(Simulation.TIMELINE.getSimulationTime());\r
+               }\r
+               assertDisplays(expected);\r
+       }\r
+\r
+       @Override\r
+       protected void compute()\r
+       {\r
+               super.compute();\r
+               System.out.println("update: value is " + getDisplayedValue());\r
+       }\r
+}\r
index a7b96ee..5eaf27a 100644 (file)
-package era.mi.logic.wires;
-
-import static era.mi.logic.types.Bit.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.types.Bit;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.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<WireObserver> observers = new ArrayList<WireObserver>();
-       public final int length;
-       private List<WireEnd> inputs = new ArrayList<WireEnd>();
-
-       public Wire(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.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 (WireEnd 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;
-                       // Random number?
-                       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
-        */
-       public boolean addObserver(WireObserver ob)
-       {
-               return observers.add(ob);
-       }
-
-       private void notifyObservers(BitVector oldValues)
-       {
-               for (WireObserver o : observers)
-                       o.update(this, oldValues);
-       }
-
-       /**
-        * Create and register a {@link WireEnd} object, which is tied to this {@link Wire}.
-        */
-       public WireEnd createEnd()
-       {
-               return new WireEnd(false);
-       }
-
-       /**
-        * Create a {@link WireEnd} object, which is tied to this {@link Wire}. This {@link WireEnd} cannot written to.
-        */
-       public WireEnd createReadOnlyEnd()
-       {
-               return new WireEnd(true);
-       }
-
-       private void registerInput(WireEnd toRegister)
-       {
-               inputs.add(toRegister);
-       }
-
-       /**
-        * A {@link WireEnd} 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 WireEnd
-       {
-               private boolean open;
-               private BitVector inputValues;
-
-               private WireEnd(boolean readOnly)
-               {
-                       super();
-                       open = !readOnly; // TODO: that makes sense, doesn't it?
-                       initValues();
-                       if (!readOnly)
-                               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.");
-                       Simulation.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.");
-                       Simulation.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 WireEnd} is currently feeding into the associated {@link Wire}.
-                */
-               public Bit getInputValue()
-               {
-                       return getInputValue(0);
-               }
-
-               /**
-                * @return The value which the {@link WireEnd} 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 WireEnd} 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 WireEnd} now feeds Z into the associated {@link Wire}.
-                */
-               public void clearSignals()
-               {
-                       feedSignals(Z.toVector(length));
-               }
-
-               public BitVector wireValuesExcludingMe()
-               {
-                       BitVectorMutator mutator = BitVectorMutator.empty();
-                       for (WireEnd wireEnd : inputs)
-                       {
-                               if (wireEnd == this)
-                                       continue;
-                               mutator.join(wireEnd.inputValues);
-                       }
-                       return mutator.get();
-               }
-
-               /**
-                * 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 inputValues.toString();
-                       // return String.format("%s \nFeeding: %s", WireArray.this.toString(), Arrays.toString(inputValues));
-               }
-
-               public void close()
-               {
-                       inputs.remove(this);
-                       open = false;
-               }
-
-               public int length()
-               {
-                       return length;
-               }
-
-               public boolean addObserver(WireObserver ob)
-               {
-                       return Wire.this.addObserver(ob);
-               }
-
-               public Wire getWire()
-               {
-                       return Wire.this;
-               }
-       }
-
-       @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 WireEnd[] extractEnds(Wire[] w)
-       {
-               WireEnd[] inputs = new WireEnd[w.length];
-               for (int i = 0; i < w.length; i++)
-                       inputs[i] = w[i].createEnd();
-               return inputs;
-       }
+package era.mi.logic.wires;\r
+\r
+import static era.mi.logic.types.Bit.U;\r
+import static era.mi.logic.types.Bit.Z;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.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
+\r
+       public Wire(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.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 WireObserver}, who will be notified when the value of the {@link Wire} is updated.\r
+        * \r
+        * @param ob The {@link WireObserver} to be notified of changes.\r
+        * @return true if the given {@link WireObserver} 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 createEnd()\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\r
+       {\r
+               private List<WireObserver> observers = new ArrayList<WireObserver>();\r
+\r
+               private ReadEnd()\r
+               {\r
+                       super();\r
+                       Wire.this.attachEnd(this);\r
+               }\r
+\r
+               public void update(BitVector oldValues)\r
+               {\r
+                       for (WireObserver ob : observers)\r
+                               ob.update(this, oldValues);\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 boolean addObserver(WireObserver ob)\r
+               {\r
+                       return observers.add(ob);\r
+               }\r
+\r
+               public Wire getWire()\r
+               {\r
+                       return Wire.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
+                       Simulation.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
+                       Simulation.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
+               // Arrays.toString(values), inputs.stream().map(i -> Arrays.toString(i.inputValues)).reduce((s1, s2) -> s1 + s2)\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].createEnd();\r
+               return inputs;\r
+       }\r
 }
\ No newline at end of file
 }
\ No newline at end of file
index 9258e0a..b282a9d 100644 (file)
@@ -1,8 +1,9 @@
-package era.mi.logic.wires;
-
-import era.mi.logic.types.BitVector;
-
-public interface WireObserver
-{
-       public void update(Wire initiator, BitVector oldValues);
-}
+package era.mi.logic.wires;\r
+\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+\r
+public interface WireObserver\r
+{\r
+       public void update(ReadEnd initiator, BitVector oldValues);\r
+}\r