Fixed Merger, Mux, Splitter: onedirectional again. Tests added.
authorFabian Stemmler <stemmler@in.tum.de>
Fri, 10 May 2019 21:24:00 +0000 (23:24 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Fri, 10 May 2019 21:24:00 +0000 (23:24 +0200)
era.mi/src/era/mi/logic/Util.java
era.mi/src/era/mi/logic/components/Mapper.java [new file with mode: 0644]
era.mi/src/era/mi/logic/components/Merger.java
era.mi/src/era/mi/logic/components/Merger2.java [deleted file]
era.mi/src/era/mi/logic/components/Mux.java
era.mi/src/era/mi/logic/components/Mux2.java [deleted file]
era.mi/src/era/mi/logic/components/Splitter.java
era.mi/src/era/mi/logic/components/TriState.java [deleted file]
era.mi/src/era/mi/logic/components/TriStateBuffer.java [new file with mode: 0644]
era.mi/src/era/mi/logic/tests/ComponentTest.java
era.mi/src/era/mi/logic/wires/WireArray.java

index 6f1b93f..6bca6d0 100644 (file)
@@ -4,28 +4,28 @@ import java.util.Arrays;
 
 public final class Util
 {
-       
-       @SuppressWarnings("unchecked")
-       public static <T> T[] concat(T[]... arrays)
+    
+    @SuppressWarnings("unchecked")
+    public static <T> T[] concat(T[]... arrays)
+    {
+       if (arrays.length == 0)
+           throw new IllegalArgumentException("Cannot concatenate 0 arrays.");
+
+       int length = 0;
+       for (T[] array : arrays)
+           length += array.length;
+
+       T[] newArray = Arrays.copyOf(arrays[0], length);
+       int appendIndex = arrays[0].length;
+       for (int i = 1; i < arrays.length; i++)
        {
-               if(arrays.length == 0)
-                       throw new IllegalArgumentException("Cannot concatenate 0 arrays.");
-               
-               int length = 0;
-               for(T[] array : arrays)
-                       length += array.length;
-               
-               T[] newArray = Arrays.copyOf(arrays[0], length);
-               int appendIndex = arrays[0].length;
-               for(int i = 1; i < arrays.length; i++)
-               {
-                       System.arraycopy(arrays[i], 0, newArray, appendIndex, arrays[i].length);
-                       appendIndex += arrays[i].length;
-               }
-               
-               return newArray;
+           System.arraycopy(arrays[i], 0, newArray, appendIndex, arrays[i].length);
+           appendIndex += arrays[i].length;
        }
 
+       return newArray;
+    }
+
 //     @SuppressWarnings("unchecked")
 //     public static <T> T[][] split(T[] array, int... lengths)
 //     {
@@ -47,46 +47,46 @@ public final class Util
 //             
 //             return (T[][]) newArray;
 //     }
-       
-       public static Bit[] and(Bit[] a, Bit[] b)
-       {
-               return binBitOp(a, b, (bA, bB) -> Bit.and(bA, bB));
-       }
-       
-       public static Bit[] or(Bit[] a, Bit[] b)
-       {
-               return binBitOp(a, b, (bA, bB) -> Bit.or(bA, bB));
-       }
-       
-       public static Bit[] xor(Bit[] a, Bit[] b)
-       {
-               return binBitOp(a, b, (bA, bB) -> Bit.xor(bA, bB));
-       }
-       
-       private static Bit[] binBitOp(Bit[] a, Bit[] b, BitOp op)
-       {
-               if(a.length != b.length)
-                       throw new IllegalArgumentException("Bit Arrays were not of equal length.");
-               Bit[] out = new Bit[a.length];
-               for(int i = 0; i < a.length; i++)
-               {
-                       out[i] = op.execute(a[i], b[i]);
-               }
-               return out;
-       }
-       
-       public static Bit[] not(Bit[] a)
+
+    public static Bit[] and(Bit[] a, Bit[] b)
+    {
+       return binBitOp(a, b, (bA, bB) -> Bit.and(bA, bB));
+    }
+
+    public static Bit[] or(Bit[] a, Bit[] b)
+    {
+       return binBitOp(a, b, (bA, bB) -> Bit.or(bA, bB));
+    }
+
+    public static Bit[] xor(Bit[] a, Bit[] b)
+    {
+       return binBitOp(a, b, (bA, bB) -> Bit.xor(bA, bB));
+    }
+
+    private static Bit[] binBitOp(Bit[] a, Bit[] b, BitOp op)
+    {
+       if (a.length != b.length)
+           throw new IllegalArgumentException("Bit Arrays were not of equal length.");
+       Bit[] out = new Bit[a.length];
+       for (int i = 0; i < a.length; i++)
        {
-               Bit[] out = new Bit[a.length];
-               for(int i = 0; i < a.length; i++)
-               {
-                       out[i] = a[i].not();
-               }
-               return out;
+           out[i] = op.execute(a[i], b[i]);
        }
-       
-       interface BitOp
+       return out;
+    }
+
+    public static Bit[] not(Bit[] a)
+    {
+       Bit[] out = new Bit[a.length];
+       for (int i = 0; i < a.length; i++)
        {
-               Bit execute(Bit a, Bit b);
+           out[i] = a[i].not();
        }
+       return out;
+    }
+
+    interface BitOp
+    {
+       Bit execute(Bit a, Bit b);
+    }
 }
diff --git a/era.mi/src/era/mi/logic/components/Mapper.java b/era.mi/src/era/mi/logic/components/Mapper.java
new file mode 100644 (file)
index 0000000..ef3f235
--- /dev/null
@@ -0,0 +1,66 @@
+package era.mi.logic.components;
+
+import era.mi.logic.wires.WireArray;
+import era.mi.logic.wires.WireArray.WireArrayInput;
+import era.mi.logic.wires.WireArrayObserver;
+
+public class Mapper implements WireArrayObserver
+{
+    private int[] inBeginningIndex, outBeginningIndex;
+    private WireArray[] inputs;
+    private WireArrayInput[] outputsI;
+
+    public Mapper(WireArray[] inputs, WireArray[] outputs)
+    {
+       this.inputs = inputs.clone();
+
+       int beginningIndex = 0;
+       for (int i = 0; i < inputs.length; i++)
+       {
+           inBeginningIndex[i] = beginningIndex;
+           beginningIndex += inputs[i].length;
+           inputs[i].addObserver(this);
+       }
+       int inputsLength = beginningIndex;
+       beginningIndex = 0;
+       for (int i = 0; i < outputs.length; i++)
+       {
+           outputsI[i] = outputs[i].createInput();
+           outBeginningIndex[i] = beginningIndex;
+           beginningIndex += outputs[i].length;
+       }
+       if (inputsLength != beginningIndex)
+           throw new IllegalArgumentException("Mapper inputs must add up to the same length as outputs. ("
+                   + inputsLength + ", " + beginningIndex + ").");
+    }
+
+    @Override
+    public void update(WireArray initiator)
+    {
+       for (int i = 0; i < inputs.length; i++)
+       {
+           if (inputs[i] == initiator)
+           {
+               int inB = inBeginningIndex[i];
+//             int outB = outBeginningIndex TODO
+           }
+       }
+    }
+
+    // binary search
+    private int findLower(int[] sorted, int value)
+    {
+       int a = 0, b = sorted.length;
+       while (a < (b - 1))
+       {
+           int inspect = (a + b) >> 1;
+           if (sorted[inspect] == value)
+               return inspect;
+           if (sorted[inspect] > value)
+               b = inspect;
+           else
+               a = inspect;
+       }
+       return a;
+    }
+}
index eb910a4..534b2ca 100644 (file)
@@ -1,61 +1,68 @@
 package era.mi.logic.components;
 
-import era.mi.logic.Util;
-import era.mi.logic.Bit;
-import era.mi.logic.WireArray;
-import era.mi.logic.WireArrayObserver;
+import era.mi.logic.wires.WireArray;
+import era.mi.logic.wires.WireArray.WireArrayInput;
+import era.mi.logic.wires.WireArrayObserver;
 
-@Deprecated
 public class Merger implements WireArrayObserver
 {
-       private WireArray out;
-       private WireArray[] inputs;
-       
-       //TODO: General problem with this concept; New inputs coming in at the same time override each other
-       
-       /**
-        * 
-        * @param union The output of merging n {@link WireArray}s into one. Must have length = a1.length() + a2.length() + ... + an.length().
-        * @param inputs The inputs to be merged into the union
-        */
-       public Merger(WireArray union, WireArray... inputs)
-       {
-               this.inputs = inputs;
-               this.out = union;
-               
-               int length = 0;
-               for(WireArray input : inputs)
-               {
-                       length += input.length();
-                       input.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().");
-       }
+    private WireArrayInput outI;
+    private WireArray[] inputs;
+    private int[] beginningIndex;
 
-       protected void compute()
-       {
-               Bit[][] bits = new Bit[inputs.length][];
-               for(int i = 0; i < inputs.length; i++)
-                       bits[i] = inputs[i].getValues();
-               Bit[] newOut = Util.concat(bits);
-               out.feedSignals(newOut);
-       }
+    /**
+     * 
+     * @param union  The output of merging n {@link WireArray}s into one. Must have
+     *               length = a1.length() + a2.length() + ... + an.length().
+     * @param inputs The inputs to be merged into the union
+     */
+    public Merger(WireArray union, WireArray... inputs)
+    {
+       this.inputs = inputs;
+       this.outI = union.createInput();
+       this.beginningIndex = new int[inputs.length];
 
-       public WireArray getInput(int index)
-       {
-               return inputs[index];
-       }
-       
-       public WireArray getUnion()
-       {
-               return out;
-       }
-       
-       @Override
-       public void update(WireArray initiator)
+       int length = 0;
+       for (int i = 0; i < inputs.length; i++)
        {
-               compute(); //No inner delay
+           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 WireArray getInput(int index)
+    {
+       return inputs[index];
+    }
+
+    public WireArray getUnion()
+    {
+       return outI.owner;
+    }
+
+    @Override
+    public void update(WireArray initiator)
+    {
+       int index = find(initiator);
+       int beginning = beginningIndex[index];
+       outI.feedSignals(beginning, initiator.getValues());
+    }
+
+    private int find(WireArray w)
+    {
+       for (int i = 0; i < inputs.length; i++)
+           if (inputs[i] == w)
+               return i;
+       return -1;
+    }
+
+    public WireArray[] getInputs()
+    {
+       return inputs.clone();
+    }
 }
diff --git a/era.mi/src/era/mi/logic/components/Merger2.java b/era.mi/src/era/mi/logic/components/Merger2.java
deleted file mode 100644 (file)
index ca24254..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-package era.mi.logic.components;
-
-import era.mi.logic.WireArray;
-import era.mi.logic.WireArrayObserver;
-
-public class Merger2 implements WireArrayObserver
-{
-       private WireArray out;
-       private WireArray[] inputs;
-       private int[] beginningIndex;
-       
-       /**
-        * 
-        * @param union The output of merging n {@link WireArray}s into one. Must have length = a1.length() + a2.length() + ... + an.length().
-        * @param inputs The inputs to be merged into the union
-        */
-       public Merger2(WireArray union, WireArray... 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 WireArray getInput(int index)
-       {
-               return inputs[index];
-       }
-       
-       public WireArray getUnion()
-       {
-               return out;
-       }
-       
-       @Override
-       public void update(WireArray initiator)
-       {
-               int index = find(initiator);
-               int beginning = beginningIndex[index];
-               out.feedSignals(beginning, initiator.getValues());
-       }
-       
-       private int find(WireArray w)
-       {
-               for(int i = 0; i < inputs.length; i++)
-                       if(inputs[i] == w)
-                               return i;
-               return -1;
-       }
-
-       public WireArray getOut()
-       {
-               return out;
-       }
-
-       public WireArray[] getInputs()
-       {
-               return inputs.clone();
-       }
-}
index 0b19e7c..0fd7fd4 100644 (file)
@@ -1,77 +1,72 @@
 package era.mi.logic.components;
 
-import era.mi.logic.Bit;
 import era.mi.logic.wires.WireArray;
+import era.mi.logic.wires.WireArray.WireArrayInput;
 
 /**
- * Models a Multiplexer. A is selected when select bit is 1, B when select bit is 0. Outputs X otherwise.
- * @author Fabian
+ * Models a multiplexer. Takes an arbitrary amount of input {@link WireArray}s, one of which,
+ * as determined by select, is put through to the output.
+ * @author Fabian Stemmler
  *
  */
 public class Mux extends BasicComponent
 {
-       private WireArray a, b, out;
        private WireArray select;
-       private final int size;
-       
+       private WireArrayInput outI;
+       private WireArray[] inputs;
+       private final int outputSize;
        /**
-        * {@link WireArray}s a, b and out must be of uniform length, select
-        * @param a Must be of uniform length with b and out.
-        * @param b Must be of uniform length with a and out.
-        * @param select C
-        * @param out Must be of uniform length with a and b.
+        * Input {@link WireArray}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, WireArray a, WireArray b, WireArray select, WireArray out)
+       public Mux(int processTime, WireArray out, WireArray select, WireArray... inputs)
        {
                super(processTime);
-               size = a.length;
-               if(b.length != out.length || b.length != size)
-                       throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");
-               this.a = a;
-               a.addObserver(this);
-               this.b = b;
-               b.addObserver(this);
-               this.select = select;
-               select.addObserver(this);
-               this.out = out;
-       }
-
-       @Override
-       protected void compute()
-       {
-               WireArray active = b;
-               switch(select.getValue())
+               outputSize = out.length;
+               
+               this.inputs = inputs.clone();
+               for(int i = 0; i < this.inputs.length; i++)
                {
-               case ONE:
-                       active = a;
-               case ZERO:
-                       out.feedSignals(active.getValues());
-                       break;
-               default:
-                       Bit[] newValues = new Bit[size];
-                       for(int i = 0; i < size; i++)
-                               newValues[i] = Bit.X;
-                       out.feedSignals(newValues);
+                       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 + ").");
+               
+               outI = out.createInput();
        }
-
-       public WireArray getA()
-       {
-               return a;
-       }
-
-       public WireArray getB()
-       {
-               return b;
-       }
-
+       
        public WireArray getOut()
        {
-               return out;
+               return outI.owner;
        }
 
        public WireArray getSelect()
        {
                return select;
        }
+
+       @Override
+       public void compute() {
+               int selectValue;
+               if(!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) >= inputs.length)
+               {
+                       outI.clearSignals();
+                       return;
+               }
+               
+               WireArray active = inputs[selectValue];
+               outI.feedSignals(active.getValues());
+       }
 }
diff --git a/era.mi/src/era/mi/logic/components/Mux2.java b/era.mi/src/era/mi/logic/components/Mux2.java
deleted file mode 100644 (file)
index c0c4ce3..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-package era.mi.logic.components;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.wires.WireArray;
-import era.mi.logic.wires.WireArray.WireArrayInput;
-import era.mi.logic.wires.WireArrayObserver;
-
-/**
- * Models a Multiplexer. A is selected when select bit is 1, B when select bit is 0. Outputs X otherwise.
- * @author Fabian Stemmler
- *
- */
-public class Mux2 implements WireArrayObserver
-{
-       private WireArray select;
-       private WireArrayInput outI;
-       private WireArrayInput[] inputs;
-       private final int size;
-       private final int processTime;
-       private int selected;
-       
-       /**
-        * {@link WireArray}s a, b and out must be of uniform length, select
-        * @param out Must be of uniform length with a and b.
-        * @param select Indexes the input array which is to be mapped to the output
-        * @param inputs One of these inputs is mapped to the output, depending on the select wires 
-        */
-       public Mux2(int processTime, WireArray out, WireArray select, WireArray... inputs)
-       {
-               this.processTime = processTime;
-               size = out.length;
-               
-               this.inputs = new WireArrayInput[inputs.length];
-               for(int i = 0; i < this.inputs.length; i++)
-               {
-                       if(inputs[i].length != size)
-                               throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");
-                       this.inputs[i] = inputs[i].createInput();
-                       inputs[i].addObserver(this);
-               }
-               
-               this.select = select;
-               select.addObserver(this);
-               selected = -1;
-               
-               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 + ").");
-               
-               outI = out.createInput();
-               out.addObserver(this);
-       }
-       
-       public WireArray getOut()
-       {
-               return outI.owner;
-       }
-
-       public WireArray getSelect()
-       {
-               return select;
-       }
-
-       @Override
-       public void update(WireArray initiator) {
-               int selectValue;
-               if(!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) > size)
-               {
-                       if(initiator == select)
-                       {
-                               Simulation.TIMELINE.addEvent((e) -> {
-                                       if(selected != -1)
-                                       {
-                                               inputs[selected].clearSignals();
-                                               selected = -1;
-                                               outI.clearSignals();
-                                       }
-                               }, processTime);
-                       }
-                       return;
-               }
-               
-               WireArrayInput active = inputs[selectValue];
-               Simulation.TIMELINE.addEvent((e) -> {
-                       if(initiator == select)
-                       {
-                               if(selected != -1)
-                                       inputs[selected].clearSignals();
-                               selected = selectValue;
-                               active.feedSignals(outI.owner.getValues());
-                               outI.feedSignals(active.owner.getValues());
-                       }
-                       else if(initiator == outI.owner)
-                               active.feedSignals(outI.owner.getValues());
-                       else if(initiator == active.owner)
-                               outI.feedSignals(active.owner.getValues());
-               }, processTime);
-       }
-}
index 58d48e7..5475fa1 100644 (file)
@@ -2,17 +2,18 @@ package era.mi.logic.components;
 
 import era.mi.logic.Bit;
 import era.mi.logic.wires.WireArray;
+import era.mi.logic.wires.WireArray.WireArrayInput;
 import era.mi.logic.wires.WireArrayObserver;
 
 public class Splitter implements WireArrayObserver
 {
        private WireArray input;
-       private WireArray[] outputs;
+       private WireArrayInput[] outputs;
        
        public Splitter(WireArray input, WireArray... outputs)
        {
                this.input = input;
-               this.outputs = outputs;
+               this.outputs = WireArray.extractInputs(outputs);
                input.addObserver(this);
                int length = 0;
                for(WireArray out : outputs)
@@ -28,22 +29,12 @@ public class Splitter implements WireArrayObserver
                Bit[] inputBits = input.getValues();
                for(int i = 0; i < outputs.length; i++)
                {
-                       Bit[] outputBits = new Bit[outputs[i].length];
-                       System.arraycopy(inputBits, startIndex, outputBits, 0, outputs[i].length);
+                       Bit[] outputBits = new Bit[outputs[i].owner.length];
+                       System.arraycopy(inputBits, startIndex, outputBits, 0, outputs[i].owner.length);
                        outputs[i].feedSignals(outputBits);
-                       startIndex += outputs[i].length;
+                       startIndex += outputs[i].owner.length;
                }
        }
-
-       public WireArray getInput()
-       {
-               return input;
-       }
-       
-       public WireArray[] getOutputs()
-       {
-               return outputs.clone();
-       }
        
        @Override
        public void update(WireArray initiator)
diff --git a/era.mi/src/era/mi/logic/components/TriState.java b/era.mi/src/era/mi/logic/components/TriState.java
deleted file mode 100644 (file)
index 2bddbf1..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-package era.mi.logic.components;
-
-import era.mi.logic.Bit;
-import era.mi.logic.wires.WireArray;
-import era.mi.logic.wires.WireArray.WireArrayInput;
-
-public class TriState extends BasicComponent{
-       WireArray in, enable;
-       WireArrayInput outI;
-       
-       public TriState(int processTime, WireArray in, WireArray out, WireArray enable) {
-               super(processTime);
-               if(in.length != out.length)
-                       throw new IllegalArgumentException("Tri-state output must have the same amount of bits as the input. Input: " + in.length + " Output: " + out.length);
-               if(enable.length != 1)
-                       throw new IllegalArgumentException("Tri-state enable must have exactly one bit, not " + enable.length + ".");
-               this.in = in;
-               in.addObserver(this);
-               this.enable = enable;
-               enable.addObserver(this);
-               outI = out.createInput();
-       }
-       
-       @Override
-       protected void compute()
-       {
-               if(enable.getValue() == Bit.ONE)
-                       outI.feedSignals(in.getValues());
-               else
-                       outI.clearSignals();
-       }
-
-}
diff --git a/era.mi/src/era/mi/logic/components/TriStateBuffer.java b/era.mi/src/era/mi/logic/components/TriStateBuffer.java
new file mode 100644 (file)
index 0000000..4000ae6
--- /dev/null
@@ -0,0 +1,33 @@
+package era.mi.logic.components;
+
+import era.mi.logic.Bit;
+import era.mi.logic.wires.WireArray;
+import era.mi.logic.wires.WireArray.WireArrayInput;
+
+public class TriStateBuffer extends BasicComponent{
+       WireArray in, enable;
+       WireArrayInput outI;
+       
+       public TriStateBuffer(int processTime, WireArray in, WireArray out, WireArray enable) {
+               super(processTime);
+               if(in.length != out.length)
+                       throw new IllegalArgumentException("Tri-state output must have the same amount of bits as the input. Input: " + in.length + " Output: " + out.length);
+               if(enable.length != 1)
+                       throw new IllegalArgumentException("Tri-state enable must have exactly one bit, not " + enable.length + ".");
+               this.in = in;
+               in.addObserver(this);
+               this.enable = enable;
+               enable.addObserver(this);
+               outI = out.createInput();
+       }
+       
+       @Override
+       protected void compute()
+       {
+               if(enable.getValue() == Bit.ONE)
+                       outI.feedSignals(in.getValues());
+               else
+                       outI.clearSignals();
+       }
+
+}
index 722c52a..a18228b 100644 (file)
@@ -3,13 +3,15 @@ package era.mi.logic.tests;
 import static org.junit.jupiter.api.Assertions.*;
 
 import java.util.Arrays;
-import java.util.function.LongConsumer;
 
 import org.junit.jupiter.api.Test;
 
 import era.mi.logic.Bit;
 import era.mi.logic.Simulation;
-import era.mi.logic.components.Mux2;
+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;
@@ -19,273 +21,323 @@ import era.mi.logic.wires.WireArray.WireArrayInput;
 class ComponentTest
 {
 
-//     @Test
-//     void circuitExampleTest()
-//     {
-//             Simulation.TIMELINE.reset();
-//             WireArray a = new WireArray(1, 1), b = new WireArray(1, 1), c = new WireArray(1, 10), d = new WireArray(2, 1), e = new WireArray(1, 1),
-//                             f = new WireArray(1, 1), g = new WireArray(1, 1), h = new WireArray(2, 1), i = new WireArray(2, 1), j = new WireArray(1, 1), k = new WireArray(1, 1);
-//             new AndGate(1, a, b, f);
-//             new NotGate(1, f, g);
-//             new Merger2(h, c, g);
-//             new Mux(1, h, d, e, i);
-//             new Splitter(i, k, j);
-//             
-//             a.createInput().feedSignals(Bit.ZERO);
-//             b.createInput().feedSignals(Bit.ONE);
-//             c.createInput().feedSignals(Bit.ZERO);
-//             d.createInput().feedSignals(Bit.ONE, Bit.ONE);
-//             e.createInput().feedSignals(Bit.ONE);
-//             
-//             while(Simulation.TIMELINE.hasNext())
-//             {
-//                     Simulation.TIMELINE.executeNext();
-//             }
-//             
-//             assertEquals(Simulation.TIMELINE.getSimulationTime(), 14);
-//             assertEquals(Bit.ONE, j.getValue());
-//             assertEquals(Bit.ZERO, k.getValue());
-//     }
-//
-//     @Test
-//     void splitterTest()
-//     {
-//             Simulation.TIMELINE.reset();
-//             WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), in = new WireArray(8, 1);
-//             in.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO,Bit.ONE, Bit.ZERO, Bit.ONE);
-//             new Splitter(in, a, b, c);
-//             
-//             while(Simulation.TIMELINE.hasNext())
-//             {
-//                     Simulation.TIMELINE.executeNext();
-//             }
-//             
-//             assertTrue(Arrays.equals(a.getValues(), new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO }));
-//             assertTrue(Arrays.equals(b.getValues(), new Bit[] { Bit.ONE, Bit.ZERO }));
-//             assertTrue(Arrays.equals(c.getValues(), new Bit[] { Bit.ONE, Bit.ZERO, Bit.ONE }));
-//     }
-//     
-//     @Test
-//     void mergerTest()
-//     {
-//             Simulation.TIMELINE.reset();
-//             WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), out = new WireArray(8, 1);
-//             a.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);
-//             b.createInput().feedSignals(Bit.ONE, Bit.ZERO);
-//             c.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-//             
-//             new Merger2(out, a, b, c);
-//             
-//             while(Simulation.TIMELINE.hasNext())
-//             {
-//                     Simulation.TIMELINE.executeNext();
-//             }
-//             
-//             assertTrue(Arrays.equals(out.getValues(), new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE }));
-//     }
-       
        @Test
-       void muxTest()
+       void circuitExampleTest()
        {
                Simulation.TIMELINE.reset();
-               WireArray a = new WireArray(1, 3), b = new WireArray(1, 2), select = new WireArray(1, 1), out = new WireArray(1, 1);
-               WireArrayInput selectIn = select.createInput();
+               WireArray a = new WireArray(1, 1), b = new WireArray(1, 1), c = new WireArray(1, 10), d = new WireArray(2, 1), e = new WireArray(1, 1),
+                               f = new WireArray(1, 1), g = new WireArray(1, 1), h = new WireArray(2, 1), i = new WireArray(2, 1), j = new WireArray(1, 1), k = new WireArray(1, 1);
+               new AndGate(1, a, b, f);
+               new NotGate(1, f, g);
+               new Merger(h, c, g);
+               new Mux(1, i, e, h, d);
+               new Splitter(i, k, j);
                
-               selectIn.feedSignals(Bit.ZERO);
-               a.createInput().feedSignals(Bit.ONE);
-               b.createInput().feedSignals(Bit.ZERO);
+               a.createInput().feedSignals(Bit.ZERO);
+               b.createInput().feedSignals(Bit.ONE);
+               c.createInput().feedSignals(Bit.ZERO);
+               d.createInput().feedSignals(Bit.ONE, Bit.ONE);
+               e.createInput().feedSignals(Bit.ZERO);
                
-               new Mux2(1, out, select, a, b);
-               assertEquals(Bit.Z, out.getValue());
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-
-               assertEquals(Bit.ONE, out.getValue());
-               selectIn.feedSignals(Bit.ONE);
                while(Simulation.TIMELINE.hasNext())
                {
                        Simulation.TIMELINE.executeNext();
                }
                
-               assertEquals(out.getValue(), Bit.ZERO);
+               assertEquals(Bit.ONE, j.getValue());
+               assertEquals(Bit.ZERO, k.getValue());
        }
 
-       @Test
-       void andTest()
+    @Test
+    void splitterTest()
+    {
+       Simulation.TIMELINE.reset();
+       WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), in = new WireArray(8, 1);
+       in.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
+       new Splitter(in, a, b, c);
+
+       while (Simulation.TIMELINE.hasNext())
        {
-               Simulation.TIMELINE.reset();
-               AndGate gate = new AndGate(1, new WireArray(4, 1), new WireArray(4, 1), new WireArray(4, 1));
-               gate.getA().createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
-               gate.getB().createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-               
-               
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               assertTrue(Arrays.equals(gate.getOut().getValues(), new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO }));
+           Simulation.TIMELINE.executeNext();
        }
-       
-       @Test
-       void orTest()
+
+       assertTrue(Arrays.equals(a.getValues(), new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO }));
+       assertTrue(Arrays.equals(b.getValues(), new Bit[] { Bit.ONE, Bit.ZERO }));
+       assertTrue(Arrays.equals(c.getValues(), new Bit[] { Bit.ONE, Bit.ZERO, Bit.ONE }));
+    }
+
+    @Test
+    void mergerTest()
+    {
+       Simulation.TIMELINE.reset();
+       WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), out = new WireArray(8, 1);
+       a.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);
+       b.createInput().feedSignals(Bit.ONE, Bit.ZERO);
+       c.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
+
+       new Merger(out, a, b, c);
+
+       while (Simulation.TIMELINE.hasNext())
        {
-               Simulation.TIMELINE.reset();
-               OrGate gate = new OrGate(1, new WireArray(4, 1), new WireArray(4, 1), new WireArray(4, 1));
-               gate.getA().createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
-               gate.getB().createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-               
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               
-               assertTrue(Arrays.equals(gate.getOut().getValues(), new Bit[] { Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE }));
+           Simulation.TIMELINE.executeNext();
        }
-       
-       @Test
-       void rsLatchCircuitTest()
+
+       assertTrue(Arrays.equals(out.getValues(),
+               new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE }));
+    }
+
+    @Test
+    void triStateBufferTest()
+    {
+       WireArray a = new WireArray(1, 1), b = new WireArray(1, 1), en = new WireArray(1, 1),
+               notEn = new WireArray(1, 1);
+       new NotGate(1, en, notEn);
+       new TriStateBuffer(1, a, b, en);
+       new TriStateBuffer(1, b, a, notEn);
+
+       WireArrayInput enI = en.createInput(), aI = a.createInput(), bI = b.createInput();
+       enI.feedSignals(Bit.ONE);
+       aI.feedSignals(Bit.ONE);
+
+       while (Simulation.TIMELINE.hasNext())
        {
-               Simulation.TIMELINE.reset();
-               WireArray r = new WireArray(1, 1), s = new WireArray(1, 1), t1 = new WireArray(1, 15), t2 = new WireArray(1, 1), q = new WireArray(1, 1),
-                               nq = new WireArray(1, 1);
-               
-               new OrGate(1, r, nq, t2);
-               new OrGate(1, s, q, t1);
-               new NotGate(1, t2, q);
-               new NotGate(1, t1, nq);
-       
-               WireArrayInput sIn = s.createInput(), rIn = r.createInput();
-               
-               sIn.feedSignals(Bit.ONE);
-               rIn.feedSignals(Bit.ZERO);
-               
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               
-               assertEquals(q.getValue(), Bit.ONE);
-               assertEquals(nq.getValue(), Bit.ZERO);
-               
-               sIn.feedSignals(Bit.ZERO);
-               
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               
-               assertEquals(q.getValue(), Bit.ONE);
-               assertEquals(nq.getValue(), Bit.ZERO);
-               
-               rIn.feedSignals(Bit.ONE);
-               
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               
-               assertEquals(q.getValue(), Bit.ZERO);
-               assertEquals(nq.getValue(), Bit.ONE);
+           Simulation.TIMELINE.executeNext();
        }
-       
-       @Test
-       void numericValueTest()
+
+       assertEquals(Bit.ONE, b.getValue());
+
+       bI.feedSignals(Bit.ZERO);
+
+       while (Simulation.TIMELINE.hasNext())
        {
-               Simulation.TIMELINE.reset();
-               
-               WireArray a = new WireArray(4, 1);
-               a.createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);
-               
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               
-               assertEquals(a.getUnsignedValue(), 15);
-               assertEquals(a.getSignedValue(), -1);
+           Simulation.TIMELINE.executeNext();
        }
