values = U.toVector(length);\r
}\r
\r
- private void recalculateSingleInput()\r
- {\r
- setNewValues(inputs.get(0).getInputValues());\r
- }\r
-\r
- private void recalculateMultipleInputs()\r
- {\r
- BitVectorMutator mutator = BitVectorMutator.empty();\r
- for (ReadWriteEnd wireArrayEnd : inputs)\r
- mutator.join(wireArrayEnd.getInputValues());\r
- setNewValues(mutator.get());\r
- }\r
-\r
private void setNewValues(BitVector newValues)\r
{\r
if (values.equals(newValues))\r
\r
void recalculate()\r
{\r
- switch (inputs.size())\r
+ if (inputs.size() == 0)\r
+ setNewValues(BitVector.of(Bit.U, length));\r
+ else\r
{\r
- case 0:\r
- return;\r
- case 1:\r
- recalculateSingleInput();\r
- break;\r
- default:\r
- recalculateMultipleInputs();\r
+ BitVectorMutator mutator = BitVectorMutator.empty();\r
+ for (ReadWriteEnd wireArrayEnd : inputs)\r
+ mutator.join(wireArrayEnd.getInputValues());\r
+ setNewValues(mutator.toBitVector());\r
}\r
}\r
\r
+ /**\r
+ * Forces a Wire to take on specific values. If the new values differ from the old ones, the observers of the Wire will be notified.\r
+ * WARNING! Use this with care! The preferred way of writing the values is ReadWriteEnd.feedSignals(BitVector)\r
+ * \r
+ * @param values The values the <code>Wire</code> will have immediately after this method is called\r
+ */\r
+ public void forceValues(BitVector values)\r
+ {\r
+ setNewValues(values);\r
+ }\r
+\r
/**\r
* The {@link Wire} is interpreted as an unsigned integer with n bits.\r
* \r
return val;\r
}\r
\r
+ /**\r
+ * Returns the least significant bit (LSB)\r
+ */\r
public Bit getValue()\r
{\r
return getValue(0);\r
}\r
\r
+ /**\r
+ * Returns the least significant bit (LSB) of the given index\r
+ */\r
public Bit getValue(int index)\r
{\r
- return values.getBit(index);\r
+ return values.getLSBit(index);\r
}\r
\r
public BitVector getValues(int start, int end)\r
\r
public class ReadWriteEnd extends ReadEnd\r
{\r
- private boolean open;\r
+ private boolean open, isWriting;\r
private BitVector inputValues;\r
\r
ReadWriteEnd()\r
{\r
super();\r
open = true;\r
+ isWriting = true;\r
initValues();\r
registerInput(this);\r
}\r
timeline.addEvent(e -> setValues(startingBit, bitVector), travelTime);\r
}\r
\r
- private void setValues(int startingBit, BitVector newValues)\r
+ /**\r
+ * Sets the values that are being fed into the {@link Wire}. The preferred way of setting {@link ReadWriteEnd} values is via\r
+ * feedValues(...) with a delay.\r
+ */\r
+ void setValues(int startingBit, BitVector newValues)\r
{\r
// index check covered in equals\r
if (!inputValues.equalsWithOffset(newValues, startingBit))\r
}\r
}\r
\r
- private void setValues(BitVector newValues)\r
+ /**\r
+ * Sets the values that are being fed into the {@link Wire}. The preferred way of setting {@link ReadWriteEnd} values is via\r
+ * feedValues(...) with a delay.\r
+ */\r
+ void setValues(BitVector newValues)\r
{\r
if (inputValues.equals(newValues))\r
return;\r
}\r
\r
/**\r
- * @return The value (of bit 0) the {@link ReadEnd} is currently feeding into the associated {@link Wire}.\r
+ * @return The value (of bit 0) the {@link ReadEnd} is currently feeding into the associated {@link Wire}.Returns the least\r
+ * significant bit (LSB)\r
*/\r
public Bit getInputValue()\r
{\r
\r
/**\r
* @return The value which the {@link ReadEnd} is currently feeding into the associated {@link Wire} at the indexed {@link Bit}.\r
+ * Returns the least significant bit (LSB)\r
+ * \r
*/\r
public Bit getInputValue(int index)\r
{\r
- return inputValues.getBit(index);\r
+ return inputValues.getLSBit(index);\r
}\r
\r
/**\r
*/\r
public BitVector getInputValues()\r
{\r
- return getInputValues(0, length);\r
+ return inputValues;\r
}\r
\r
public BitVector getInputValues(int start, int end)\r
continue;\r
mutator.join(wireEnd.inputValues);\r
}\r
- return mutator.get();\r
+ return mutator.toBitVector();\r
}\r
\r
@Override\r
{\r
return inputValues.toString();\r
}\r
+\r
+ @Override\r
+ public void close()\r
+ {\r
+ super.close();\r
+ open = false;\r
+ }\r
+\r
+ void setWriting(boolean isWriting)\r
+ {\r
+ if (this.isWriting != isWriting)\r
+ {\r
+ this.isWriting = isWriting;\r
+ if (isWriting)\r
+ inputs.add(this);\r
+ else\r
+ inputs.remove(this);\r
+ Wire.this.recalculate();\r
+ }\r
+ }\r
+\r
+ boolean isWriting()\r
+ {\r
+ return isWriting;\r
+ }\r
}\r
\r
@Override\r
inputs[i] = w[i].createReadWriteEnd();\r
return inputs;\r
}\r
+\r
+ // TODO Fix ReadWriteEnd feeding signals to entire Wire (Z) instead of only selected Bits\r
+ /**\r
+ * Fuses the selected bits of two wires together. If the bits change in one Wire, the other is changed accordingly immediately. Warning:\r
+ * The bits are permanently fused together.\r
+ * \r
+ * @param a The {@link Wire} to be (partially) fused with b\r
+ * @param b The {@link Wire} to be (partially) fused with a\r
+ * @param fromA The first bit of {@link Wire} a to be fused\r
+ * @param fromB The first bit of {@link Wire} b to be fused\r
+ * @param length The amount of bits to fuse\r
+ */\r
+ public static void fuse(Wire a, Wire b, int fromA, int fromB, int length)\r
+ {\r
+ ReadWriteEnd rA = a.createReadWriteEnd(), rB = b.createReadWriteEnd();\r
+ rA.setWriting(false);\r
+ rB.setWriting(false);\r
+ rA.setValues(BitVector.of(Bit.Z, a.length));\r
+ rB.setValues(BitVector.of(Bit.Z, b.length));\r
+ Fusion aF = new Fusion(rB, fromA, fromB, length), bF = new Fusion(rA, fromB, fromA, length);\r
+ rA.registerObserver(aF);\r
+ rB.registerObserver(bF);\r
+ aF.update(rA);\r
+ bF.update(rB);\r
+ }\r
+\r
+ /**\r
+ * \r
+ * Fuses two wires together. If the bits change in one Wire, the other is changed accordingly immediately. Warning: The bits are\r
+ * permanently fused together.\r
+ * \r
+ * @param a The {@link Wire} to be fused with b\r
+ * @param b The {@link Wire} to be fused with a\r
+ */\r
+ public static void fuse(Wire a, Wire b)\r
+ {\r
+ fuse(a, b, 0, 0, a.length);\r
+ }\r
+\r
+ private static class Fusion implements LogicObserver\r
+ {\r
+ private ReadWriteEnd target;\r
+ int fromSource, fromTarget, length;\r
+\r
+ public Fusion(ReadWriteEnd target, int fromSource, int fromTarget, int length)\r
+ {\r
+ this.target = target;\r
+ this.fromSource = fromSource;\r
+ this.fromTarget = fromTarget;\r
+ this.length = length;\r
+ }\r
+\r
+ @Override\r
+ public void update(LogicObservable initiator)\r
+ {\r
+ ReadWriteEnd source = (ReadWriteEnd) initiator;\r
+ if (source.getWire().inputs.size() - (source.isWriting() ? 1 : 0) == 0)\r
+ target.setWriting(false);\r
+ else\r
+ {\r
+ target.setWriting(true);\r
+ BitVector targetInput = source.wireValuesExcludingMe().subVector(fromSource, fromSource + length);\r
+ target.setValues(fromTarget, targetInput);\r
+ }\r
+ }\r
+ }\r
}
\ No newline at end of file