added demux; added getAllInputs() and getAllOutputs() for all components
authorFabian Stemmler <stemmler@in.tum.de>
Sun, 12 May 2019 17:05:12 +0000 (19:05 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Sun, 12 May 2019 17:05:12 +0000 (19:05 +0200)
17 files changed:
era.mi/src/era/mi/logic/components/BasicComponent.java
era.mi/src/era/mi/logic/components/BitDisplay.java
era.mi/src/era/mi/logic/components/Clock.java
era.mi/src/era/mi/logic/components/Component.java [new file with mode: 0644]
era.mi/src/era/mi/logic/components/Demux.java [new file with mode: 0644]
era.mi/src/era/mi/logic/components/Merger.java
era.mi/src/era/mi/logic/components/Mux.java
era.mi/src/era/mi/logic/components/Splitter.java
era.mi/src/era/mi/logic/components/TriStateBuffer.java
era.mi/src/era/mi/logic/components/gates/AndGate.java
era.mi/src/era/mi/logic/components/gates/NotGate.java
era.mi/src/era/mi/logic/components/gates/OrGate.java
era.mi/src/era/mi/logic/components/gates/XorGate.java
era.mi/src/era/mi/logic/tests/ComponentTest.java
era.mi/src/era/mi/logic/tests/Connector.java
era.mi/src/era/mi/logic/wires/WireArray.java
era.mi/src/era/mi/logic/wires/WireArrayObserver.java

index ddcf4ce..930e3a5 100644 (file)
@@ -1,10 +1,11 @@
 package era.mi.logic.components;
 
+import era.mi.logic.Bit;
 import era.mi.logic.Simulation;
 import era.mi.logic.wires.WireArray;
 import era.mi.logic.wires.WireArrayObserver;
 
-public abstract class BasicComponent implements WireArrayObserver
+public abstract class BasicComponent implements WireArrayObserver, Component
 {
        private int processTime;
        
@@ -20,7 +21,7 @@ public abstract class BasicComponent implements WireArrayObserver
        }
        
        @Override
-       public void update(WireArray initiator)
+       public void update(WireArray initiator, Bit[] oldValues)
        {
                Simulation.TIMELINE.addEvent((e) -> {compute();}, processTime);
        }
index f783c62..051010b 100644 (file)
@@ -1,6 +1,9 @@
 package era.mi.logic.components;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 import era.mi.logic.Bit;
 import era.mi.logic.wires.WireArray;
@@ -33,4 +36,16 @@ public class BitDisplay extends BasicComponent
        {
                return Arrays.equals(displayedValue, values);
        }
+
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(in));
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(new ArrayList<WireArray>());
+       }
 }
index 9f2ecca..5d3f7db 100644 (file)
@@ -1,5 +1,9 @@
 package era.mi.logic.components;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 import era.mi.logic.Bit;
 import era.mi.logic.Simulation;
 import era.mi.logic.timeline.TimelineEvent;
@@ -7,20 +11,28 @@ import era.mi.logic.timeline.TimelineEventHandler;
 import era.mi.logic.wires.WireArray;
 import era.mi.logic.wires.WireArray.WireArrayInput;
 
-public class Clock implements TimelineEventHandler
+public class Clock implements TimelineEventHandler, Component
 {
        private boolean toggle = false;
        private WireArrayInput outI;
+       private int delta;
        
-       public Clock(WireArray out)
+       /**
+        * 
+        * @param out {@link WireArray} the clock's impulses are fed into
+        * @param delta ticks between rising and falling edge
+        */
+       public Clock(WireArray out, int delta)
        {
+               this.delta = delta;
                this.outI = out.createInput();
+               Simulation.TIMELINE.addEvent(this, 50);
        }
 
        @Override
        public void handle(TimelineEvent e)
        {
-               Simulation.TIMELINE.addEvent(this, 50);
+               addToTimeline();
                outI.feedSignals(new Bit[] { toggle ? Bit.ONE : Bit.ZERO });
                toggle = !toggle;
        }
@@ -29,4 +41,21 @@ public class Clock implements TimelineEventHandler
        {
                return outI.owner;
        }
+       
+       private void addToTimeline()
+       {
+               Simulation.TIMELINE.addEvent(this, delta);
+       }
+
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList());
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(outI.owner));
+       }
 }