-       
-       @Test
-       void multipleInputs()
+
+       assertEquals(Bit.X, b.getValue());
+       assertEquals(Bit.ONE, a.getValue());
+
+       aI.clearSignals();
+       enI.feedSignals(Bit.ZERO);
+
+       while (Simulation.TIMELINE.hasNext())
        {
-               Simulation.TIMELINE.reset();
-               WireArray w = new WireArray(2, 1);
-               WireArrayInput wI1 = w.createInput(), wI2 = w.createInput();
-               wI1.feedSignals(Bit.ONE, Bit.Z);
-               wI2.feedSignals(Bit.Z, Bit.X);
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               assertTrue(Arrays.equals(w.getValues(), new Bit[] { Bit.ONE, Bit.X }));
-               
-               wI2.feedSignals(Bit.ZERO, Bit.Z);
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               assertTrue(Arrays.equals(w.getValues(), new Bit[] { Bit.X, Bit.Z }));
-               
-               wI2.feedSignals(Bit.Z, Bit.Z);
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               assertTrue(Arrays.equals(w.getValues(), new Bit[] { Bit.ONE, Bit.Z }));
-               
-               wI2.feedSignals(Bit.ONE, Bit.Z);
-               w.addObserver((i) -> fail("WireArray notified observer, although value did not change."));
-               while(Simulation.TIMELINE.hasNext())
-               {
-                       Simulation.TIMELINE.executeNext();
-               }
-               assertTrue(Arrays.equals(w.getValues(), new Bit[] { Bit.ONE, Bit.Z }));
+           Simulation.TIMELINE.executeNext();
        }
