added more doc to Timeline; added functionality to Bit
authorFabian Stemmler <stemmler@in.tum.de>
Sun, 12 May 2019 12:27:09 +0000 (14:27 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Sun, 12 May 2019 12:27:09 +0000 (14:27 +0200)
era.mi/src/era/mi/logic/Bit.java
era.mi/src/era/mi/logic/Util.java
era.mi/src/era/mi/logic/tests/ComponentTest.java
era.mi/src/era/mi/logic/tests/Connector.java
era.mi/src/era/mi/logic/timeline/Timeline.java
era.mi/src/era/mi/logic/timeline/TimelineEvent.java
era.mi/src/era/mi/logic/wires/WireArray.java

index e7c9396..58a538a 100644 (file)
-package era.mi.logic;
-
-public enum Bit
-{
-       ONE, ZERO, Z, X;
-
-       public static Bit and(Bit a, Bit b)
-       {
-               return a.and(b);
-       }
-
-       public Bit and(Bit other)
-       {
-               if (equals(Bit.ZERO) || other.equals(Bit.ZERO))
-                       return Bit.ZERO;
-               else if (equals(other) && equals(Bit.ONE))
-                       return Bit.ONE;
-               else
-                       return Bit.X;
-       }
-
-       public static Bit or(Bit a, Bit b)
-       {
-               return a.or(b);
-       }
-
-       public Bit or(Bit other)
-       {
-               if (equals(Bit.ONE) || other.equals(Bit.ONE))
-                       return Bit.ONE;
-               else if (equals(other) && equals(Bit.ZERO))
-                       return Bit.ZERO;
-               else
-                       return Bit.X;
-       }
-
-       public static Bit xor(Bit a, Bit b)
-       {
-               return a.xor(b);
-       }
-
-       public Bit xor(Bit other)
-       {
-               // I'm uncertain how this should behave for cases where one value is neither 1 nor 0.
-               // TODO: Implement xor
-               return Bit.X;
-       }
-
-       public Bit not()
-       {
-               switch (this)
-                       {
-                       case ONE:
-                               return Bit.ZERO;
-                       case ZERO:
-                               return Bit.ONE;
-                       default:
-                               return Bit.X;
-                       }
-       }
-
-       /**
-        * Rules for two bits that get directly connected<br>
-        * <code><table>
-        * <tbody>
-        * <tr><td><td>X<td>0<td>1<td>Z</tr>
-        * <tr><td>X<td>X<td>X<td>X<td>X</tr>
-        * <tr><td>0<td>X<td>0<td>X<td>0</tr>
-        * <tr><td>1<td>X<td>X<td>1<td>1</tr>
-        * <tr><td>Z<td>X<td>0<td>1<td>Z</tr>
-        * </tbody>
-        * </table><code>
-        * 
-        * @return the result according to the table
-        * 
-        * @author Christian Femers
-        */
-       public Bit combineWith(Bit other)
-       {
-               if (this == other)
-                       return this;
-               if (this == X || other == X)
-                       return X;
-               if (other == Z)
-                       return this;
-               if (this == Z)
-                       return other;
-               return X;
-       }
-
-       public static Bit combine(Bit a, Bit b)
-       {
-               return a.combineWith(b);
-       }
-}
+package era.mi.logic;\r
+\r
+import java.util.Arrays;\r
+\r
+public enum Bit\r
+{\r
+       ONE, ZERO, Z, X;\r
+\r
+       public static Bit and(Bit a, Bit b)\r
+       {\r
+               return a.and(b);\r
+       }\r
+\r
+       public Bit and(Bit other)\r
+       {\r
+               if (equals(Bit.ZERO) || other.equals(Bit.ZERO))\r
+                       return Bit.ZERO;\r
+               else if (equals(other) && equals(Bit.ONE))\r
+                       return Bit.ONE;\r
+               else\r
+                       return Bit.X;\r
+       }\r
+\r
+       public static Bit or(Bit a, Bit b)\r
+       {\r
+               return a.or(b);\r
+       }\r
+\r
+       public Bit or(Bit other)\r
+       {\r
+               if (equals(Bit.ONE) || other.equals(Bit.ONE))\r
+                       return Bit.ONE;\r
+               else if (equals(other) && equals(Bit.ZERO))\r
+                       return Bit.ZERO;\r
+               else\r
+                       return Bit.X;\r
+       }\r
+\r
+       public static Bit xor(Bit a, Bit b)\r
+       {\r
+               return a.xor(b);\r
+       }\r
+\r
+       public Bit xor(Bit other)\r
+       {\r
+               if(this == Bit.X || this == Bit.Z\r
+                               || other == Bit.X || other == Bit.Z)\r
+                       return Bit.X;\r
+               else\r
+                       return this == other ? Bit.ZERO : Bit.ONE;\r
+       }\r
+\r
+       public Bit not()\r
+       {\r
+               switch (this)\r
+                       {\r
+                       case ONE:\r
+                               return Bit.ZERO;\r
+                       case ZERO:\r
+                               return Bit.ONE;\r
+                       default:\r
+                               return Bit.X;\r
+                       }\r
+       }\r
+       \r
+       public Bit[] makeArray(int length)\r
+       {\r
+               Bit[] bits = new Bit[length];\r
+               Arrays.fill(bits, this);\r
+               return bits;\r
+       }\r
+\r
+       /**\r
+        * Rules for two bits that get directly connected<br>\r
+        * <code><table>\r
+        * <tbody>\r
+        * <tr><td><td>X<td>0<td>1<td>Z</tr>\r
+        * <tr><td>X<td>X<td>X<td>X<td>X</tr>\r
+        * <tr><td>0<td>X<td>0<td>X<td>0</tr>\r
+        * <tr><td>1<td>X<td>X<td>1<td>1</tr>\r
+        * <tr><td>Z<td>X<td>0<td>1<td>Z</tr>\r
+        * </tbody>\r
+        * </table><code>\r
+        * \r
+        * @return the result according to the table\r
+        * \r
+        * @author Christian Femers\r
+        */\r
+       public Bit combineWith(Bit other)\r
+       {\r
+               if (this == other)\r
+                       return this;\r
+               if (this == X || other == X)\r
+                       return X;\r
+               if (other == Z)\r
+                       return this;\r
+               if (this == Z)\r
+                       return other;\r
+               return X;\r
+       }\r
+\r
+       public static Bit combine(Bit a, Bit b)\r
+       {\r
+               return a.combineWith(b);\r
+       }\r
+}\r
index 6aec884..3ca16b7 100644 (file)
@@ -85,16 +85,9 @@ public final class Util
        return out;
     }
     
