WireEnd functionality split into ReadEnd and ReadWriteEnd
[Mograsim.git] / era.mi / src / era / mi / logic / wires / Wire.java
index a7b96ee..9dba1fe 100644 (file)
@@ -1,6 +1,7 @@
 package era.mi.logic.wires;
 
-import static era.mi.logic.types.Bit.*;
+import static era.mi.logic.types.Bit.U;
+import static era.mi.logic.types.Bit.Z;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -20,9 +21,9 @@ public class Wire
 {
        private BitVector values;
        public final int travelTime;
-       private List<WireObserver> observers = new ArrayList<WireObserver>();
+       private List<ReadEnd> attached = new ArrayList<ReadEnd>();
        public final int length;
-       private List<WireEnd> inputs = new ArrayList<WireEnd>();
+       private List<ReadWriteEnd> inputs = new ArrayList<ReadWriteEnd>();
 
        public Wire(int length, int travelTime)
        {
@@ -47,7 +48,7 @@ public class Wire
        private void recalculateMultipleInputs()
        {
                BitVectorMutator mutator = BitVectorMutator.empty();
-               for (WireEnd wireArrayEnd : inputs)
+               for (ReadWriteEnd wireArrayEnd : inputs)
                        mutator.join(wireArrayEnd.getInputValues());
                setNewValues(mutator.get());
        }
@@ -112,7 +113,6 @@ public class Wire
                        case Z:
                        case X:
                                return 0; // TODO: Proper handling for getUnsignedValue(), if not all bits are 1 or 0;
-                       // Random number?
                        case ONE:
                                val |= mask;
                                break;
@@ -170,57 +170,189 @@ public class Wire
         * 
         * @author Fabian Stemmler
         */
-       public boolean addObserver(WireObserver ob)
+       private void attachEnd(ReadEnd end)
        {
-               return observers.add(ob);
+               attached.add(end);
+       }
+
+       private void detachEnd(ReadEnd end)
+       {
+               attached.remove(end);
        }
 
        private void notifyObservers(BitVector oldValues)
        {
-               for (WireObserver o : observers)
-                       o.update(this, oldValues);
+               for (ReadEnd o : attached)
+                       o.update(oldValues);
        }
 
        /**
-        * Create and register a {@link WireEnd} object, which is tied to this {@link Wire}.
+        * Create and register a {@link ReadWriteEnd} object, which is tied to this {@link Wire}. This {@link ReadWriteEnd} can be written to.
         */
-       public WireEnd createEnd()
+       public ReadWriteEnd createEnd()
        {
-               return new WireEnd(false);
+               return new ReadWriteEnd();
        }
 
        /**
-        * Create a {@link WireEnd} object, which is tied to this {@link Wire}. This {@link WireEnd} cannot written to.
+        * Create a {@link ReadEnd} object, which is tied to this {@link Wire}. This {@link ReadEnd} cannot be written to.
         */
-       public WireEnd createReadOnlyEnd()
+       public ReadEnd createReadOnlyEnd()
        {
-               return new WireEnd(true);
+               return new ReadEnd();
        }
 
-       private void registerInput(WireEnd toRegister)
+       private void registerInput(ReadWriteEnd toRegister)
        {
                inputs.add(toRegister);
        }
 
        /**
-        * A {@link WireEnd} feeds a constant signal into the {@link Wire} it is tied to. The combination of all inputs determines the
+        * A {@link ReadEnd} feeds a constant signal into the {@link Wire} it is tied to. The combination of all inputs determines the
         * {@link Wire}s final value. X dominates all other inputs Z does not affect the final value, unless there are no other inputs than Z 0
         * and 1 turn into X when they are mixed
         * 
         * @author Fabian Stemmler
         */
-       public class WireEnd
+       public class ReadEnd
+       {
+               private List<WireObserver> observers = new ArrayList<WireObserver>();
+
+               private ReadEnd()
+               {
+                       super();
+                       Wire.this.attachEnd(this);
+               }
+
+               public void update(BitVector oldValues)
+               {
+                       for (WireObserver ob : observers)
+                               ob.update(this, oldValues);
+               }
+
+               /**
+                * Included for convenient use on {@link Wire}s of length 1.
+                * 
+                * @return The value of bit 0.
+                * 
+                * @author Fabian Stemmler
+                */
+               public Bit getValue()
+               {
+                       return Wire.this.getValue();
+               }
+
+               /**
+                * @param index Index of the requested bit.
+                * @return The value of the indexed bit.
+                * 
+                * @author Fabian Stemmler
+                */
+               public Bit getValue(int index)
+               {
+                       return Wire.this.getValue(index);
+               }
+
+               /**
+                * @param index Index of the requested bit.
+                * @return The value of the indexed bit.
+                * 
+                * @author Fabian Stemmler
+                */
+               public BitVector getValues()
+               {
+                       return Wire.this.getValues();
+               }
+
+               /**
+                * @param start Start of the wanted segment. (inclusive)
+                * @param end   End of the wanted segment. (exclusive)
+                * @return The values of the segment of {@link Bit}s indexed.
+                * 
+                * @author Fabian Stemmler
+                */
+               public BitVector getValues(int start, int end)
+               {
+                       return Wire.this.getValues(start, end);
+               }
+
+               /**
+                * The {@link Wire} is interpreted as an unsigned integer with n bits.
+                * 
+                * @return <code>true</code> if all bits are either <code>Bit.ONE</code> or <code>Bit.ZERO</code> (they do not all have to have the
+                *         same value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is returned otherwise.
+                * 
+                * @author Fabian Stemmler
+                */
+               public boolean hasNumericValue()
+               {
+                       return Wire.this.hasNumericValue();
+               }
+
+               /**
+                * The {@link Wire} is interpreted as an unsigned integer with n bits.
+                * 
+                * @return The unsigned value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
+                * 
+                * @author Fabian Stemmler
+                */
+               public long getUnsignedValue()
+               {
+                       return Wire.this.getUnsignedValue();
+               }
+
+               /**
+                * The {@link Wire} is interpreted as a signed integer with n bits.
+                * 
+                * @return The signed value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
+                * 
+                * @author Fabian Stemmler
+                */
+               public long getSignedValue()
+               {
+                       return Wire.this.getSignedValue();
+               }
+
+               @Override
+               public String toString()
+               {
+                       return Wire.this.toString();
+               }
+
+               public void close()
+               {
+                       inputs.remove(this);
+                       detachEnd(this);
+                       recalculate();
+               }
+
+               public int length()
+               {
+                       return length;
+               }
+
+               public boolean addObserver(WireObserver ob)
+               {
+                       return observers.add(ob);
+               }
+
+               public Wire getWire()
+               {
+                       return Wire.this;
+               }
+       }
+
+       public class ReadWriteEnd extends ReadEnd
        {
                private boolean open;
                private BitVector inputValues;
 
-               private WireEnd(boolean readOnly)
+               private ReadWriteEnd()
                {
                        super();
-                       open = !readOnly; // TODO: that makes sense, doesn't it?
+                       open = true;
                        initValues();
-                       if (!readOnly)
-                               registerInput(this);
+                       registerInput(this);
                }
 
                private void initValues()
@@ -286,7 +418,7 @@ public class Wire
                }
 
                /**
-                * @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 ReadEnd} is currently feeding into the associated {@link Wire}.
                 */
                public Bit getInputValue()
                {
@@ -294,7 +426,7 @@ public class Wire
                }
 
                /**
-                * @return The value which the {@link WireEnd} is currently feeding into the associated {@link Wire} at the indexed {@link Bit}.
+                * @return The value which the {@link ReadEnd} is currently feeding into the associated {@link Wire} at the indexed {@link Bit}.
                 */
                public Bit getInputValue(int index)
                {
@@ -302,7 +434,7 @@ public class Wire
                }
 
                /**
-                * @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 ReadEnd} is currently feeding into the associated {@link Wire}.
                 */
                public BitVector getInputValues()
                {
@@ -315,7 +447,7 @@ public class Wire
                }
 
                /**
-                * {@link WireEnd} now feeds Z into the associated {@link Wire}.
+                * {@link ReadEnd} now feeds Z into the associated {@link Wire}.
                 */
                public void clearSignals()
                {
@@ -325,7 +457,7 @@ public class Wire
                public BitVector wireValuesExcludingMe()
                {
                        BitVectorMutator mutator = BitVectorMutator.empty();
-                       for (WireEnd wireEnd : inputs)
+                       for (ReadWriteEnd wireEnd : inputs)
                        {
                                if (wireEnd == this)
                                        continue;
@@ -334,115 +466,10 @@ public class Wire
                        return mutator.get();
                }
 
-               /**
-                * Included for convenient use on {@link Wire}s of length 1.
-                * 
-                * @return The value of bit 0.
-                * 
-                * @author Fabian Stemmler
-                */
-               public Bit getValue()
-               {
-                       return Wire.this.getValue();
-               }
-
-               /**
-                * @param index Index of the requested bit.
-                * @return The value of the indexed bit.
-                * 
-                * @author Fabian Stemmler
-                */
-               public Bit getValue(int index)
-               {
-                       return Wire.this.getValue(index);
-               }
-
-               /**
-                * @param index Index of the requested bit.
-                * @return The value of the indexed bit.
-                * 
-                * @author Fabian Stemmler
-                */
-               public BitVector getValues()
-               {
-                       return Wire.this.getValues();
-               }
-
-               /**
-                * @param start Start of the wanted segment. (inclusive)
-                * @param end   End of the wanted segment. (exclusive)
-                * @return The values of the segment of {@link Bit}s indexed.
-                * 
-                * @author Fabian Stemmler
-                */
-               public BitVector getValues(int start, int end)
-               {
-                       return Wire.this.getValues(start, end);
-               }
-
-               /**
-                * The {@link Wire} is interpreted as an unsigned integer with n bits.
-                * 
-                * @return <code>true</code> if all bits are either <code>Bit.ONE</code> or <code>Bit.ZERO</code> (they do not all have to have the
-                *         same value), not <code>Bit.X</code> or <code>Bit.Z</code>. <code>false</code> is returned otherwise.
-                * 
-                * @author Fabian Stemmler
-                */
-               public boolean hasNumericValue()
-               {
-                       return Wire.this.hasNumericValue();
-               }
-
-               /**
-                * The {@link Wire} is interpreted as an unsigned integer with n bits.
-                * 
-                * @return The unsigned value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
-                * 
-                * @author Fabian Stemmler
-                */
-               public long getUnsignedValue()
-               {
-                       return Wire.this.getUnsignedValue();
-               }
-
-               /**
-                * The {@link Wire} is interpreted as a signed integer with n bits.
-                * 
-                * @return The signed value of the {@link Wire}'s bits, where value 0 corresponds with 2^0, value 1 is 2^1 and so on.
-                * 
-                * @author Fabian Stemmler
-                */
-               public long getSignedValue()
-               {
-                       return Wire.this.getSignedValue();
-               }
-
                @Override
                public String toString()
                {
                        return inputValues.toString();
-                       // return String.format("%s \nFeeding: %s", WireArray.this.toString(), Arrays.toString(inputValues));
-               }
-
-               public void close()
-               {
-                       inputs.remove(this);
-                       open = false;
-               }
-
-               public int length()
-               {
-                       return length;
-               }
-
-               public boolean addObserver(WireObserver ob)
-               {
-                       return Wire.this.addObserver(ob);
-               }
-
-               public Wire getWire()
-               {
-                       return Wire.this;
                }
        }
 
@@ -453,9 +480,9 @@ public class Wire
                // Arrays.toString(values), inputs.stream().map(i -> Arrays.toString(i.inputValues)).reduce((s1, s2) -> s1 + s2)
        }
 
-       public static WireEnd[] extractEnds(Wire[] w)
+       public static ReadEnd[] extractEnds(Wire[] w)
        {
-               WireEnd[] inputs = new WireEnd[w.length];
+               ReadEnd[] inputs = new ReadEnd[w.length];
                for (int i = 0; i < w.length; i++)
                        inputs[i] = w[i].createEnd();
                return inputs;