-       
-       @Test
-       void wireConnections()
+
+       assertEquals(Bit.ZERO, a.getValue());
+
+    }
+
+    @Test
+    void muxTest()
+    {
+       Simulation.TIMELINE.reset();
+       WireArray a = new WireArray(4, 3), b = new WireArray(4, 6), c = new WireArray(4, 4),
+               select = new WireArray(2, 5), out = new WireArray(4, 1);
+       WireArrayInput selectIn = select.createInput();
+
+       selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
+       a.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+       c.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
+
+       new Mux(1, out, select, a, b, c);
+       while (Simulation.TIMELINE.hasNext())
        {
-               // Nur ein Experiment, was Ã¼ber mehrere 'passive' Bausteine hinweg passieren würde
-               
-               Simulation.TIMELINE.reset();
+           Simulation.TIMELINE.executeNext();
+       }
 
-               WireArray a = new WireArray(1, 2);
-               WireArray b = new WireArray(1, 2);
-               WireArray c = new WireArray(1, 2);
-               WireArrayInput aI = a.createInput();
-               WireArrayInput bI = b.createInput();
-               WireArrayInput cI = c.createInput();
-
-               TestBitDisplay test = new TestBitDisplay(c);
-               LongConsumer print = time -> System.out.format("Time %2d\n   %s\n   %s\n   %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);
-
-               Connector c1 = new Connector(b, c);
-               test.assertAfterSimulationIs(print, Bit.Z);
-               System.out.println("ONE");
-               bI.feedSignals(Bit.ONE);
-               test.assertAfterSimulationIs(print, Bit.ONE);
-               System.out.println("ZERO");
-               bI.feedSignals(Bit.ZERO);
-               test.assertAfterSimulationIs(print, Bit.ZERO);
-               System.out.println("Z");
-               bI.feedSignals(Bit.Z);
-               test.assertAfterSimulationIs(Bit.Z);
+       assertTrue(Arrays.equals(new Bit[] { Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO }, out.getValues()));
+       selectIn.feedSignals(Bit.ZERO, Bit.ONE);
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
        }
 
-       private static void assertBitArrayEquals(Bit[] actual, Bit... expected)
+       assertTrue(Arrays.equals(new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE }, out.getValues()));
+
+       selectIn.feedSignals(Bit.ONE, Bit.ONE);
+       while (Simulation.TIMELINE.hasNext())
        {
-               assertArrayEquals(expected, actual);
+           Simulation.TIMELINE.executeNext();
        }