-    public static Bit[] arrayOfZ(int length)
-    {
-    Bit[] out = new Bit[length];
-    Arrays.fill(out, Bit.Z);
-    return out;
-    }
-    
     /**
      * uses the {@link Bit#combineWith(Bit)} method, does not create a new array,
-     * the result is stored in the fist array.
+     * the result is stored in the first array.
      * 
      * @author Christian Femers
      */
index a407b8d..c49e004 100644 (file)
-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.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.wires.WireArray;
-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 Merger(h, c, g);
-               new Mux(1, i, e, h, d);
-               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.ZERO);
-               
-               Simulation.TIMELINE.executeAll();
-               
-               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);
-
-       Simulation.TIMELINE.executeAll();
-
-       assertArrayEquals(new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO }, a.getValues());
-       assertArrayEquals(new Bit[] { Bit.ONE, Bit.ZERO }, b.getValues());
-       assertArrayEquals(new Bit[] { Bit.ONE, Bit.ZERO, Bit.ONE }, c.getValues());
-    }
-
-    @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);
-
-       Simulation.TIMELINE.executeAll();
-
-       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);
-
-       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();
-       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);
-       Simulation.TIMELINE.executeAll();
-
-       assertArrayEquals(new Bit[] { Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO }, out.getValues());
-       selectIn.feedSignals(Bit.ZERO, Bit.ONE);
-       Simulation.TIMELINE.executeAll();
-
-       assertArrayEquals(new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE }, out.getValues());
-
-       selectIn.feedSignals(Bit.ONE, Bit.ONE);
-       Simulation.TIMELINE.executeAll();
-
-       assertArrayEquals(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);
-
-       Simulation.TIMELINE.executeAll();
-       assertArrayEquals(new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO }, gate.getOut().getValues());
-    }
-
-    @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);
-
-       Simulation.TIMELINE.executeAll();
-
-       assertArrayEquals(new Bit[] { Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE }, gate.getOut().getValues());
-    }
-
-    @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);
-
-       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();
-
-       WireArray a = new WireArray(4, 1);
-       a.createInput().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();
-       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);
-       Simulation.TIMELINE.executeAll();
-       assertArrayEquals(new Bit[] { Bit.ONE, Bit.X }, w.getValues());
-
-       wI2.feedSignals(Bit.ZERO, Bit.Z);
-       Simulation.TIMELINE.executeAll();
-       assertArrayEquals(new Bit[] { Bit.X, Bit.Z }, w.getValues());
-
-       wI2.feedSignals(Bit.Z, Bit.Z);
-       Simulation.TIMELINE.executeAll();
-       assertArrayEquals(new Bit[] { Bit.ONE, Bit.Z }, w.getValues());
-
-       wI2.feedSignals(Bit.ONE, Bit.Z);
-       w.addObserver((i) -> fail("WireArray notified observer, although value did not change."));
-       Simulation.TIMELINE.executeAll();
-       assertArrayEquals(new Bit[] { Bit.ONE, Bit.Z }, w.getValues());
-    }
-
-       @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);
-               TestBitDisplay test2 = new TestBitDisplay(a);
-               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);
-
-               Connector c1 = new Connector(b, c);
-               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);
-               
-               Connector c2 = new Connector(a, b);
-               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(Bit[] actual, Bit... expected)
-    {
-       assertArrayEquals(expected, actual);
-    }
-}
+package era.mi.logic.tests;\r
+\r
+import static org.junit.jupiter.api.Assertions.*;\r
+\r
+import java.util.Arrays;\r
+import java.util.function.LongConsumer;\r
+\r
+import org.junit.jupiter.api.Test;\r
+\r
+import era.mi.logic.Bit;\r
+import era.mi.logic.Simulation;\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.wires.WireArray;\r
+import era.mi.logic.wires.WireArray.WireArrayInput;\r
+\r
+class ComponentTest\r
+{\r
+    \r
+       @Test\r
+       void circuitExampleTest()\r
+       {\r
+               Simulation.TIMELINE.reset();\r
+               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),\r
+                               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);\r
+               new AndGate(1, a, b, f);\r
+               new NotGate(1, f, g);\r
+               new Merger(h, c, g);\r
+               new Mux(1, i, e, h, d);\r
+               new Splitter(i, k, j);\r
+               \r
+               a.createInput().feedSignals(Bit.ZERO);\r
+               b.createInput().feedSignals(Bit.ONE);\r
+               c.createInput().feedSignals(Bit.ZERO);\r
+               d.createInput().feedSignals(Bit.ONE, Bit.ONE);\r
+               e.createInput().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
+       WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), in = new WireArray(8, 1);\r
+       in.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+       new Splitter(in, a, b, c);\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
+       WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), out = new WireArray(8, 1);\r
+       a.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+       b.createInput().feedSignals(Bit.ONE, Bit.ZERO);\r
+       c.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+       new Merger(out, a, b, c);\r
+\r
+       Simulation.TIMELINE.executeAll();\r
+\r
+       assertTrue(Arrays.equals(out.getValues(),\r
+               new Bit[] { 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
+       WireArray a = new WireArray(1, 1), b = new WireArray(1, 1), en = new WireArray(1, 1),\r
+               notEn = new WireArray(1, 1);\r
+       new NotGate(1, en, notEn);\r
+       new TriStateBuffer(1, a, b, en);\r
+       new TriStateBuffer(1, b, a, notEn);\r
+\r
+       WireArrayInput enI = en.createInput(), aI = a.createInput(), bI = b.createInput();\r
+       enI.feedSignals(Bit.ONE);\r
+       aI.feedSignals(Bit.ONE);\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
+       WireArray a = new WireArray(4, 3), b = new WireArray(4, 6), c = new WireArray(4, 4),\r
+               select = new WireArray(2, 5), out = new WireArray(4, 1);\r
+       WireArrayInput selectIn = select.createInput();\r
+\r
+       selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+       a.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+       c.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+       new Mux(1, out, select, a, b, c);\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 andTest()\r
+    {\r
+       Simulation.TIMELINE.reset();\r
+       AndGate gate = new AndGate(1, new WireArray(4, 1), new WireArray(4, 1), new WireArray(4, 1));\r
+       gate.getA().createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+       gate.getB().createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+       Simulation.TIMELINE.executeAll();\r
+       assertBitArrayEquals(gate.getOut().getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+    }\r
+\r
+    @Test\r
+    void orTest()\r
+    {\r
+       Simulation.TIMELINE.reset();\r
+       OrGate gate = new OrGate(1, new WireArray(4, 1), new WireArray(4, 1), new WireArray(4, 1));\r
+       gate.getA().createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+       gate.getB().createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+       Simulation.TIMELINE.executeAll();\r
+\r
+       assertBitArrayEquals(gate.getOut().getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+    }\r
+\r
+    @Test\r
+    void rsLatchCircuitTest()\r
+    {\r
+       Simulation.TIMELINE.reset();\r
+       WireArray r = new WireArray(1, 1), s = new WireArray(1, 1), t1 = new WireArray(1, 15), t2 = new WireArray(1, 1),\r
+               q = new WireArray(1, 1), nq = new WireArray(1, 1);\r
+\r
+       new OrGate(1, r, nq, t2);\r
+       new OrGate(1, s, q, t1);\r
+       new NotGate(1, t2, q);\r
+       new NotGate(1, t1, nq);\r
+\r
+       WireArrayInput sIn = s.createInput(), rIn = r.createInput();\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
+       WireArray a = new WireArray(4, 1);\r
+       a.createInput().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
+       WireArray w = new WireArray(2, 1);\r
+       WireArrayInput wI1 = w.createInput(), wI2 = w.createInput();\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
+       w.addObserver((i) -> fail("WireArray notified observer, although value did not change."));\r
+       Simulation.TIMELINE.executeAll();\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
+               WireArray a = new WireArray(1, 2);\r
+               WireArray b = new WireArray(1, 2);\r
+               WireArray c = new WireArray(1, 2);\r
+               WireArrayInput aI = a.createInput();\r
+               WireArrayInput bI = b.createInput();\r
+               WireArrayInput cI = c.createInput();\r
+\r
+               TestBitDisplay test = new TestBitDisplay(c);\r
+               TestBitDisplay test2 = new TestBitDisplay(a);\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
+               Connector c1 = new Connector(b, c);\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
+               Connector c2 = new Connector(a, b);\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(Bit[] actual, Bit... expected)\r
+    {\r
+       assertArrayEquals(expected, actual);\r
+    }\r
+}\r
index c843237..112f6fc 100644 (file)
@@ -15,7 +15,7 @@ public class Connector implements WireArrayObserver
        public Connector(WireArray a, WireArray b)\r
        {\r
                if (a.length != b.length)\r
-                       throw new IllegalArgumentException("WireArray width does not match: " + a.length + ", " + b.length);\r
+                       throw new IllegalArgumentException(String.format("WireArray width does not match: %o, %o", a.length, b.length));\r
                this.a = a;\r
                this.b = b;\r
                a.addObserver(this);\r
index 2392f4c..2578a9b 100644 (file)
-package era.mi.logic.timeline;
-
-import java.util.PriorityQueue;
-
-/**
- * Orders Events by the time they are due to be executed. Can execute Events individually.
- * @author Fabian Stemmler
- *
- */
-public class Timeline
-{
-       private PriorityQueue<InnerEvent> events;
-       private long currentTime = 0;
-       
-       public Timeline(int initCapacity)
-       {
-               events = new PriorityQueue<InnerEvent>(initCapacity, (a, b) -> {
-                       long difference = a.getTiming() - b.getTiming();
-                       if(difference == 0)
-                               return 0;
-                       return difference < 0 ? -1 : 1;
-               });
-       }
-       
-       public boolean hasNext()
-       {
-               return !events.isEmpty();
-       }
-
-       public void executeNext()
-       {
-               InnerEvent first = events.poll();
-               currentTime = first.getTiming();
-               first.run();
-       }
-       
-       public void executeAll()
-       {
-               while (hasNext())
-                       executeNext();
-       }
-
-       public long getSimulationTime()
-       {
-               return currentTime;
-       }
-       
-       public void reset()
-       {
-               events.clear();
-               currentTime = 0;
-       }
-       
-       /**
-        * Adds an Event to the {@link Timeline}
-        * @param function The {@link TimelineEventHandler} that will be executed, when the {@link InnerEvent} occurs on the timeline.
-        * @param relativeTiming The amount of MI ticks in which the {@link InnerEvent} is called, starting from the current time.
-        */
-       public void addEvent(TimelineEventHandler function, int relativeTiming)
-       {
-               long timing = currentTime + relativeTiming;
-               events.add(new InnerEvent(function, new TimelineEvent(timing), timing));
-       }
-       
-       private class InnerEvent
-       {
-
-               private final long timing;
-               private final TimelineEventHandler function;
-               private final TimelineEvent event;
-               
-               /**
-                * Creates an {@link InnerEvent}
-                * @param function {@link TimelineEventHandler} to be executed when the {@link InnerEvent} occurs
-                * @param timing Point in the MI simulation {@link Timeline}, at which the {@link InnerEvent} is executed;
-                */
-               InnerEvent(TimelineEventHandler function, TimelineEvent event, long timing)
-               {
-                       this.function = function;
-                       this.event = event;
-                       this.timing = timing;
-               }
-
-               public long getTiming()
-               {
-                       return timing;
-               }
-               
-               public void run()
-               {
-                       function.handle(event);
-               }
-               
-       }
+package era.mi.logic.timeline;\r
+\r
+import java.util.PriorityQueue;\r
+\r
+/**\r
+ * Orders Events by the time they are due to be executed. Can execute Events individually.\r
+ * @author Fabian Stemmler\r
+ *\r
+ */\r
+public class Timeline\r
+{\r
+       private PriorityQueue<InnerEvent> events;\r
+       private long currentTime = 0;\r
+       \r
+       public Timeline(int initCapacity)\r
+       {\r
+               events = new PriorityQueue<InnerEvent>(initCapacity, (a, b) -> {\r
+                       long difference = a.getTiming() - b.getTiming();\r
+                       if(difference == 0)\r
+                               return 0;\r
+                       return difference < 0 ? -1 : 1;\r
+               });\r
+       }\r
+       \r
+       public boolean hasNext()\r
+       {\r
+               return !events.isEmpty();\r
+       }\r
+\r
+       public void executeNext()\r
+       {\r
+               InnerEvent first = events.poll();\r
+               currentTime = first.getTiming();\r
+               first.run();\r
+       }\r
+       \r
+       public void executeAll()\r
+       {\r
+               while (hasNext())\r
+                       executeNext();\r
+       }\r
+\r
+       public long getSimulationTime()\r
+       {\r
+               return currentTime;\r
+       }\r
+       \r
+       public void reset()\r
+       {\r
+               events.clear();\r
+               currentTime = 0;\r
+       }\r
+       \r
+       /**\r
+        * Adds an Event to the {@link Timeline}\r
+        * @param function The {@link TimelineEventHandler} that will be executed, when the {@link InnerEvent} occurs on the timeline.\r
+        * @param relativeTiming The amount of MI ticks in which the {@link InnerEvent} is called, starting from the current time.\r
+        */\r
+       public void addEvent(TimelineEventHandler function, int relativeTiming)\r
+       {\r
+               long timing = currentTime + relativeTiming;\r
+               events.add(new InnerEvent(function, new TimelineEvent(timing), timing));\r
+       }\r
+       \r
+       private class InnerEvent\r
+       {\r
+\r
+               private final long timing;\r
+               private final TimelineEventHandler function;\r
+               private final TimelineEvent event;\r
+               \r
+               /**\r
+                * Creates an {@link InnerEvent}\r
+                * @param function {@link TimelineEventHandler} to be executed when the {@link InnerEvent} occurs\r
+                * @param timing Point in the MI simulation {@link Timeline}, at which the {@link InnerEvent} is executed;\r
+                */\r
+               InnerEvent(TimelineEventHandler function, TimelineEvent event, long timing)\r
+               {\r
+                       this.function = function;\r
+                       this.event = event;\r
+                       this.timing = timing;\r
+               }\r
+\r
+               public long getTiming()\r
+               {\r
+                       return timing;\r
+               }\r
+               \r
+               public void run()\r
+               {\r
+                       function.handle(event);\r
+               }\r
+               \r
+               @Override\r
+               public String toString()\r
+               {\r
+                       return event.toString();\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public String toString()\r
+       {\r
+               return "simulation time: " + currentTime + ", " + events.toString();\r
+       }\r
 }
\ No newline at end of file
index 6cec907..6840349 100644 (file)
@@ -1,17 +1,27 @@
-package era.mi.logic.timeline;
-
-public class TimelineEvent
-{
-       private final long timing;
-       
-       TimelineEvent(long timing)
-       {
-               super();
-               this.timing = timing;
-       }
-
-       public long getTiming()
-       {
-               return timing;
-       }
+package era.mi.logic.timeline;\r
+\r
+/**\r
+ * A class that stores all relevant information about an event in the {@link Timeline}. Currently, there is not much relevant information to store.\r
+ * @author Fabian Stemmler\r
+ *\r
+ */\r
+public class TimelineEvent\r
+{\r
+       private final long timing;\r
+       \r
+       TimelineEvent(long timing)\r
+       {\r
+               super();\r
+               this.timing = timing;\r
+       }\r
+\r
+       public long getTiming()\r
+       {\r
+               return timing;\r
+       }\r
+       \r
+       public String toString()\r
+       {\r
+               return "timestamp: " + timing;\r
+       }\r
 }
\ No newline at end of file
index 370cbbd..29b3575 100644 (file)
-package era.mi.logic.wires;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-import era.mi.logic.Bit;
-import era.mi.logic.Simulation;
-import era.mi.logic.Util;
-
-/**
- * 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)
-    {
-       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))
-       {
-           System.arraycopy(input.getValues(), 0, values, 0, length);
-           notifyObservers();
-       }
-    }
-
-    private void recalculateMultipleInputs()
-    {
-       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;
-       }
-    }
-
-    private void recalculate()
-    {
-       switch (inputs.size())
-       {
-       case 0:
-           return;
-       case 1:
-           recalculateSingleInput();
-           break;
-       default:
-           recalculateMultipleInputs();
-       }
-    }
-
-    /**
-     * 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)
-       {
-           if (b != Bit.ZERO && b != Bit.ONE)
-               return false;
-       }
-       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++)
-       {
-           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;
-    }
-
-    /**
-     * 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)
-       {
-           int shifts = 64 - length;
-           return (val << shifts) >> shifts;
-       }
-       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)
-       {
-           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 Bit[] wireValuesExcludingMe() 
-       {
-               Bit[] bits = Util.arrayOfZ(length);
-               for (WireArrayInput wai : inputs) 
-               {
-                       if(wai == this)
-                               continue;
-                       Util.combineInto(bits, wai.getValues());
-               }
-               return bits;
-       }
-
-       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);
-       }
-    }
-
-    @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;
-    }
+package era.mi.logic.wires;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import era.mi.logic.Bit;\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.Util;\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 WireArray\r
+{\r
+       private Bit[] values;\r
+       public final int travelTime;\r
+       private List<WireArrayObserver> observers = new ArrayList<WireArrayObserver>();\r
+       public final int length;\r
+       private List<WireArrayInput> inputs = new ArrayList<WireArrayInput>();\r
+\r
+       public WireArray(int length, int travelTime)\r
+       {\r
+               if (length < 1)\r
+                       throw new IllegalArgumentException(String.format("Tried to create an array of wires with length %o, 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 = Bit.Z.makeArray(length);\r
+       }\r
+\r
+       private void recalculateSingleInput()\r
+       {\r
+               WireArrayInput input = inputs.get(0);\r
+               if (!Arrays.equals(input.getValues(), values))\r
+               {\r
+                       System.arraycopy(input.getValues(), 0, values, 0, length);\r
+                       notifyObservers();\r
+               }\r
+       }\r
+\r
+       private void recalculateMultipleInputs()\r
+       {\r
+               Iterator<WireArrayInput> it = inputs.iterator();\r
+               Bit[] newValues = it.next().inputValues.clone();\r
+\r
+               while (it.hasNext())\r
+               {\r
+                       WireArrayInput input = it.next();\r
+                       Bit[] bits = input.getValues();\r
+                       for (int i = 0; i < length; i++)\r
+                       {\r
+                               if (Bit.Z.equals(bits[i]) || newValues[i].equals(bits[i]))\r
+                                       continue;\r
+                               else if (Bit.Z.equals(newValues[i]))\r
+                                       newValues[i] = bits[i];\r
+                               else\r
+                                       newValues[i] = Bit.X;\r
+                       }\r
+               }\r
+\r
+               if (!Arrays.equals(newValues, values))\r
+               {\r
+                       notifyObservers();\r
+                       values = newValues;\r
+               }\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 WireArray 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\r
+        *         <code>Bit.ZERO</code> (they do not all have to have the same value),\r
+        *         not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is\r
+        *         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 WireArray is interpreted as an unsigned integer with n bits.\r
+        * \r
+        * @return The unsigned value of the {@link WireArray}'s bits, where value 0\r
+        *         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 (int i = 0; i < length; i++)\r
+               {\r
+                       switch (values[i])\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
+                       // Random number?\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 WireArray is interpreted as a signed integer with n bits.\r
+        * \r
+        * @return The signed value of the {@link WireArray}'s bits, where value 0\r
+        *         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
+       /**\r
+        * Included for convenient use on {@link WireArray}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 getValue(0);\r
+       }\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 values[index];\r
+       }\r
+\r
+       public Bit[] getValues(int start, int end)\r
+       {\r
+               int length = end - start;\r
+               Bit[] bits = new Bit[length];\r
+               System.arraycopy(values, start, bits, 0, length);\r
+               return bits;\r
+       }\r
+\r
+       /**\r
+        * @return An array of length n containing the values of the n bits in the\r
+        *         {@link WireArray}. Can be safely modified.\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       public Bit[] getValues()\r
+       {\r
+               return values.clone();\r
+       }\r
+\r
+       /**\r
+        * Adds an {@link WireArrayObserver}, who will be notified when the value of the\r
+        * {@link WireArray} is updated.\r
+        * \r
+        * @param ob The {@link WireArrayObserver} to be notified of changes.\r
+        * @return true if the given {@link WireArrayObserver} was not already\r
+        *         registered, false otherwise\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       public boolean addObserver(WireArrayObserver ob)\r
+       {\r
+               return observers.add(ob);\r
+       }\r
+\r
+       private void notifyObservers()\r
+       {\r
+               for (WireArrayObserver o : observers)\r
+                       o.update(this);\r
+       }\r
+\r
+       /**\r
+        * Create and register a {@link WireArrayInput} object, which is tied to this\r
+        * {@link WireArray}.\r
+        */\r
+       public WireArrayInput createInput()\r
+       {\r
+               return new WireArrayInput(this);\r
+       }\r
+\r
+       private void registerInput(WireArrayInput toRegister)\r
+       {\r
+               inputs.add(toRegister);\r
+       }\r
+\r
+       /**\r
+        * A {@link WireArrayInput} feeds a constant signal into the {@link WireArray}\r
+        * it is tied to. The combination of all inputs determines the\r
+        * {@link WireArray}s final value. X dominates all other inputs Z does not\r
+        * affect the final value, unless there are no other inputs than Z 0 and 1 turn\r
+        * into X when they are mixed\r
+        * \r
+        * @author Fabian Stemmler\r
+        */\r
+       public class WireArrayInput\r
+       {\r
+               public final WireArray owner;\r
+               private Bit[] inputValues;\r
+\r
+               private WireArrayInput(WireArray owner)\r
+               {\r
+                       super();\r
+                       this.owner = owner;\r
+                       initValues();\r
+                       owner.registerInput(this);\r
+               }\r
+\r
+               private void initValues()\r
+               {\r
+                       inputValues = Bit.Z.makeArray(length);\r
+               }\r
+\r
+               /**\r
+                * Sets the wires values. This takes up time, as specified by the\r
+                * {@link WireArray}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
+                       if (newValues.length == length)\r
+                       {\r
+                               feedSignals(0, newValues);\r
+                       } else\r
+                               throw new IllegalArgumentException(String.format("Attempted to input %o bits instead of %o bits.", newValues.length, length));\r
+               }\r
+\r
+               /**\r
+                * Sets values of a subarray of wires. This takes up time, as specified by the\r
+                * {@link WireArray}s travel time.\r
+                * \r
+                * @param newValues   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, Bit... newValues)\r
+               {\r
+                       Simulation.TIMELINE.addEvent((e) -> setValues(startingBit, newValues), travelTime);\r
+               }\r
+\r
+               private void setValues(int startingBit, Bit... newValues)\r
+               {\r
+                       int exclLastIndex = startingBit + newValues.length;\r
+                       if (length < exclLastIndex)\r
+                               throw new ArrayIndexOutOfBoundsException(String.format("Attempted to input bits from index %o to %o when there are only %o wires.", startingBit, exclLastIndex - 1, length));\r
+                       if (!Arrays.equals(inputValues, startingBit, exclLastIndex, newValues, 0, newValues.length))\r
+                       {\r
+                               System.arraycopy(newValues, 0, inputValues, startingBit, newValues.length);\r
+                               owner.recalculate();\r
+                       }\r
+               }\r
+\r
+               /**\r
+                * Returns a copy (safe to modify) of the values the {@link WireArrayInput} is currently feeding into the associated {@link WireArray}.\r
+                */\r
+               public Bit[] getValues()\r
+               {\r
+                       return inputValues.clone();\r
+               }\r
+\r
+               /**\r
+                * {@link WireArrayInput} now feeds Z into the associated {@link WireArray}.\r
+                */\r
+               public void clearSignals()\r
+               {\r
+                       feedSignals(Bit.Z.makeArray(length));\r
+               }\r
+\r
+               public Bit[] wireValuesExcludingMe() \r
+               {\r
+                       Bit[] bits = Bit.Z.makeArray(length);\r
+                       for (WireArrayInput wai : inputs) \r
+                       {\r
+                               if(wai == this)\r
+                                       continue;\r
+                               Util.combineInto(bits, wai.getValues());\r
+                       }\r
+                       return bits;\r
+               }\r
+               \r
+               @Override\r
+               public String toString()\r
+               {\r
+                       return Arrays.toString(inputValues);\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public String toString()\r
+       {\r
+               return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), Arrays.toString(values), inputs);\r
+       }\r
+\r
+       public static WireArrayInput[] extractInputs(WireArray[] w)\r
+       {\r
+               WireArrayInput[] inputs = new WireArrayInput[w.length];\r
+               for (int i = 0; i < w.length; i++)\r
+                       inputs[i] = w[i].createInput();\r
+               return inputs;\r
+       }\r
 }
\ No newline at end of file