diff --git a/era.mi/src/era/mi/logic/components/Component.java b/era.mi/src/era/mi/logic/components/Component.java
new file mode 100644 (file)
index 0000000..2d40cc2
--- /dev/null
@@ -0,0 +1,21 @@
+package era.mi.logic.components;
+
+import java.util.List;
+
+import era.mi.logic.wires.WireArray;
+
+public interface Component
+{
+
+       /**
+        * Returns immutable list of all inputs to the {@link Component} (including e.g. the select bits to a MUX).
+        * Intended for visualization in the UI.
+        */
+       public List<WireArray> getAllInputs();
+       
+       /**
+        * Returns immutable list of all outputs to the {@link Component}.
+        * Intended for visualization in the UI.
+        */
+       public List<WireArray> getAllOutputs();
+}
diff --git a/era.mi/src/era/mi/logic/components/Demux.java b/era.mi/src/era/mi/logic/components/Demux.java
new file mode 100644 (file)
index 0000000..e5f49f4
--- /dev/null
@@ -0,0 +1,83 @@
+package era.mi.logic.components;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import era.mi.logic.wires.WireArray;
+import era.mi.logic.wires.WireArray.WireArrayInput;
+
+/**
+ * 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 Demux extends BasicComponent
+{
+       private final WireArray select, in;
+       private final WireArray[] outputs;
+       private final WireArrayInput[] outputsI;
+       private final int outputSize;
+       private int selected = -1;
+       
+       /**
+        * 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 outputs One of these inputs is mapped to the output, depending on the select bits
+        */
+       public Demux(int processTime, WireArray in, WireArray select, WireArray... outputs)
+       {
+               super(processTime);
+               outputSize = in.length;
+               
+               this.in = in;
+               this.outputs = outputs;
+               this.outputsI = new WireArrayInput[outputs.length];
+               for(int i = 0; i < this.outputsI.length; i++)
+               {
+                       if(outputs[i].length != outputSize)
+                               throw new IllegalArgumentException("All DEMUX wire arrays must be of uniform length!");
+                       this.outputsI[i] = outputs[i].createInput();
+               }
+               
+               this.select = select;
+               select.addObserver(this);
+               
+               int maxInputs = 1 << select.length;
+               if(this.outputsI.length > maxInputs)
+                       throw new IllegalArgumentException("There are more outputs ("
+                                       + this.outputsI.length + ") to the DEMUX than supported by "
+                                       + select.length + " select bits (" + maxInputs + ").");
+               in.addObserver(this);
+       }
+
+       @Override
+       public void compute() {
+               int selectValue = select.hasNumericValue() ? (int) select.getUnsignedValue() : -1;
+               if(selectValue >= outputsI.length)
+                       selectValue = -1;
+               
+               if(selected != selectValue && selected != -1)
+                       outputsI[selected].clearSignals();
+               
+               selected = selectValue;
+               
+               if(selectValue != -1)
+                       outputsI[selectValue].feedSignals(in.getValues());
+       }
+
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(in, select));
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(outputs));
+       }
+}
index 534b2ca..591bfc1 100644 (file)
@@ -1,10 +1,15 @@
 package era.mi.logic.components;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+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 Merger implements WireArrayObserver
+public class Merger implements WireArrayObserver, Component
 {
     private WireArrayInput outI;
     private WireArray[] inputs;
@@ -46,7 +51,7 @@ public class Merger implements WireArrayObserver
     }
 
     @Override
-    public void update(WireArray initiator)
+    public void update(WireArray initiator, Bit[] oldValues)
     {
        int index = find(initiator);
        int beginning = beginningIndex[index];
@@ -65,4 +70,16 @@ public class Merger implements WireArrayObserver
     {
        return inputs.clone();
     }
+
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(inputs));
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(outI.owner));
+       }
 }
index 0fd7fd4..4e09f92 100644 (file)
@@ -1,5 +1,10 @@
 package era.mi.logic.components;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 import era.mi.logic.wires.WireArray;
 import era.mi.logic.wires.WireArray.WireArrayInput;
 
@@ -69,4 +74,18 @@ public class Mux extends BasicComponent
                WireArray active = inputs[selectValue];
                outI.feedSignals(active.getValues());
        }
+
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               ArrayList<WireArray> wires = new ArrayList<WireArray>(Arrays.asList(inputs));
+               wires.add(select);
+               return Collections.unmodifiableList(wires);
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(outI.owner));
+       }
 }
index 5475fa1..2a52327 100644 (file)
@@ -37,7 +37,7 @@ public class Splitter implements WireArrayObserver
        }
        
        @Override
-       public void update(WireArray initiator)
+       public void update(WireArray initiator, Bit[] oldValues)
        {
                compute();
        }
index 4000ae6..c21c476 100644 (file)
@@ -1,5 +1,9 @@
 package era.mi.logic.components;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 import era.mi.logic.Bit;
 import era.mi.logic.wires.WireArray;
 import era.mi.logic.wires.WireArray.WireArrayInput;
@@ -30,4 +34,16 @@ public class TriStateBuffer extends BasicComponent{
                        outI.clearSignals();
        }
 
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(in, enable));
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(outI.owner));
+       }
+
 }
index b3269cb..5c81406 100644 (file)
@@ -1,5 +1,9 @@
 package era.mi.logic.components.gates;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 import era.mi.logic.Util;
 import era.mi.logic.components.BasicComponent;
 import era.mi.logic.wires.WireArray;
@@ -40,4 +44,16 @@ public class AndGate extends BasicComponent
        {
                return out;
        }
+
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(a, b));
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(out));
+       }
 }
index 1aba6b8..6a011be 100644 (file)
@@ -1,5 +1,9 @@
 package era.mi.logic.components.gates;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 import era.mi.logic.Util;
 import era.mi.logic.components.BasicComponent;
 import era.mi.logic.wires.WireArray;