+
+       assertTrue(Arrays.equals(new Bit[] { Bit.Z, Bit.Z, Bit.Z, Bit.Z }, out.getValues()));
+
+    }
+
+    @Test
+    void andTest()
+    {
+       Simulation.TIMELINE.reset();
+       AndGate gate = new AndGate(1, new WireArray(4, 1), new WireArray(4, 1), new WireArray(4, 1));
+       gate.getA().createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
+       gate.getB().createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
+
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+       assertTrue(Arrays.equals(gate.getOut().getValues(), new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO }));
+    }
+
+    @Test
+    void orTest()
+    {
+       Simulation.TIMELINE.reset();
+       OrGate gate = new OrGate(1, new WireArray(4, 1), new WireArray(4, 1), new WireArray(4, 1));
+       gate.getA().createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
+       gate.getB().createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
+
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+
+       assertTrue(Arrays.equals(gate.getOut().getValues(), new Bit[] { Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE }));
+    }
+
+    @Test
+    void rsLatchCircuitTest()
+    {
+       Simulation.TIMELINE.reset();
+       WireArray r = new WireArray(1, 1), s = new WireArray(1, 1), t1 = new WireArray(1, 15), t2 = new WireArray(1, 1),
+               q = new WireArray(1, 1), nq = new WireArray(1, 1);
+
+       new OrGate(1, r, nq, t2);
+       new OrGate(1, s, q, t1);
+       new NotGate(1, t2, q);
+       new NotGate(1, t1, nq);
+
+       WireArrayInput sIn = s.createInput(), rIn = r.createInput();
+
+       sIn.feedSignals(Bit.ONE);
+       rIn.feedSignals(Bit.ZERO);
+
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+
+       assertEquals(q.getValue(), Bit.ONE);
+       assertEquals(nq.getValue(), Bit.ZERO);
+
+       sIn.feedSignals(Bit.ZERO);
+
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+
+       assertEquals(q.getValue(), Bit.ONE);
+       assertEquals(nq.getValue(), Bit.ZERO);
+
+       rIn.feedSignals(Bit.ONE);
+
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+
+       assertEquals(q.getValue(), Bit.ZERO);
+       assertEquals(nq.getValue(), Bit.ONE);
+    }
+
+    @Test
+    void numericValueTest()
+    {
+       Simulation.TIMELINE.reset();
+
+       WireArray a = new WireArray(4, 1);
+       a.createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);
+
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+
+       assertEquals(a.getUnsignedValue(), 15);
+       assertEquals(a.getSignedValue(), -1);
+    }
+
+    @Test
+    void multipleInputs()
+    {
+       Simulation.TIMELINE.reset();
+       WireArray w = new WireArray(2, 1);
+       WireArrayInput wI1 = w.createInput(), wI2 = w.createInput();
+       wI1.feedSignals(Bit.ONE, Bit.Z);
+       wI2.feedSignals(Bit.Z, Bit.X);
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+       assertTrue(Arrays.equals(w.getValues(), new Bit[] { Bit.ONE, Bit.X }));
+
+       wI2.feedSignals(Bit.ZERO, Bit.Z);
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+       assertTrue(Arrays.equals(w.getValues(), new Bit[] { Bit.X, Bit.Z }));
+
+       wI2.feedSignals(Bit.Z, Bit.Z);
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+       assertTrue(Arrays.equals(w.getValues(), new Bit[] { Bit.ONE, Bit.Z }));
+
+       wI2.feedSignals(Bit.ONE, Bit.Z);
+       w.addObserver((i) -> fail("WireArray notified observer, although value did not change."));
+       while (Simulation.TIMELINE.hasNext())
+       {
+           Simulation.TIMELINE.executeNext();
+       }
+       assertTrue(Arrays.equals(w.getValues(), new Bit[] { Bit.ONE, Bit.Z }));
+    }
+
+//     @Test
+//     void wireConnections()
+//     {
+//             // Nur ein Experiment, was Ã¼ber mehrere 'passive' Bausteine hinweg passieren würde
+//             
+//             Simulation.TIMELINE.reset();
+//
+//             WireArray a = new WireArray(1, 2);
+//             WireArray b = new WireArray(1, 2);
+//             WireArray c = new WireArray(1, 2);
+//             WireArrayInput aI = a.createInput();
+//             WireArrayInput bI = b.createInput();
+//             WireArrayInput cI = c.createInput();
+//
+//             TestBitDisplay test = new TestBitDisplay(c);
+//             LongConsumer print = time -> System.out.format("Time %2d\n   %s\n   %s\n   %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);
+//
+//             Connector c1 = new Connector(b, c);
+//             test.assertAfterSimulationIs(print, Bit.Z);
+//             System.out.println("ONE");
+//             bI.feedSignals(Bit.ONE);
+//             test.assertAfterSimulationIs(print, Bit.ONE);
+//             System.out.println("ZERO");
+//             bI.feedSignals(Bit.ZERO);
+//             test.assertAfterSimulationIs(print, Bit.ZERO);
+//             System.out.println("Z");
+//             bI.feedSignals(Bit.Z);
+//             test.assertAfterSimulationIs(Bit.Z);
+//     }
+
+    private static void assertBitArrayEquals(Bit[] actual, Bit... expected)
+    {
+       assertArrayEquals(expected, actual);
+    }
 }
