From: Daniel Kirschten Date: Wed, 19 Jun 2019 11:04:01 +0000 (+0200) Subject: Merge commit '28314e7a9a3c3ebfcc4db8e9f1875507063ae6e6' into development X-Git-Url: https://mograsim.net/gitweb/?a=commitdiff_plain;h=1696b802fc36276d5135a1e5e74b601ae9776b08;hp=e1db47ab3504bbfe8543c9a986d2a89d001ff650;p=Mograsim.git Merge commit '28314e7a9a3c3ebfcc4db8e9f1875507063ae6e6' into development --- 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 9375004a..9fef1763 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 0c8a4b8b..0505b4ce 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 6e4e50ad..20bcad1e 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