@@ -34,4 +38,16 @@ public class NotGate extends BasicComponent
        {
                return out;
        }
+       
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(in));
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(out));
+       }
 }
index c1d95a7..8e145d1 100644 (file)
@@ -1,5 +1,9 @@
 package era.mi.logic.components.gates;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 import era.mi.logic.Util;
 import era.mi.logic.components.BasicComponent;
 import era.mi.logic.wires.WireArray;
@@ -40,4 +44,16 @@ public class OrGate extends BasicComponent
        {
                return out;
        }
+       
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(a, b));
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(out));
+       }
 }
index c7a9455..b13dd2b 100644 (file)
@@ -1,5 +1,9 @@
 package era.mi.logic.components.gates;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 import era.mi.logic.Util;
 import era.mi.logic.components.BasicComponent;
 import era.mi.logic.wires.WireArray;
@@ -39,4 +43,16 @@ public class XorGate extends BasicComponent
        {
                return out;
        }
+       
+       @Override
+       public List<WireArray> getAllInputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(a, b));
+       }
+
+       @Override
+       public List<WireArray> getAllOutputs()
+       {
+               return Collections.unmodifiableList(Arrays.asList(out));
+       }
 }
index f3858f5..3ee5576 100644 (file)
@@ -9,6 +9,7 @@ import org.junit.jupiter.api.Test;
 
 import era.mi.logic.Bit;
 import era.mi.logic.Simulation;
+import era.mi.logic.components.Demux;
 import era.mi.logic.components.Merger;
 import era.mi.logic.components.Mux;
 import era.mi.logic.components.Splitter;
@@ -139,6 +140,39 @@ class ComponentTest
 
     }
 
+    @Test
+    void demuxTest()
+    {
+       Simulation.TIMELINE.reset();
+       WireArray a = new WireArray(4, 3), b = new WireArray(4, 6), c = new WireArray(4, 4),
+               select = new WireArray(2, 5), in = new WireArray(4, 1);
+       WireArrayInput selectIn = select.createInput();
+
+       selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
+       in.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+
+       new Demux(1, in, select, a, b, c);
+       Simulation.TIMELINE.executeAll();
+
+       assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+       assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+       assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+       selectIn.feedSignals(Bit.ZERO, Bit.ONE);
+       Simulation.TIMELINE.executeAll();
+
+       assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+       assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+       assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+
+       selectIn.feedSignals(Bit.ONE, Bit.ONE);
+       Simulation.TIMELINE.executeAll();
+
+       assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+       assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+       assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+
+    }
+    
     @Test
     void andTest()
     {
@@ -234,7 +268,7 @@ class ComponentTest
        assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
 
        wI2.feedSignals(Bit.ONE, Bit.Z);
-       w.addObserver((i) -> fail("WireArray notified observer, although value did not change."));
+       w.addObserver((i, oldValues) -> fail("WireArray notified observer, although value did not change."));
        Simulation.TIMELINE.executeAll();
        assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
     }
index fcdf6e8..7887ff2 100644 (file)
@@ -1,5 +1,6 @@
 package era.mi.logic.tests;
 
+import era.mi.logic.Bit;
 import era.mi.logic.Simulation;
 import era.mi.logic.wires.WireArray;
 import era.mi.logic.wires.WireArray.WireArrayInput;
@@ -25,7 +26,7 @@ public class Connector implements WireArrayObserver
        }
 
        @Override
-       public void update(WireArray initiator)
+       public void update(WireArray initiator, Bit[] oldValues)
        {
                Simulation.TIMELINE.addEvent((e) ->
                {
index add55f7..c2e974a 100644 (file)
@@ -42,8 +42,9 @@ public class WireArray
                WireArrayInput input = inputs.get(0);
                if (!Arrays.equals(input.getValues(), values))
                {
+                       Bit[] oldValues = values.clone();
                        System.arraycopy(input.getValues(), 0, values, 0, length);
-                       notifyObservers();
+                       notifyObservers(oldValues);
                }
        }
 
@@ -69,8 +70,9 @@ public class WireArray
 
                if (!Arrays.equals(newValues, values))
                {
-                       notifyObservers();
+                       Bit[] oldValues = values;
                        values = newValues;
+                       notifyObservers(oldValues);
                }
        }
 
@@ -217,10 +219,10 @@ public class WireArray
                return observers.add(ob);
        }
 
-       private void notifyObservers()
+       private void notifyObservers(Bit[] oldValues)
        {
                for (WireArrayObserver o : observers)
-                       o.update(this);
+                       o.update(this, oldValues);
        }
 
        /**
index c0766a2..2c807bb 100644 (file)
@@ -1,6 +1,8 @@
 package era.mi.logic.wires;
 
+import era.mi.logic.Bit;
+
 public interface WireArrayObserver
 {
-       public void update(WireArray initiator);
+       public void update(WireArray initiator, Bit[] oldValues);
 }