From bcf8d773c7a836c2ee17e17a49c296ebf31d2777 Mon Sep 17 00:00:00 2001 From: Fabian Stemmler Date: Sun, 12 May 2019 19:05:12 +0200 Subject: [PATCH] added demux; added getAllInputs() and getAllOutputs() for all components --- .../mi/logic/components/BasicComponent.java | 5 +- .../era/mi/logic/components/BitDisplay.java | 15 ++++ era.mi/src/era/mi/logic/components/Clock.java | 35 +++++++- .../era/mi/logic/components/Component.java | 21 +++++ era.mi/src/era/mi/logic/components/Demux.java | 83 +++++++++++++++++++ .../src/era/mi/logic/components/Merger.java | 21 ++++- era.mi/src/era/mi/logic/components/Mux.java | 19 +++++ .../src/era/mi/logic/components/Splitter.java | 2 +- .../mi/logic/components/TriStateBuffer.java | 16 ++++ .../mi/logic/components/gates/AndGate.java | 16 ++++ .../mi/logic/components/gates/NotGate.java | 16 ++++ .../era/mi/logic/components/gates/OrGate.java | 16 ++++ .../mi/logic/components/gates/XorGate.java | 16 ++++ .../src/era/mi/logic/tests/ComponentTest.java | 36 +++++++- era.mi/src/era/mi/logic/tests/Connector.java | 3 +- era.mi/src/era/mi/logic/wires/WireArray.java | 10 ++- .../era/mi/logic/wires/WireArrayObserver.java | 4 +- 17 files changed, 319 insertions(+), 15 deletions(-) create mode 100644 era.mi/src/era/mi/logic/components/Component.java create mode 100644 era.mi/src/era/mi/logic/components/Demux.java diff --git a/era.mi/src/era/mi/logic/components/BasicComponent.java b/era.mi/src/era/mi/logic/components/BasicComponent.java index ddcf4cea..930e3a52 100644 --- a/era.mi/src/era/mi/logic/components/BasicComponent.java +++ b/era.mi/src/era/mi/logic/components/BasicComponent.java @@ -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); } diff --git a/era.mi/src/era/mi/logic/components/BitDisplay.java b/era.mi/src/era/mi/logic/components/BitDisplay.java index f783c627..051010b7 100644 --- a/era.mi/src/era/mi/logic/components/BitDisplay.java +++ b/era.mi/src/era/mi/logic/components/BitDisplay.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList(in)); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(new ArrayList()); + } } diff --git a/era.mi/src/era/mi/logic/components/Clock.java b/era.mi/src/era/mi/logic/components/Clock.java index 9f2ecca6..5d3f7db2 100644 --- a/era.mi/src/era/mi/logic/components/Clock.java +++ b/era.mi/src/era/mi/logic/components/Clock.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList()); + } + + @Override + public List 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 index 00000000..2d40cc24 --- /dev/null +++ b/era.mi/src/era/mi/logic/components/Component.java @@ -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 getAllInputs(); + + /** + * Returns immutable list of all outputs to the {@link Component}. + * Intended for visualization in the UI. + */ + public List 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 index 00000000..e5f49f41 --- /dev/null +++ b/era.mi/src/era/mi/logic/components/Demux.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList(in, select)); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(Arrays.asList(outputs)); + } +} diff --git a/era.mi/src/era/mi/logic/components/Merger.java b/era.mi/src/era/mi/logic/components/Merger.java index 534b2ca6..591bfc1b 100644 --- a/era.mi/src/era/mi/logic/components/Merger.java +++ b/era.mi/src/era/mi/logic/components/Merger.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList(inputs)); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(Arrays.asList(outI.owner)); + } } diff --git a/era.mi/src/era/mi/logic/components/Mux.java b/era.mi/src/era/mi/logic/components/Mux.java index 0fd7fd46..4e09f925 100644 --- a/era.mi/src/era/mi/logic/components/Mux.java +++ b/era.mi/src/era/mi/logic/components/Mux.java @@ -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 getAllInputs() + { + ArrayList wires = new ArrayList(Arrays.asList(inputs)); + wires.add(select); + return Collections.unmodifiableList(wires); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(Arrays.asList(outI.owner)); + } } diff --git a/era.mi/src/era/mi/logic/components/Splitter.java b/era.mi/src/era/mi/logic/components/Splitter.java index 5475fa17..2a52327a 100644 --- a/era.mi/src/era/mi/logic/components/Splitter.java +++ b/era.mi/src/era/mi/logic/components/Splitter.java @@ -37,7 +37,7 @@ public class Splitter implements WireArrayObserver } @Override - public void update(WireArray initiator) + public void update(WireArray initiator, Bit[] oldValues) { compute(); } diff --git a/era.mi/src/era/mi/logic/components/TriStateBuffer.java b/era.mi/src/era/mi/logic/components/TriStateBuffer.java index 4000ae66..c21c4768 100644 --- a/era.mi/src/era/mi/logic/components/TriStateBuffer.java +++ b/era.mi/src/era/mi/logic/components/TriStateBuffer.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList(in, enable)); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(Arrays.asList(outI.owner)); + } + } diff --git a/era.mi/src/era/mi/logic/components/gates/AndGate.java b/era.mi/src/era/mi/logic/components/gates/AndGate.java index b3269cbd..5c814064 100644 --- a/era.mi/src/era/mi/logic/components/gates/AndGate.java +++ b/era.mi/src/era/mi/logic/components/gates/AndGate.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList(a, b)); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(Arrays.asList(out)); + } } diff --git a/era.mi/src/era/mi/logic/components/gates/NotGate.java b/era.mi/src/era/mi/logic/components/gates/NotGate.java index 1aba6b86..6a011bee 100644 --- a/era.mi/src/era/mi/logic/components/gates/NotGate.java +++ b/era.mi/src/era/mi/logic/components/gates/NotGate.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList(in)); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(Arrays.asList(out)); + } } diff --git a/era.mi/src/era/mi/logic/components/gates/OrGate.java b/era.mi/src/era/mi/logic/components/gates/OrGate.java index c1d95a78..8e145d15 100644 --- a/era.mi/src/era/mi/logic/components/gates/OrGate.java +++ b/era.mi/src/era/mi/logic/components/gates/OrGate.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList(a, b)); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(Arrays.asList(out)); + } } diff --git a/era.mi/src/era/mi/logic/components/gates/XorGate.java b/era.mi/src/era/mi/logic/components/gates/XorGate.java index c7a94550..b13dd2bc 100644 --- a/era.mi/src/era/mi/logic/components/gates/XorGate.java +++ b/era.mi/src/era/mi/logic/components/gates/XorGate.java @@ -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 getAllInputs() + { + return Collections.unmodifiableList(Arrays.asList(a, b)); + } + + @Override + public List getAllOutputs() + { + return Collections.unmodifiableList(Arrays.asList(out)); + } } diff --git a/era.mi/src/era/mi/logic/tests/ComponentTest.java b/era.mi/src/era/mi/logic/tests/ComponentTest.java index f3858f52..3ee55760 100644 --- a/era.mi/src/era/mi/logic/tests/ComponentTest.java +++ b/era.mi/src/era/mi/logic/tests/ComponentTest.java @@ -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); } diff --git a/era.mi/src/era/mi/logic/tests/Connector.java b/era.mi/src/era/mi/logic/tests/Connector.java index fcdf6e8b..7887ff25 100644 --- a/era.mi/src/era/mi/logic/tests/Connector.java +++ b/era.mi/src/era/mi/logic/tests/Connector.java @@ -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) -> { diff --git a/era.mi/src/era/mi/logic/wires/WireArray.java b/era.mi/src/era/mi/logic/wires/WireArray.java index add55f71..c2e974ae 100644 --- a/era.mi/src/era/mi/logic/wires/WireArray.java +++ b/era.mi/src/era/mi/logic/wires/WireArray.java @@ -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); } /** diff --git a/era.mi/src/era/mi/logic/wires/WireArrayObserver.java b/era.mi/src/era/mi/logic/wires/WireArrayObserver.java index c0766a2b..2c807bb3 100644 --- a/era.mi/src/era/mi/logic/wires/WireArrayObserver.java +++ b/era.mi/src/era/mi/logic/wires/WireArrayObserver.java @@ -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); } -- 2.17.1