index 8cceebe..44cd751 100644 (file)
@@ -10,298 +10,340 @@ import era.mi.logic.Simulation;
 
 /**
  * Represents an array of wires that can store n bits of information.
+ * 
  * @author Fabian Stemmler
  *
  */
 public class WireArray
 {
-       private Bit[] values;
-       public final int travelTime;
-       private List<WireArrayObserver> observers = new ArrayList<WireArrayObserver>();
-       public final int length;
-       private List<WireArrayInput> inputs = new ArrayList<WireArrayInput>();
-       
-       public WireArray(int length, int travelTime)
+    private Bit[] values;
+    public final int travelTime;
+    private List<WireArrayObserver> observers = new ArrayList<WireArrayObserver>();
+    public final int length;
+    private List<WireArrayInput> inputs = new ArrayList<WireArrayInput>();
+
+    public WireArray(int length, int travelTime)
+    {
+       if (length < 1)
+           throw new IllegalArgumentException("Tried to create an array of wires with length " + length
+                   + ", but a length of less than 1 makes no sense.");
+       this.length = length;
+       this.travelTime = travelTime;
+       initValues();
+    }
+
+    private void initValues()
+    {
+       values = new Bit[length];
+       for (int i = 0; i < length; i++)
+           values[i] = Bit.Z;
+    }
+
+    private void recalculateSingleInput()
+    {
+       WireArrayInput input = inputs.get(0);
+       if (!Arrays.equals(input.getValues(), values))
        {
-               if(length < 1)
-                       throw new IllegalArgumentException("Tried to create an array of wires with length " + length + ", but a length of less than 1 makes no sense.");
-               this.length = length;
-               this.travelTime = travelTime;
-               initValues();
+           System.arraycopy(input.getValues(), 0, values, 0, length);
+           notifyObservers();
        }
-       
-       private void initValues()
+    }
+
+    private void recalculateMultipleInputs()
+    {
+       Iterator<WireArrayInput> it = inputs.iterator();
+       Bit[] newValues = it.next().values.clone();
+
+       while (it.hasNext())
        {
-               values = new Bit[length];
-               for(int i = 0; i < length; i++)
-                       values[i] = Bit.Z;
+           WireArrayInput input = it.next();
+           Bit[] bits = input.getValues();
+           for (int i = 0; i < length; i++)
+           {
+               if (Bit.Z.equals(bits[i]) || newValues[i].equals(bits[i]))
+                   continue;
+               else if (Bit.Z.equals(newValues[i]))
+                   newValues[i] = bits[i];
+               else
+                   newValues[i] = Bit.X;
+           }
        }
-       
-       private void recalculateSingleInput()
+
+       if (!Arrays.equals(newValues, values))
        {
-               WireArrayInput input = inputs.get(0);
-               if(!Arrays.equals(input.getValues(), values))
-               {
-                       System.arraycopy(input.getValues(), 0, values, 0, length);
-                       notifyObservers();
-               }
+           notifyObservers();
+           values = newValues;
        }
-       
-       private void recalculateMultipleInputs()
+    }
+
+    private void recalculate()
+    {
+       switch (inputs.size())
        {
-               Iterator<WireArrayInput> it = inputs.iterator();
-               Bit[] newValues = it.next().values.clone();
-               
-               while(it.hasNext())
-               {
-                       WireArrayInput input = it.next();
-                       Bit[] bits = input.getValues();
-                       for(int i = 0; i < length; i++)
-                       {
-                               if(Bit.Z.equals(bits[i]) || newValues[i].equals(bits[i]))
-                                       continue;
-                               else if(Bit.Z.equals(newValues[i]))
-                                       newValues[i] = bits[i];
-                               else
-                                       newValues[i] = Bit.X;
-                       }
-               }
-               
-               if(!Arrays.equals(newValues, values))
-               {
-                       notifyObservers();
-                       values = newValues;
-               }
+       case 0:
+           return;
+       case 1:
+           recalculateSingleInput();
+           break;
+       default:
+           recalculateMultipleInputs();
        }
+    }
 
-       private void recalculate()
+    /**
+     * The WireArray 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)
        {
-               switch(inputs.size())
-               {
-               case 0:
-                       return;
-               case 1:
-                       recalculateSingleInput();
-                       break;
-               default:
-                       recalculateMultipleInputs();
-               }
+           if (b != Bit.ZERO && b != Bit.ONE)
+               return false;
        }
-       
-       /**
-        * The WireArray 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 true;
+    }
+
+    /**
+     * The WireArray is interpreted as an unsigned integer with n bits.
+     * 
+     * @return The unsigned value of the {@link WireArray}'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 (int i = 0; i < length; i++)
        {
-               for(Bit b : values)
-               {
-                       if(b != Bit.ZERO && b != Bit.ONE)
-                               return false;
-               }
-               return true;
+           switch (values[i])
+           {
+           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;
        }
-       
-       /**
-        * The WireArray is interpreted as an unsigned integer with n bits.
-        * @return The unsigned value of the {@link WireArray}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
-        * 
-        * @author Fabian Stemmler
-        */
-       public long getUnsignedValue()
+       return val;
+    }
+
+    /**
+     * The WireArray is interpreted as a signed integer with n bits.
+     * 
+     * @return The signed value of the {@link WireArray}'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)
        {
-               long val = 0;
-               long mask = 1;
-               for(int i = 0; i < length; i++)
-               {
-                       switch(values[i])
-                       {
-                       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;
+           int shifts = 64 - length;
+           return (val << shifts) >> shifts;
        }
-       
-       /**
-        * The WireArray is interpreted as a signed integer with n bits.
-        * @return The signed value of the {@link WireArray}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
-        * 
-        * @author Fabian Stemmler
-        */
-       public long getSignedValue()
+       return val;
+    }
+
+    /**
+     * Included for convenient use on {@link WireArray}s of length 1.
+     * 
+     * @return The value of bit 0.
+     * 
+     * @author Fabian Stemmler
+     */
+    public Bit getValue()
+    {
+       return getValue(0);
+    }
+
+    /**
+     * 
+     * @param index Index of the requested bit.
+     * @return The value of the indexed bit.
+     * 
+     * @author Fabian Stemmler
+     */
+    public Bit getValue(int index)
+    {
+       return values[index];
+    }
+
+    public Bit[] getValues(int start, int end)
+    {
+       int length = end - start;
+       Bit[] bits = new Bit[length];
+       System.arraycopy(values, start, bits, 0, length);
+       return bits;
+    }
+
+    /**
+     * @return An array of length n containing the values of the n bits in the
+     *         {@link WireArray}. Can be safely modified.
+     * 
+     * @author Fabian Stemmler
+     */
+    public Bit[] getValues()
+    {
+       return values.clone();
+    }
+
+    /**
+     * Adds an {@link WireArrayObserver}, who will be notified when the value of the
+     * {@link WireArray} is updated.
+     * 
+     * @param ob The {@link WireArrayObserver} to be notified of changes.
+     * @return true if the given {@link WireArrayObserver} was not already
+     *         registered, false otherwise
+     * 
+     * @author Fabian Stemmler
+     */
+    public boolean addObserver(WireArrayObserver ob)
+    {
+       return observers.add(ob);
+    }
+
+    private void notifyObservers()
+    {
+       for (WireArrayObserver o : observers)
+           o.update(this);
+    }
+
+    /**
+     * Create and register a {@link WireArrayInput} object, which is tied to this
+     * {@link WireArray}.
+     */
+    public WireArrayInput createInput()
+    {
+       return new WireArrayInput(this);
+    }
+
+    private void registerInput(WireArrayInput toRegister)
+    {
+       inputs.add(toRegister);
+    }
+
+    /**
+     * A {@link WireArrayInput} feeds a constant signal into the {@link WireArray}
+     * it is tied to. The combination of all inputs determines the
+     * {@link WireArray}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 WireArrayInput
+    {
+       public final WireArray owner;
+       private Bit[] values;
+
+       private WireArrayInput(WireArray owner)
        {
-               long val = getUnsignedValue();
-               long mask = 1 << (length - 1);
-               if((mask & val) != 0)
-               {
-                       int shifts = 64 - length;
-                       return (val << shifts) >> shifts;
-               }
-               return val;
+           super();
+           this.owner = owner;
+           initValues();
+           owner.registerInput(this);
        }
-       
-       /**
-        * Included for convenient use on {@link WireArray}s of length 1.
-        * @return The value of bit 0.
-        * 
-        * @author Fabian Stemmler
-        */
-       public Bit getValue()
+
+       private void initValues()
        {
-               return getValue(0);
+           values = new Bit[length];
+           for (int i = 0; i < length; i++)
+               values[i] = Bit.Z;
        }
