Some things can still be improved, but it should be way more readable
now.
15 files changed:
package era.mi.logic.components;\r
\r
import era.mi.logic.Simulation;\r
package era.mi.logic.components;\r
\r
import era.mi.logic.Simulation;\r
-import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.WireObserver;\r
\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.WireObserver;\r
\r
- public void update(Wire initiator, Bit[] oldValues)\r
+ public void update(Wire initiator, BitVector oldValues)\r
{\r
Simulation.TIMELINE.addEvent(e -> compute(), processTime);\r
}\r
{\r
Simulation.TIMELINE.addEvent(e -> compute(), processTime);\r
}\r
package era.mi.logic.components;\r
\r
package era.mi.logic.components;\r
\r
-import java.util.Arrays;\r
import java.util.List;\r
\r
import era.mi.logic.types.Bit;\r
import java.util.List;\r
\r
import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public class BitDisplay extends BasicComponent\r
{\r
private final WireEnd in;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public class BitDisplay extends BasicComponent\r
{\r
private final WireEnd in;\r
- private Bit[] displayedValue;\r
+ private BitVector displayedValue;\r
\r
public BitDisplay(WireEnd in)\r
{\r
\r
public BitDisplay(WireEnd in)\r
{\r
displayedValue = in.getValues();\r
}\r
\r
displayedValue = in.getValues();\r
}\r
\r
- public Bit[] getDisplayedValue()\r
+ public BitVector getDisplayedValue()\r
{\r
return displayedValue;\r
}\r
\r
public boolean isDisplaying(Bit... values)\r
{\r
{\r
return displayedValue;\r
}\r
\r
public boolean isDisplaying(Bit... values)\r
{\r
- return Arrays.equals(displayedValue, values);\r
+ return displayedValue.equals(BitVector.of(values));\r
import java.util.List;
import era.mi.logic.Simulation;
import java.util.List;
import era.mi.logic.Simulation;
-import era.mi.logic.types.Bit;
+import era.mi.logic.types.BitVector;
import era.mi.logic.wires.Wire;
import era.mi.logic.wires.Wire.WireEnd;
import era.mi.logic.wires.WireObserver;
import era.mi.logic.wires.Wire;
import era.mi.logic.wires.Wire.WireEnd;
import era.mi.logic.wires.WireObserver;
- public void update(Wire initiator, Bit[] oldValues)
+ public void update(Wire initiator, BitVector oldValues)
{
if (connected)
Simulation.TIMELINE.addEvent(e -> update(initiator), 1);
{
if (connected)
Simulation.TIMELINE.addEvent(e -> update(initiator), 1);
\r
import java.util.List;\r
\r
\r
import java.util.List;\r
\r
-import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
import era.mi.logic.wires.WireObserver;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
import era.mi.logic.wires.WireObserver;\r
- public void update(Wire initiator, Bit[] oldValues)\r
+ public void update(Wire initiator, BitVector oldValues)\r
{\r
int index = find(initiator);\r
int beginning = beginningIndex[index];\r
{\r
int index = find(initiator);\r
int beginning = beginningIndex[index];\r
package era.mi.logic.components;\r
\r
package era.mi.logic.components;\r
\r
-import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
import era.mi.logic.wires.WireObserver;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
import era.mi.logic.wires.WireObserver;\r
\r
protected void compute()\r
{\r
\r
protected void compute()\r
{\r
+ BitVector inputBits = input.getValues();\r
- Bit[] inputBits = input.getValues();\r
for (int i = 0; i < outputs.length; i++)\r
{\r
for (int i = 0; i < outputs.length; i++)\r
{\r
- Bit[] outputBits = new Bit[outputs[i].length()];\r
- System.arraycopy(inputBits, startIndex, outputBits, 0, outputs[i].length());\r
- outputs[i].feedSignals(outputBits);\r
+ outputs[i].feedSignals(inputBits.subVector(startIndex, startIndex + outputs[i].length()));\r
startIndex += outputs[i].length();\r
}\r
}\r
\r
@Override\r
startIndex += outputs[i].length();\r
}\r
}\r
\r
@Override\r
- public void update(Wire initiator, Bit[] oldValues)\r
+ public void update(Wire initiator, BitVector oldValues)\r
package era.mi.logic.components.gates;\r
\r
package era.mi.logic.components.gates;\r
\r
-import era.mi.logic.Util;\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public class AndGate extends MultiInputGate\r
{\r
public AndGate(int processTime, WireEnd out, WireEnd... in)\r
{\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public class AndGate extends MultiInputGate\r
{\r
public AndGate(int processTime, WireEnd out, WireEnd... in)\r
{\r
- super(processTime, Util::and, out, in);\r
+ super(processTime, BitVectorMutator::and, out, in);\r
import java.util.List;\r
\r
import era.mi.logic.components.BasicComponent;\r
import java.util.List;\r
\r
import era.mi.logic.components.BasicComponent;\r
-import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
+import era.mi.logic.types.MutationOperation;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public abstract class MultiInputGate extends BasicComponent\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public abstract class MultiInputGate extends BasicComponent\r
protected WireEnd[] in;\r
protected WireEnd out;\r
protected final int length;\r
protected WireEnd[] in;\r
protected WireEnd out;\r
protected final int length;\r
- protected Operation op;\r
+ protected MutationOperation op;\r
- protected MultiInputGate(int processTime, Operation op, WireEnd out, WireEnd... in)\r
+ protected MultiInputGate(int processTime, MutationOperation op, WireEnd out, WireEnd... in)\r
{\r
super(processTime);\r
this.op = op;\r
{\r
super(processTime);\r
this.op = op;\r
@Override\r
protected void compute()\r
{\r
@Override\r
protected void compute()\r
{\r
- Bit[] result = in[0].getValues();\r
- for (int i = 1; i < in.length; i++)\r
- result = op.execute(result, in[i].getValues());\r
- out.feedSignals(result);\r
- }\r
-\r
- protected interface Operation\r
- {\r
- public Bit[] execute(Bit[] a, Bit[] b);\r
+ BitVectorMutator mutator = BitVectorMutator.empty();\r
+ for (WireEnd w : in)\r
+ op.apply(mutator, w.getValues());\r
+ out.feedSignals(mutator.get());\r
\r
import java.util.List;\r
\r
\r
import java.util.List;\r
\r
-import era.mi.logic.Util;\r
import era.mi.logic.components.BasicComponent;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
import era.mi.logic.components.BasicComponent;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
@Override\r
protected void compute()\r
{\r
@Override\r
protected void compute()\r
{\r
- out.feedSignals(Util.not(in.getValues()));\r
+ out.feedSignals(in.getValues().not());\r
}\r
\r
public WireEnd getIn()\r
}\r
\r
public WireEnd getIn()\r
package era.mi.logic.components.gates;\r
\r
package era.mi.logic.components.gates;\r
\r
-import era.mi.logic.Util;\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public class OrGate extends MultiInputGate\r
{\r
public OrGate(int processTime, WireEnd out, WireEnd... in)\r
{\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public class OrGate extends MultiInputGate\r
{\r
public OrGate(int processTime, WireEnd out, WireEnd... in)\r
{\r
- super(processTime, Util::or, out, in);\r
+ super(processTime, BitVectorMutator::or, out, in);\r
package era.mi.logic.components.gates;\r
\r
package era.mi.logic.components.gates;\r
\r
-import era.mi.logic.Util;\r
+import era.mi.logic.types.BitVector.BitVectorMutator;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
/**\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
/**\r
{\r
public XorGate(int processTime, WireEnd out, WireEnd... in)\r
{\r
{\r
public XorGate(int processTime, WireEnd out, WireEnd... in)\r
{\r
- super(processTime, Util::xor, out, in);\r
+ super(processTime, BitVectorMutator::xor, out, in);\r
\r
import static org.junit.jupiter.api.Assertions.*;\r
\r
\r
import static org.junit.jupiter.api.Assertions.*;\r
\r
-import java.util.Arrays;\r
import java.util.function.LongConsumer;\r
\r
import org.junit.jupiter.api.Test;\r
import java.util.function.LongConsumer;\r
\r
import org.junit.jupiter.api.Test;\r
import era.mi.logic.components.gates.OrGate;\r
import era.mi.logic.components.gates.XorGate;\r
import era.mi.logic.types.Bit;\r
import era.mi.logic.components.gates.OrGate;\r
import era.mi.logic.components.gates.XorGate;\r
import era.mi.logic.types.Bit;\r
+import era.mi.logic.types.BitVector;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
\r
Simulation.TIMELINE.executeAll();\r
\r
\r
Simulation.TIMELINE.executeAll();\r
\r
- assertTrue(\r
- Arrays.equals(out.getValues(), new Bit[] { Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE }));\r
+ assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE);\r
test2.assertAfterSimulationIs(Bit.ONE);\r
}\r
\r
test2.assertAfterSimulationIs(Bit.ONE);\r
}\r
\r
- private static void assertBitArrayEquals(Bit[] actual, Bit... expected)\r
+ private static void assertBitArrayEquals(BitVector actual, Bit... expected)\r
- assertArrayEquals(expected, actual);\r
+ assertArrayEquals(expected, actual.getBits());\r
\r
import static org.junit.jupiter.api.Assertions.assertArrayEquals;\r
\r
\r
import static org.junit.jupiter.api.Assertions.assertArrayEquals;\r
\r
-import java.util.Arrays;\r
import java.util.function.LongConsumer;\r
\r
import era.mi.logic.Simulation;\r
import java.util.function.LongConsumer;\r
\r
import era.mi.logic.Simulation;\r
\r
public void assertDisplays(Bit... expected)\r
{\r
\r
public void assertDisplays(Bit... expected)\r
{\r
- assertArrayEquals(expected, getDisplayedValue());\r
+ assertArrayEquals(expected, getDisplayedValue().getBits());\r
}\r
\r
public void assertAfterSimulationIs(Bit... expected)\r
}\r
\r
public void assertAfterSimulationIs(Bit... expected)\r
protected void compute()\r
{\r
super.compute();\r
protected void compute()\r
{\r
super.compute();\r
- System.out.println("update: value is " + Arrays.toString(getDisplayedValue()));\r
+ System.out.println("update: value is " + getDisplayedValue());\r
*
* @see Object#equals(Object)
*/
*
* @see Object#equals(Object)
*/
- public boolean equals(BitVector other, int offset)
+ public boolean equalsWithOffset(BitVector other, int offset)
{
if (other == null)
return false;
{
if (other == null)
return false;
package era.mi.logic.wires;
package era.mi.logic.wires;
+import static era.mi.logic.types.Bit.*;
+
import java.util.ArrayList;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
import java.util.List;
import era.mi.logic.Simulation;
import java.util.List;
import era.mi.logic.Simulation;
-import era.mi.logic.Util;
import era.mi.logic.types.Bit;
import era.mi.logic.types.Bit;
+import era.mi.logic.types.BitVector;
+import era.mi.logic.types.BitVector.BitVectorMutator;
/**
* Represents an array of wires that can store n bits of information.
/**
* Represents an array of wires that can store n bits of information.
+ private BitVector values;
public final int travelTime;
private List<WireObserver> observers = new ArrayList<WireObserver>();
public final int length;
public final int travelTime;
private List<WireObserver> observers = new ArrayList<WireObserver>();
public final int length;
private void initValues()
{
private void initValues()
{
- values = Bit.U.makeArray(length);
+ values = U.toVector(length);
}
private void recalculateSingleInput()
{
}
private void recalculateSingleInput()
{
- WireEnd input = inputs.get(0);
- if (!Arrays.equals(input.getInputValues(), values))
- {
- Bit[] oldValues = values.clone();
- System.arraycopy(input.getInputValues(), 0, values, 0, length);
- notifyObservers(oldValues);
- }
+ setNewValues(inputs.get(0).getInputValues());
}
private void recalculateMultipleInputs()
{
}
private void recalculateMultipleInputs()
{
- Iterator<WireEnd> it = inputs.iterator();
- Bit[] newValues = it.next().inputValues.clone();
-
- while (it.hasNext())
- {
- WireEnd input = it.next();
- Bit[] bits = input.getInputValues();
- for (int i = 0; i < length; i++)
- {
- newValues[i] = newValues[i].join(bits[i]);
- }
- }
+ BitVectorMutator mutator = BitVectorMutator.empty();
+ for (WireEnd wireArrayEnd : inputs)
+ mutator.join(wireArrayEnd.getInputValues());
+ setNewValues(mutator.get());
+ }
- if (!Arrays.equals(newValues, values))
- {
- Bit[] oldValues = values;
- values = newValues;
- notifyObservers(oldValues);
- }
+ private void setNewValues(BitVector newValues)
+ {
+ if (values.equals(newValues))
+ return;
+ BitVector oldValues = values;
+ values = newValues;
+ notifyObservers(oldValues);
}
private void recalculate()
}
private void recalculate()
{
long val = 0;
long mask = 1;
{
long val = 0;
long mask = 1;
- for (int i = 0; i < length; i++)
public Bit getValue(int index)
{
public Bit getValue(int index)
{
+ return values.getBit(index);
- public Bit[] getValues(int start, int end)
+ public BitVector getValues(int start, int end)
- int length = end - start;
- Bit[] bits = new Bit[length];
- System.arraycopy(values, start, bits, 0, length);
- return bits;
+ return values.subVector(start, end);
- public Bit[] getValues()
+ public BitVector getValues()
return observers.add(ob);
}
return observers.add(ob);
}
- private void notifyObservers(Bit[] oldValues)
+ private void notifyObservers(BitVector oldValues)
{
for (WireObserver o : observers)
o.update(this, oldValues);
{
for (WireObserver o : observers)
o.update(this, oldValues);
public class WireEnd
{
private boolean open;
public class WireEnd
{
private boolean open;
- private Bit[] inputValues;
+ private BitVector inputValues;
private WireEnd(boolean readOnly)
{
super();
private WireEnd(boolean readOnly)
{
super();
+ open = !readOnly; // TODO: that makes sense, doesn't it?
initValues();
if (!readOnly)
registerInput(this);
initValues();
if (!readOnly)
registerInput(this);
private void initValues()
{
private void initValues()
{
- inputValues = Bit.U.makeArray(length);
+ inputValues = U.toVector(length);
*/
public void feedSignals(Bit... newValues)
{
*/
public void feedSignals(Bit... newValues)
{
- if (newValues.length != length)
+ feedSignals(BitVector.of(newValues));
+ }
+
+ public void feedSignals(BitVector newValues)
+ {
+ if (newValues.length() != length)
throw new IllegalArgumentException(
throw new IllegalArgumentException(
- String.format("Attempted to input %d bits instead of %d bits.", newValues.length, length));
- feedSignals(0, newValues);
+ String.format("Attempted to input %d bits instead of %d bits.", newValues.length(), length));
+ if (!open)
+ throw new RuntimeException("Attempted to write to closed WireArrayEnd.");
+ Simulation.TIMELINE.addEvent(e -> setValues(newValues), travelTime);
}
/**
* Sets values of a subarray of wires. This takes up time, as specified by the {@link Wire}s travel time.
*
}
/**
* Sets values of a subarray of wires. This takes up time, as specified by the {@link Wire}s travel time.
*
- * @param newValues The new values the wires should take on.
+ * @param bitVector The new values the wires should take on.
* @param startingBit The first index of the subarray of wires.
*
* @author Fabian Stemmler
*/
* @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, BitVector bitVector)
{
if (!open)
throw new RuntimeException("Attempted to write to closed WireArrayEnd.");
{
if (!open)
throw new RuntimeException("Attempted to write to closed WireArrayEnd.");
- Simulation.TIMELINE.addEvent((e) -> setValues(startingBit, newValues), travelTime);
+ Simulation.TIMELINE.addEvent(e -> setValues(startingBit, bitVector), travelTime);
- private void setValues(int startingBit, Bit... newValues)
+ private void setValues(int startingBit, BitVector newValues)
- int exclLastIndex = startingBit + newValues.length;
- if (length < exclLastIndex)
- throw new ArrayIndexOutOfBoundsException(
- String.format("Attempted to input bits from index %d to %d when there are only %d wires.", startingBit,
- exclLastIndex - 1, length));
- if (!Arrays.equals(inputValues, startingBit, exclLastIndex, newValues, 0, newValues.length))
+ // index check covered in equals
+ if (!inputValues.equalsWithOffset(newValues, startingBit))
- System.arraycopy(newValues, 0, inputValues, startingBit, newValues.length);
+ Bit[] vals = inputValues.getBits();
+ System.arraycopy(newValues.getBits(), 0, vals, startingBit, newValues.length());
+ inputValues = BitVector.of(vals);
Wire.this.recalculate();
}
}
Wire.this.recalculate();
}
}
+ private void setValues(BitVector newValues)
+ {
+ if (inputValues.equals(newValues))
+ return;
+ inputValues = newValues;
+ Wire.this.recalculate();
+ }
+
/**
* @return The value (of bit 0) the {@link WireEnd} is currently feeding into the associated {@link Wire}.
*/
/**
* @return The value (of bit 0) the {@link WireEnd} is currently feeding into the associated {@link Wire}.
*/
*/
public Bit getInputValue(int index)
{
*/
public Bit getInputValue(int index)
{
- return inputValues[index];
+ return inputValues.getBit(index);
}
/**
* @return A copy (safe to modify) of the values the {@link WireEnd} is currently feeding into the associated {@link Wire}.
*/
}
/**
* @return A copy (safe to modify) of the values the {@link WireEnd} is currently feeding into the associated {@link Wire}.
*/
- public Bit[] getInputValues()
+ public BitVector getInputValues()
{
return getInputValues(0, length);
}
{
return getInputValues(0, length);
}
- public Bit[] getInputValues(int start, int end)
+ public BitVector getInputValues(int start, int end)
- int length = end - start;
- Bit[] bits = new Bit[length];
- System.arraycopy(inputValues, start, bits, 0, length);
- return bits;
+ return inputValues.subVector(start, end);
*/
public void clearSignals()
{
*/
public void clearSignals()
{
- feedSignals(Bit.Z.makeArray(length));
+ feedSignals(Z.toVector(length));
- public Bit[] wireValuesExcludingMe()
+ public BitVector wireValuesExcludingMe()
- Bit[] bits = Bit.Z.makeArray(length);
- for (WireEnd wai : inputs)
+ BitVectorMutator mutator = BitVectorMutator.empty();
+ for (WireEnd wireEnd : inputs)
- Util.combineInto(bits, wai.getInputValues());
+ mutator.join(wireEnd.inputValues);
*
* @author Fabian Stemmler
*/
*
* @author Fabian Stemmler
*/
- public Bit[] getValues()
+ public BitVector getValues()
{
return Wire.this.getValues();
}
{
return Wire.this.getValues();
}
*
* @author Fabian Stemmler
*/
*
* @author Fabian Stemmler
*/
- public Bit[] getValues(int start, int end)
+ public BitVector getValues(int start, int end)
{
return Wire.this.getValues(start, end);
}
{
return Wire.this.getValues(start, end);
}
@Override
public String toString()
{
@Override
public String toString()
{
- return Arrays.toString(inputValues);
+ return inputValues.toString();
// return String.format("%s \nFeeding: %s", WireArray.this.toString(), Arrays.toString(inputValues));
}
// return String.format("%s \nFeeding: %s", WireArray.this.toString(), Arrays.toString(inputValues));
}
@Override
public String toString()
{
@Override
public String toString()
{
- return String.format("wire 0x%08x value: %s inputs: %s", hashCode(), Arrays.toString(values), inputs);
+ 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)
}
// Arrays.toString(values), inputs.stream().map(i -> Arrays.toString(i.inputValues)).reduce((s1, s2) -> s1 + s2)
}
package era.mi.logic.wires;
package era.mi.logic.wires;
-import era.mi.logic.types.Bit;
+import era.mi.logic.types.BitVector;
public interface WireObserver
{
public interface WireObserver
{
- public void update(Wire initiator, Bit[] oldValues);
+ public void update(Wire initiator, BitVector oldValues);