+ // TODO checks
+ for (int i = 0; i < width; i++)
+ fuse(a, b, fromA + i, fromB + i);
+// ReadWriteEnd rA = a.createReadWriteEnd(), rB = b.createReadWriteEnd();
+// rA.registerObserver(x -> rB.feedSignals(fromB, rA.wireValuesExcludingMe().subVector(fromA, fromA + width)));
+// rB.registerObserver(x -> rA.feedSignals(fromA, rB.wireValuesExcludingMe().subVector(fromB, fromB + width)));
+//
+// rA.setValues(0, BitVector.of(Bit.Z, fromA));
+// rB.setValues(0, BitVector.of(Bit.Z, fromB));
+// rA.setValues(fromA + width, BitVector.of(Bit.Z, a.width - width - fromA));
+// rB.setValues(fromB + width, BitVector.of(Bit.Z, b.width - width - fromB));
+//
+// rA.notifyObservers();
+// rB.notifyObservers();
+ }
+
+ /**
+ * Fuses one bit of two wires together. If this bit changes in one Wire, the other is changed accordingly immediately. Warning: The bits
+ * are permanently fused together.
+ *
+ * @param a The {@link Wire} to be (partially) fused with b
+ * @param b The {@link Wire} to be (partially) fused with a
+ * @param bitA The bit of {@link Wire} a to be fused
+ * @param bitB The bit of {@link Wire} b to be fused
+ */
+ private static void fuse(Wire a, Wire b, int bitA, int bitB)
+ {
+ if (a.fusedBits == null)
+ a.fusedBits = new FusionedBit[a.width];
+ if (b.fusedBits == null)
+ b.fusedBits = new FusionedBit[b.width];
+ FusionedBit oldFusionA = a.fusedBits[bitA];
+ FusionedBit oldFusionB = b.fusedBits[bitB];
+ if (oldFusionA == null)
+ if (oldFusionB == null)
+ {
+ FusionedBit fusion = new FusionedBit();
+ fusion.addParticipatingWireBit(a, bitA);
+ fusion.addParticipatingWireBit(b, bitB);
+ } else
+ oldFusionB.addParticipatingWireBit(a, bitA);
+ else if (oldFusionB == null)
+ oldFusionA.addParticipatingWireBit(b, bitB);
+ else
+ oldFusionA.mergeOtherIntoThis(oldFusionB);
+ }
+
+ private static class FusionedBit
+ {
+ private final List<WireBit> participatingWireBits;
+
+ public FusionedBit()
+ {
+ this.participatingWireBits = new ArrayList<>();
+ }
+
+ public void addParticipatingWireBit(Wire w, int bit)
+ {
+ addParticipatingWireBit(new WireBit(w, bit));
+ }
+
+ private void addParticipatingWireBit(WireBit wb)
+ {
+ wb.wire.fusedBits[wb.bit] = this;
+ participatingWireBits.add(wb);
+ wb.wire.invalidateCachedValuesForAllFusedWires();
+ }
+
+ public void mergeOtherIntoThis(FusionedBit other)
+ {
+ for (WireBit wb : other.participatingWireBits)
+ addParticipatingWireBit(wb);
+ }