package era.mi.logic.components;
+import era.mi.logic.Bit;
import era.mi.logic.Simulation;
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArrayObserver;
-public abstract class BasicComponent implements WireArrayObserver
+public abstract class BasicComponent implements WireArrayObserver, Component
{
private int processTime;
}
@Override
- public void update(WireArray initiator)
+ public void update(WireArray initiator, Bit[] oldValues)
{
Simulation.TIMELINE.addEvent((e) -> {compute();}, processTime);
}
package era.mi.logic.components;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import era.mi.logic.Bit;
import era.mi.logic.wires.WireArray;
{
return Arrays.equals(displayedValue, values);
}
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(in));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(new ArrayList<WireArray>());
+ }
}
package era.mi.logic.components;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import era.mi.logic.Bit;
import era.mi.logic.Simulation;
import era.mi.logic.timeline.TimelineEvent;
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
-public class Clock implements TimelineEventHandler
+public class Clock implements TimelineEventHandler, Component
{
private boolean toggle = false;
private WireArrayInput outI;
+ private int delta;
- public Clock(WireArray out)
+ /**
+ *
+ * @param out {@link WireArray} the clock's impulses are fed into
+ * @param delta ticks between rising and falling edge
+ */
+ public Clock(WireArray out, int delta)
{
+ this.delta = delta;
this.outI = out.createInput();
+ Simulation.TIMELINE.addEvent(this, 50);
}
@Override
public void handle(TimelineEvent e)
{
- Simulation.TIMELINE.addEvent(this, 50);
+ addToTimeline();
outI.feedSignals(new Bit[] { toggle ? Bit.ONE : Bit.ZERO });
toggle = !toggle;
}
{
return outI.owner;
}
+
+ private void addToTimeline()
+ {
+ Simulation.TIMELINE.addEvent(this, delta);
+ }
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList());
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(outI.owner));
+ }
}
--- /dev/null
+package era.mi.logic.components;
+
+import java.util.List;
+
+import era.mi.logic.wires.WireArray;
+
+public interface Component
+{
+
+ /**
+ * Returns immutable list of all inputs to the {@link Component} (including e.g. the select bits to a MUX).
+ * Intended for visualization in the UI.
+ */
+ public List<WireArray> getAllInputs();
+
+ /**
+ * Returns immutable list of all outputs to the {@link Component}.
+ * Intended for visualization in the UI.
+ */
+ public List<WireArray> getAllOutputs();
+}
--- /dev/null
+package era.mi.logic.components;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import era.mi.logic.wires.WireArray;
+import era.mi.logic.wires.WireArray.WireArrayInput;
+
+/**
+ * Models a multiplexer. Takes an arbitrary amount of input {@link WireArray}s, one of which,
+ * as determined by select, is put through to the output.
+ * @author Fabian Stemmler
+ *
+ */
+public class Demux extends BasicComponent
+{
+ private final WireArray select, in;
+ private final WireArray[] outputs;
+ private final WireArrayInput[] outputsI;
+ private final int outputSize;
+ private int selected = -1;
+
+ /**
+ * Input {@link WireArray}s and out must be of uniform length
+ * @param out Must be of uniform length with all inputs.
+ * @param select Indexes the input array which is to be mapped to the output. Must have enough bits
+ * to index all inputs.
+ * @param outputs One of these inputs is mapped to the output, depending on the select bits
+ */
+ public Demux(int processTime, WireArray in, WireArray select, WireArray... outputs)
+ {
+ super(processTime);
+ outputSize = in.length;
+
+ this.in = in;
+ this.outputs = outputs;
+ this.outputsI = new WireArrayInput[outputs.length];
+ for(int i = 0; i < this.outputsI.length; i++)
+ {
+ if(outputs[i].length != outputSize)
+ throw new IllegalArgumentException("All DEMUX wire arrays must be of uniform length!");
+ this.outputsI[i] = outputs[i].createInput();
+ }
+
+ this.select = select;
+ select.addObserver(this);
+
+ int maxInputs = 1 << select.length;
+ if(this.outputsI.length > maxInputs)
+ throw new IllegalArgumentException("There are more outputs ("
+ + this.outputsI.length + ") to the DEMUX than supported by "
+ + select.length + " select bits (" + maxInputs + ").");
+ in.addObserver(this);
+ }
+
+ @Override
+ public void compute() {
+ int selectValue = select.hasNumericValue() ? (int) select.getUnsignedValue() : -1;
+ if(selectValue >= outputsI.length)
+ selectValue = -1;
+
+ if(selected != selectValue && selected != -1)
+ outputsI[selected].clearSignals();
+
+ selected = selectValue;
+
+ if(selectValue != -1)
+ outputsI[selectValue].feedSignals(in.getValues());
+ }
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(in, select));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(outputs));
+ }
+}
package era.mi.logic.components;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import era.mi.logic.Bit;
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
import era.mi.logic.wires.WireArrayObserver;
-public class Merger implements WireArrayObserver
+public class Merger implements WireArrayObserver, Component
{
private WireArrayInput outI;
private WireArray[] inputs;
}
@Override
- public void update(WireArray initiator)
+ public void update(WireArray initiator, Bit[] oldValues)
{
int index = find(initiator);
int beginning = beginningIndex[index];
{
return inputs.clone();
}
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(inputs));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(outI.owner));
+ }
}
package era.mi.logic.components;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
WireArray active = inputs[selectValue];
outI.feedSignals(active.getValues());
}
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ ArrayList<WireArray> wires = new ArrayList<WireArray>(Arrays.asList(inputs));
+ wires.add(select);
+ return Collections.unmodifiableList(wires);
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(outI.owner));
+ }
}
}
@Override
- public void update(WireArray initiator)
+ public void update(WireArray initiator, Bit[] oldValues)
{
compute();
}
package era.mi.logic.components;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import era.mi.logic.Bit;
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
outI.clearSignals();
}
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(in, enable));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(outI.owner));
+ }
+
}
package era.mi.logic.components.gates;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import era.mi.logic.Util;
import era.mi.logic.components.BasicComponent;
import era.mi.logic.wires.WireArray;
{
return out;
}
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(a, b));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(out));
+ }
}
package era.mi.logic.components.gates;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import era.mi.logic.Util;
import era.mi.logic.components.BasicComponent;
import era.mi.logic.wires.WireArray;
{
return out;
}
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(in));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(out));
+ }
}
package era.mi.logic.components.gates;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import era.mi.logic.Util;
import era.mi.logic.components.BasicComponent;
import era.mi.logic.wires.WireArray;
{
return out;
}
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(a, b));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(out));
+ }
}
package era.mi.logic.components.gates;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import era.mi.logic.Util;
import era.mi.logic.components.BasicComponent;
import era.mi.logic.wires.WireArray;
{
return out;
}
+
+ @Override
+ public List<WireArray> getAllInputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(a, b));
+ }
+
+ @Override
+ public List<WireArray> getAllOutputs()
+ {
+ return Collections.unmodifiableList(Arrays.asList(out));
+ }
}
import era.mi.logic.Bit;
import era.mi.logic.Simulation;
+import era.mi.logic.components.Demux;
import era.mi.logic.components.Merger;
import era.mi.logic.components.Mux;
import era.mi.logic.components.Splitter;
}
+ @Test
+ void demuxTest()
+ {
+ Simulation.TIMELINE.reset();
+ WireArray a = new WireArray(4, 3), b = new WireArray(4, 6), c = new WireArray(4, 4),
+ select = new WireArray(2, 5), in = new WireArray(4, 1);
+ WireArrayInput selectIn = select.createInput();
+
+ selectIn.feedSignals(Bit.ZERO, Bit.ZERO);
+ in.createInput().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+
+ new Demux(1, in, select, a, b, c);
+ Simulation.TIMELINE.executeAll();
+
+ assertBitArrayEquals(a.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ selectIn.feedSignals(Bit.ZERO, Bit.ONE);
+ Simulation.TIMELINE.executeAll();
+
+ assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(c.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO);
+
+ selectIn.feedSignals(Bit.ONE, Bit.ONE);
+ Simulation.TIMELINE.executeAll();
+
+ assertBitArrayEquals(a.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(b.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+ assertBitArrayEquals(c.getValues(), Bit.Z, Bit.Z, Bit.Z, Bit.Z);
+
+ }
+
@Test
void andTest()
{
assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
wI2.feedSignals(Bit.ONE, Bit.Z);
- w.addObserver((i) -> fail("WireArray notified observer, although value did not change."));
+ w.addObserver((i, oldValues) -> fail("WireArray notified observer, although value did not change."));
Simulation.TIMELINE.executeAll();
assertBitArrayEquals(w.getValues(), Bit.ONE, Bit.Z);
}
package era.mi.logic.tests;
+import era.mi.logic.Bit;
import era.mi.logic.Simulation;
import era.mi.logic.wires.WireArray;
import era.mi.logic.wires.WireArray.WireArrayInput;
}
@Override
- public void update(WireArray initiator)
+ public void update(WireArray initiator, Bit[] oldValues)
{
Simulation.TIMELINE.addEvent((e) ->
{
WireArrayInput input = inputs.get(0);
if (!Arrays.equals(input.getValues(), values))
{
+ Bit[] oldValues = values.clone();
System.arraycopy(input.getValues(), 0, values, 0, length);
- notifyObservers();
+ notifyObservers(oldValues);
}
}
if (!Arrays.equals(newValues, values))
{
- notifyObservers();
+ Bit[] oldValues = values;
values = newValues;
+ notifyObservers(oldValues);
}
}
return observers.add(ob);
}
- private void notifyObservers()
+ private void notifyObservers(Bit[] oldValues)
{
for (WireArrayObserver o : observers)
- o.update(this);
+ o.update(this, oldValues);
}
/**
package era.mi.logic.wires;
+import era.mi.logic.Bit;
+
public interface WireArrayObserver
{
- public void update(WireArray initiator);
+ public void update(WireArray initiator, Bit[] oldValues);
}