From e2cfc152b70fb4b2d8abb8ff4c901ceacf4c89cc Mon Sep 17 00:00:00 2001 From: Fabian Stemmler Date: Tue, 18 Jun 2019 21:38:22 +0200 Subject: [PATCH] Logic Wire bits can now be fused together (Wire.fuse(...)) --- .../mograsim/logic/core/LogicObserver.java | 1 + .../logic/core/tests/ComponentTest.java | 30 +++++++++ .../net/mograsim/logic/core/wires/Wire.java | 66 ++++++++++++++++++- 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObserver.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObserver.java index 5955656f..259fe4d7 100644 --- a/net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObserver.java +++ b/net.mograsim.logic.core/src/net/mograsim/logic/core/LogicObserver.java @@ -1,5 +1,6 @@ package net.mograsim.logic.core; +@FunctionalInterface public interface LogicObserver { public void update(LogicObservable initiator); diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/tests/ComponentTest.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/tests/ComponentTest.java index 38d1b7c6..a595f056 100644 --- a/net.mograsim.logic.core/src/net/mograsim/logic/core/tests/ComponentTest.java +++ b/net.mograsim.logic.core/src/net/mograsim/logic/core/tests/ComponentTest.java @@ -87,6 +87,36 @@ class ComponentTest assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE); } + @Test + void fusionTest() + { + t.reset(); + Wire a = new Wire(t, 3, 1), b = new Wire(t, 2, 1), c = new Wire(t, 3, 1), out = new Wire(t, 8, 1); + Wire.fuse(a, out, 0, 0, a.length); + Wire.fuse(b, out, 0, a.length, b.length); + Wire.fuse(c, out, 0, a.length + b.length, c.length); + ReadWriteEnd rA = a.createReadWriteEnd(); + rA.feedSignals(Bit.ZERO, Bit.ONE, Bit.ZERO); + ReadWriteEnd rB = b.createReadWriteEnd(); + rB.feedSignals(Bit.ONE, Bit.ZERO); + ReadWriteEnd rC = c.createReadWriteEnd(); + rC.feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE); + t.executeAll(); + assertBitArrayEquals(out.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE); + out.createReadWriteEnd().feedSignals(Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO, Bit.ONE, Bit.ZERO); + t.executeAll(); + assertBitArrayEquals(rA.getValues(), Bit.X, Bit.X, Bit.X); + assertBitArrayEquals(rB.getValues(), Bit.X, Bit.X); + assertBitArrayEquals(rC.getValues(), Bit.X, Bit.X, Bit.X); + rA.clearSignals(); + rB.clearSignals(); + rC.clearSignals(); + t.executeAll(); + assertBitArrayEquals(rA.getValues(), Bit.ONE, Bit.ZERO, Bit.ONE); + assertBitArrayEquals(rB.getValues(), Bit.ZERO, Bit.ONE); + assertBitArrayEquals(rC.getValues(), Bit.ZERO, Bit.ONE, Bit.ZERO); + } + @Test void triStateBufferTest() { diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/wires/Wire.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/wires/Wire.java index bae4cb41..04ca9ce3 100644 --- a/net.mograsim.logic.core/src/net/mograsim/logic/core/wires/Wire.java +++ b/net.mograsim.logic.core/src/net/mograsim/logic/core/wires/Wire.java @@ -419,7 +419,11 @@ public class Wire timeline.addEvent(e -> setValues(startingBit, bitVector), travelTime); } - private void setValues(int startingBit, BitVector newValues) + /** + * Sets the values that are being fed into the {@link Wire}. The preferred way of setting {@link ReadWriteEnd} values is via + * feedValues(...) with a delay. + */ + void setValues(int startingBit, BitVector newValues) { // index check covered in equals if (!inputValues.equalsWithOffset(newValues, startingBit)) @@ -431,7 +435,11 @@ public class Wire } } - private void setValues(BitVector newValues) + /** + * Sets the values that are being fed into the {@link Wire}. The preferred way of setting {@link ReadWriteEnd} values is via + * feedValues(...) with a delay. + */ + void setValues(BitVector newValues) { if (inputValues.equals(newValues)) return; @@ -509,4 +517,58 @@ public class Wire inputs[i] = w[i].createReadWriteEnd(); return inputs; } + + /** + * @formatter:off + * Fuses the selected bits of two wires together. If the bits change in one Wire, the other is changed accordingly immediately. + * Warning: The bits are permanently fused together. + * @formatter:on + * @param a The {@link Wire} to be (partially) fused with b + * @param b The {@link Wire} to be (partially) fused with a + * @param fromA The first bit of {@link Wire} a to be fused + * @param fromB The first bit of {@link Wire} b to be fused + * @param length The amount of bits to fuse + */ + public static void fuse(Wire a, Wire b, int fromA, int fromB, int length) + { + ReadWriteEnd rA = a.createReadWriteEnd(), rB = b.createReadWriteEnd(); + rA.setValues(BitVector.of(Bit.Z, a.length)); + rB.setValues(BitVector.of(Bit.Z, b.length)); + rA.registerObserver(new Fusion(rB, fromA, fromB, length)); + rB.registerObserver(new Fusion(rA, fromB, fromA, length)); + } + + /** + * @formatter:off + * Fuses the selected bits of two wires together. If the bits change in one Wire, the other is changed accordingly immediately. + * Warning: The bits are permanently fused together. + * @formatter:on + * @param a The {@link Wire} to be fused with b + * @param b The {@link Wire} to be fused with a + */ + public static void fuse(Wire a, Wire b) + { + fuse(a, b, 0, 0, a.length); + } + + private static class Fusion implements LogicObserver + { + private ReadWriteEnd target; + int fromSource, fromTarget, length; + + public Fusion(ReadWriteEnd target, int fromSource, int fromTarget, int length) + { + this.target = target; + this.fromSource = fromSource; + this.fromTarget = fromTarget; + this.length = length; + } + + @Override + public void update(LogicObservable initiator) + { + ReadWriteEnd read = (ReadWriteEnd) initiator; + target.setValues(fromTarget, read.wireValuesExcludingMe().subVector(fromSource, fromSource + length)); + } + } } \ No newline at end of file -- 2.17.1