import era.mi.logic.timeline.Timeline;
-public class Simulation
-{
+public class Simulation {
public final static Timeline TIMELINE = new Timeline(11);
-
- public static void main(String[] args)
- {
+
+ public static void main(String[] args) {
}
}
\ No newline at end of file
import java.util.Arrays;
-public final class Util
-{
-
- @SuppressWarnings("unchecked")
- public static <T> T[] concat(T[]... arrays)
- {
- if (arrays.length == 0)
- throw new IllegalArgumentException("Cannot concatenate 0 arrays.");
+public final class Util {
- int length = 0;
- for (T[] array : arrays)
- length += array.length;
+ @SuppressWarnings("unchecked")
+ public static <T> T[] concat(T[]... arrays) {
+ if (arrays.length == 0)
+ throw new IllegalArgumentException("Cannot concatenate 0 arrays.");
- T[] newArray = Arrays.copyOf(arrays[0], length);
- int appendIndex = arrays[0].length;
- for (int i = 1; i < arrays.length; i++)
- {
- System.arraycopy(arrays[i], 0, newArray, appendIndex, arrays[i].length);
- appendIndex += arrays[i].length;
- }
+ int length = 0;
+ for (T[] array : arrays)
+ length += array.length;
+
+ T[] newArray = Arrays.copyOf(arrays[0], length);
+ int appendIndex = arrays[0].length;
+ for (int i = 1; i < arrays.length; i++) {
+ System.arraycopy(arrays[i], 0, newArray, appendIndex, arrays[i].length);
+ appendIndex += arrays[i].length;
+ }
- return newArray;
- }
+ return newArray;
+ }
// @SuppressWarnings("unchecked")
// public static <T> T[][] split(T[] array, int... lengths)
// return (T[][]) newArray;
// }
- public static Bit[] and(Bit[] a, Bit[] b)
- {
- return binBitOp(a, b, (bA, bB) -> Bit.and(bA, bB));
- }
+ public static Bit[] and(Bit[] a, Bit[] b) {
+ return binBitOp(a, b, (bA, bB) -> Bit.and(bA, bB));
+ }
- public static Bit[] or(Bit[] a, Bit[] b)
- {
- return binBitOp(a, b, (bA, bB) -> Bit.or(bA, bB));
- }
+ public static Bit[] or(Bit[] a, Bit[] b) {
+ return binBitOp(a, b, (bA, bB) -> Bit.or(bA, bB));
+ }
- public static Bit[] xor(Bit[] a, Bit[] b)
- {
- return binBitOp(a, b, (bA, bB) -> Bit.xor(bA, bB));
- }
+ public static Bit[] xor(Bit[] a, Bit[] b) {
+ return binBitOp(a, b, (bA, bB) -> Bit.xor(bA, bB));
+ }
- private static Bit[] binBitOp(Bit[] a, Bit[] b, BitOp op)
- {
- if (a.length != b.length)
- throw new IllegalArgumentException("Bit Arrays were not of equal length.");
- Bit[] out = new Bit[a.length];
- for (int i = 0; i < a.length; i++)
- {
- out[i] = op.execute(a[i], b[i]);
+ private static Bit[] binBitOp(Bit[] a, Bit[] b, BitOp op) {
+ if (a.length != b.length)
+ throw new IllegalArgumentException("Bit Arrays were not of equal length.");
+ Bit[] out = new Bit[a.length];
+ for (int i = 0; i < a.length; i++) {
+ out[i] = op.execute(a[i], b[i]);
+ }
+ return out;
}
- return out;
- }
- public static Bit[] not(Bit[] a)
- {
- Bit[] out = new Bit[a.length];
- for (int i = 0; i < a.length; i++)
- {
- out[i] = a[i].not();
+ public static Bit[] not(Bit[] a) {
+ Bit[] out = new Bit[a.length];
+ for (int i = 0; i < a.length; i++) {
+ out[i] = a[i].not();
+ }
+ return out;
}
- return out;
- }
-
- /**
- * uses the {@link Bit#combineWith(Bit)} method, does not create a new array,
- * the result is stored in the first array.
- *
- * @author Christian Femers
- */
- public static Bit[] combineInto(Bit[] dest, Bit[] addition)
- {
- if (dest.length != addition.length)
- throw new IllegalArgumentException("Bit Arrays were not of equal length.");
- for (int i = 0; i < addition.length; i++) {
- dest[i] = dest[i].combineWith(addition[i]);
+
+ /**
+ * uses the {@link Bit#combineWith(Bit)} method, does not create a new array, the result is stored in the first array.
+ *
+ * @author Christian Femers
+ */
+ public static Bit[] combineInto(Bit[] dest, Bit[] addition) {
+ if (dest.length != addition.length)
+ throw new IllegalArgumentException("Bit Arrays were not of equal length.");
+ for (int i = 0; i < addition.length; i++) {
+ dest[i] = dest[i].combineWith(addition[i]);
+ }
+ return dest;
}
- return dest;
- }
- interface BitOp
- {
- Bit execute(Bit a, Bit b);
- }
+ interface BitOp {
+ Bit execute(Bit a, Bit b);
+ }
}
/**
* A basic component that recomputes all outputs (with a delay), when it is updated.
+ *
* @author Fabian Stemmler
*/
-public abstract class BasicComponent implements WireArrayObserver, Component
-{
+public abstract class BasicComponent implements WireArrayObserver, 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)
- {
+ public BasicComponent(int processTime) {
this.processTime = processTime > 0 ? processTime : 1;
}
-
+
@Override
- public void update(WireArray initiator, Bit[] oldValues)
- {
- Simulation.TIMELINE.addEvent((e) -> {compute();}, processTime);
+ public void update(WireArray initiator, Bit[] oldValues) {
+ Simulation.TIMELINE.addEvent((e) -> {
+ compute();
+ }, processTime);
}
-
+
protected abstract void compute();
}
import era.mi.logic.Bit;
import era.mi.logic.wires.WireArray;
-public class BitDisplay extends BasicComponent
-{
+public class BitDisplay extends BasicComponent {
private final WireArray in;
private Bit[] displayedValue;
- public BitDisplay(WireArray in)
- {
+ public BitDisplay(WireArray in) {
super(1);
this.in = in;
in.addObserver(this);
}
@Override
- protected void compute()
- {
+ protected void compute() {
displayedValue = in.getValues();
}
- public Bit[] getDisplayedValue()
- {
+ public Bit[] getDisplayedValue() {
return displayedValue;
}
- public boolean isDisplaying(Bit... values)
- {
+ public boolean isDisplaying(Bit... values) {
return Arrays.equals(displayedValue, values);
}
@Override
- public List<WireArray> getAllInputs()
- {
+ public List<WireArray> getAllInputs() {
return Collections.unmodifiableList(Arrays.asList(in));
}
@Override
- public List<WireArray> getAllOutputs()
- {
+ public List<WireArray> getAllOutputs() {
return Collections.unmodifiableList(new ArrayList<WireArray>());
}
}
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
-public class Clock implements TimelineEventHandler, Component
-{
+public class Clock implements TimelineEventHandler, Component {
private boolean toggle = false;
private WireArrayInput outI;
private int delta;
-
+
/**
*
- * @param out {@link WireArray} the clock's impulses are fed into
+ * @param out {@link WireArray} the clock's impulses are fed into
* @param delta ticks between rising and falling edge
*/
- public Clock(WireArray out, int delta)
- {
+ public Clock(WireArray out, int delta) {
this.delta = delta;
this.outI = out.createInput();
Simulation.TIMELINE.addEvent(this, 50);
}
@Override
- public void handle(TimelineEvent e)
- {
+ public void handle(TimelineEvent e) {
addToTimeline();
outI.feedSignals(new Bit[] { toggle ? Bit.ONE : Bit.ZERO });
toggle = !toggle;
}
- public WireArray getOut()
- {
+ public WireArray getOut() {
return outI.owner;
}
-
- private void addToTimeline()
- {
+
+ private void addToTimeline() {
Simulation.TIMELINE.addEvent(this, delta);
}
@Override
- public List<WireArray> getAllInputs()
- {
+ public List<WireArray> getAllInputs() {
return Collections.unmodifiableList(Arrays.asList());
}
@Override
- public List<WireArray> getAllOutputs()
- {
+ public List<WireArray> getAllOutputs() {
return Collections.unmodifiableList(Arrays.asList(outI.owner));
}
}
import era.mi.logic.wires.WireArray;
-public interface Component
-{
+public interface Component {
/**
- * Returns immutable list of all inputs to the {@link Component} (including e.g. the select bits to a MUX).
- * Intended for visualization in the UI.
+ * Returns immutable list of all inputs to the {@link Component} (including e.g. the select bits to a MUX). Intended for visualization
+ * in the UI.
*/
public List<WireArray> getAllInputs();
-
+
/**
- * Returns immutable list of all outputs to the {@link Component}.
- * Intended for visualization in the UI.
+ * Returns immutable list of all outputs to the {@link Component}. Intended for visualization in the UI.
*/
public List<WireArray> getAllOutputs();
}
import era.mi.logic.wires.WireArray.WireArrayInput;
/**
- * Models a multiplexer. Takes an arbitrary amount of input {@link WireArray}s, one of which,
- * as determined by select, is put through to the output.
+ * Models a multiplexer. Takes an arbitrary amount of input {@link WireArray}s, one of which, as determined by select, is put through to the
+ * output.
+ *
* @author Fabian Stemmler
*
*/
-public class Demux extends BasicComponent
-{
+public class Demux extends BasicComponent {
private final WireArray select, in;
private final WireArray[] outputs;
private final WireArrayInput[] outputsI;
private final int outputSize;
private int selected = -1;
-
+
/**
* Input {@link WireArray}s and out must be of uniform length
- * @param out Must be of uniform length with all inputs.
- * @param select Indexes the input array which is to be mapped to the output. Must have enough bits
- * to index all inputs.
+ *
+ * @param out Must be of uniform length with all inputs.
+ * @param select Indexes the input array which is to be mapped to the output. Must have enough bits to index all inputs.
* @param outputs One of these inputs is mapped to the output, depending on the select bits
*/
- public Demux(int processTime, WireArray in, WireArray select, WireArray... outputs)
- {
+ public Demux(int processTime, WireArray in, WireArray select, WireArray... outputs) {
super(processTime);
outputSize = in.length;
-
+
this.in = in;
this.outputs = outputs;
this.outputsI = new WireArrayInput[outputs.length];
- for(int i = 0; i < this.outputsI.length; i++)
- {
- if(outputs[i].length != outputSize)
+ for (int i = 0; i < this.outputsI.length; i++) {
+ if (outputs[i].length != outputSize)
throw new IllegalArgumentException("All DEMUX wire arrays must be of uniform length!");
this.outputsI[i] = outputs[i].createInput();
}
-
+
this.select = select;
select.addObserver(this);
-
+
int maxInputs = 1 << select.length;
- if(this.outputsI.length > maxInputs)
- throw new IllegalArgumentException("There are more outputs ("
- + this.outputsI.length + ") to the DEMUX than supported by "
+ if (this.outputsI.length > maxInputs)
+ throw new IllegalArgumentException("There are more outputs (" + this.outputsI.length + ") to the DEMUX than supported by "
+ select.length + " select bits (" + maxInputs + ").");
in.addObserver(this);
}
@Override
public void compute() {
int selectValue = select.hasNumericValue() ? (int) select.getUnsignedValue() : -1;
- if(selectValue >= outputsI.length)
+ if (selectValue >= outputsI.length)
selectValue = -1;
-
- if(selected != selectValue && selected != -1)
+
+ if (selected != selectValue && selected != -1)
outputsI[selected].clearSignals();
-
+
selected = selectValue;
-
- if(selectValue != -1)
+
+ if (selectValue != -1)
outputsI[selectValue].feedSignals(in.getValues());
}
@Override
- public List<WireArray> getAllInputs()
- {
+ public List<WireArray> getAllInputs() {
return Collections.unmodifiableList(Arrays.asList(in, select));
}
@Override
- public List<WireArray> getAllOutputs()
- {
+ public List<WireArray> getAllOutputs() {
return Collections.unmodifiableList(Arrays.asList(outputs));
}
}
* @author Christian Femers
*
*/
-public class ManualSwitch implements Component
-{
+public class ManualSwitch implements Component {
private WireArray output;
private WireArrayInput outputI;
private boolean isOn;
-
- public ManualSwitch(WireArray output)
- {
- if(output.length != 1)
+
+ public ManualSwitch(WireArray output) {
+ if (output.length != 1)
throw new IllegalArgumentException("Switch output can be only a single wire");
this.output = output;
this.outputI = output.createInput();
}
-
- public void switchOn()
- {
+
+ public void switchOn() {
setState(true);
}
-
- public void switchOff()
- {
+
+ public void switchOff() {
setState(false);
}
-
- public void toggle()
- {
+
+ public void toggle() {
setState(!isOn);
}
-
- public void setState(boolean isOn)
- {
- if(this.isOn == isOn)
+
+ public void setState(boolean isOn) {
+ if (this.isOn == isOn)
return;
this.isOn = isOn;
outputI.feedSignals(getValue());
}
-
- public boolean isOn()
- {
+
+ public boolean isOn() {
return isOn;
}
-
- public Bit getValue()
- {
+
+ public Bit getValue() {
return isOn ? Bit.ONE : Bit.ZERO;
}
import era.mi.logic.wires.WireArray.WireArrayInput;
import era.mi.logic.wires.WireArrayObserver;
-public class Merger implements WireArrayObserver, Component
-{
- private WireArrayInput outI;
- private WireArray[] inputs;
- private int[] beginningIndex;
+public class Merger implements WireArrayObserver, Component {
+ private WireArrayInput outI;
+ private WireArray[] inputs;
+ private int[] beginningIndex;
- /**
- *
- * @param union The output of merging n {@link WireArray}s into one. Must have
- * length = a1.length() + a2.length() + ... + an.length().
- * @param inputs The inputs to be merged into the union
- */
- public Merger(WireArray union, WireArray... inputs)
- {
- this.inputs = inputs;
- this.outI = union.createInput();
- this.beginningIndex = new int[inputs.length];
+ /**
+ *
+ * @param union The output of merging n {@link WireArray}s into one. Must have length = a1.length() + a2.length() + ... + an.length().
+ * @param inputs The inputs to be merged into the union
+ */
+ public Merger(WireArray union, WireArray... inputs) {
+ this.inputs = inputs;
+ this.outI = union.createInput();
+ 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);
- }
+ 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().");
- }
+ 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 WireArray getInput(int index)
- {
- return inputs[index];
- }
+ public WireArray getInput(int index) {
+ return inputs[index];
+ }
- public WireArray getUnion()
- {
- return outI.owner;
- }
+ public WireArray getUnion() {
+ return outI.owner;
+ }
- @Override
- public void update(WireArray initiator, Bit[] oldValues)
- {
- int index = find(initiator);
- int beginning = beginningIndex[index];
- outI.feedSignals(beginning, initiator.getValues());
- }
+ @Override
+ public void update(WireArray initiator, Bit[] oldValues) {
+ int index = find(initiator);
+ int beginning = beginningIndex[index];
+ outI.feedSignals(beginning, initiator.getValues());
+ }
- private int find(WireArray w)
- {
- for (int i = 0; i < inputs.length; i++)
- if (inputs[i] == w)
- return i;
- return -1;
- }
+ private int find(WireArray w) {
+ for (int i = 0; i < inputs.length; i++)
+ if (inputs[i] == w)
+ return i;
+ return -1;
+ }
- public WireArray[] getInputs()
- {
- return inputs.clone();
- }
+ public WireArray[] getInputs() {
+ return inputs.clone();
+ }
@Override
- public List<WireArray> getAllInputs()
- {
+ public List<WireArray> getAllInputs() {
return Collections.unmodifiableList(Arrays.asList(inputs));
}
@Override
- public List<WireArray> getAllOutputs()
- {
+ public List<WireArray> getAllOutputs() {
return Collections.unmodifiableList(Arrays.asList(outI.owner));
}
}
import era.mi.logic.wires.WireArray.WireArrayInput;
/**
- * Models a multiplexer. Takes an arbitrary amount of input {@link WireArray}s, one of which,
- * as determined by select, is put through to the output.
+ * Models a multiplexer. Takes an arbitrary amount of input {@link WireArray}s, one of which, as determined by select, is put through to the
+ * output.
+ *
* @author Fabian Stemmler
*
*/
-public class Mux extends BasicComponent
-{
+public class Mux extends BasicComponent {
private WireArray select;
private WireArrayInput outI;
private WireArray[] inputs;
private final int outputSize;
+
/**
* Input {@link WireArray}s and out must be of uniform length
- * @param out Must be of uniform length with all inputs.
- * @param select Indexes the input array which is to be mapped to the output. Must have enough bits
- * to index all inputs.
+ *
+ * @param 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, WireArray out, WireArray select, WireArray... inputs)
- {
+ public Mux(int processTime, WireArray out, WireArray select, WireArray... inputs) {
super(processTime);
outputSize = out.length;
-
+
this.inputs = inputs.clone();
- for(int i = 0; i < this.inputs.length; i++)
- {
- if(inputs[i].length != outputSize)
+ 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 "
+ 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 + ").");
-
+
outI = out.createInput();
}
-
- public WireArray getOut()
- {
+
+ public WireArray getOut() {
return outI.owner;
}
- public WireArray getSelect()
- {
+ public WireArray getSelect() {
return select;
}
@Override
public void compute() {
int selectValue;
- if(!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) >= inputs.length)
- {
+ if (!select.hasNumericValue() || (selectValue = (int) select.getUnsignedValue()) >= inputs.length) {
outI.clearSignals();
return;
}
-
+
WireArray active = inputs[selectValue];
outI.feedSignals(active.getValues());
}
@Override
- public List<WireArray> getAllInputs()
- {
+ public List<WireArray> getAllInputs() {
ArrayList<WireArray> wires = new ArrayList<WireArray>(Arrays.asList(inputs));
wires.add(select);
return Collections.unmodifiableList(wires);
}
@Override
- public List<WireArray> getAllOutputs()
- {
+ public List<WireArray> getAllOutputs() {
return Collections.unmodifiableList(Arrays.asList(outI.owner));
}
}
import era.mi.logic.wires.WireArray.WireArrayInput;
import era.mi.logic.wires.WireArrayObserver;
-public class Splitter implements WireArrayObserver
-{
+public class Splitter implements WireArrayObserver {
private WireArray input;
private WireArrayInput[] outputs;
-
- public Splitter(WireArray input, WireArray... outputs)
- {
+
+ public Splitter(WireArray input, WireArray... outputs) {
this.input = input;
this.outputs = WireArray.extractInputs(outputs);
input.addObserver(this);
int length = 0;
- for(WireArray out : outputs)
+ for (WireArray 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().");
+
+ 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()
- {
+ protected void compute() {
int startIndex = 0;
Bit[] inputBits = input.getValues();
- for(int i = 0; i < outputs.length; i++)
- {
+ for (int i = 0; i < outputs.length; i++) {
Bit[] outputBits = new Bit[outputs[i].owner.length];
System.arraycopy(inputBits, startIndex, outputBits, 0, outputs[i].owner.length);
outputs[i].feedSignals(outputBits);
startIndex += outputs[i].owner.length;
}
}
-
+
@Override
- public void update(WireArray initiator, Bit[] oldValues)
- {
+ public void update(WireArray initiator, Bit[] oldValues) {
compute();
}
}
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
-public class TriStateBuffer extends BasicComponent{
+public class TriStateBuffer extends BasicComponent {
WireArray in, enable;
WireArrayInput outI;
-
+
public TriStateBuffer(int processTime, WireArray in, WireArray out, WireArray enable) {
super(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)
+ 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);
enable.addObserver(this);
outI = out.createInput();
}
-
+
@Override
- protected void compute()
- {
- if(enable.getValue() == Bit.ONE)
+ protected void compute() {
+ if (enable.getValue() == Bit.ONE)
outI.feedSignals(in.getValues());
else
outI.clearSignals();
}
@Override
- public List<WireArray> getAllInputs()
- {
+ public List<WireArray> getAllInputs() {
return Collections.unmodifiableList(Arrays.asList(in, enable));
}
@Override
- public List<WireArray> getAllOutputs()
- {
+ public List<WireArray> getAllOutputs() {
return Collections.unmodifiableList(Arrays.asList(outI.owner));
}
import era.mi.logic.Util;
import era.mi.logic.wires.WireArray;
-public class AndGate extends MultiInputGate
-{
- public AndGate(int processTime, WireArray out, WireArray... in)
- {
+public class AndGate extends MultiInputGate {
+ public AndGate(int processTime, WireArray out, WireArray... in) {
super(processTime, Util::and, out, in);
}
}
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
-public abstract class MultiInputGate extends BasicComponent
-{
+public abstract class MultiInputGate extends BasicComponent {
protected WireArray[] in;
protected WireArray out;
protected WireArrayInput outI;
protected final int length;
protected Operation op;
-
- protected MultiInputGate(int processTime, Operation op, WireArray out, WireArray... in)
- {
+
+ protected MultiInputGate(int processTime, Operation op, WireArray out, WireArray... in) {
super(processTime);
this.op = op;
length = out.length;
this.in = in.clone();
- if(in.length < 1)
+ if (in.length < 1)
throw new IllegalArgumentException(String.format("Cannot create gate with %d wires.", in.length));
- for(WireArray w : in)
- {
- if(w.length != length)
+ for (WireArray w : in) {
+ if (w.length != length)
throw new IllegalArgumentException("All wires connected to the gate must be of uniform length.");
w.addObserver(this);
}
outI = out.createInput();
}
-
@Override
- public List<WireArray> getAllInputs()
- {
+ public List<WireArray> getAllInputs() {
return Collections.unmodifiableList(Arrays.asList(in));
}
@Override
- public List<WireArray> getAllOutputs()
- {
+ public List<WireArray> getAllOutputs() {
return Collections.unmodifiableList(Arrays.asList(out));
}
-
- protected void compute()
- {
+
+ protected void compute() {
Bit[] result = in[0].getValues();
- for(int i = 1; i < in.length; i++)
+ for (int i = 1; i < in.length; i++)
result = op.execute(result, in[i].getValues());
outI.feedSignals(result);
}
-
- protected interface Operation
- {
+
+ protected interface Operation {
public Bit[] execute(Bit[] a, Bit[] b);
}
}
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
-public class NotGate extends BasicComponent
-{
+public class NotGate extends BasicComponent {
private WireArray in, out;
private WireArrayInput outI;
-
- public NotGate(int processTime, WireArray in, WireArray out)
- {
+ public NotGate(int processTime, WireArray in, WireArray out) {
super(processTime);
this.in = in;
in.addObserver(this);
this.out = out;
outI = out.createInput();
}
-
- public void compute()
- {
+
+ public void compute() {
outI.feedSignals(Util.not(in.getValues()));
}
- public WireArray getIn()
- {
+ public WireArray getIn() {
return in;
}
- public WireArray getOut()
- {
+ public WireArray getOut() {
return out;
}
-
+
@Override
- public List<WireArray> getAllInputs()
- {
+ public List<WireArray> getAllInputs() {
return Collections.unmodifiableList(Arrays.asList(in));
}
@Override
- public List<WireArray> getAllOutputs()
- {
+ public List<WireArray> getAllOutputs() {
return Collections.unmodifiableList(Arrays.asList(out));
}
}
import era.mi.logic.Util;
import era.mi.logic.wires.WireArray;
-public class OrGate extends MultiInputGate
-{
- public OrGate(int processTime, WireArray out, WireArray... in)
- {
+public class OrGate extends MultiInputGate {
+ public OrGate(int processTime, WireArray out, WireArray... in) {
super(processTime, Util::or, out, in);
}
}
/**
* Outputs 1 when the number of 1 inputs is odd.
+ *
* @author Fabian Stemmler
*/
-public class XorGate extends MultiInputGate
-{
- public XorGate(int processTime, WireArray out, WireArray... in)
- {
+public class XorGate extends MultiInputGate {
+ public XorGate(int processTime, WireArray out, WireArray... in) {
super(processTime, Util::xor, out, in);
}
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
-class ComponentTest
-{
-
+class ComponentTest {
+
@Test
- void circuitExampleTest()
- {
+ void circuitExampleTest() {
Simulation.TIMELINE.reset();
- WireArray a = new WireArray(1, 1), b = new WireArray(1, 1), c = new WireArray(1, 10), d = new WireArray(2, 1), e = new WireArray(1, 1),
- f = new WireArray(1, 1), g = new WireArray(1, 1), h = new WireArray(2, 1), i = new WireArray(2, 1), j = new WireArray(1, 1), k = new WireArray(1, 1);
+ WireArray a = new WireArray(1, 1), b = new WireArray(1, 1), c = new WireArray(1, 10), d = new WireArray(2, 1),
+ e = new WireArray(1, 1), f = new WireArray(1, 1), g = new WireArray(1, 1), h = new WireArray(2, 1), i = new WireArray(2, 1),
+ j = new WireArray(1, 1), k = new WireArray(1, 1);
new AndGate(1, f, a, b);
new NotGate(1, f, g);
new Merger(h, c, g);
new Mux(1, i, e, h, d);
new Splitter(i, k, j);
-
+
a.createInput().feedSignals(Bit.ZERO);
b.createInput().feedSignals(Bit.ONE);
c.createInput().feedSignals(Bit.ZERO);
d.createInput().feedSignals(Bit.ONE, Bit.ONE);
e.createInput().feedSignals(Bit.ZERO);
-
+
Simulation.TIMELINE.executeAll();
-
+
assertEquals(Bit.ONE, j.getValue());
assertEquals(Bit.ZERO, k.getValue());
}
- @Test
- void splitterTest()
- {
- Simulation.TIMELINE.reset();
- WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), in = new WireArray(8, 1);
- in.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
- new Splitter(in, a, b, c);
+ @Test
+ void splitterTest() {
+ Simulation.TIMELINE.reset();
+ WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), in = new WireArray(8, 1);
+ in.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
+ new Splitter(in, a, b, c);
+
+ 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();
+ WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), out = new WireArray(8, 1);
+ a.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);
+ b.createInput().feedSignals(Bit.ONE, Bit.ZERO);
+ c.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
+
+ new Merger(out, a, b, c);
+
+ Simulation.TIMELINE.executeAll();
+
+ assertTrue(
+ Arrays.equals(out.getValues(), new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE }));
+ }
+
+ @Test
+ void triStateBufferTest() {
+ WireArray a = new WireArray(1, 1), b = new WireArray(1, 1), en = new WireArray(1, 1), notEn = new WireArray(1, 1);
+ new NotGate(1, en, notEn);
+ new TriStateBuffer(1, a, b, en);
+ new TriStateBuffer(1, b, a, notEn);
+
+ WireArrayInput enI = en.createInput(), aI = a.createInput(), bI = b.createInput();
+ enI.feedSignals(Bit.ONE);
+ aI.feedSignals(Bit.ONE);
+
+ 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();
+ WireArray a = new WireArray(4, 3), b = new WireArray(4, 6), c = new WireArray(4, 4), select = new WireArray(2, 5),
+ out = new WireArray(4, 1);
+ WireArrayInput selectIn = select.createInput();
+
+ selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
+ a.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+ c.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
+
+ new Mux(1, out, select, a, b, c);
+ 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();
+ WireArray a = new WireArray(4, 3), b = new WireArray(4, 6), c = new WireArray(4, 4), select = new WireArray(2, 5),
+ in = new WireArray(4, 1);
+ WireArrayInput selectIn = select.createInput();
+
+ selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
+ in.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+
+ new Demux(1, in, select, a, b, c);
+ Simulation.TIMELINE.executeAll();
+
+ assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ selectIn.feedSignals(Bit.ZERO, Bit.ONE);
+ Simulation.TIMELINE.executeAll();
- Simulation.TIMELINE.executeAll();
+ assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
- 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);
- }
+ selectIn.feedSignals(Bit.ONE, Bit.ONE);
+ Simulation.TIMELINE.executeAll();
+
+ assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+
+ }
+
+ @Test
+ void andTest() {
+ Simulation.TIMELINE.reset();
+ WireArray a = new WireArray(4, 1), b = new WireArray(4, 3), c = new WireArray(4, 1);
+ new AndGate(1, c, a, b);
+ a.createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
+ b.createInput().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();
+ WireArray a = new WireArray(4, 1), b = new WireArray(4, 3), c = new WireArray(4, 1);
+ new OrGate(1, c, a, b);
+ a.createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
+ b.createInput().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 mergerTest()
- {
- Simulation.TIMELINE.reset();
- WireArray a = new WireArray(3, 1), b = new WireArray(2, 1), c = new WireArray(3, 1), out = new WireArray(8, 1);
- a.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO);
- b.createInput().feedSignals(Bit.ONE, Bit.ZERO);
- c.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
+ @Test
+ void xorTest() {
+ Simulation.TIMELINE.reset();
+ WireArray a = new WireArray(3, 1), b = new WireArray(3, 2), c = new WireArray(3, 1), d = new WireArray(3, 1);
+ new XorGate(1, d, a, b, c);
+ a.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
+ b.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
+ c.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
- new Merger(out, a, b, c);
+ Simulation.TIMELINE.executeAll();
- Simulation.TIMELINE.executeAll();
+ assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);
+ }
- assertTrue(Arrays.equals(out.getValues(),
- new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE }));
- }
+ @Test
+ void rsLatchCircuitTest() {
+ Simulation.TIMELINE.reset();
+ WireArray r = new WireArray(1, 1), s = new WireArray(1, 1), t1 = new WireArray(1, 15), t2 = new WireArray(1, 1),
+ q = new WireArray(1, 1), nq = new WireArray(1, 1);
- @Test
- void triStateBufferTest()
- {
- WireArray a = new WireArray(1, 1), b = new WireArray(1, 1), en = new WireArray(1, 1),
- notEn = new WireArray(1, 1);
- new NotGate(1, en, notEn);
- new TriStateBuffer(1, a, b, en);
- new TriStateBuffer(1, b, a, notEn);
+ new OrGate(1, t2, r, nq);
+ new OrGate(1, t1, s, q);
+ new NotGate(1, t2, q);
+ new NotGate(1, t1, nq);
- WireArrayInput enI = en.createInput(), aI = a.createInput(), bI = b.createInput();
- enI.feedSignals(Bit.ONE);
- aI.feedSignals(Bit.ONE);
+ WireArrayInput sIn = s.createInput(), rIn = r.createInput();
- Simulation.TIMELINE.executeAll();
-
- assertEquals(Bit.ONE, b.getValue());
+ sIn.feedSignals(Bit.ONE);
+ rIn.feedSignals(Bit.ZERO);
- bI.feedSignals(Bit.ZERO);
+ Simulation.TIMELINE.executeAll();
- Simulation.TIMELINE.executeAll();
+ assertEquals(Bit.ONE, q.getValue());
+ assertEquals(Bit.ZERO, nq.getValue());
- 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();
- WireArray a = new WireArray(4, 3), b = new WireArray(4, 6), c = new WireArray(4, 4),
- select = new WireArray(2, 5), out = new WireArray(4, 1);
- WireArrayInput selectIn = select.createInput();
-
- selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
- a.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
- c.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
-
- new Mux(1, out, select, a, b, c);
- 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);
-
- }
+ sIn.feedSignals(Bit.ZERO);
- @Test
- void demuxTest()
- {
- Simulation.TIMELINE.reset();
- WireArray a = new WireArray(4, 3), b = new WireArray(4, 6), c = new WireArray(4, 4),
- select = new WireArray(2, 5), in = new WireArray(4, 1);
- WireArrayInput selectIn = select.createInput();
+ Simulation.TIMELINE.executeAll();
+ assertEquals(Bit.ONE, q.getValue());
+ assertEquals(Bit.ZERO, nq.getValue());
- selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
- in.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+ rIn.feedSignals(Bit.ONE);
- new Demux(1, in, select, a, b, c);
- Simulation.TIMELINE.executeAll();
+ Simulation.TIMELINE.executeAll();
- assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
- assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
- assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
- selectIn.feedSignals(Bit.ZERO, Bit.ONE);
- Simulation.TIMELINE.executeAll();
+ assertEquals(Bit.ZERO, q.getValue());
+ assertEquals(Bit.ONE, nq.getValue());
+ }
- assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
- assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
- assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+ @Test
+ void numericValueTest() {
+ Simulation.TIMELINE.reset();
- selectIn.feedSignals(Bit.ONE, Bit.ONE);
- Simulation.TIMELINE.executeAll();
+ WireArray a = new WireArray(4, 1);
+ a.createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ONE, Bit.ONE);
- assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
- assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
- assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ Simulation.TIMELINE.executeAll();
- }
-
- @Test
- void andTest()
- {
- Simulation.TIMELINE.reset();
- WireArray a = new WireArray(4, 1), b = new WireArray(4, 3), c = new WireArray(4, 1);
- new AndGate(1, c, a, b);
- a.createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
- b.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
+ assertEquals(15, a.getUnsignedValue());
+ assertEquals(-1, a.getSignedValue());
+ }
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(c.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ZERO);
- }
+ @Test
+ void multipleInputs() {
+ Simulation.TIMELINE.reset();
+ WireArray w = new WireArray(2, 1);
+ WireArrayInput wI1 = w.createInput(), wI2 = w.createInput();
+ wI1.feedSignals(Bit.ONE, Bit.Z);
+ wI2.feedSignals(Bit.Z, Bit.X);
+ Simulation.TIMELINE.executeAll();
+ assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.X);
- @Test
- void orTest()
- {
- Simulation.TIMELINE.reset();
- WireArray a = new WireArray(4, 1), b = new WireArray(4, 3), c = new WireArray(4, 1);
- new OrGate(1, c, a, b);
- a.createInput().feedSignals(Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ZERO);
- b.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);
+ wI2.feedSignals(Bit.ZERO, Bit.Z);
+ Simulation.TIMELINE.executeAll();
+ assertBitArrayEquals(w.getValues(), Bit.X, Bit.Z);
- Simulation.TIMELINE.executeAll();
+ wI2.feedSignals(Bit.Z, Bit.Z);
+ Simulation.TIMELINE.executeAll();
+ assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
- assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ONE, Bit.ZERO, Bit.ONE);
- }
-
- @Test
- void xorTest()
- {
- Simulation.TIMELINE.reset();
- WireArray a = new WireArray(3, 1), b = new WireArray(3, 2), c = new WireArray(3, 1), d = new WireArray(3, 1);
- new XorGate(1, d, a, b, c);
- a.createInput().feedSignals(Bit.ZERO, Bit.ONE, Bit.ONE);
- b.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
- c.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE);
-
- Simulation.TIMELINE.executeAll();
-
- assertBitArrayEquals(d.getValues(), Bit.ZERO, Bit.ONE, Bit.ONE);
- }
-
- @Test
- void rsLatchCircuitTest()
- {
- Simulation.TIMELINE.reset();
- WireArray r = new WireArray(1, 1), s = new WireArray(1, 1), t1 = new WireArray(1, 15), t2 = new WireArray(1, 1),
- q = new WireArray(1, 1), nq = new WireArray(1, 1);
-
- new OrGate(1, t2, r, nq);
- new OrGate(1, t1, s, q);
- new NotGate(1, t2, q);
- new NotGate(1, t1, nq);
-
- WireArrayInput sIn = s.createInput(), rIn = r.createInput();
-
- 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();
-
- WireArray a = new WireArray(4, 1);
- a.createInput().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();
- WireArray w = new WireArray(2, 1);
- WireArrayInput wI1 = w.createInput(), wI2 = w.createInput();
- 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);
- }
+ 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()
- {
+ void wireConnections() {
// Nur ein Experiment, was über mehrere 'passive' Bausteine hinweg passieren würde
-
+
Simulation.TIMELINE.reset();
WireArray a = new WireArray(1, 2);
System.err.println("Z");
bI.feedSignals(Bit.Z);
test.assertAfterSimulationIs(print, Bit.Z);
-
+
new Connector(a, b);
System.err.println("Z 2");
aI.feedSignals(Bit.Z);
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);
}
- private static void assertBitArrayEquals(Bit[] actual, Bit... expected)
- {
- assertArrayEquals(expected, actual);
- }
+ private static void assertBitArrayEquals(Bit[] actual, Bit... expected) {
+ assertArrayEquals(expected, actual);
+ }
}
import era.mi.logic.wires.WireArray.WireArrayInput;
import era.mi.logic.wires.WireArrayObserver;
-public class Connector implements WireArrayObserver
-{
+public class Connector implements WireArrayObserver {
private final WireArray a;
// private final WireArray b;
private final WireArrayInput aI;
private final WireArrayInput bI;
- public Connector(WireArray a, WireArray b)
- {
+ public Connector(WireArray a, WireArray 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;
}
@Override
- public void update(WireArray initiator, Bit[] oldValues)
- {
- Simulation.TIMELINE.addEvent((e) ->
- {
+ public void update(WireArray initiator, Bit[] oldValues) {
+ Simulation.TIMELINE.addEvent((e) -> {
if (initiator == a)
bI.feedSignals(aI.wireValuesExcludingMe());
else
}
- private void drawSwitch(Graphics g, ManualSwitch ms, String text, double posX1, double posY1, double posX2,
- double posY2) {
+ private void drawSwitch(Graphics g, ManualSwitch ms, String text, double posX1, double posY1, double posX2, double posY2) {
int x1 = gX(posX1) - 5;
int x2 = gX(posX2) + 5;
int y1 = gY(posY1) - 5;
import era.mi.logic.components.BitDisplay;
import era.mi.logic.wires.WireArray;
-public final class TestBitDisplay extends BitDisplay
-{
+public final class TestBitDisplay extends BitDisplay {
- public TestBitDisplay(WireArray in)
- {
+ public TestBitDisplay(WireArray in) {
super(in);
}
- public void assertDisplays(Bit... expected)
- {
+ public void assertDisplays(Bit... expected) {
assertArrayEquals(expected, getDisplayedValue());
}
- public void assertAfterSimulationIs(Bit... expected)
- {
+ 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());
- }
+ 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()
- {
+ protected void compute() {
super.compute();
System.out.println("update: value is " + Arrays.toString(getDisplayedValue()));
}
/**
* Orders Events by the time they are due to be executed. Can execute Events individually.
+ *
* @author Fabian Stemmler
*
*/
-public class Timeline
-{
+public class Timeline {
private PriorityQueue<InnerEvent> events;
private long currentTime = 0;
-
+
private final List<Consumer<TimelineEvent>> eventAddedListener;
-
- public Timeline(int initCapacity)
- {
+
+ public Timeline(int initCapacity) {
events = new PriorityQueue<InnerEvent>(initCapacity, (a, b) -> {
long difference = a.getTiming() - b.getTiming();
- if(difference == 0)
+ if (difference == 0)
return 0;
return difference < 0 ? -1 : 1;
});
-
+
eventAddedListener = new ArrayList<>();
}
-
- public boolean hasNext()
- {
+
+ public boolean hasNext() {
return !events.isEmpty();
}
- public void executeNext()
- {
+ public void executeNext() {
InnerEvent first = events.poll();
currentTime = first.getTiming();
first.run();
}
-
- public void executeAll()
- {
+
+ public void executeAll() {
while (hasNext())
executeNext();
}
-
+
/**
- * Executes all events up to a given simulation timestamp. The simulation
- * process can be constrained by a real world timestamp.
+ * Executes all events up to a given simulation timestamp. The simulation process can be constrained by a real world timestamp.
*
- * @param timestamp the simulation timestamp up to which the events will be
- * processed
- * @param stopMillis the System.currentTimeMillis() when simulation definitely
- * needs to stop.
+ * @param timestamp the simulation timestamp up to which the events will be processed
+ * @param stopMillis the System.currentTimeMillis() when simulation definitely needs to stop.
* @return if it was possible to fulfil the goal in the given real world time.
* @author Christian Femers
*/
- public ExecutionResult executeUpTo(long timestamp, long stopMillis)
- {
- if (events.isEmpty())
- {
+ public ExecutionResult executeUpTo(long timestamp, long stopMillis) {
+ if (events.isEmpty()) {
currentTime = timestamp;
return ExecutionResult.NOTHING_DONE;
}
int checkStop = 0;
InnerEvent first = events.peek();
- while (first != null && first.getTiming() <= timestamp)
- {
+ while (first != null && first.getTiming() <= timestamp) {
events.remove();
currentTime = first.getTiming();
first.run();
return ExecutionResult.DONE_IN_TIME;
}
- public long getSimulationTime()
- {
+ public long getSimulationTime() {
return currentTime;
}
- public long nextEventTime()
- {
- if(!hasNext())
+ public long nextEventTime() {
+ if (!hasNext())
return -1;
else
return events.peek().timing;
}
-
- public void reset()
- {
+
+ public void reset() {
events.clear();
currentTime = 0;
}
- public void addEventAddedListener(Consumer<TimelineEvent> listener)
- {
+ public void addEventAddedListener(Consumer<TimelineEvent> listener) {
eventAddedListener.add(listener);
}
- public void removeEventAddedListener(Consumer<TimelineEvent> listener)
- {
+
+ public void removeEventAddedListener(Consumer<TimelineEvent> listener) {
eventAddedListener.remove(listener);
}
-
+
/**
* Adds an Event to the {@link Timeline}
- * @param function The {@link TimelineEventHandler} that will be executed, when the {@link InnerEvent} occurs on the timeline.
+ *
+ * @param function The {@link TimelineEventHandler} that will be executed, when the {@link InnerEvent} occurs on the timeline.
* @param relativeTiming The amount of MI ticks in which the {@link InnerEvent} is called, starting from the current time.
*/
- public void addEvent(TimelineEventHandler function, int relativeTiming)
- {
+ public void addEvent(TimelineEventHandler function, int relativeTiming) {
long timing = currentTime + relativeTiming;
TimelineEvent event = new TimelineEvent(timing);
events.add(new InnerEvent(function, event, timing));
eventAddedListener.forEach(l -> l.accept(event));
}
-
- private class InnerEvent
- {
+
+ private class InnerEvent {
private final long timing;
private final TimelineEventHandler function;
private final TimelineEvent event;
-
+
/**
* Creates an {@link InnerEvent}
+ *
* @param function {@link TimelineEventHandler} to be executed when the {@link InnerEvent} occurs
- * @param timing Point in the MI simulation {@link Timeline}, at which the {@link InnerEvent} is executed;
+ * @param timing Point in the MI simulation {@link Timeline}, at which the {@link InnerEvent} is executed;
*/
- InnerEvent(TimelineEventHandler function, TimelineEvent event, long timing)
- {
+ InnerEvent(TimelineEventHandler function, TimelineEvent event, long timing) {
this.function = function;
this.event = event;
this.timing = timing;
}
- public long getTiming()
- {
+ public long getTiming() {
return timing;
}
-
- public void run()
- {
+
+ public void run() {
function.handle(event);
}
-
+
@Override
- public String toString()
- {
+ public String toString() {
return event.toString();
}
}
-
+
@Override
- public String toString()
- {
+ public String toString() {
return "simulation time: " + currentTime + ", " + events.toString();
}
-
- public static long toNanoseconds(long ticks)
- {
- return ticks; //TODO: Alter this when it has been determined how ticks should relate to real time.
+
+ public static long toNanoseconds(long ticks) {
+ return ticks; // TODO: Alter this when it has been determined how ticks should relate to real time.
}
-
- public enum ExecutionResult
- {
- NOTHING_DONE, DONE_IN_TIME, RAN_OUT_OF_TIME
+
+ public enum ExecutionResult {
+ NOTHING_DONE, DONE_IN_TIME, RAN_OUT_OF_TIME
}
}
\ No newline at end of file
package era.mi.logic.timeline;
/**
- * A class that stores all relevant information about an event in the {@link Timeline}. Currently, there is not much relevant information to store.
+ * A class that stores all relevant information about an event in the {@link Timeline}. Currently, there is not much relevant information to
+ * store.
+ *
* @author Fabian Stemmler
*
*/
-public class TimelineEvent
-{
+public class TimelineEvent {
private final long timing;
-
- TimelineEvent(long timing)
- {
+
+ TimelineEvent(long timing) {
super();
this.timing = timing;
}
- public long getTiming()
- {
+ public long getTiming() {
return timing;
}
-
- public String toString()
- {
+
+ public String toString() {
return "timestamp: " + timing;
}
}
\ No newline at end of file
package era.mi.logic.timeline;
-public interface TimelineEventHandler
-{
+public interface TimelineEventHandler {
public void handle(TimelineEvent e);
}
\ No newline at end of file
* @author Fabian Stemmler
*
*/
-public class WireArray
-{
+public class WireArray {
private Bit[] values;
public final int travelTime;
private List<WireArrayObserver> observers = new ArrayList<WireArrayObserver>();
public final int length;
private List<WireArrayInput> inputs = new ArrayList<WireArrayInput>();
- public WireArray(int length, int travelTime)
- {
+ public WireArray(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));
+ 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()
- {
+ private void initValues() {
values = Bit.Z.makeArray(length);
}
- private void recalculateSingleInput()
- {
+ private void recalculateSingleInput() {
WireArrayInput input = inputs.get(0);
- if (!Arrays.equals(input.getValues(), values))
- {
+ if (!Arrays.equals(input.getValues(), values)) {
Bit[] oldValues = values.clone();
System.arraycopy(input.getValues(), 0, values, 0, length);
notifyObservers(oldValues);
}
}
- private void recalculateMultipleInputs()
- {
+ private void recalculateMultipleInputs() {
Iterator<WireArrayInput> it = inputs.iterator();
Bit[] newValues = it.next().inputValues.clone();
- while (it.hasNext())
- {
+ while (it.hasNext()) {
WireArrayInput input = it.next();
Bit[] bits = input.getValues();
- for (int i = 0; i < length; i++)
- {
+ for (int i = 0; i < length; i++) {
if (Bit.Z.equals(bits[i]) || newValues[i].equals(bits[i]))
continue;
else if (Bit.Z.equals(newValues[i]))
}
}
- if (!Arrays.equals(newValues, values))
- {
+ if (!Arrays.equals(newValues, values)) {
Bit[] oldValues = values;
values = newValues;
notifyObservers(oldValues);
}
}
- private void recalculate()
- {
- switch (inputs.size())
- {
+ private void recalculate() {
+ switch (inputs.size()) {
case 0:
return;
case 1:
/**
* The WireArray 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.
+ * @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)
- {
+ public boolean hasNumericValue() {
+ for (Bit b : values) {
if (b != Bit.ZERO && b != Bit.ONE)
return false;
}
/**
* The WireArray is interpreted as an unsigned integer with n bits.
*
- * @return The unsigned value of the {@link WireArray}'s bits, where value 0
- * corresponds with 2^0, value 1 is 2^1 and so on.
+ * @return The unsigned value of the {@link WireArray}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
*
* @author Fabian Stemmler
*/
- public long getUnsignedValue()
- {
+ public long getUnsignedValue() {
long val = 0;
long mask = 1;
- for (int i = 0; i < length; i++)
- {
- switch (values[i])
- {
+ for (int i = 0; i < length; i++) {
+ switch (values[i]) {
default:
case Z:
case X:
/**
* The WireArray is interpreted as a signed integer with n bits.
*
- * @return The signed value of the {@link WireArray}'s bits, where value 0
- * corresponds with 2^0, value 1 is 2^1 and so on.
+ * @return The signed value of the {@link WireArray}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
*
* @author Fabian Stemmler
*/
- public long getSignedValue()
- {
+ public long getSignedValue() {
long val = getUnsignedValue();
long mask = 1 << (length - 1);
- if ((mask & val) != 0)
- {
+ if ((mask & val) != 0) {
int shifts = 64 - length;
return (val << shifts) >> shifts;
}
*
* @author Fabian Stemmler
*/
- public Bit getValue()
- {
+ public Bit getValue() {
return getValue(0);
}
*
* @author Fabian Stemmler
*/
- public Bit getValue(int index)
- {
+ public Bit getValue(int index) {
return values[index];
}
- public Bit[] getValues(int start, int end)
- {
+ public Bit[] getValues(int start, int end) {
int length = end - start;
Bit[] bits = new Bit[length];
System.arraycopy(values, start, bits, 0, length);
}
/**
- * @return An array of length n containing the values of the n bits in the
- * {@link WireArray}. Can be safely modified.
+ * @return An array of length n containing the values of the n bits in the {@link WireArray}. Can be safely modified.
*
* @author Fabian Stemmler
*/
- public Bit[] getValues()
- {
+ public Bit[] getValues() {
return values.clone();
}
/**
- * Adds an {@link WireArrayObserver}, who will be notified when the value of the
- * {@link WireArray} is updated.
+ * Adds an {@link WireArrayObserver}, who will be notified when the value of the {@link WireArray} is updated.
*
* @param ob The {@link WireArrayObserver} to be notified of changes.
- * @return true if the given {@link WireArrayObserver} was not already
- * registered, false otherwise
+ * @return true if the given {@link WireArrayObserver} was not already registered, false otherwise
*
* @author Fabian Stemmler
*/
- public boolean addObserver(WireArrayObserver ob)
- {
+ public boolean addObserver(WireArrayObserver ob) {
return observers.add(ob);
}
- private void notifyObservers(Bit[] oldValues)
- {
+ private void notifyObservers(Bit[] oldValues) {
for (WireArrayObserver o : observers)
o.update(this, oldValues);
}
/**
- * Create and register a {@link WireArrayInput} object, which is tied to this
- * {@link WireArray}.
+ * Create and register a {@link WireArrayInput} object, which is tied to this {@link WireArray}.
*/
- public WireArrayInput createInput()
- {
+ public WireArrayInput createInput() {
return new WireArrayInput(this);
}
- private void registerInput(WireArrayInput toRegister)
- {
+ private void registerInput(WireArrayInput toRegister) {
inputs.add(toRegister);
}
/**
- * A {@link WireArrayInput} feeds a constant signal into the {@link WireArray}
- * it is tied to. The combination of all inputs determines the
- * {@link WireArray}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
+ * A {@link WireArrayInput} feeds a constant signal into the {@link WireArray} it is tied to. The combination of all inputs determines
+ * the {@link WireArray}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 WireArrayInput
- {
+ public class WireArrayInput {
public final WireArray owner;
private Bit[] inputValues;
- private WireArrayInput(WireArray owner)
- {
+ private WireArrayInput(WireArray owner) {
super();
this.owner = owner;
initValues();
owner.registerInput(this);
}
- private void initValues()
- {
+ private void initValues() {
inputValues = Bit.Z.makeArray(length);
}
/**
- * Sets the wires values. This takes up time, as specified by the
- * {@link WireArray}s travel time.
+ * Sets the wires values. This takes up time, as specified by the {@link WireArray}s travel time.
*
* @param newValues The new values the wires should take on.
*
* @author Fabian Stemmler
*/
- public void feedSignals(Bit... newValues)
- {
- if (newValues.length == length)
- {
+ public void feedSignals(Bit... newValues) {
+ if (newValues.length == length) {
feedSignals(0, newValues);
} else
- throw new IllegalArgumentException(String.format("Attempted to input %o bits instead of %o bits.", newValues.length, length));
+ throw new IllegalArgumentException(
+ String.format("Attempted to input %o bits instead of %o bits.", newValues.length, length));
}
/**
- * Sets values of a subarray of wires. This takes up time, as specified by the
- * {@link WireArray}s travel time.
+ * Sets values of a subarray of wires. This takes up time, as specified by the {@link WireArray}s travel time.
*
* @param newValues 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, Bit... newValues)
- {
+ public void feedSignals(int startingBit, Bit... newValues) {
Simulation.TIMELINE.addEvent((e) -> setValues(startingBit, newValues), travelTime);
}
- private void setValues(int startingBit, Bit... newValues)
- {
+ private void setValues(int startingBit, Bit... newValues) {
int exclLastIndex = startingBit + newValues.length;
if (length < exclLastIndex)
- throw new ArrayIndexOutOfBoundsException(String.format("Attempted to input bits from index %o to %o when there are only %o wires.", startingBit, exclLastIndex - 1, length));
- if (!Arrays.equals(inputValues, startingBit, exclLastIndex, newValues, 0, newValues.length))
- {
+ throw new ArrayIndexOutOfBoundsException(
+ String.format("Attempted to input bits from index %o to %o when there are only %o wires.", startingBit,
+ exclLastIndex - 1, length));
+ if (!Arrays.equals(inputValues, startingBit, exclLastIndex, newValues, 0, newValues.length)) {
System.arraycopy(newValues, 0, inputValues, startingBit, newValues.length);
owner.recalculate();
}
}
/**
- * Returns a copy (safe to modify) of the values the {@link WireArrayInput} is currently feeding into the associated {@link WireArray}.
+ * Returns a copy (safe to modify) of the values the {@link WireArrayInput} is currently feeding into the associated
+ * {@link WireArray}.
*/
- public Bit[] getValues()
- {
+ public Bit[] getValues() {
return inputValues.clone();
}
/**
* {@link WireArrayInput} now feeds Z into the associated {@link WireArray}.
*/
- public void clearSignals()
- {
+ public void clearSignals() {
feedSignals(Bit.Z.makeArray(length));
}
- public Bit[] wireValuesExcludingMe()
- {
+ public Bit[] wireValuesExcludingMe() {
Bit[] bits = Bit.Z.makeArray(length);
- for (WireArrayInput wai : inputs)
- {
- if(wai == this)
+ for (WireArrayInput wai : inputs) {
+ if (wai == this)
continue;
Util.combineInto(bits, wai.getValues());
}
return bits;
}
-
+
@Override
- public String toString()
- {
+ public String toString() {
return Arrays.toString(inputValues);
}
}
@Override
- public String toString()
- {
+ public String toString() {
return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), Arrays.toString(values), inputs);
}
- public static WireArrayInput[] extractInputs(WireArray[] w)
- {
+ public static WireArrayInput[] extractInputs(WireArray[] w) {
WireArrayInput[] inputs = new WireArrayInput[w.length];
for (int i = 0; i < w.length; i++)
inputs[i] = w[i].createInput();
import era.mi.logic.Bit;
-public interface WireArrayObserver
-{
+public interface WireArrayObserver {
public void update(WireArray initiator, Bit[] oldValues);
}