-       
+
        /**
+        * Sets the wires values. This takes up time, as specified by the
+        * {@link WireArray}s travel time.
         * 
-        * @param index Index of the requested bit.
-        * @return The value of the indexed bit.
+        * @param newValues The new values the wires should take on.
         * 
         * @author Fabian Stemmler
         */
-       public Bit getValue(int index)
-       {
-               return values[index];
-       }
-       
-       public Bit[] getValues(int start, int end)
+       public void feedSignals(Bit... newValues)
        {
-               int length = end - start;
-               Bit[] bits = new Bit[length];
-               System.arraycopy(values, start, bits, 0, length);               
-               return bits;
+           if (newValues.length == length)
+           {
+               feedSignals(0, newValues);
+           } else
+               throw new IllegalArgumentException(
+                       "Attempted to input " + newValues.length + " bits instead of " + length + " bits.");
        }
-       
-       
+
        /**
-        * @return An array of length n containing the values of the n bits in the {@link WireArray}. Can be safely modified.
+        * Sets values of a subarray of wires. This takes up time, as specified by the
+        * {@link WireArray}s travel time.
         * 
-        * @author Fabian Stemmler
-        */
-       public Bit[] getValues()
-       {
-               return values.clone();
-       }
-       
-       /**
-        * Adds an {@link WireArrayObserver}, who will be notified when the value of the {@link WireArray} is updated.
-        * @param ob The {@link WireArrayObserver} to be notified of changes.
-        * @return true if the given {@link WireArrayObserver} was not already registered, false otherwise
+        * @param newValues   The new values the wires should take on.
+        * @param startingBit The first index of the subarray of wires.
         * 
         * @author Fabian Stemmler
         */
