-package era.mi.logic.components;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.WireObserver;
-
-/**
- * A basic component that recomputes all outputs (with a delay), when it is updated.
- *
- * @author Fabian Stemmler
- */
-public abstract class BasicComponent implements WireObserver, Component
-{
- private int processTime;
-
- /**
- *
- * @param processTime Amount of time this component takes to update its outputs. Must be more than 0, otherwise 1 is assumed.
- *
- * @author Fabian Stemmler
- */
- public BasicComponent(int processTime)
- {
- this.processTime = processTime > 0 ? processTime : 1;
- }
-
- @Override
- public void update(Wire initiator, BitVector oldValues)
- {
- Simulation.TIMELINE.addEvent(e -> compute(), processTime);
- }
-
- protected abstract void compute();
-}
+package era.mi.logic.components;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.WireObserver;\r
+\r
+/**\r
+ * A basic component that recomputes all outputs (with a delay), when it is updated.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+public abstract class BasicComponent implements WireObserver, Component\r
+{\r
+ private int processTime;\r
+\r
+ /**\r
+ * \r
+ * @param processTime Amount of time this component takes to update its outputs. Must be more than 0, otherwise 1 is assumed.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+ public BasicComponent(int processTime)\r
+ {\r
+ this.processTime = processTime > 0 ? processTime : 1;\r
+ }\r
+\r
+ @Override\r
+ public void update(ReadEnd initiator, BitVector oldValues)\r
+ {\r
+ Simulation.TIMELINE.addEvent(e -> compute(), processTime);\r
+ }\r
+\r
+ protected abstract void compute();\r
+}\r
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.types.Bit;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class BitDisplay extends BasicComponent
-{
- private final WireEnd in;
- private BitVector displayedValue;
-
- public BitDisplay(WireEnd in)
- {
- super(1);
- this.in = in;
- in.addObserver(this);
- compute();
- }
-
- @Override
- protected void compute()
- {
- displayedValue = in.getValues();
- }
-
- public BitVector getDisplayedValue()
- {
- return displayedValue;
- }
-
- public boolean isDisplaying(Bit... values)
- {
- return displayedValue.equals(BitVector.of(values));
- }
-
- @Override
- public List<WireEnd> getAllInputs()
- {
- return List.of(in);
- }
-
- @Override
- public List<WireEnd> getAllOutputs()
- {
- return List.of();
- }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class BitDisplay extends BasicComponent\r
+{\r
+ private final ReadEnd in;\r
+ private BitVector displayedValue;\r
+\r
+ public BitDisplay(ReadEnd in)\r
+ {\r
+ super(1);\r
+ this.in = in;\r
+ in.addObserver(this);\r
+ compute();\r
+ }\r
+\r
+ @Override\r
+ protected void compute()\r
+ {\r
+ displayedValue = in.getValues();\r
+ }\r
+\r
+ public BitVector getDisplayedValue()\r
+ {\r
+ return displayedValue;\r
+ }\r
+\r
+ public boolean isDisplaying(Bit... values)\r
+ {\r
+ return displayedValue.equals(BitVector.of(values));\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of(in);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of();\r
+ }\r
+}\r
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.timeline.TimelineEvent;
-import era.mi.logic.timeline.TimelineEventHandler;
-import era.mi.logic.types.Bit;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class Clock implements TimelineEventHandler, Component
-{
- private boolean toggle = false;
- private WireEnd out;
- private int delta;
-
- /**
- *
- * @param out {@link Wire} the clock's impulses are fed into
- * @param delta ticks between rising and falling edge
- */
- public Clock(WireEnd out, int delta)
- {
- this.delta = delta;
- this.out = out;
- addToTimeline();
- }
-
- @Override
- public void handle(TimelineEvent e)
- {
- addToTimeline();
- out.feedSignals(toggle ? Bit.ONE : Bit.ZERO);
- toggle = !toggle;
- }
-
- public WireEnd getOut()
- {
- return out;
- }
-
- private void addToTimeline()
- {
- Simulation.TIMELINE.addEvent(this, delta);
- }
-
- @Override
- public List<WireEnd> getAllInputs()
- {
- return List.of();
- }
-
- @Override
- public List<WireEnd> getAllOutputs()
- {
- return List.of(out);
- }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.timeline.TimelineEvent;\r
+import era.mi.logic.timeline.TimelineEventHandler;\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.wires.Wire;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class Clock implements TimelineEventHandler, Component\r
+{\r
+ private boolean toggle = false;\r
+ private ReadWriteEnd out;\r
+ private int delta;\r
+\r
+ /**\r
+ * \r
+ * @param out {@link Wire} the clock's impulses are fed into\r
+ * @param delta ticks between rising and falling edge\r
+ */\r
+ public Clock(ReadWriteEnd out, int delta)\r
+ {\r
+ this.delta = delta;\r
+ this.out = out;\r
+ addToTimeline();\r
+ }\r
+\r
+ @Override\r
+ public void handle(TimelineEvent e)\r
+ {\r
+ addToTimeline();\r
+ out.feedSignals(toggle ? Bit.ONE : Bit.ZERO);\r
+ toggle = !toggle;\r
+ }\r
+\r
+ public ReadWriteEnd getOut()\r
+ {\r
+ return out;\r
+ }\r
+\r
+ private void addToTimeline()\r
+ {\r
+ Simulation.TIMELINE.addEvent(this, delta);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of();\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(out);\r
+ }\r
+}\r
\r
import java.util.List;\r
\r
-import era.mi.logic.wires.Wire.WireEnd;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
\r
public interface Component\r
{\r
* Returns immutable list of all inputs to the {@link Component} (including e.g. the select bits to a MUX). Intended for visualization\r
* in the UI.\r
*/\r
- public List<WireEnd> getAllInputs();\r
+ public List<ReadEnd> getAllInputs();\r
\r
/**\r
* Returns immutable list of all outputs to the {@link Component}. Intended for visualization in the UI.\r
*/\r
- public List<WireEnd> getAllOutputs();\r
+ public List<ReadWriteEnd> getAllOutputs();\r
}\r
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-import era.mi.logic.wires.WireObserver;
-
-public class Connector implements WireObserver, Component
-{
- private boolean connected;
- private final WireEnd a;
- private final WireEnd b;
-
- public Connector(WireEnd a, WireEnd b)
- {
- if (a.length() != b.length())
- throw new IllegalArgumentException(String.format("WireArray width does not match: %d, %d", a.length(), b.length()));
- this.a = a;
- this.b = b;
- a.addObserver(this);
- b.addObserver(this);
- }
-
- public void connect()
- {
- connected = true;
- update(a.getWire());
- update(b.getWire());
- }
-
- public void disconnect()
- {
- connected = false;
- a.clearSignals();
- b.clearSignals();
- }
-
- public void setConnection(boolean connected)
- {
- if (connected)
- connect();
- else
- disconnect();
- }
-
- @Override
- public void update(Wire initiator, BitVector oldValues)
- {
- if (connected)
- Simulation.TIMELINE.addEvent(e -> update(initiator), 1);
- }
-
- private void update(Wire initiator)
- {
- if (initiator == a.getWire())
- b.feedSignals(a.wireValuesExcludingMe());
- else
- a.feedSignals(b.wireValuesExcludingMe());
- }
-
- @Override
- public List<WireEnd> getAllInputs()
- {
- return List.of(a, b);
- }
-
- @Override
- public List<WireEnd> getAllOutputs()
- {
- return List.of(a, b);
- }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+import era.mi.logic.wires.WireObserver;\r
+\r
+public class Connector implements WireObserver, Component\r
+{\r
+ private boolean connected;\r
+ private final ReadWriteEnd a;\r
+ private final ReadWriteEnd b;\r
+\r
+ public Connector(ReadWriteEnd a, ReadWriteEnd b)\r
+ {\r
+ if (a.length() != b.length())\r
+ throw new IllegalArgumentException(String.format("WireArray width does not match: %d, %d", a.length(), b.length()));\r
+ this.a = a;\r
+ this.b = b;\r
+ a.addObserver(this);\r
+ b.addObserver(this);\r
+ }\r
+\r
+ public void connect()\r
+ {\r
+ connected = true;\r
+ update(a);\r
+ update(b);\r
+ }\r
+\r
+ public void disconnect()\r
+ {\r
+ connected = false;\r
+ a.clearSignals();\r
+ b.clearSignals();\r
+ }\r
+\r
+ public void setConnection(boolean connected)\r
+ {\r
+ if (connected)\r
+ connect();\r
+ else\r
+ disconnect();\r
+ }\r
+\r
+ @Override\r
+ public void update(ReadEnd initiator, BitVector oldValues)\r
+ {\r
+ if (connected)\r
+ Simulation.TIMELINE.addEvent(e -> update(initiator), 1);\r
+ }\r
+\r
+ private void update(ReadEnd initiator)\r
+ {\r
+ if (initiator == a)\r
+ b.feedSignals(a.wireValuesExcludingMe());\r
+ else\r
+ a.feedSignals(b.wireValuesExcludingMe());\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of(a, b);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(a, b);\r
+ }\r
+}\r
import java.util.List;\r
\r
import era.mi.logic.wires.Wire;\r
-import era.mi.logic.wires.Wire.WireEnd;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
\r
/**\r
* Models a multiplexer. Takes an arbitrary amount of input {@link Wire}s, one of which, as determined by select, is put through to the\r
*/\r
public class Demux extends BasicComponent\r
{\r
- private final WireEnd select, in;\r
- private final WireEnd[] outputs;\r
+ private final ReadEnd select, in;\r
+ private final ReadWriteEnd[] outputs;\r
private final int outputSize;\r
private int selected = -1;\r
\r
* @param select Indexes the output array to which the input is mapped. Must have enough bits to index all outputs.\r
* @param outputs One of these outputs receives the input signal, depending on the select bits\r
*/\r
- public Demux(int processTime, WireEnd in, WireEnd select, WireEnd... outputs)\r
+ public Demux(int processTime, ReadEnd in, ReadEnd select, ReadWriteEnd... outputs)\r
{\r
super(processTime);\r
outputSize = in.length();\r
}\r
\r
@Override\r
- public List<WireEnd> getAllInputs()\r
+ public List<ReadEnd> getAllInputs()\r
{\r
return List.of(in, select);\r
}\r
\r
@Override\r
- public List<WireEnd> getAllOutputs()\r
+ public List<ReadWriteEnd> getAllOutputs()\r
{\r
return List.of(outputs);\r
}\r
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.types.Bit;
-import era.mi.logic.wires.Wire.WireEnd;
-
-/**
- * This class models a simple on/off (ONE/ZERO) switch for user interaction.
- *
- * @author Christian Femers
- *
- */
-public class ManualSwitch implements Component
-{
- private WireEnd output;
- private boolean isOn;
-
- public ManualSwitch(WireEnd output)
- {
- if (output.length() != 1)
- throw new IllegalArgumentException("Switch output can be only a single wire");
- this.output = output;
- }
-
- public void switchOn()
- {
- setState(true);
- }
-
- public void switchOff()
- {
- setState(false);
- }
-
- public void toggle()
- {
- setState(!isOn);
- }
-
- public void setState(boolean isOn)
- {
- if (this.isOn == isOn)
- return;
- this.isOn = isOn;
- output.feedSignals(getValue());
- }
-
- public boolean isOn()
- {
- return isOn;
- }
-
- public Bit getValue()
- {
- return isOn ? Bit.ONE : Bit.ZERO;
- }
-
- @Override
- public List<WireEnd> getAllInputs()
- {
- return List.of();
- }
-
- @Override
- public List<WireEnd> getAllOutputs()
- {
- return List.of(output);
- }
-
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+/**\r
+ * This class models a simple on/off (ONE/ZERO) switch for user interaction.\r
+ *\r
+ * @author Christian Femers\r
+ *\r
+ */\r
+public class ManualSwitch implements Component\r
+{\r
+ private ReadWriteEnd output;\r
+ private boolean isOn;\r
+\r
+ public ManualSwitch(ReadWriteEnd output)\r
+ {\r
+ if (output.length() != 1)\r
+ throw new IllegalArgumentException("Switch output can be only a single wire");\r
+ this.output = output;\r
+ }\r
+\r
+ public void switchOn()\r
+ {\r
+ setState(true);\r
+ }\r
+\r
+ public void switchOff()\r
+ {\r
+ setState(false);\r
+ }\r
+\r
+ public void toggle()\r
+ {\r
+ setState(!isOn);\r
+ }\r
+\r
+ public void setState(boolean isOn)\r
+ {\r
+ if (this.isOn == isOn)\r
+ return;\r
+ this.isOn = isOn;\r
+ output.feedSignals(getValue());\r
+ }\r
+\r
+ public boolean isOn()\r
+ {\r
+ return isOn;\r
+ }\r
+\r
+ public Bit getValue()\r
+ {\r
+ return isOn ? Bit.ONE : Bit.ZERO;\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of();\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(output);\r
+ }\r
+\r
+}\r
-package era.mi.logic.components;
-
-import java.util.List;
-
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-import era.mi.logic.wires.WireObserver;
-
-public class Merger implements WireObserver, Component
-{
- private WireEnd out;
- private WireEnd[] inputs;
- private int[] beginningIndex;
-
- /**
- *
- * @param union The output of merging n {@link Wire}s into one. Must have length = a1.length() + a2.length() + ... + an.length().
- * @param inputs The inputs to be merged into the union
- */
- public Merger(WireEnd union, WireEnd... inputs)
- {
- this.inputs = inputs;
- this.out = union;
- this.beginningIndex = new int[inputs.length];
-
- int length = 0;
- for (int i = 0; i < inputs.length; i++)
- {
- beginningIndex[i] = length;
- length += inputs[i].length();
- inputs[i].addObserver(this);
- }
-
- if (length != union.length())
- throw new IllegalArgumentException(
- "The output of merging n WireArrays into one must have length = a1.length() + a2.length() + ... + an.length().");
- }
-
- public WireEnd getInput(int index)
- {
- return inputs[index];
- }
-
- public WireEnd getUnion()
- {
- return out;
- }
-
- @Override
- public void update(Wire initiator, BitVector oldValues)
- {
- int index = find(initiator);
- int beginning = beginningIndex[index];
- out.feedSignals(beginning, inputs[index].getValues());
- }
-
- private int find(Wire w)
- {
- for (int i = 0; i < inputs.length; i++)
- if (inputs[i].getWire() == w)
- return i;
- return -1;
- }
-
- public WireEnd[] getInputs()
- {
- return inputs.clone();
- }
-
- @Override
- public List<WireEnd> getAllInputs()
- {
- return List.of(inputs);
- }
-
- @Override
- public List<WireEnd> getAllOutputs()
- {
- return List.of(out);
- }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+import era.mi.logic.wires.WireObserver;\r
+\r
+public class Merger implements WireObserver, Component\r
+{\r
+ private ReadWriteEnd out;\r
+ private ReadEnd[] inputs;\r
+ private int[] beginningIndex;\r
+\r
+ /**\r
+ * \r
+ * @param union The output of merging n {@link Wire}s into one. Must have length = a1.length() + a2.length() + ... + an.length().\r
+ * @param inputs The inputs to be merged into the union\r
+ */\r
+ public Merger(ReadWriteEnd union, ReadEnd... inputs)\r
+ {\r
+ this.inputs = inputs;\r
+ this.out = union;\r
+ this.beginningIndex = new int[inputs.length];\r
+\r
+ int length = 0;\r
+ for (int i = 0; i < inputs.length; i++)\r
+ {\r
+ beginningIndex[i] = length;\r
+ length += inputs[i].length();\r
+ inputs[i].addObserver(this);\r
+ }\r
+\r
+ if (length != union.length())\r
+ throw new IllegalArgumentException(\r
+ "The output of merging n WireArrays into one must have length = a1.length() + a2.length() + ... + an.length().");\r
+ }\r
+\r
+ public ReadEnd getInput(int index)\r
+ {\r
+ return inputs[index];\r
+ }\r
+\r
+ public ReadEnd getUnion()\r
+ {\r
+ return out;\r
+ }\r
+\r
+ @Override\r
+ public void update(ReadEnd initiator, BitVector oldValues)\r
+ {\r
+ int index = find(initiator);\r
+ int beginning = beginningIndex[index];\r
+ out.feedSignals(beginning, inputs[index].getValues());\r
+ }\r
+\r
+ private int find(ReadEnd r)\r
+ {\r
+ for (int i = 0; i < inputs.length; i++)\r
+ if (inputs[i] == r)\r
+ return i;\r
+ return -1;\r
+ }\r
+\r
+ public ReadEnd[] getInputs()\r
+ {\r
+ return inputs.clone();\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of(inputs);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(out);\r
+ }\r
+}\r
-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.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-
-/**
- * Models a multiplexer. Takes an arbitrary amount of input {@link Wire}s, one of which, as determined by select, is put through to the
- * output.
- *
- * @author Fabian Stemmler
- *
- */
-public class Mux extends BasicComponent
-{
- private WireEnd select;
- private WireEnd out;
- private WireEnd[] inputs;
- private final int outputSize;
-
- /**
- * Input {@link Wire}s and out must be of uniform length
- *
- * @param out Must be of uniform length with all inputs.
- * @param select Indexes the input array which is to be mapped to the output. Must have enough bits to index all inputs.
- * @param inputs One of these inputs is mapped to the output, depending on the select bits
- */
- public Mux(int processTime, WireEnd out, WireEnd select, WireEnd... inputs)
- {
- super(processTime);
- outputSize = out.length();
-
- this.inputs = inputs.clone();
- for (int i = 0; i < this.inputs.length; i++)
- {
- if (inputs[i].length() != outputSize)
- throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");
- inputs[i].addObserver(this);
- }
-
- this.select = select;
- select.addObserver(this);
-
- int maxInputs = 1 << select.length();
- if (this.inputs.length > maxInputs)
- throw new IllegalArgumentException("There are more inputs (" + this.inputs.length + ") to the MUX than supported by "
- + select.length() + " select bits (" + maxInputs + ").");
-
- this.out = out;
- }
-
- public WireEnd getOut()
- {
- return out;
- }
-
- public WireEnd getSelect()
- {
- return select;
- }
-
- @Override
- public void compute()
- {
- int selectValue;
- if (!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) >= inputs.length)
- {
- out.clearSignals();
- return;
- }
-
- WireEnd active = inputs[selectValue];
- out.feedSignals(active.getValues());
- }
-
- @Override
- public List<WireEnd> getAllInputs()
- {
- ArrayList<WireEnd> wires = new ArrayList<WireEnd>(Arrays.asList(inputs));
- wires.add(select);
- return Collections.unmodifiableList(wires);
- }
-
- @Override
- public List<WireEnd> getAllOutputs()
- {
- return List.of(out);
- }
-}
+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.wires.Wire;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+/**\r
+ * Models a multiplexer. Takes an arbitrary amount of input {@link Wire}s, one of which, as determined by select, is put through to the\r
+ * output.\r
+ * \r
+ * @author Fabian Stemmler\r
+ *\r
+ */\r
+public class Mux extends BasicComponent\r
+{\r
+ private ReadEnd select;\r
+ private ReadWriteEnd out;\r
+ private ReadEnd[] inputs;\r
+ private final int outputSize;\r
+\r
+ /**\r
+ * Input {@link Wire}s and out must be of uniform length\r
+ * \r
+ * @param out Must be of uniform length with all inputs.\r
+ * @param select Indexes the input array which is to be mapped to the output. Must have enough bits to index all inputs.\r
+ * @param inputs One of these inputs is mapped to the output, depending on the select bits\r
+ */\r
+ public Mux(int processTime, ReadWriteEnd out, ReadEnd select, ReadEnd... inputs)\r
+ {\r
+ super(processTime);\r
+ outputSize = out.length();\r
+\r
+ this.inputs = inputs.clone();\r
+ for (int i = 0; i < this.inputs.length; i++)\r
+ {\r
+ if (inputs[i].length() != outputSize)\r
+ throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");\r
+ inputs[i].addObserver(this);\r
+ }\r
+\r
+ this.select = select;\r
+ select.addObserver(this);\r
+\r
+ int maxInputs = 1 << select.length();\r
+ if (this.inputs.length > maxInputs)\r
+ throw new IllegalArgumentException("There are more inputs (" + this.inputs.length + ") to the MUX than supported by "\r
+ + select.length() + " select bits (" + maxInputs + ").");\r
+\r
+ this.out = out;\r
+ }\r
+\r
+ public ReadEnd getOut()\r
+ {\r
+ return out;\r
+ }\r
+\r
+ public ReadEnd getSelect()\r
+ {\r
+ return select;\r
+ }\r
+\r
+ @Override\r
+ public void compute()\r
+ {\r
+ int selectValue;\r
+ if (!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) >= inputs.length)\r
+ {\r
+ out.clearSignals();\r
+ return;\r
+ }\r
+\r
+ ReadEnd active = inputs[selectValue];\r
+ out.feedSignals(active.getValues());\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ ArrayList<ReadEnd> wires = new ArrayList<ReadEnd>(Arrays.asList(inputs));\r
+ wires.add(select);\r
+ return Collections.unmodifiableList(wires);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(out);\r
+ }\r
+}\r
-package era.mi.logic.components;
-
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-import era.mi.logic.wires.WireObserver;
-
-public class Splitter implements WireObserver
-{
- private WireEnd input;
- private WireEnd[] outputs;
-
- public Splitter(WireEnd input, WireEnd... outputs)
- {
- this.input = input;
- this.outputs = outputs;
- input.addObserver(this);
- int length = 0;
- for (WireEnd out : outputs)
- length += out.length();
-
- if (input.length() != length)
- throw new IllegalArgumentException(
- "The input of splitting one into n WireArrays must have length = a1.length() + a2.length() + ... + an.length().");
- }
-
- protected void compute()
- {
- BitVector inputBits = input.getValues();
- int startIndex = 0;
- for (int i = 0; i < outputs.length; i++)
- {
- outputs[i].feedSignals(inputBits.subVector(startIndex, startIndex + outputs[i].length()));
- startIndex += outputs[i].length();
- }
- }
-
- @Override
- public void update(Wire initiator, BitVector oldValues)
- {
- compute();
- }
-}
+package era.mi.logic.components;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+import era.mi.logic.wires.WireObserver;\r
+\r
+public class Splitter implements WireObserver, Component\r
+{\r
+ private ReadEnd input;\r
+ private ReadWriteEnd[] outputs;\r
+\r
+ public Splitter(ReadEnd input, ReadWriteEnd... outputs)\r
+ {\r
+ this.input = input;\r
+ this.outputs = outputs;\r
+ input.addObserver(this);\r
+ int length = 0;\r
+ for (ReadEnd out : outputs)\r
+ length += out.length();\r
+\r
+ if (input.length() != length)\r
+ throw new IllegalArgumentException(\r
+ "The input of splitting one into n WireArrays must have length = a1.length() + a2.length() + ... + an.length().");\r
+ }\r
+\r
+ protected void compute()\r
+ {\r
+ BitVector inputBits = input.getValues();\r
+ int startIndex = 0;\r
+ for (int i = 0; i < outputs.length; i++)\r
+ {\r
+ outputs[i].feedSignals(inputBits.subVector(startIndex, startIndex + outputs[i].length()));\r
+ startIndex += outputs[i].length();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void update(ReadEnd initiator, BitVector oldValues)\r
+ {\r
+ compute();\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of(input);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(outputs);\r
+ }\r
+}\r
import java.util.List;\r
\r
import era.mi.logic.types.Bit;\r
-import era.mi.logic.wires.Wire.WireEnd;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
\r
public class TriStateBuffer extends BasicComponent\r
{\r
- WireEnd in, enable;\r
- WireEnd out;\r
+ ReadEnd in, enable;\r
+ ReadWriteEnd out;\r
\r
- public TriStateBuffer(int processTime, WireEnd in, WireEnd out, WireEnd enable)\r
+ public TriStateBuffer(int processTime, ReadEnd in, ReadWriteEnd out, ReadEnd enable)\r
{\r
super(processTime);\r
if (in.length() != out.length())\r
}\r
\r
@Override\r
- public List<WireEnd> getAllInputs()\r
+ public List<ReadEnd> getAllInputs()\r
{\r
return List.of(in, enable);\r
}\r
\r
@Override\r
- public List<WireEnd> getAllOutputs()\r
+ public List<ReadWriteEnd> getAllOutputs()\r
{\r
return List.of(out);\r
}\r
-package era.mi.logic.components.gates;
-
-import era.mi.logic.types.BitVector.BitVectorMutator;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class AndGate extends MultiInputGate
-{
- public AndGate(int processTime, WireEnd out, WireEnd... in)
- {
- super(processTime, BitVectorMutator::and, out, in);
- }
-}
+package era.mi.logic.components.gates;\r
+\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class AndGate extends MultiInputGate\r
+{\r
+ public AndGate(int processTime, ReadWriteEnd out, ReadEnd... in)\r
+ {\r
+ super(processTime, BitVectorMutator::and, out, in);\r
+ }\r
+}\r
import era.mi.logic.components.BasicComponent;\r
import era.mi.logic.types.BitVector.BitVectorMutator;\r
import era.mi.logic.types.MutationOperation;\r
-import era.mi.logic.wires.Wire.WireEnd;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
\r
public abstract class MultiInputGate extends BasicComponent\r
{\r
- protected WireEnd[] in;\r
- protected WireEnd out;\r
+ protected ReadEnd[] in;\r
+ protected ReadWriteEnd out;\r
protected final int length;\r
protected MutationOperation op;\r
\r
- protected MultiInputGate(int processTime, MutationOperation op, WireEnd out, WireEnd... in)\r
+ protected MultiInputGate(int processTime, MutationOperation op, ReadWriteEnd out, ReadEnd... in)\r
{\r
super(processTime);\r
this.op = op;\r
this.in = in.clone();\r
if (in.length < 1)\r
throw new IllegalArgumentException(String.format("Cannot create gate with %d wires.", in.length));\r
- for (WireEnd w : in)\r
+ for (ReadEnd w : in)\r
{\r
if (w.length() != length)\r
throw new IllegalArgumentException("All wires connected to the gate must be of uniform length.");\r
}\r
\r
@Override\r
- public List<WireEnd> getAllInputs()\r
+ public List<ReadEnd> getAllInputs()\r
{\r
return List.of(in);\r
}\r
\r
@Override\r
- public List<WireEnd> getAllOutputs()\r
+ public List<ReadWriteEnd> getAllOutputs()\r
{\r
return List.of(out);\r
}\r
protected void compute()\r
{\r
BitVectorMutator mutator = BitVectorMutator.empty();\r
- for (WireEnd w : in)\r
+ for (ReadEnd w : in)\r
op.apply(mutator, w.getValues());\r
out.feedSignals(mutator.get());\r
}\r
-package era.mi.logic.components.gates;
-
-import java.util.List;
-
-import era.mi.logic.components.BasicComponent;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class NotGate extends BasicComponent
-{
- private WireEnd in;
- private WireEnd out;
-
- public NotGate(int processTime, WireEnd in, WireEnd out)
- {
- super(processTime);
- this.in = in;
- in.addObserver(this);
- this.out = out;
- }
-
- @Override
- protected void compute()
- {
- out.feedSignals(in.getValues().not());
- }
-
- public WireEnd getIn()
- {
- return in;
- }
-
- public WireEnd getOut()
- {
- return out;
- }
-
- @Override
- public List<WireEnd> getAllInputs()
- {
- return List.of(in);
- }
-
- @Override
- public List<WireEnd> getAllOutputs()
- {
- return List.of(out);
- }
-}
+package era.mi.logic.components.gates;\r
+\r
+import java.util.List;\r
+\r
+import era.mi.logic.components.BasicComponent;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class NotGate extends BasicComponent\r
+{\r
+ private ReadEnd in;\r
+ private ReadWriteEnd out;\r
+\r
+ public NotGate(int processTime, ReadEnd in, ReadWriteEnd out)\r
+ {\r
+ super(processTime);\r
+ this.in = in;\r
+ in.addObserver(this);\r
+ this.out = out;\r
+ }\r
+\r
+ @Override\r
+ protected void compute()\r
+ {\r
+ out.feedSignals(in.getValues().not());\r
+ }\r
+\r
+ public ReadEnd getIn()\r
+ {\r
+ return in;\r
+ }\r
+\r
+ public ReadEnd getOut()\r
+ {\r
+ return out;\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of(in);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(out);\r
+ }\r
+}\r
-package era.mi.logic.components.gates;
-
-import era.mi.logic.types.BitVector.BitVectorMutator;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public class OrGate extends MultiInputGate
-{
- public OrGate(int processTime, WireEnd out, WireEnd... in)
- {
- super(processTime, BitVectorMutator::or, out, in);
- }
-}
+package era.mi.logic.components.gates;\r
+\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+public class OrGate extends MultiInputGate\r
+{\r
+ public OrGate(int processTime, ReadWriteEnd out, ReadEnd... in)\r
+ {\r
+ super(processTime, BitVectorMutator::or, out, in);\r
+ }\r
+}\r
-package era.mi.logic.components.gates;
-
-import era.mi.logic.types.BitVector.BitVectorMutator;
-import era.mi.logic.wires.Wire.WireEnd;
-
-/**
- * Outputs 1 when the number of 1 inputs is odd.
- *
- * @author Fabian Stemmler
- */
-public class XorGate extends MultiInputGate
-{
- public XorGate(int processTime, WireEnd out, WireEnd... in)
- {
- super(processTime, BitVectorMutator::xor, out, in);
- }
-
-}
+package era.mi.logic.components.gates;\r
+\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+/**\r
+ * Outputs 1 when the number of 1 inputs is odd.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+public class XorGate extends MultiInputGate\r
+{\r
+ public XorGate(int processTime, ReadWriteEnd out, ReadEnd... in)\r
+ {\r
+ super(processTime, BitVectorMutator::xor, out, in);\r
+ }\r
+\r
+}\r
-package era.mi.logic.tests;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.function.LongConsumer;
-
-import org.junit.jupiter.api.Test;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.components.Connector;
-import era.mi.logic.components.Demux;
-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.components.gates.XorGate;
-import era.mi.logic.types.Bit;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.wires.Wire;
-import era.mi.logic.wires.Wire.WireEnd;
-
-@SuppressWarnings("unused")
-class ComponentTest
-{
-
- @Test
- void circuitExampleTest()
- {
- Simulation.TIMELINE.reset();
- Wire a = new Wire(1, 1), b = new Wire(1, 1), c = new Wire(1, 10), d = new Wire(2, 1), e = new Wire(1, 1), f = new Wire(1, 1),
- g = new Wire(1, 1), h = new Wire(2, 1), i = new Wire(2, 1), j = new Wire(1, 1), k = new Wire(1, 1);
- new AndGate(1, f.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
- new NotGate(1, f.createReadOnlyEnd(), g.createEnd());
- new Merger(h.createEnd(), c.createReadOnlyEnd(), g.createReadOnlyEnd());
- new Mux(1, i.createEnd(), e.createReadOnlyEnd(), h.createReadOnlyEnd(), d.createReadOnlyEnd());
- new Splitter(i.createReadOnlyEnd(), k.createEnd(), j.createEnd());
-
- a.createEnd().feedSignals(Bit.ZERO);
- b.createEnd().feedSignals(Bit.ONE);
- c.createEnd().feedSignals(Bit.ZERO);
- d.createEnd().feedSignals(Bit.ONE, Bit.ONE);
- e.createEnd().feedSignals(Bit.ZERO);
-
- Simulation.TIMELINE.executeAll();
-
- assertEquals(Bit.ONE, j.getValue());
- assertEquals(Bit.ZERO, k.getValue());
- }
-
- @Test
- void splitterTest()
- {
- Simulation.TIMELINE.reset();
- Wire a = new Wire(3, 1), b = new Wire(2, 1), c = new Wire(3, 1), in = new Wire(8, 1);
- in.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
- new Splitter(in.createReadOnlyEnd(), a.createEnd(), b.createEnd(), c.createEnd());
-
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(a.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO);
- assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO);
- assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE);
- }
-
- @Test
- void mergerTest()
- {
- Simulation.TIMELINE.reset();
- Wire a = new Wire(3, 1), b = new Wire(2, 1), c = new Wire(3, 1), out = new Wire(8, 1);
- a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);
- b.createEnd().feedSignals(Bit.ONE, Bit.ZERO);
- c.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
- new Merger(out.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
-
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
- }
-
- @Test
- void triStateBufferTest()
- {
- Wire a = new Wire(1, 1), b = new Wire(1, 1), en = new Wire(1, 1), notEn = new Wire(1, 1);
- new NotGate(1, en.createReadOnlyEnd(), notEn.createEnd());
- new TriStateBuffer(1, a.createReadOnlyEnd(), b.createEnd(), en.createReadOnlyEnd());
- new TriStateBuffer(1, b.createReadOnlyEnd(), a.createEnd(), notEn.createReadOnlyEnd());
-
- WireEnd enI = en.createEnd(), aI = a.createEnd(), bI = b.createEnd();
- enI.feedSignals(Bit.ONE);
- aI.feedSignals(Bit.ONE);
- bI.feedSignals(Bit.Z);
-
- 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();
- Wire a = new Wire(4, 3), b = new Wire(4, 6), c = new Wire(4, 4), select = new Wire(2, 5), out = new Wire(4, 1);
- WireEnd selectIn = select.createEnd();
-
- selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
- a.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
- c.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- new Mux(1, out.createEnd(), select.createReadOnlyEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(out.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
- selectIn.feedSignals(Bit.ZERO, Bit.ONE);
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- selectIn.feedSignals(Bit.ONE, Bit.ONE);
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(out.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
-
- }
-
- @Test
- void demuxTest()
- {
- Simulation.TIMELINE.reset();
- Wire a = new Wire(4, 3), b = new Wire(4, 6), c = new Wire(4, 4), select = new Wire(2, 5), in = new Wire(4, 1);
- WireEnd selectIn = select.createEnd();
-
- selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
- in.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-
- new Demux(1, in.createReadOnlyEnd(), select.createReadOnlyEnd(), a.createEnd(), b.createEnd(), c.createEnd());
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
- assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);
- assertBitArrayEquals(c.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);
- selectIn.feedSignals(Bit.ZERO, Bit.ONE);
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
- assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);
- 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.U, Bit.U, Bit.U, Bit.U);
- assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
-
- }
-
- @Test
- void andTest()
- {
- Simulation.TIMELINE.reset();
- Wire a = new Wire(4, 1), b = new Wire(4, 3), c = new Wire(4, 1);
- new AndGate(1, c.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
- a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
- b.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);
- }
-
- @Test
- void orTest()
- {
- Simulation.TIMELINE.reset();
- Wire a = new Wire(4, 1), b = new Wire(4, 3), c = new Wire(4, 1);
- new OrGate(1, c.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
- a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
- b.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);
- }
-
- @Test
- void xorTest()
- {
- Simulation.TIMELINE.reset();
- Wire a = new Wire(3, 1), b = new Wire(3, 2), c = new Wire(3, 1), d = new Wire(3, 1);
- new XorGate(1, d.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
- a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
- b.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
- c.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);
- }
-
- @Test
- void notTest()
- {
- Simulation.TIMELINE.reset();
- Wire a = new Wire(3, 1), b = new Wire(3, 2);
- new NotGate(1, a.createReadOnlyEnd(), b.createEnd());
- a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
-
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO, Bit.ZERO);
- }
-
- @Test
- void rsLatchCircuitTest()
- {
- Simulation.TIMELINE.reset();
- Wire r = new Wire(1, 1), s = new Wire(1, 1), t1 = new Wire(1, 15), t2 = new Wire(1, 1), q = new Wire(1, 1), nq = new Wire(1, 1);
-
- new OrGate(1, t2.createEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd());
- new OrGate(1, t1.createEnd(), s.createReadOnlyEnd(), q.createReadOnlyEnd());
- new NotGate(1, t2.createReadOnlyEnd(), q.createEnd());
- new NotGate(1, t1.createReadOnlyEnd(), nq.createEnd());
-
- WireEnd sIn = s.createEnd(), rIn = r.createEnd();
-
- 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();
-
- Wire a = new Wire(4, 1);
- a.createEnd().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();
- Wire w = new Wire(2, 1);
- WireEnd wI1 = w.createEnd(), wI2 = w.createEnd();
- wI1.feedSignals(Bit.ONE, Bit.Z);
- wI2.feedSignals(Bit.Z, Bit.X);
- Simulation.TIMELINE.executeAll();
- assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.X);
-
- wI2.feedSignals(Bit.ZERO, Bit.Z);
- Simulation.TIMELINE.executeAll();
- assertBitArrayEquals(w.getValues(), Bit.X, Bit.Z);
-
- wI2.feedSignals(Bit.Z, Bit.Z);
- Simulation.TIMELINE.executeAll();
- assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
-
- wI2.feedSignals(Bit.ONE, Bit.Z);
- w.addObserver((i, oldValues) -> fail("WireArray notified observer, although value did not change."));
- Simulation.TIMELINE.executeAll();
- assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
- }
-
- @Test
- void wireConnections()
- {
- // Nur ein Experiment, was über mehrere 'passive' Bausteine hinweg passieren würde
-
- Simulation.TIMELINE.reset();
-
- Wire a = new Wire(1, 2);
- Wire b = new Wire(1, 2);
- Wire c = new Wire(1, 2);
- WireEnd aI = a.createEnd();
- WireEnd bI = b.createEnd();
- WireEnd cI = c.createEnd();
-
- TestBitDisplay test = new TestBitDisplay(c.createReadOnlyEnd());
- TestBitDisplay test2 = new TestBitDisplay(a.createReadOnlyEnd());
- 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);
-
- new Connector(b.createEnd(), c.createEnd()).connect();
- 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);
-
- new Connector(a.createEnd(), b.createEnd()).connect();
- 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(BitVector actual, Bit... expected)
- {
- assertArrayEquals(expected, actual.getBits());
- }
-}
+package era.mi.logic.tests;\r
+\r
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;\r
+import static org.junit.jupiter.api.Assertions.assertEquals;\r
+import static org.junit.jupiter.api.Assertions.fail;\r
+\r
+import java.util.function.LongConsumer;\r
+\r
+import org.junit.jupiter.api.Test;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.components.Connector;\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
+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.components.gates.XorGate;\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+import era.mi.logic.wires.Wire.ReadWriteEnd;\r
+\r
+class ComponentTest\r
+{\r
+\r
+ @Test\r
+ void circuitExampleTest()\r
+ {\r
+ Simulation.TIMELINE.reset();\r
+ Wire a = new Wire(1, 1), b = new Wire(1, 1), c = new Wire(1, 10), d = new Wire(2, 1), e = new Wire(1, 1), f = new Wire(1, 1),\r
+ g = new Wire(1, 1), h = new Wire(2, 1), i = new Wire(2, 1), j = new Wire(1, 1), k = new Wire(1, 1);\r
+ new AndGate(1, f.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+ new NotGate(1, f.createReadOnlyEnd(), g.createEnd());\r
+ new Merger(h.createEnd(), c.createReadOnlyEnd(), g.createReadOnlyEnd());\r
+ new Mux(1, i.createEnd(), e.createReadOnlyEnd(), h.createReadOnlyEnd(), d.createReadOnlyEnd());\r
+ new Splitter(i.createReadOnlyEnd(), k.createEnd(), j.createEnd());\r
+\r
+ a.createEnd().feedSignals(Bit.ZERO);\r
+ b.createEnd().feedSignals(Bit.ONE);\r
+ c.createEnd().feedSignals(Bit.ZERO);\r
+ d.createEnd().feedSignals(Bit.ONE, Bit.ONE);\r
+ e.createEnd().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
+ Wire a = new Wire(3, 1), b = new Wire(2, 1), c = new Wire(3, 1), in = new Wire(8, 1);\r
+ in.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+ new Splitter(in.createReadOnlyEnd(), a.createEnd(), b.createEnd(), c.createEnd());\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
+ Wire a = new Wire(3, 1), b = new Wire(2, 1), c = new Wire(3, 1), out = new Wire(8, 1);\r
+ a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+ b.createEnd().feedSignals(Bit.ONE, Bit.ZERO);\r
+ c.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ new Merger(out.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(out.getValues(), 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
+ Wire a = new Wire(1, 1), b = new Wire(1, 1), en = new Wire(1, 1), notEn = new Wire(1, 1);\r
+ new NotGate(1, en.createReadOnlyEnd(), notEn.createEnd());\r
+ new TriStateBuffer(1, a.createReadOnlyEnd(), b.createEnd(), en.createReadOnlyEnd());\r
+ new TriStateBuffer(1, b.createReadOnlyEnd(), a.createEnd(), notEn.createReadOnlyEnd());\r
+\r
+ ReadWriteEnd enI = en.createEnd(), aI = a.createEnd(), bI = b.createEnd();\r
+ enI.feedSignals(Bit.ONE);\r
+ aI.feedSignals(Bit.ONE);\r
+ bI.feedSignals(Bit.Z);\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
+ Wire a = new Wire(4, 3), b = new Wire(4, 6), c = new Wire(4, 4), select = new Wire(2, 5), out = new Wire(4, 1);\r
+ ReadWriteEnd selectIn = select.createEnd();\r
+\r
+ selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+ a.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+ c.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ new Mux(1, out.createEnd(), select.createReadOnlyEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\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 demuxTest()\r
+ {\r
+ Simulation.TIMELINE.reset();\r
+ Wire a = new Wire(4, 3), b = new Wire(4, 6), c = new Wire(4, 4), select = new Wire(2, 5), in = new Wire(4, 1);\r
+ ReadWriteEnd selectIn = select.createEnd();\r
+\r
+ selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+ in.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+\r
+ new Demux(1, in.createReadOnlyEnd(), select.createReadOnlyEnd(), a.createEnd(), b.createEnd(), c.createEnd());\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+ assertBitArrayEquals(b.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);\r
+ assertBitArrayEquals(c.getValues(), Bit.U, Bit.U, Bit.U, Bit.U);\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.U, Bit.U, Bit.U, Bit.U);\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.U, Bit.U, Bit.U, Bit.U);\r
+ assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+\r
+ }\r
+\r
+ @Test\r
+ void andTest()\r
+ {\r
+ Simulation.TIMELINE.reset();\r
+ Wire a = new Wire(4, 1), b = new Wire(4, 3), c = new Wire(4, 1);\r
+ new AndGate(1, c.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+ a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+ b.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+ }\r
+\r
+ @Test\r
+ void orTest()\r
+ {\r
+ Simulation.TIMELINE.reset();\r
+ Wire a = new Wire(4, 1), b = new Wire(4, 3), c = new Wire(4, 1);\r
+ new OrGate(1, c.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+ a.createEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+ b.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+ }\r
+\r
+ @Test\r
+ void xorTest()\r
+ {\r
+ Simulation.TIMELINE.reset();\r
+ Wire a = new Wire(3, 1), b = new Wire(3, 2), c = new Wire(3, 1), d = new Wire(3, 1);\r
+ new XorGate(1, d.createEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+ a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);\r
+ b.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+ c.createEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);\r
+ }\r
+\r
+ @Test\r
+ void notTest()\r
+ {\r
+ Simulation.TIMELINE.reset();\r
+ Wire a = new Wire(3, 1), b = new Wire(3, 2);\r
+ new NotGate(1, a.createReadOnlyEnd(), b.createEnd());\r
+ a.createEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);\r
+\r
+ Simulation.TIMELINE.executeAll();\r
+\r
+ assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+ }\r
+\r
+ @Test\r
+ void rsLatchCircuitTest()\r
+ {\r
+ Simulation.TIMELINE.reset();\r
+ Wire r = new Wire(1, 1), s = new Wire(1, 1), t1 = new Wire(1, 15), t2 = new Wire(1, 1), q = new Wire(1, 1), nq = new Wire(1, 1);\r
+\r
+ new OrGate(1, t2.createEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd());\r
+ new OrGate(1, t1.createEnd(), s.createReadOnlyEnd(), q.createReadOnlyEnd());\r
+ new NotGate(1, t2.createReadOnlyEnd(), q.createEnd());\r
+ new NotGate(1, t1.createReadOnlyEnd(), nq.createEnd());\r
+\r
+ ReadWriteEnd sIn = s.createEnd(), rIn = r.createEnd();\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
+ Wire a = new Wire(4, 1);\r
+ a.createEnd().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
+ Wire w = new Wire(2, 1);\r
+ ReadWriteEnd wI1 = w.createEnd(), wI2 = w.createEnd();\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
+ ReadEnd rE = w.createReadOnlyEnd();\r
+ rE.addObserver((i, oldValues) -> fail("WireEnd notified observer, although value did not change."));\r
+ Simulation.TIMELINE.executeAll();\r
+ rE.close();\r
+ wI1.feedSignals(Bit.X, Bit.X);\r
+ Simulation.TIMELINE.executeAll();\r
+ wI1.addObserver((i, oldValues) -> fail("WireEnd notified observer, although it was closed."));\r
+ wI1.close();\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
+ Wire a = new Wire(1, 2);\r
+ Wire b = new Wire(1, 2);\r
+ Wire c = new Wire(1, 2);\r
+ ReadWriteEnd aI = a.createEnd();\r
+ ReadWriteEnd bI = b.createEnd();\r
+ ReadWriteEnd cI = c.createEnd();\r
+\r
+ TestBitDisplay test = new TestBitDisplay(c.createReadOnlyEnd());\r
+ TestBitDisplay test2 = new TestBitDisplay(a.createReadOnlyEnd());\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
+ new Connector(b.createEnd(), c.createEnd()).connect();\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
+ new Connector(a.createEnd(), b.createEnd()).connect();\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(BitVector actual, Bit... expected)\r
+ {\r
+ assertArrayEquals(expected, actual.getBits());\r
+ }\r
+}\r
-package era.mi.logic.tests;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-
-import java.util.function.LongConsumer;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.components.BitDisplay;
-import era.mi.logic.types.Bit;
-import era.mi.logic.wires.Wire.WireEnd;
-
-public final class TestBitDisplay extends BitDisplay
-{
-
- public TestBitDisplay(WireEnd in)
- {
- super(in);
- }
-
- public void assertDisplays(Bit... expected)
- {
- assertArrayEquals(expected, getDisplayedValue().getBits());
- }
-
- public void assertAfterSimulationIs(Bit... expected)
- {
- Simulation.TIMELINE.executeAll();
- assertDisplays(expected);
- }
-
- public void assertAfterSimulationIs(LongConsumer r, Bit... expected)
- {
- while (Simulation.TIMELINE.hasNext())
- {
- Simulation.TIMELINE.executeNext();
- r.accept(Simulation.TIMELINE.getSimulationTime());
- }
- assertDisplays(expected);
- }
-
- @Override
- protected void compute()
- {
- super.compute();
- System.out.println("update: value is " + getDisplayedValue());
- }
-}
+package era.mi.logic.tests;\r
+\r
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;\r
+\r
+import java.util.function.LongConsumer;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.components.BitDisplay;\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+\r
+public final class TestBitDisplay extends BitDisplay\r
+{\r
+\r
+ public TestBitDisplay(ReadEnd in)\r
+ {\r
+ super(in);\r
+ }\r
+\r
+ public void assertDisplays(Bit... expected)\r
+ {\r
+ assertArrayEquals(expected, getDisplayedValue().getBits());\r
+ }\r
+\r
+ public void assertAfterSimulationIs(Bit... expected)\r
+ {\r
+ Simulation.TIMELINE.executeAll();\r
+ assertDisplays(expected);\r
+ }\r
+\r
+ public void assertAfterSimulationIs(LongConsumer r, Bit... expected)\r
+ {\r
+ while (Simulation.TIMELINE.hasNext())\r
+ {\r
+ Simulation.TIMELINE.executeNext();\r
+ r.accept(Simulation.TIMELINE.getSimulationTime());\r
+ }\r
+ assertDisplays(expected);\r
+ }\r
+\r
+ @Override\r
+ protected void compute()\r
+ {\r
+ super.compute();\r
+ System.out.println("update: value is " + getDisplayedValue());\r
+ }\r
+}\r
-package era.mi.logic.wires;
-
-import static era.mi.logic.types.Bit.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import era.mi.logic.Simulation;
-import era.mi.logic.types.Bit;
-import era.mi.logic.types.BitVector;
-import era.mi.logic.types.BitVector.BitVectorMutator;
-
-/**
- * Represents an array of wires that can store n bits of information.
- *
- * @author Fabian Stemmler
- *
- */
-public class Wire
-{
- private BitVector values;
- public final int travelTime;
- private List<WireObserver> observers = new ArrayList<WireObserver>();
- public final int length;
- private List<WireEnd> inputs = new ArrayList<WireEnd>();
-
- public Wire(int length, int travelTime)
- {
- if (length < 1)
- throw new IllegalArgumentException(
- String.format("Tried to create an array of wires with length %d, but a length of less than 1 makes no sense.", length));
- this.length = length;
- this.travelTime = travelTime;
- initValues();
- }
-
- private void initValues()
- {
- values = U.toVector(length);
- }
-
- private void recalculateSingleInput()
- {
- setNewValues(inputs.get(0).getInputValues());
- }
-
- private void recalculateMultipleInputs()
- {
- BitVectorMutator mutator = BitVectorMutator.empty();
- for (WireEnd wireArrayEnd : inputs)
- mutator.join(wireArrayEnd.getInputValues());
- setNewValues(mutator.get());
- }
-
- private void setNewValues(BitVector newValues)
- {
- if (values.equals(newValues))
- return;
- BitVector oldValues = values;
- values = newValues;
- notifyObservers(oldValues);
- }
-
- private void recalculate()
- {
- switch (inputs.size())
- {
- case 0:
- return;
- case 1:
- recalculateSingleInput();
- break;
- default:
- recalculateMultipleInputs();
- }
- }
-
- /**
- * The {@link Wire} 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 {@link Wire} is interpreted as an unsigned integer with n bits.
- *
- * @return The unsigned value of the {@link Wire}'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 (Bit bit : values)
- {
- switch (bit)
- {
- 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 {@link Wire} is interpreted as a signed integer with n bits.
- *
- * @return The signed value of the {@link Wire}'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;
- }
-
- public Bit getValue()
- {
- return getValue(0);
- }
-
- public Bit getValue(int index)
- {
- return values.getBit(index);
- }
-
- public BitVector getValues(int start, int end)
- {
- return values.subVector(start, end);
- }
-
- public BitVector getValues()
- {
- return values;
- }
-
- /**
- * Adds an {@link WireObserver}, who will be notified when the value of the {@link Wire} is updated.
- *
- * @param ob The {@link WireObserver} to be notified of changes.
- * @return true if the given {@link WireObserver} was not already registered, false otherwise
- *
- * @author Fabian Stemmler
- */
- public boolean addObserver(WireObserver ob)
- {
- return observers.add(ob);
- }
-
- private void notifyObservers(BitVector oldValues)
- {
- for (WireObserver o : observers)
- o.update(this, oldValues);
- }
-
- /**
- * Create and register a {@link WireEnd} object, which is tied to this {@link Wire}.
- */
- public WireEnd createEnd()
- {
- return new WireEnd(false);
- }
-
- /**
- * Create a {@link WireEnd} object, which is tied to this {@link Wire}. This {@link WireEnd} cannot written to.
- */
- public WireEnd createReadOnlyEnd()
- {
- return new WireEnd(true);
- }
-
- private void registerInput(WireEnd toRegister)
- {
- inputs.add(toRegister);
- }
-
- /**
- * A {@link WireEnd} feeds a constant signal into the {@link Wire} it is tied to. The combination of all inputs determines the
- * {@link Wire}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 WireEnd
- {
- private boolean open;
- private BitVector inputValues;
-
- private WireEnd(boolean readOnly)
- {
- super();
- open = !readOnly; // TODO: that makes sense, doesn't it?
- initValues();
- if (!readOnly)
- registerInput(this);
- }
-
- private void initValues()
- {
- inputValues = U.toVector(length);
- }
-
- /**
- * Sets the wires values. This takes up time, as specified by the {@link Wire}s travel time.
- *
- * @param newValues The new values the wires should take on.
- *
- * @author Fabian Stemmler
- */
- public void feedSignals(Bit... newValues)
- {
- feedSignals(BitVector.of(newValues));
- }
-
- public void feedSignals(BitVector newValues)
- {
- if (newValues.length() != length)
- throw new IllegalArgumentException(
- String.format("Attempted to input %d bits instead of %d bits.", newValues.length(), length));
- if (!open)
- throw new RuntimeException("Attempted to write to closed WireArrayEnd.");
- Simulation.TIMELINE.addEvent(e -> setValues(newValues), travelTime);
- }
-
- /**
- * Sets values of a subarray of wires. This takes up time, as specified by the {@link Wire}s travel time.
- *
- * @param bitVector 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, BitVector bitVector)
- {
- if (!open)
- throw new RuntimeException("Attempted to write to closed WireArrayEnd.");
- Simulation.TIMELINE.addEvent(e -> setValues(startingBit, bitVector), travelTime);
- }
-
- private void setValues(int startingBit, BitVector newValues)
- {
- // index check covered in equals
- if (!inputValues.equalsWithOffset(newValues, startingBit))
- {
- Bit[] vals = inputValues.getBits();
- System.arraycopy(newValues.getBits(), 0, vals, startingBit, newValues.length());
- inputValues = BitVector.of(vals);
- Wire.this.recalculate();
- }
- }
-
- private void setValues(BitVector newValues)
- {
- if (inputValues.equals(newValues))
- return;
- inputValues = newValues;
- Wire.this.recalculate();
- }
-
- /**
- * @return The value (of bit 0) the {@link WireEnd} is currently feeding into the associated {@link Wire}.
- */
- public Bit getInputValue()
- {
- return getInputValue(0);
- }
-
- /**
- * @return The value which the {@link WireEnd} is currently feeding into the associated {@link Wire} at the indexed {@link Bit}.
- */
- public Bit getInputValue(int index)
- {
- return inputValues.getBit(index);
- }
-
- /**
- * @return A copy (safe to modify) of the values the {@link WireEnd} is currently feeding into the associated {@link Wire}.
- */
- public BitVector getInputValues()
- {
- return getInputValues(0, length);
- }
-
- public BitVector getInputValues(int start, int end)
- {
- return inputValues.subVector(start, end);
- }
-
- /**
- * {@link WireEnd} now feeds Z into the associated {@link Wire}.
- */
- public void clearSignals()
- {
- feedSignals(Z.toVector(length));
- }
-
- public BitVector wireValuesExcludingMe()
- {
- BitVectorMutator mutator = BitVectorMutator.empty();
- for (WireEnd wireEnd : inputs)
- {
- if (wireEnd == this)
- continue;
- mutator.join(wireEnd.inputValues);
- }
- return mutator.get();
- }
-
- /**
- * Included for convenient use on {@link Wire}s of length 1.
- *
- * @return The value of bit 0.
- *
- * @author Fabian Stemmler
- */
- public Bit getValue()
- {
- return Wire.this.getValue();
- }
-
- /**
- * @param index Index of the requested bit.
- * @return The value of the indexed bit.
- *
- * @author Fabian Stemmler
- */
- public Bit getValue(int index)
- {
- return Wire.this.getValue(index);
- }
-
- /**
- * @param index Index of the requested bit.
- * @return The value of the indexed bit.
- *
- * @author Fabian Stemmler
- */
- public BitVector getValues()
- {
- return Wire.this.getValues();
- }
-
- /**
- * @param start Start of the wanted segment. (inclusive)
- * @param end End of the wanted segment. (exclusive)
- * @return The values of the segment of {@link Bit}s indexed.
- *
- * @author Fabian Stemmler
- */
- public BitVector getValues(int start, int end)
- {
- return Wire.this.getValues(start, end);
- }
-
- /**
- * The {@link Wire} is interpreted as an unsigned integer with n bits.
- *
- * @return <code>true</code> if all bits are either <code>Bit.ONE</code> or <code>Bit.ZERO</code> (they do not all have to have the
- * same value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is returned otherwise.
- *
- * @author Fabian Stemmler
- */
- public boolean hasNumericValue()
- {
- return Wire.this.hasNumericValue();
- }
-
- /**
- * The {@link Wire} is interpreted as an unsigned integer with n bits.
- *
- * @return The unsigned value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
- *
- * @author Fabian Stemmler
- */
- public long getUnsignedValue()
- {
- return Wire.this.getUnsignedValue();
- }
-
- /**
- * The {@link Wire} is interpreted as a signed integer with n bits.
- *
- * @return The signed value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
- *
- * @author Fabian Stemmler
- */
- public long getSignedValue()
- {
- return Wire.this.getSignedValue();
- }
-
- @Override
- public String toString()
- {
- return inputValues.toString();
- // return String.format("%s \nFeeding: %s", WireArray.this.toString(), Arrays.toString(inputValues));
- }
-
- public void close()
- {
- inputs.remove(this);
- open = false;
- }
-
- public int length()
- {
- return length;
- }
-
- public boolean addObserver(WireObserver ob)
- {
- return Wire.this.addObserver(ob);
- }
-
- public Wire getWire()
- {
- return Wire.this;
- }
- }
-
- @Override
- public String toString()
- {
- return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), values, inputs);
- // Arrays.toString(values), inputs.stream().map(i -> Arrays.toString(i.inputValues)).reduce((s1, s2) -> s1 + s2)
- }
-
- public static WireEnd[] extractEnds(Wire[] w)
- {
- WireEnd[] inputs = new WireEnd[w.length];
- for (int i = 0; i < w.length; i++)
- inputs[i] = w[i].createEnd();
- return inputs;
- }
+package era.mi.logic.wires;\r
+\r
+import static era.mi.logic.types.Bit.U;\r
+import static era.mi.logic.types.Bit.Z;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import era.mi.logic.Simulation;\r
+import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\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 Wire\r
+{\r
+ private BitVector values;\r
+ public final int travelTime;\r
+ private List<ReadEnd> attached = new ArrayList<ReadEnd>();\r
+ public final int length;\r
+ private List<ReadWriteEnd> inputs = new ArrayList<ReadWriteEnd>();\r
+\r
+ public Wire(int length, int travelTime)\r
+ {\r
+ if (length < 1)\r
+ throw new IllegalArgumentException(\r
+ String.format("Tried to create an array of wires with length %d, 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 = U.toVector(length);\r
+ }\r
+\r
+ private void recalculateSingleInput()\r
+ {\r
+ setNewValues(inputs.get(0).getInputValues());\r
+ }\r
+\r
+ private void recalculateMultipleInputs()\r
+ {\r
+ BitVectorMutator mutator = BitVectorMutator.empty();\r
+ for (ReadWriteEnd wireArrayEnd : inputs)\r
+ mutator.join(wireArrayEnd.getInputValues());\r
+ setNewValues(mutator.get());\r
+ }\r
+\r
+ private void setNewValues(BitVector newValues)\r
+ {\r
+ if (values.equals(newValues))\r
+ return;\r
+ BitVector oldValues = values;\r
+ values = newValues;\r
+ notifyObservers(oldValues);\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 {@link Wire} 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 <code>Bit.ZERO</code> (they do not all have to have the same\r
+ * value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is 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 {@link Wire} is interpreted as an unsigned integer with n bits.\r
+ * \r
+ * @return The unsigned value of the {@link Wire}'s bits, where value 0 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 (Bit bit : values)\r
+ {\r
+ switch (bit)\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
+ case ONE:\r
+ val |= mask;\r
+ break;\r
+ case ZERO:\r
+ }\r
+ mask = mask << 1;\r
+ }\r
+ return val;\r
+ }\r
+\r
+ /**\r
+ * The {@link Wire} is interpreted as a signed integer with n bits.\r
+ * \r
+ * @return The signed value of the {@link Wire}'s bits, where value 0 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
+ public Bit getValue()\r
+ {\r
+ return getValue(0);\r
+ }\r
+\r
+ public Bit getValue(int index)\r
+ {\r
+ return values.getBit(index);\r
+ }\r
+\r
+ public BitVector getValues(int start, int end)\r
+ {\r
+ return values.subVector(start, end);\r
+ }\r
+\r
+ public BitVector getValues()\r
+ {\r
+ return values;\r
+ }\r
+\r
+ /**\r
+ * Adds an {@link WireObserver}, who will be notified when the value of the {@link Wire} is updated.\r
+ * \r
+ * @param ob The {@link WireObserver} to be notified of changes.\r
+ * @return true if the given {@link WireObserver} was not already registered, false otherwise\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+ private void attachEnd(ReadEnd end)\r
+ {\r
+ attached.add(end);\r
+ }\r
+\r
+ private void detachEnd(ReadEnd end)\r
+ {\r
+ attached.remove(end);\r
+ }\r
+\r
+ private void notifyObservers(BitVector oldValues)\r
+ {\r
+ for (ReadEnd o : attached)\r
+ o.update(oldValues);\r
+ }\r
+\r
+ /**\r
+ * Create and register a {@link ReadWriteEnd} object, which is tied to this {@link Wire}. This {@link ReadWriteEnd} can be written to.\r
+ */\r
+ public ReadWriteEnd createEnd()\r
+ {\r
+ return new ReadWriteEnd();\r
+ }\r
+\r
+ /**\r
+ * Create a {@link ReadEnd} object, which is tied to this {@link Wire}. This {@link ReadEnd} cannot be written to.\r
+ */\r
+ public ReadEnd createReadOnlyEnd()\r
+ {\r
+ return new ReadEnd();\r
+ }\r
+\r
+ private void registerInput(ReadWriteEnd toRegister)\r
+ {\r
+ inputs.add(toRegister);\r
+ }\r
+\r
+ /**\r
+ * A {@link ReadEnd} feeds a constant signal into the {@link Wire} it is tied to. The combination of all inputs determines the\r
+ * {@link Wire}s final value. X dominates all other inputs Z does not affect the final value, unless there are no other inputs than Z 0\r
+ * and 1 turn into X when they are mixed\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+ public class ReadEnd\r
+ {\r
+ private List<WireObserver> observers = new ArrayList<WireObserver>();\r
+\r
+ private ReadEnd()\r
+ {\r
+ super();\r
+ Wire.this.attachEnd(this);\r
+ }\r
+\r
+ public void update(BitVector oldValues)\r
+ {\r
+ for (WireObserver ob : observers)\r
+ ob.update(this, oldValues);\r
+ }\r
+\r
+ /**\r
+ * Included for convenient use on {@link Wire}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 Wire.this.getValue();\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 Wire.this.getValue(index);\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 BitVector getValues()\r
+ {\r
+ return Wire.this.getValues();\r
+ }\r
+\r
+ /**\r
+ * @param start Start of the wanted segment. (inclusive)\r
+ * @param end End of the wanted segment. (exclusive)\r
+ * @return The values of the segment of {@link Bit}s indexed.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+ public BitVector getValues(int start, int end)\r
+ {\r
+ return Wire.this.getValues(start, end);\r
+ }\r
+\r
+ /**\r
+ * The {@link Wire} 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 <code>Bit.ZERO</code> (they do not all have to have the\r
+ * same value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is returned otherwise.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+ public boolean hasNumericValue()\r
+ {\r
+ return Wire.this.hasNumericValue();\r
+ }\r
+\r
+ /**\r
+ * The {@link Wire} is interpreted as an unsigned integer with n bits.\r
+ * \r
+ * @return The unsigned value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+ public long getUnsignedValue()\r
+ {\r
+ return Wire.this.getUnsignedValue();\r
+ }\r
+\r
+ /**\r
+ * The {@link Wire} is interpreted as a signed integer with n bits.\r
+ * \r
+ * @return The signed value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.\r
+ * \r
+ * @author Fabian Stemmler\r
+ */\r
+ public long getSignedValue()\r
+ {\r
+ return Wire.this.getSignedValue();\r
+ }\r
+\r
+ @Override\r
+ public String toString()\r
+ {\r
+ return Wire.this.toString();\r
+ }\r
+\r
+ public void close()\r
+ {\r
+ inputs.remove(this);\r
+ detachEnd(this);\r
+ recalculate();\r
+ }\r
+\r
+ public int length()\r
+ {\r
+ return length;\r
+ }\r
+\r
+ public boolean addObserver(WireObserver ob)\r
+ {\r
+ return observers.add(ob);\r
+ }\r
+\r
+ public Wire getWire()\r
+ {\r
+ return Wire.this;\r
+ }\r
+ }\r
+\r
+ public class ReadWriteEnd extends ReadEnd\r
+ {\r
+ private boolean open;\r
+ private BitVector inputValues;\r
+\r
+ private ReadWriteEnd()\r
+ {\r
+ super();\r
+ open = true;\r
+ initValues();\r
+ registerInput(this);\r
+ }\r
+\r
+ private void initValues()\r
+ {\r
+ inputValues = U.toVector(length);\r
+ }\r
+\r
+ /**\r
+ * Sets the wires values. This takes up time, as specified by the {@link Wire}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
+ feedSignals(BitVector.of(newValues));\r
+ }\r
+\r
+ public void feedSignals(BitVector newValues)\r
+ {\r
+ if (newValues.length() != length)\r
+ throw new IllegalArgumentException(\r
+ String.format("Attempted to input %d bits instead of %d bits.", newValues.length(), length));\r
+ if (!open)\r
+ throw new RuntimeException("Attempted to write to closed WireArrayEnd.");\r
+ Simulation.TIMELINE.addEvent(e -> setValues(newValues), travelTime);\r
+ }\r
+\r
+ /**\r
+ * Sets values of a subarray of wires. This takes up time, as specified by the {@link Wire}s travel time.\r
+ * \r
+ * @param bitVector 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, BitVector bitVector)\r
+ {\r
+ if (!open)\r
+ throw new RuntimeException("Attempted to write to closed WireArrayEnd.");\r
+ Simulation.TIMELINE.addEvent(e -> setValues(startingBit, bitVector), travelTime);\r
+ }\r
+\r
+ private void setValues(int startingBit, BitVector newValues)\r
+ {\r
+ // index check covered in equals\r
+ if (!inputValues.equalsWithOffset(newValues, startingBit))\r
+ {\r
+ Bit[] vals = inputValues.getBits();\r
+ System.arraycopy(newValues.getBits(), 0, vals, startingBit, newValues.length());\r
+ inputValues = BitVector.of(vals);\r
+ Wire.this.recalculate();\r
+ }\r
+ }\r
+\r
+ private void setValues(BitVector newValues)\r
+ {\r
+ if (inputValues.equals(newValues))\r
+ return;\r
+ inputValues = newValues;\r
+ Wire.this.recalculate();\r
+ }\r
+\r
+ /**\r
+ * @return The value (of bit 0) the {@link ReadEnd} is currently feeding into the associated {@link Wire}.\r
+ */\r
+ public Bit getInputValue()\r
+ {\r
+ return getInputValue(0);\r
+ }\r
+\r
+ /**\r
+ * @return The value which the {@link ReadEnd} is currently feeding into the associated {@link Wire} at the indexed {@link Bit}.\r
+ */\r
+ public Bit getInputValue(int index)\r
+ {\r
+ return inputValues.getBit(index);\r
+ }\r
+\r
+ /**\r
+ * @return A copy (safe to modify) of the values the {@link ReadEnd} is currently feeding into the associated {@link Wire}.\r
+ */\r
+ public BitVector getInputValues()\r
+ {\r
+ return getInputValues(0, length);\r
+ }\r
+\r
+ public BitVector getInputValues(int start, int end)\r
+ {\r
+ return inputValues.subVector(start, end);\r
+ }\r
+\r
+ /**\r
+ * {@link ReadEnd} now feeds Z into the associated {@link Wire}.\r
+ */\r
+ public void clearSignals()\r
+ {\r
+ feedSignals(Z.toVector(length));\r
+ }\r
+\r
+ public BitVector wireValuesExcludingMe()\r
+ {\r
+ BitVectorMutator mutator = BitVectorMutator.empty();\r
+ for (ReadWriteEnd wireEnd : inputs)\r
+ {\r
+ if (wireEnd == this)\r
+ continue;\r
+ mutator.join(wireEnd.inputValues);\r
+ }\r
+ return mutator.get();\r
+ }\r
+\r
+ @Override\r
+ public String toString()\r
+ {\r
+ return inputValues.toString();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public String toString()\r
+ {\r
+ return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), values, inputs);\r
+ // Arrays.toString(values), inputs.stream().map(i -> Arrays.toString(i.inputValues)).reduce((s1, s2) -> s1 + s2)\r
+ }\r
+\r
+ public static ReadEnd[] extractEnds(Wire[] w)\r
+ {\r
+ ReadEnd[] inputs = new ReadEnd[w.length];\r
+ for (int i = 0; i < w.length; i++)\r
+ inputs[i] = w[i].createEnd();\r
+ return inputs;\r
+ }\r
}
\ No newline at end of file
-package era.mi.logic.wires;
-
-import era.mi.logic.types.BitVector;
-
-public interface WireObserver
-{
- public void update(Wire initiator, BitVector oldValues);
-}
+package era.mi.logic.wires;\r
+\r
+import era.mi.logic.types.BitVector;\r
+import era.mi.logic.wires.Wire.ReadEnd;\r
+\r
+public interface WireObserver\r
+{\r
+ public void update(ReadEnd initiator, BitVector oldValues);\r
+}\r