--- /dev/null
+package net.mograsim.logic.core;\r
+\r
+public interface LogicObservable\r
+{\r
+ public void registerObserver(LogicObserver ob);\r
+\r
+ public void notifyObservers();\r
+\r
+// public InnerState getInnerState();\r
+}\r
--- /dev/null
+package net.mograsim.logic.core;\r
+\r
+public interface LogicObserver\r
+{\r
+ public void update(LogicObservable initiator);\r
+}\r
-package net.mograsim.logic.core.components;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.WireObserver;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-
-/**
- * A basic component that recomputes all outputs (with a delay), when it is updated.
- *
- * @author Fabian Stemmler
- */
-public abstract class BasicComponent extends Component implements WireObserver
-{
- 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(Timeline timeline, int processTime)
- {
- super(timeline);
- this.processTime = processTime > 0 ? processTime : 1;
- }
-
- @Override
- public void update(ReadEnd initiator, BitVector oldValues)
- {
- timeline.addEvent(e -> compute(), processTime);
- }
-
- protected abstract void compute();
-}
+package net.mograsim.logic.core.components;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\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 extends Component implements LogicObserver\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(Timeline timeline, int processTime)\r
+ {\r
+ super(timeline);\r
+ this.processTime = processTime > 0 ? processTime : 1;\r
+ }\r
+\r
+ @Override\r
+ public void update(LogicObservable initiator)\r
+ {\r
+ timeline.addEvent(e -> compute(), processTime);\r
+ }\r
+\r
+ protected abstract void compute();\r
+}\r
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class BitDisplay extends BasicComponent
-{
- private final ReadEnd in;
- private BitVector displayedValue;
-
- public BitDisplay(Timeline timeline, ReadEnd in)
- {
- super(timeline, 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<ReadEnd> getAllInputs()
- {
- return List.of(in);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of();
- }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.types.BitVector;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class BitDisplay extends BasicComponent\r
+{\r
+ private final ReadEnd in;\r
+ private BitVector displayedValue;\r
+\r
+ public BitDisplay(Timeline timeline, ReadEnd in)\r
+ {\r
+ super(timeline, 1);\r
+ this.in = in;\r
+ in.registerObserver(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 net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.WireObserver;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class Connector extends Component implements WireObserver
-{
- private boolean connected;
- private final ReadWriteEnd a;
- private final ReadWriteEnd b;
-
- public Connector(Timeline timeline, ReadWriteEnd a, ReadWriteEnd b)
- {
- super(timeline);
- 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);
- update(b);
- }
-
- public void disconnect()
- {
- connected = false;
- a.clearSignals();
- b.clearSignals();
- }
-
- public void setConnection(boolean connected)
- {
- if (connected)
- connect();
- else
- disconnect();
- }
-
- @Override
- public void update(ReadEnd initiator, BitVector oldValues)
- {
- if (connected)
- timeline.addEvent(e -> update(initiator), 1);
- }
-
- private void update(ReadEnd initiator)
- {
- if (initiator == a)
- b.feedSignals(a.wireValuesExcludingMe());
- else
- a.feedSignals(b.wireValuesExcludingMe());
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(a, b);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(a, b);
- }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class Connector extends Component implements LogicObserver\r
+{\r
+ private boolean connected;\r
+ private final ReadWriteEnd a;\r
+ private final ReadWriteEnd b;\r
+\r
+ public Connector(Timeline timeline, ReadWriteEnd a, ReadWriteEnd b)\r
+ {\r
+ super(timeline);\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.registerObserver(this);\r
+ b.registerObserver(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(LogicObservable initiator)\r
+ {\r
+ if (connected)\r
+ timeline.addEvent(e -> innerUpdate(initiator), 1);\r
+ }\r
+\r
+ private void innerUpdate(LogicObservable 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
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.Wire;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-/**
- * 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 Demux extends BasicComponent
-{
- private final ReadEnd select, in;
- private final ReadWriteEnd[] outputs;
- private final int outputSize;
- private int selected = -1;
-
- /**
- * Output {@link Wire}s and in must be of uniform length
- *
- * @param in Must be of uniform length with all outputs.
- * @param select Indexes the output array to which the input is mapped. Must have enough bits to index all outputs.
- * @param outputs One of these outputs receives the input signal, depending on the select bits
- */
- public Demux(Timeline timeline, int processTime, ReadEnd in, ReadEnd select, ReadWriteEnd... outputs)
- {
- super(timeline, processTime);
- outputSize = in.length();
-
- this.in = in;
- this.outputs = outputs;
- for (int i = 0; i < this.outputs.length; i++)
- {
- if (outputs[i].length() != outputSize)
- throw new IllegalArgumentException("All DEMUX wire arrays must be of uniform length!");
- this.outputs[i] = outputs[i];
- }
-
- this.select = select;
- select.addObserver(this);
-
- int maxInputs = 1 << select.length();
- if (this.outputs.length > maxInputs)
- throw new IllegalArgumentException("There are more outputs (" + this.outputs.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 >= outputs.length)
- selectValue = -1;
-
- if (selected != selectValue && selected != -1)
- outputs[selected].clearSignals();
-
- selected = selectValue;
-
- if (selectValue != -1)
- outputs[selectValue].feedSignals(in.getValues());
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(in, select);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(outputs);
- }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.wires.Wire;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.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 Demux extends BasicComponent\r
+{\r
+ private final ReadEnd select, in;\r
+ private final ReadWriteEnd[] outputs;\r
+ private final int outputSize;\r
+ private int selected = -1;\r
+\r
+ /**\r
+ * Output {@link Wire}s and in must be of uniform length\r
+ * \r
+ * @param in Must be of uniform length with all outputs.\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(Timeline timeline, int processTime, ReadEnd in, ReadEnd select, ReadWriteEnd... outputs)\r
+ {\r
+ super(timeline, processTime);\r
+ outputSize = in.length();\r
+\r
+ this.in = in;\r
+ this.outputs = outputs;\r
+ for (int i = 0; i < this.outputs.length; i++)\r
+ {\r
+ if (outputs[i].length() != outputSize)\r
+ throw new IllegalArgumentException("All DEMUX wire arrays must be of uniform length!");\r
+ this.outputs[i] = outputs[i];\r
+ }\r
+\r
+ this.select = select;\r
+ select.registerObserver(this);\r
+\r
+ int maxInputs = 1 << select.length();\r
+ if (this.outputs.length > maxInputs)\r
+ throw new IllegalArgumentException("There are more outputs (" + this.outputs.length + ") to the DEMUX than supported by "\r
+ + select.length() + " select bits (" + maxInputs + ").");\r
+ in.registerObserver(this);\r
+ }\r
+\r
+ @Override\r
+ public void compute()\r
+ {\r
+ int selectValue = select.hasNumericValue() ? (int) select.getUnsignedValue() : -1;\r
+ if (selectValue >= outputs.length)\r
+ selectValue = -1;\r
+\r
+ if (selected != selectValue && selected != -1)\r
+ outputs[selected].clearSignals();\r
+\r
+ selected = selectValue;\r
+\r
+ if (selectValue != -1)\r
+ outputs[selectValue].feedSignals(in.getValues());\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of(in, select);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(outputs);\r
+ }\r
+}\r
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire;
-import net.mograsim.logic.core.wires.WireObserver;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class Merger extends Component implements WireObserver
-{
- private ReadWriteEnd out;
- private ReadEnd[] 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(Timeline timeline, ReadWriteEnd union, ReadEnd... inputs)
- {
- super(timeline);
- 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 ReadEnd getInput(int index)
- {
- return inputs[index];
- }
-
- public ReadEnd getUnion()
- {
- return out;
- }
-
- @Override
- public void update(ReadEnd initiator, BitVector oldValues)
- {
- int index = find(initiator);
- int beginning = beginningIndex[index];
- out.feedSignals(beginning, inputs[index].getValues());
- }
-
- private int find(ReadEnd r)
- {
- for (int i = 0; i < inputs.length; i++)
- if (inputs[i] == r)
- return i;
- return -1;
- }
-
- public ReadEnd[] getInputs()
- {
- return inputs.clone();
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(inputs);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(out);
- }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.wires.Wire;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class Merger extends Component implements LogicObserver\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(Timeline timeline, ReadWriteEnd union, ReadEnd... inputs)\r
+ {\r
+ super(timeline);\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].registerObserver(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(LogicObservable initiator)\r
+ {\r
+ int index = find(initiator);\r
+ int beginning = beginningIndex[index];\r
+ out.feedSignals(beginning, inputs[index].getValues());\r
+ }\r
+\r
+ private int find(LogicObservable 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
{
if (inputs[i].length() != outputSize)
throw new IllegalArgumentException("All MUX wire arrays must be of uniform length!");
- inputs[i].addObserver(this);
+ inputs[i].registerObserver(this);
}
this.select = select;
- select.addObserver(this);
+ select.registerObserver(this);
int maxInputs = 1 << select.length();
if (this.inputs.length > maxInputs)
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.WireObserver;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class Splitter extends Component implements WireObserver
-{
- private ReadEnd input;
- private ReadWriteEnd[] outputs;
-
- public Splitter(Timeline timeline, ReadEnd input, ReadWriteEnd... outputs)
- {
- super(timeline);
- this.input = input;
- this.outputs = outputs;
- input.addObserver(this);
- int length = 0;
- for (ReadEnd 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(ReadEnd initiator, BitVector oldValues)
- {
- compute();
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(input);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(outputs);
- }
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.BitVector;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class Splitter extends Component implements LogicObserver\r
+{\r
+ private ReadEnd input;\r
+ private ReadWriteEnd[] outputs;\r
+\r
+ public Splitter(Timeline timeline, ReadEnd input, ReadWriteEnd... outputs)\r
+ {\r
+ super(timeline);\r
+ this.input = input;\r
+ this.outputs = outputs;\r
+ input.registerObserver(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(LogicObservable initiator)\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
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class TriStateBuffer extends BasicComponent
-{
- ReadEnd in, enable;
- ReadWriteEnd out;
-
- public TriStateBuffer(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out, ReadEnd enable)
- {
- super(timeline, processTime);
- if (in.length() != out.length())
- throw new IllegalArgumentException(
- "Tri-state output must have the same amount of bits as the input. Input: " + in.length() + " Output: " + out.length());
- if (enable.length() != 1)
- throw new IllegalArgumentException("Tri-state enable must have exactly one bit, not " + enable.length() + ".");
- this.in = in;
- in.addObserver(this);
- this.enable = enable;
- enable.addObserver(this);
- this.out = out;
- }
-
- @Override
- protected void compute()
- {
- if (enable.getValue() == Bit.ONE)
- out.feedSignals(in.getValues());
- else
- out.clearSignals();
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(in, enable);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(out);
- }
-
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class TriStateBuffer extends BasicComponent\r
+{\r
+ ReadEnd in, enable;\r
+ ReadWriteEnd out;\r
+\r
+ public TriStateBuffer(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out, ReadEnd enable)\r
+ {\r
+ super(timeline, processTime);\r
+ if (in.length() != out.length())\r
+ throw new IllegalArgumentException(\r
+ "Tri-state output must have the same amount of bits as the input. Input: " + in.length() + " Output: " + out.length());\r
+ if (enable.length() != 1)\r
+ throw new IllegalArgumentException("Tri-state enable must have exactly one bit, not " + enable.length() + ".");\r
+ this.in = in;\r
+ in.registerObserver(this);\r
+ this.enable = enable;\r
+ enable.registerObserver(this);\r
+ this.out = out;\r
+ }\r
+\r
+ @Override\r
+ protected void compute()\r
+ {\r
+ if (enable.getValue() == Bit.ONE)\r
+ out.feedSignals(in.getValues());\r
+ else\r
+ out.clearSignals();\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of(in, enable);\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(out);\r
+ }\r
+\r
+}\r
-package net.mograsim.logic.core.components.gates;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.MutationOperation;
-import net.mograsim.logic.core.types.BitVector.BitVectorMutator;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public abstract class MultiInputGate extends BasicComponent
-{
- protected ReadEnd[] in;
- protected ReadWriteEnd out;
- protected final int length;
- protected MutationOperation op;
-
- protected MultiInputGate(Timeline timeline, int processTime, MutationOperation op, ReadWriteEnd out, ReadEnd... in)
- {
- super(timeline, processTime);
- this.op = op;
- length = out.length();
- this.in = in.clone();
- if (in.length < 1)
- throw new IllegalArgumentException(String.format("Cannot create gate with %d wires.", in.length));
- for (ReadEnd w : in)
- {
- if (w.length() != length)
- throw new IllegalArgumentException("All wires connected to the gate must be of uniform length.");
- w.addObserver(this);
- }
- this.out = out;
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(in);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(out);
- }
-
- @Override
- protected void compute()
- {
- BitVectorMutator mutator = BitVectorMutator.empty();
- for (ReadEnd w : in)
- op.apply(mutator, w.getValues());
- out.feedSignals(mutator.get());
- }
-}
+package net.mograsim.logic.core.components.gates;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.components.BasicComponent;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.MutationOperation;\r
+import net.mograsim.logic.core.types.BitVector.BitVectorMutator;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public abstract class MultiInputGate extends BasicComponent\r
+{\r
+ protected ReadEnd[] in;\r
+ protected ReadWriteEnd out;\r
+ protected final int length;\r
+ protected MutationOperation op;\r
+\r
+ protected MultiInputGate(Timeline timeline, int processTime, MutationOperation op, ReadWriteEnd out, ReadEnd... in)\r
+ {\r
+ super(timeline, processTime);\r
+ this.op = op;\r
+ length = out.length();\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 (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
+ w.registerObserver(this);\r
+ }\r
+ this.out = 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
+ @Override\r
+ protected void compute()\r
+ {\r
+ BitVectorMutator mutator = BitVectorMutator.empty();\r
+ for (ReadEnd w : in)\r
+ op.apply(mutator, w.getValues());\r
+ out.feedSignals(mutator.get());\r
+ }\r
+}\r
-package net.mograsim.logic.core.components.gates;
-
-import java.util.List;
-
-import net.mograsim.logic.core.components.BasicComponent;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-public class NotGate extends BasicComponent
-{
- private ReadEnd in;
- private ReadWriteEnd out;
-
- public NotGate(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out)
- {
- super(timeline, processTime);
- this.in = in;
- in.addObserver(this);
- this.out = out;
- }
-
- @Override
- protected void compute()
- {
- out.feedSignals(in.getValues().not());
- }
-
- public ReadEnd getIn()
- {
- return in;
- }
-
- public ReadEnd getOut()
- {
- return out;
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of(in);
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(out);
- }
-}
+package net.mograsim.logic.core.components.gates;\r
+\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.components.BasicComponent;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+public class NotGate extends BasicComponent\r
+{\r
+ private ReadEnd in;\r
+ private ReadWriteEnd out;\r
+\r
+ public NotGate(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out)\r
+ {\r
+ super(timeline, processTime);\r
+ this.in = in;\r
+ in.registerObserver(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 net.mograsim.logic.core.tests;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.util.function.LongConsumer;
-
-import org.junit.jupiter.api.Test;
-
-import net.mograsim.logic.core.components.Connector;
-import net.mograsim.logic.core.components.Demux;
-import net.mograsim.logic.core.components.Merger;
-import net.mograsim.logic.core.components.Mux;
-import net.mograsim.logic.core.components.Splitter;
-import net.mograsim.logic.core.components.TriStateBuffer;
-import net.mograsim.logic.core.components.gates.AndGate;
-import net.mograsim.logic.core.components.gates.NotGate;
-import net.mograsim.logic.core.components.gates.OrGate;
-import net.mograsim.logic.core.components.gates.XorGate;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-class ComponentTest
-{
- private Timeline t = new Timeline(11);
-
- @Test
- void circuitExampleTest()
- {
- Wire a = new Wire(t, 1, 1), b = new Wire(t, 1, 1), c = new Wire(t, 1, 10), d = new Wire(t, 2, 1), e = new Wire(t, 1, 1),
- f = new Wire(t, 1, 1), g = new Wire(t, 1, 1), h = new Wire(t, 2, 1), i = new Wire(t, 2, 1), j = new Wire(t, 1, 1),
- k = new Wire(t, 1, 1);
- new AndGate(t, 1, f.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
- new NotGate(t, 1, f.createReadOnlyEnd(), g.createReadWriteEnd());
- new Merger(t, h.createReadWriteEnd(), c.createReadOnlyEnd(), g.createReadOnlyEnd());
- new Mux(t, 1, i.createReadWriteEnd(), e.createReadOnlyEnd(), h.createReadOnlyEnd(), d.createReadOnlyEnd());
- new Splitter(t, i.createReadOnlyEnd(), k.createReadWriteEnd(), j.createReadWriteEnd());
-
- a.createReadWriteEnd().feedSignals(Bit.ZERO);
- b.createReadWriteEnd().feedSignals(Bit.ONE);
- c.createReadWriteEnd().feedSignals(Bit.ZERO);
- d.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE);
- e.createReadWriteEnd().feedSignals(Bit.ZERO);
-
- t.executeAll();
-
- assertEquals(Bit.ONE, j.getValue());
- assertEquals(Bit.ZERO, k.getValue());
- }
-
- @Test
- void splitterTest()
- {
- t.reset();
- Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), in = new Wire(t, 8, 1);
- in.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
- new Splitter(t, in.createReadOnlyEnd(), a.createReadWriteEnd(), b.createReadWriteEnd(), c.createReadWriteEnd());
-
- t.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()
- {
- t.reset();
- Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), out = new Wire(t, 8, 1);
- a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);
- b.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO);
- c.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
- new Merger(t, out.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
-
- t.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(t, 1, 1), b = new Wire(t, 1, 1), en = new Wire(t, 1, 1), notEn = new Wire(t, 1, 1);
- new NotGate(t, 1, en.createReadOnlyEnd(), notEn.createReadWriteEnd());
- new TriStateBuffer(t, 1, a.createReadOnlyEnd(), b.createReadWriteEnd(), en.createReadOnlyEnd());
- new TriStateBuffer(t, 1, b.createReadOnlyEnd(), a.createReadWriteEnd(), notEn.createReadOnlyEnd());
-
- ReadWriteEnd enI = en.createReadWriteEnd(), aI = a.createReadWriteEnd(), bI = b.createReadWriteEnd();
- enI.feedSignals(Bit.ONE);
- aI.feedSignals(Bit.ONE);
- bI.feedSignals(Bit.Z);
-
- t.executeAll();
-
- assertEquals(Bit.ONE, b.getValue());
-
- bI.feedSignals(Bit.ZERO);
-
- t.executeAll();
-
- assertEquals(Bit.X, b.getValue());
- assertEquals(Bit.ONE, a.getValue());
-
- aI.clearSignals();
- enI.feedSignals(Bit.ZERO);
-
- t.executeAll();
-
- assertEquals(Bit.ZERO, a.getValue());
-
- }
-
- @Test
- void muxTest()
- {
- t.reset();
- Wire a = new Wire(t, 4, 3), b = new Wire(t, 4, 6), c = new Wire(t, 4, 4), select = new Wire(t, 2, 5), out = new Wire(t, 4, 1);
- ReadWriteEnd selectIn = select.createReadWriteEnd();
-
- selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
- a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
- c.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- new Mux(t, 1, out.createReadWriteEnd(), select.createReadOnlyEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(),
- c.createReadOnlyEnd());
- t.executeAll();
-
- assertBitArrayEquals(out.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
- selectIn.feedSignals(Bit.ZERO, Bit.ONE);
- t.executeAll();
-
- assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- selectIn.feedSignals(Bit.ONE, Bit.ONE);
- t.executeAll();
-
- assertBitArrayEquals(out.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
-
- }
-
- @Test
- void demuxTest()
- {
- t.reset();
- Wire a = new Wire(t, 4, 3), b = new Wire(t, 4, 6), c = new Wire(t, 4, 4), select = new Wire(t, 2, 5), in = new Wire(t, 4, 1);
- ReadWriteEnd selectIn = select.createReadWriteEnd();
-
- selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
- in.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
-
- new Demux(t, 1, in.createReadOnlyEnd(), select.createReadOnlyEnd(), a.createReadWriteEnd(), b.createReadWriteEnd(),
- c.createReadWriteEnd());
- t.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);
- t.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);
- t.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()
- {
- t.reset();
- Wire a = new Wire(t, 4, 1), b = new Wire(t, 4, 3), c = new Wire(t, 4, 1);
- new AndGate(t, 1, c.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
- a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
- b.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- t.executeAll();
-
- assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);
- }
-
- @Test
- void orTest()
- {
- t.reset();
- Wire a = new Wire(t, 4, 1), b = new Wire(t, 4, 3), c = new Wire(t, 4, 1);
- new OrGate(t, 1, c.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());
- a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
- b.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- t.executeAll();
-
- assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);
- }
-
- @Test
- void xorTest()
- {
- t.reset();
- Wire a = new Wire(t, 3, 1), b = new Wire(t, 3, 2), c = new Wire(t, 3, 1), d = new Wire(t, 3, 1);
- new XorGate(t, 1, d.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());
- a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
- b.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
- c.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
- t.executeAll();
-
- assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);
- }
-
- @Test
- void notTest()
- {
- t.reset();
- Wire a = new Wire(t, 3, 1), b = new Wire(t, 3, 2);
- new NotGate(t, 1, a.createReadOnlyEnd(), b.createReadWriteEnd());
- a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
-
- t.executeAll();
-
- assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO, Bit.ZERO);
- }
-
- @Test
- void rsLatchCircuitTest()
- {
- t.reset();
- Wire r = new Wire(t, 1, 1), s = new Wire(t, 1, 1), t1 = new Wire(t, 1, 15), t2 = new Wire(t, 1, 1), q = new Wire(t, 1, 1),
- nq = new Wire(t, 1, 1);
-
- new OrGate(t, 1, t2.createReadWriteEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd());
- new OrGate(t, 1, t1.createReadWriteEnd(), s.createReadOnlyEnd(), q.createReadOnlyEnd());
- new NotGate(t, 1, t2.createReadOnlyEnd(), q.createReadWriteEnd());
- new NotGate(t, 1, t1.createReadOnlyEnd(), nq.createReadWriteEnd());
-
- ReadWriteEnd sIn = s.createReadWriteEnd(), rIn = r.createReadWriteEnd();
-
- sIn.feedSignals(Bit.ONE);
- rIn.feedSignals(Bit.ZERO);
-
- t.executeAll();
-
- assertEquals(Bit.ONE, q.getValue());
- assertEquals(Bit.ZERO, nq.getValue());
-
- sIn.feedSignals(Bit.ZERO);
-
- t.executeAll();
- assertEquals(Bit.ONE, q.getValue());
- assertEquals(Bit.ZERO, nq.getValue());
-
- rIn.feedSignals(Bit.ONE);
-
- t.executeAll();
-
- assertEquals(Bit.ZERO, q.getValue());
- assertEquals(Bit.ONE, nq.getValue());
- }
-
- @Test
- void numericValueTest()
- {
- t.reset();
-
- Wire a = new Wire(t, 4, 1);
- a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);
-
- t.executeAll();
-
- assertEquals(15, a.getUnsignedValue());
- assertEquals(-1, a.getSignedValue());
- }
-
- boolean flag = false;
-
- @Test
- void simpleTimelineTest()
- {
- Timeline t = new Timeline(3);
- flag = false;
- t.addEvent((e) ->
- {
- if (!flag)
- fail();
- flag = false;
- }, 15);
- t.addEvent((e) ->
- {
- if (flag)
- fail();
- flag = true;
- }, 10);
- t.addEvent((e) ->
- {
- if (flag)
- fail();
- flag = true;
- }, 20);
- t.addEvent((e) ->
- {
- fail("Only supposed to execute until timestamp 20, not 25");
- }, 25);
-
- t.executeUntil(t.laterThan(20), 100);
-
- if (!flag)
- fail();
- }
-
- @Test
- void multipleInputs()
- {
- t.reset();
- Wire w = new Wire(t, 2, 1);
- ReadWriteEnd wI1 = w.createReadWriteEnd(), wI2 = w.createReadWriteEnd();
- wI1.feedSignals(Bit.ONE, Bit.Z);
- wI2.feedSignals(Bit.Z, Bit.X);
- t.executeAll();
- assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.X);
-
- wI2.feedSignals(Bit.ZERO, Bit.Z);
- t.executeAll();
- assertBitArrayEquals(w.getValues(), Bit.X, Bit.Z);
-
- wI2.feedSignals(Bit.Z, Bit.Z);
- t.executeAll();
- assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
-
- wI2.feedSignals(Bit.ONE, Bit.Z);
- ReadEnd rE = w.createReadOnlyEnd();
- rE.addObserver((i, oldValues) -> fail("WireEnd notified observer, although value did not change."));
- t.executeAll();
- rE.close();
- wI1.feedSignals(Bit.X, Bit.X);
- t.executeAll();
- wI1.addObserver((i, oldValues) -> fail("WireEnd notified observer, although it was closed."));
- wI1.close();
- assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
- }
-
- @Test
- void wireConnections()
- {
- // Nur ein Experiment, was über mehrere 'passive' Bausteine hinweg passieren würde
-
- t.reset();
-
- Wire a = new Wire(t, 1, 2);
- Wire b = new Wire(t, 1, 2);
- Wire c = new Wire(t, 1, 2);
- ReadWriteEnd aI = a.createReadWriteEnd();
- ReadWriteEnd bI = b.createReadWriteEnd();
- ReadWriteEnd cI = c.createReadWriteEnd();
-
- TestBitDisplay test = new TestBitDisplay(t, c.createReadOnlyEnd());
- TestBitDisplay test2 = new TestBitDisplay(t, 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(t, b.createReadWriteEnd(), c.createReadWriteEnd()).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(t, a.createReadWriteEnd(), b.createReadWriteEnd()).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 net.mograsim.logic.core.tests;\r
+\r
+import static org.junit.Assert.assertTrue;\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 net.mograsim.logic.core.components.Connector;\r
+import net.mograsim.logic.core.components.Demux;\r
+import net.mograsim.logic.core.components.Merger;\r
+import net.mograsim.logic.core.components.Mux;\r
+import net.mograsim.logic.core.components.Splitter;\r
+import net.mograsim.logic.core.components.TriStateBuffer;\r
+import net.mograsim.logic.core.components.gates.AndGate;\r
+import net.mograsim.logic.core.components.gates.NotGate;\r
+import net.mograsim.logic.core.components.gates.OrGate;\r
+import net.mograsim.logic.core.components.gates.XorGate;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.types.BitVector;\r
+import net.mograsim.logic.core.wires.Wire;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+class ComponentTest\r
+{\r
+ private Timeline t = new Timeline(11);\r
+\r
+ @Test\r
+ void circuitExampleTest()\r
+ {\r
+ Wire a = new Wire(t, 1, 1), b = new Wire(t, 1, 1), c = new Wire(t, 1, 10), d = new Wire(t, 2, 1), e = new Wire(t, 1, 1),\r
+ f = new Wire(t, 1, 1), g = new Wire(t, 1, 1), h = new Wire(t, 2, 1), i = new Wire(t, 2, 1), j = new Wire(t, 1, 1),\r
+ k = new Wire(t, 1, 1);\r
+ new AndGate(t, 1, f.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+ new NotGate(t, 1, f.createReadOnlyEnd(), g.createReadWriteEnd());\r
+ new Merger(t, h.createReadWriteEnd(), c.createReadOnlyEnd(), g.createReadOnlyEnd());\r
+ new Mux(t, 1, i.createReadWriteEnd(), e.createReadOnlyEnd(), h.createReadOnlyEnd(), d.createReadOnlyEnd());\r
+ new Splitter(t, i.createReadOnlyEnd(), k.createReadWriteEnd(), j.createReadWriteEnd());\r
+\r
+ a.createReadWriteEnd().feedSignals(Bit.ZERO);\r
+ b.createReadWriteEnd().feedSignals(Bit.ONE);\r
+ c.createReadWriteEnd().feedSignals(Bit.ZERO);\r
+ d.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE);\r
+ e.createReadWriteEnd().feedSignals(Bit.ZERO);\r
+\r
+ t.executeAll();\r
+\r
+ assertEquals(Bit.ONE, j.getValue());\r
+ assertEquals(Bit.ZERO, k.getValue());\r
+ }\r
+\r
+ @Test\r
+ void splitterTest()\r
+ {\r
+ t.reset();\r
+ Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), in = new Wire(t, 8, 1);\r
+ in.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+ new Splitter(t, in.createReadOnlyEnd(), a.createReadWriteEnd(), b.createReadWriteEnd(), c.createReadWriteEnd());\r
+\r
+ t.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
+ t.reset();\r
+ Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), out = new Wire(t, 8, 1);\r
+ a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+ b.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO);\r
+ c.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ new Merger(t, out.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+\r
+ t.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(t, 1, 1), b = new Wire(t, 1, 1), en = new Wire(t, 1, 1), notEn = new Wire(t, 1, 1);\r
+ new NotGate(t, 1, en.createReadOnlyEnd(), notEn.createReadWriteEnd());\r
+ new TriStateBuffer(t, 1, a.createReadOnlyEnd(), b.createReadWriteEnd(), en.createReadOnlyEnd());\r
+ new TriStateBuffer(t, 1, b.createReadOnlyEnd(), a.createReadWriteEnd(), notEn.createReadOnlyEnd());\r
+\r
+ ReadWriteEnd enI = en.createReadWriteEnd(), aI = a.createReadWriteEnd(), bI = b.createReadWriteEnd();\r
+ enI.feedSignals(Bit.ONE);\r
+ aI.feedSignals(Bit.ONE);\r
+ bI.feedSignals(Bit.Z);\r
+\r
+ t.executeAll();\r
+\r
+ assertEquals(Bit.ONE, b.getValue());\r
+\r
+ bI.feedSignals(Bit.ZERO);\r
+\r
+ t.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
+ t.executeAll();\r
+\r
+ assertEquals(Bit.ZERO, a.getValue());\r
+\r
+ }\r
+\r
+ @Test\r
+ void muxTest()\r
+ {\r
+ t.reset();\r
+ Wire a = new Wire(t, 4, 3), b = new Wire(t, 4, 6), c = new Wire(t, 4, 4), select = new Wire(t, 2, 5), out = new Wire(t, 4, 1);\r
+ ReadWriteEnd selectIn = select.createReadWriteEnd();\r
+\r
+ selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+ a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+ c.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ new Mux(t, 1, out.createReadWriteEnd(), select.createReadOnlyEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(),\r
+ c.createReadOnlyEnd());\r
+ t.executeAll();\r
+\r
+ assertBitArrayEquals(out.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+ selectIn.feedSignals(Bit.ZERO, Bit.ONE);\r
+ t.executeAll();\r
+\r
+ assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ selectIn.feedSignals(Bit.ONE, Bit.ONE);\r
+ t.executeAll();\r
+\r
+ assertBitArrayEquals(out.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);\r
+\r
+ }\r
+\r
+ @Test\r
+ void demuxTest()\r
+ {\r
+ t.reset();\r
+ Wire a = new Wire(t, 4, 3), b = new Wire(t, 4, 6), c = new Wire(t, 4, 4), select = new Wire(t, 2, 5), in = new Wire(t, 4, 1);\r
+ ReadWriteEnd selectIn = select.createReadWriteEnd();\r
+\r
+ selectIn.feedSignals(Bit.ZERO, Bit.ZERO);\r
+ in.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);\r
+\r
+ new Demux(t, 1, in.createReadOnlyEnd(), select.createReadOnlyEnd(), a.createReadWriteEnd(), b.createReadWriteEnd(),\r
+ c.createReadWriteEnd());\r
+ t.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
+ t.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
+ t.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
+ t.reset();\r
+ Wire a = new Wire(t, 4, 1), b = new Wire(t, 4, 3), c = new Wire(t, 4, 1);\r
+ new AndGate(t, 1, c.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+ a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+ b.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ t.executeAll();\r
+\r
+ assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+ }\r
+\r
+ @Test\r
+ void orTest()\r
+ {\r
+ t.reset();\r
+ Wire a = new Wire(t, 4, 1), b = new Wire(t, 4, 3), c = new Wire(t, 4, 1);\r
+ new OrGate(t, 1, c.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd());\r
+ a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+ b.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ t.executeAll();\r
+\r
+ assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);\r
+ }\r
+\r
+ @Test\r
+ void xorTest()\r
+ {\r
+ t.reset();\r
+ Wire a = new Wire(t, 3, 1), b = new Wire(t, 3, 2), c = new Wire(t, 3, 1), d = new Wire(t, 3, 1);\r
+ new XorGate(t, 1, d.createReadWriteEnd(), a.createReadOnlyEnd(), b.createReadOnlyEnd(), c.createReadOnlyEnd());\r
+ a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);\r
+ b.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+ c.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);\r
+\r
+ t.executeAll();\r
+\r
+ assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);\r
+ }\r
+\r
+ @Test\r
+ void notTest()\r
+ {\r
+ t.reset();\r
+ Wire a = new Wire(t, 3, 1), b = new Wire(t, 3, 2);\r
+ new NotGate(t, 1, a.createReadOnlyEnd(), b.createReadWriteEnd());\r
+ a.createReadWriteEnd().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);\r
+\r
+ t.executeAll();\r
+\r
+ assertBitArrayEquals(b.getValues(), Bit.ONE, Bit.ZERO, Bit.ZERO);\r
+ }\r
+\r
+ @Test\r
+ void rsLatchCircuitTest()\r
+ {\r
+ t.reset();\r
+ Wire r = new Wire(t, 1, 1), s = new Wire(t, 1, 1), t1 = new Wire(t, 1, 15), t2 = new Wire(t, 1, 1), q = new Wire(t, 1, 1),\r
+ nq = new Wire(t, 1, 1);\r
+\r
+ new OrGate(t, 1, t2.createReadWriteEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd());\r
+ new OrGate(t, 1, t1.createReadWriteEnd(), s.createReadOnlyEnd(), q.createReadOnlyEnd());\r
+ new NotGate(t, 1, t2.createReadOnlyEnd(), q.createReadWriteEnd());\r
+ new NotGate(t, 1, t1.createReadOnlyEnd(), nq.createReadWriteEnd());\r
+\r
+ ReadWriteEnd sIn = s.createReadWriteEnd(), rIn = r.createReadWriteEnd();\r
+\r
+ sIn.feedSignals(Bit.ONE);\r
+ rIn.feedSignals(Bit.ZERO);\r
+\r
+ t.executeAll();\r
+\r
+ assertEquals(Bit.ONE, q.getValue());\r
+ assertEquals(Bit.ZERO, nq.getValue());\r
+\r
+ sIn.feedSignals(Bit.ZERO);\r
+\r
+ t.executeAll();\r
+ assertEquals(Bit.ONE, q.getValue());\r
+ assertEquals(Bit.ZERO, nq.getValue());\r
+\r
+ rIn.feedSignals(Bit.ONE);\r
+\r
+ t.executeAll();\r
+\r
+ assertEquals(Bit.ZERO, q.getValue());\r
+ assertEquals(Bit.ONE, nq.getValue());\r
+ }\r
+\r
+ @Test\r
+ void numericValueTest()\r
+ {\r
+ t.reset();\r
+\r
+ Wire a = new Wire(t, 4, 1);\r
+ a.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);\r
+\r
+ t.executeAll();\r
+\r
+ assertEquals(15, a.getUnsignedValue());\r
+ assertEquals(-1, a.getSignedValue());\r
+ }\r
+\r
+ boolean flag = false;\r
+\r
+ @Test\r
+ void simpleTimelineTest()\r
+ {\r
+ Timeline t = new Timeline(3);\r
+ flag = false;\r
+ t.addEvent((e) ->\r
+ {\r
+ if (!flag)\r
+ fail("Events executed out of order!");\r
+ flag = false;\r
+ }, 15);\r
+ t.addEvent((e) ->\r
+ {\r
+ if (flag)\r
+ fail("Events executed out of order!");\r
+ flag = true;\r
+ }, 10);\r
+ t.addEvent((e) ->\r
+ {\r
+ if (flag)\r
+ fail("Events executed out of order!");\r
+ flag = true;\r
+ }, 20);\r
+ t.addEvent((e) ->\r
+ {\r
+ fail("Only supposed to execute until timestamp 20, not 25");\r
+ }, 25);\r
+\r
+ t.executeUntil(t.laterThan(20), 100);\r
+\r
+ if (!flag)\r
+ fail("Not all events were executed in order!");\r
+ }\r
+\r
+ @Test\r
+ void multipleInputs()\r
+ {\r
+ t.reset();\r
+ Wire w = new Wire(t, 2, 1);\r
+ ReadWriteEnd wI1 = w.createReadWriteEnd(), wI2 = w.createReadWriteEnd();\r
+ wI1.feedSignals(Bit.ONE, Bit.Z);\r
+ wI2.feedSignals(Bit.Z, Bit.X);\r
+ t.executeAll();\r
+ assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.X);\r
+\r
+ wI2.feedSignals(Bit.ZERO, Bit.Z);\r
+ t.executeAll();\r
+ assertBitArrayEquals(w.getValues(), Bit.X, Bit.Z);\r
+\r
+ wI2.feedSignals(Bit.Z, Bit.Z);\r
+ t.executeAll();\r
+ assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);\r
+\r
+ wI2.feedSignals(Bit.ONE, Bit.Z);\r
+ ReadEnd rE = w.createReadOnlyEnd();\r
+ rE.registerObserver((i) -> fail("WireEnd notified observer, although value did not change."));\r
+ t.executeAll();\r
+ rE.close();\r
+ wI1.feedSignals(Bit.X, Bit.X);\r
+ t.executeAll();\r
+ wI1.registerObserver((i) -> 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
+ t.reset();\r
+\r
+ Wire a = new Wire(t, 1, 2);\r
+ Wire b = new Wire(t, 1, 2);\r
+ Wire c = new Wire(t, 1, 2);\r
+ ReadWriteEnd aI = a.createReadWriteEnd();\r
+ ReadWriteEnd bI = b.createReadWriteEnd();\r
+ ReadWriteEnd cI = c.createReadWriteEnd();\r
+\r
+ TestBitDisplay test = new TestBitDisplay(t, c.createReadOnlyEnd());\r
+ TestBitDisplay test2 = new TestBitDisplay(t, 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(t, b.createReadWriteEnd(), c.createReadWriteEnd()).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(t, a.createReadWriteEnd(), b.createReadWriteEnd()).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 net.mograsim.logic.core.wires;
-
-import static net.mograsim.logic.core.types.Bit.U;
-import static net.mograsim.logic.core.types.Bit.Z;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.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<ReadEnd> attached = new ArrayList<ReadEnd>();
- public final int length;
- private List<ReadWriteEnd> inputs = new ArrayList<ReadWriteEnd>();
- private Timeline timeline;
-
- public Wire(Timeline timeline, 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.timeline = timeline;
- 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 (ReadWriteEnd 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;
- 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
- */
- private void attachEnd(ReadEnd end)
- {
- attached.add(end);
- }
-
- private void detachEnd(ReadEnd end)
- {
- attached.remove(end);
- }
-
- private void notifyObservers(BitVector oldValues)
- {
- for (ReadEnd o : attached)
- o.update(oldValues);
- }
-
- /**
- * Create and register a {@link ReadWriteEnd} object, which is tied to this {@link Wire}. This {@link ReadWriteEnd} can be written to.
- */
- public ReadWriteEnd createReadWriteEnd()
- {
- return new ReadWriteEnd();
- }
-
- /**
- * Create a {@link ReadEnd} object, which is tied to this {@link Wire}. This {@link ReadEnd} cannot be written to.
- */
- public ReadEnd createReadOnlyEnd()
- {
- return new ReadEnd();
- }
-
- private void registerInput(ReadWriteEnd toRegister)
- {
- inputs.add(toRegister);
- }
-
- /**
- * A {@link ReadEnd} 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 ReadEnd
- {
- private List<WireObserver> observers = new ArrayList<WireObserver>();
-
- private ReadEnd()
- {
- super();
- Wire.this.attachEnd(this);
- }
-
- public void update(BitVector oldValues)
- {
- for (WireObserver ob : observers)
- ob.update(this, oldValues);
- }
-
- /**
- * 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 Wire.this.toString();
- }
-
- public void close()
- {
- inputs.remove(this);
- detachEnd(this);
- recalculate();
- }
-
- public int length()
- {
- return length;
- }
-
- public boolean addObserver(WireObserver ob)
- {
- return observers.add(ob);
- }
-
- public Wire getWire()
- {
- return Wire.this;
- }
- }
-
- public class ReadWriteEnd extends ReadEnd
- {
- private boolean open;
- private BitVector inputValues;
-
- private ReadWriteEnd()
- {
- super();
- open = true;
- initValues();
- 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.");
- 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.");
- 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 ReadEnd} is currently feeding into the associated {@link Wire}.
- */
- public Bit getInputValue()
- {
- return getInputValue(0);
- }
-
- /**
- * @return The value which the {@link ReadEnd} 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 ReadEnd} 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 ReadEnd} now feeds Z into the associated {@link Wire}.
- */
- public void clearSignals()
- {
- feedSignals(Z.toVector(length));
- }
-
- public BitVector wireValuesExcludingMe()
- {
- BitVectorMutator mutator = BitVectorMutator.empty();
- for (ReadWriteEnd wireEnd : inputs)
- {
- if (wireEnd == this)
- continue;
- mutator.join(wireEnd.inputValues);
- }
- return mutator.get();
- }
-
- @Override
- public String toString()
- {
- return inputValues.toString();
- }
- }
-
- @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 ReadEnd[] extractEnds(Wire[] w)
- {
- ReadEnd[] inputs = new ReadEnd[w.length];
- for (int i = 0; i < w.length; i++)
- inputs[i] = w[i].createReadWriteEnd();
- return inputs;
- }
+package net.mograsim.logic.core.wires;\r
+\r
+import static net.mograsim.logic.core.types.Bit.U;\r
+import static net.mograsim.logic.core.types.Bit.Z;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.types.BitVector;\r
+import net.mograsim.logic.core.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
+ private Timeline timeline;\r
+\r
+ public Wire(Timeline timeline, 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.timeline = timeline;\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 LogicObserver}, who will be notified when the value of the {@link Wire} is updated.\r
+ * \r
+ * @param ob The {@link LogicObserver} to be notified of changes.\r
+ * @return true if the given {@link LogicObserver} 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 createReadWriteEnd()\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 implements LogicObservable\r
+ {\r
+ private List<LogicObserver> observers = new ArrayList<LogicObserver>();\r
+\r
+ private ReadEnd()\r
+ {\r
+ super();\r
+ Wire.this.attachEnd(this);\r
+ }\r
+\r
+ public void update(BitVector oldValues)\r
+ {\r
+ notifyObservers();\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 Wire getWire()\r
+ {\r
+ return Wire.this;\r
+ }\r
+\r
+ @Override\r
+ public void registerObserver(LogicObserver ob)\r
+ {\r
+ observers.add(ob);\r
+ }\r
+\r
+ @Override\r
+ public void notifyObservers()\r
+ {\r
+ for (LogicObserver ob : observers)\r
+ ob.update(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
+ 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
+ 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
+ }\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].createReadWriteEnd();\r
+ return inputs;\r
+ }\r
}
\ No newline at end of file
+++ /dev/null
-package net.mograsim.logic.core.wires;
-
-import net.mograsim.logic.core.types.BitVector;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-
-public interface WireObserver
-{
- public void update(ReadEnd initiator, BitVector oldValues);
-}