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;
}
@Override
- public void update(WireArray initiator)
+ public void update(WireArray initiator, Bit[] oldValues)
{
Simulation.TIMELINE.addEvent((e) -> {compute();}, processTime);
}
package era.mi.logic.components;\r
\r
+import java.util.ArrayList;\r
import java.util.Arrays;\r
+import java.util.Collections;\r
+import java.util.List;\r
\r
import era.mi.logic.Bit;\r
import era.mi.logic.wires.WireArray;\r
{\r
return Arrays.equals(displayedValue, values);\r
}\r
+\r
+ @Override\r
+ public List<WireArray> getAllInputs()\r
+ {\r
+ return Collections.unmodifiableList(Arrays.asList(in));\r
+ }\r
+\r
+ @Override\r
+ public List<WireArray> getAllOutputs()\r
+ {\r
+ return Collections.unmodifiableList(new ArrayList<WireArray>());\r
+ }\r
}\r
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;
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;
}
{
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));
+ }
}
--- /dev/null
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.wires.WireArray;\r
+\r
+public interface Component\r
+{\r
+\r
+ /**\r
+ * Returns immutable list of all inputs to the {@link Component} (including e.g. the select bits to a MUX).\r
+ * Intended for visualization in the UI.\r
+ */\r
+ public List<WireArray> getAllInputs();\r
+ \r
+ /**\r
+ * Returns immutable list of all outputs to the {@link Component}.\r
+ * Intended for visualization in the UI.\r
+ */\r
+ public List<WireArray> getAllOutputs();\r
+}\r
--- /dev/null
+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));
+ }
+}
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;
}
@Override
- public void update(WireArray initiator)
+ public void update(WireArray initiator, Bit[] oldValues)
{
int index = find(initiator);
int beginning = beginningIndex[index];
{
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));
+ }
}
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;
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));
+ }
}
}
@Override
- public void update(WireArray initiator)
+ public void update(WireArray initiator, Bit[] oldValues)
{
compute();
}
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;
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));
+ }
+
}
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;
{
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));
+ }
}
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;
{
return out;
}
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(in));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(out));
+ }
}
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;
{
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));
+ }
}
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;
{
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));
+ }
}
\r
import era.mi.logic.Bit;\r
import era.mi.logic.Simulation;\r
+import era.mi.logic.components.Demux;\r
import era.mi.logic.components.Merger;\r
import era.mi.logic.components.Mux;\r
import era.mi.logic.components.Splitter;\r
\r
}\r
\r
+ @Test\r
+ void demuxTest()\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), in = new WireArray(4, 1);\r
+ WireArrayInput selectIn = select.createInput();\r
+\r
+ selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+ in.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+\r
+ new Demux(1, in, select, a, b, c);\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+ assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+ selectIn.feedSignals(Bit.ZERO, Bit.ONE);\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+ assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+\r
+ selectIn.feedSignals(Bit.ONE, Bit.ONE);\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+ assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+\r
+ }\r
+ \r
@Test\r
void andTest()\r
{\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
+ w.addObserver((i, oldValues) -> fail("WireArray notified observer, although value did not change."));\r
Simulation.TIMELINE.executeAll();\r
assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);\r
}\r
package era.mi.logic.tests;\r
\r
+import era.mi.logic.Bit;\r
import era.mi.logic.Simulation;\r
import era.mi.logic.wires.WireArray;\r
import era.mi.logic.wires.WireArray.WireArrayInput;\r
}\r
\r
@Override\r
- public void update(WireArray initiator)\r
+ public void update(WireArray initiator, Bit[] oldValues)\r
{\r
Simulation.TIMELINE.addEvent((e) ->\r
{\r
WireArrayInput input = inputs.get(0);\r
if (!Arrays.equals(input.getValues(), values))\r
{\r
+ Bit[] oldValues = values.clone();\r
System.arraycopy(input.getValues(), 0, values, 0, length);\r
- notifyObservers();\r
+ notifyObservers(oldValues);\r
}\r
}\r
\r
\r
if (!Arrays.equals(newValues, values))\r
{\r
- notifyObservers();\r
+ Bit[] oldValues = values;\r
values = newValues;\r
+ notifyObservers(oldValues);\r
}\r
}\r
\r
return observers.add(ob);\r
}\r
\r
- private void notifyObservers()\r
+ private void notifyObservers(Bit[] oldValues)\r
{\r
for (WireArrayObserver o : observers)\r
- o.update(this);\r
+ o.update(this, oldValues);\r
}\r
\r
/**\r
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);
}