-       public boolean addObserver(WireArrayObserver ob)
+       public void feedSignals(int startingBit, Bit... newValues)
        {
-               return observers.add(ob);
+           Simulation.TIMELINE.addEvent((e) -> setValues(startingBit, newValues), travelTime);
        }
-       
-       private void notifyObservers()
+
+       private void setValues(int startingBit, Bit... newValues)
        {
-               for(WireArrayObserver o : observers)
-                       o.update(this);
+           int exclLastIndex = startingBit + newValues.length;
+           if (length < exclLastIndex)
+               throw new ArrayIndexOutOfBoundsException("Attempted to input bits from index " + startingBit + " to "
+                       + exclLastIndex + " when there are only " + length + "wires.");
+           if (!Arrays.equals(values, startingBit, exclLastIndex, newValues, 0, newValues.length))
+           {
+               System.arraycopy(newValues, 0, values, startingBit, newValues.length);
+               owner.recalculate();
+           }
        }
-       
-       public WireArrayInput createInput()
+
+       public Bit[] getValues()
        {
-               return new WireArrayInput(this);
+           return values.clone();
        }
-       
-       private void registerInput(WireArrayInput toRegister)
+
+       public void clearSignals()
        {
-               inputs.add(toRegister);
-       }
-       
-       public class WireArrayInput {
-               public final WireArray owner;
-               private Bit[] values;
-               
-               private WireArrayInput(WireArray owner) {
-                       super();
-                       this.owner = owner;
-                       initValues();
-                       owner.registerInput(this);
-               }
-               
-               private void initValues()
-               {
-                       values = new Bit[length];
-                       for(int i = 0; i < length; i++)
-                               values[i] = Bit.Z;
-               }
-               
-               /**
-                * Sets the wires values. This takes up time, as specified by the {@link WireArray}s travel time.
-                * @param newValues The new values the wires should take on.
-                * 
-                * @author Fabian Stemmler
-                */
-               public void feedSignals(Bit... newValues)
-               {
-                       if(newValues.length == length)
-                       {
-                               feedSignals(0, newValues);
-                       }
-                       else
-                               throw new IllegalArgumentException("Attempted to input " + newValues.length + " bits instead of " + length + " bits.");
-               }
-               
-               /**
-                * Sets values of a subarray of wires. This takes up time, as specified by the {@link WireArray}s travel time.
-                * @param newValues 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, Bit... newValues)
-               {
-                       Simulation.TIMELINE.addEvent((e) -> setValues(startingBit, newValues), travelTime);
-               }
-               
-               private void setValues(int startingBit, Bit... newValues)
-               {
-                       int exclLastIndex = startingBit + newValues.length;
-                       if(length < exclLastIndex)
-                               throw new ArrayIndexOutOfBoundsException("Attempted to input bits from index " + startingBit + " to "
-                                       + exclLastIndex + " when there are only " + length + "wires.");
-                       if(!Arrays.equals(values, startingBit, exclLastIndex, newValues, 0, newValues.length))
-                       {
-                               System.arraycopy(newValues, 0, values, startingBit, newValues.length);
-                               owner.recalculate();
-                       }
-               }
-               
-               public Bit[] getValues()
-               {
-                       return values.clone();
-               }
-               
-               public void clearSignals()
-               {
-                       Bit[] bits = new Bit[length];
-                       for(int i = 0; i < length; i++)
-                               bits[i] = Bit.Z;
-                       feedSignals(bits);
-               }
-               
-               @Override
-               public String toString()
-               {
-                       return Arrays.toString(values);
-               }
+           Bit[] bits = new Bit[length];
+           for (int i = 0; i < length; i++)
+               bits[i] = Bit.Z;
+           feedSignals(bits);
        }
 
        @Override
        public String toString()
        {
-               return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), Arrays.toString(values), inputs);
+           return Arrays.toString(values);
        }
-}
+    }
+
+    @Override
+    public String toString()
+    {
+       return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), Arrays.toString(values), inputs);
+    }
+    
+    public static WireArrayInput[] extractInputs(WireArray[] w)
+    {
+       WireArrayInput[] inputs = new WireArrayInput[w.length];
+       for(int i = 0; i < w.length; i++)
+           inputs[i] = w[i].createInput();
+       return inputs;
+    }
+}
\ No newline at end of file