Shortened the memory test a bit because it was longer than necessary
[Mograsim.git] / net.mograsim.logic.model / src / net / mograsim / logic / model / snippets / highlevelstatehandlers / standard / atomic / WireForcingAtomicHighLevelStateHandler.java
index c1e8faf..276f541 100644 (file)
@@ -1,6 +1,7 @@
 package net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.atomic;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -9,52 +10,60 @@ import java.util.stream.Collectors;
 import net.mograsim.logic.core.types.Bit;
 import net.mograsim.logic.core.types.BitVector;
 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
-import net.mograsim.logic.model.model.wires.GUIWire;
+import net.mograsim.logic.model.model.wires.ModelWire;
 import net.mograsim.logic.model.serializing.IdentifyParams;
 import net.mograsim.logic.model.snippets.SnippetDefinintion;
-import net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.HighLevelStateHandlerContext;
 import net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.StandardHighLevelStateHandlerSnippetSuppliers;
 
 public class WireForcingAtomicHighLevelStateHandler implements AtomicHighLevelStateHandler
 {
-       private SubmodelComponent component;
+       private final SubmodelComponent component;
        private int logicWidth;
-       private final List<GUIWire> wiresToForce;
-       private final List<GUIWire> wiresToForceInverted;
+       private final List<ModelWire> wiresToForce;
+       private final List<ModelWire> wiresToForceUnmodifiable;
+       private final List<ModelWire> wiresToForceInverted;
+       private final List<ModelWire> wiresToForceInvertedUnmodifiable;
 
-       public WireForcingAtomicHighLevelStateHandler(HighLevelStateHandlerContext context)
+       public WireForcingAtomicHighLevelStateHandler(SubmodelComponent component)
        {
-               this(context, null);
+               this(component, null);
        }
 
-       public WireForcingAtomicHighLevelStateHandler(HighLevelStateHandlerContext context, WireForcingAtomicHighLevelStateHandlerParams params)
+       public WireForcingAtomicHighLevelStateHandler(SubmodelComponent component, WireForcingAtomicHighLevelStateHandlerParams params)
        {
-               this.component = context.component;
+               this.component = component;
                this.wiresToForce = new ArrayList<>();
+               this.wiresToForceUnmodifiable = Collections.unmodifiableList(wiresToForce);
                this.wiresToForceInverted = new ArrayList<>();
+               this.wiresToForceInvertedUnmodifiable = Collections.unmodifiableList(wiresToForceInverted);
                if (params != null)
                {
-                       Map<String, GUIWire> wiresByName = component.submodel.getWiresByName();
-                       setWiresToForce(params.wiresToForce.stream().map((Function<String, GUIWire>) wiresByName::get).collect(Collectors.toList()),
-                                       params.wiresToForceInverted.stream().map((Function<String, GUIWire>) wiresByName::get).collect(Collectors.toList()));
+                       Map<String, ModelWire> wiresByName = component.submodel.getWiresByName();
+                       setWiresToForce(params.wiresToForce.stream().map((Function<String, ModelWire>) wiresByName::get).collect(Collectors.toList()),
+                                       params.wiresToForceInverted.stream().map((Function<String, ModelWire>) wiresByName::get).collect(Collectors.toList()));
                }
+               component.submodel.addWireRemovedListener(w ->
+               {
+                       wiresToForce.removeIf(w::equals);
+                       wiresToForceInverted.removeIf(w::equals);
+               });
        }
 
-       public void set(List<GUIWire> wiresToForce, List<GUIWire> wiresToForceInverted)
+       public void set(List<ModelWire> wiresToForce, List<ModelWire> wiresToForceInverted)
        {
                setWiresToForce(wiresToForce, wiresToForceInverted);
        }
 
-       public void setWiresToForce(List<GUIWire> wiresToForce, List<GUIWire> wiresToForceInverted)
+       public void setWiresToForce(List<ModelWire> wiresToForce, List<ModelWire> wiresToForceInverted)
        {
                clearWiresToForce();
-               for (GUIWire wire : wiresToForce)
+               for (ModelWire wire : wiresToForce)
                        addWireToForce(wire, false);
-               for (GUIWire wire : wiresToForceInverted)
+               for (ModelWire wire : wiresToForceInverted)
                        addWireToForce(wire, true);
        }
 
-       public void addWireToForce(GUIWire wire, boolean inverted)
+       public void addWireToForce(ModelWire wire, boolean inverted)
        {
                if (component.submodel.getWiresByName().get(wire.name) != wire)
                        throw new IllegalArgumentException("Can only force wires belonging to the parent component of this handler");
@@ -62,6 +71,8 @@ public class WireForcingAtomicHighLevelStateHandler implements AtomicHighLevelSt
                        logicWidth = wire.logicWidth;
                else if (wire.logicWidth != logicWidth)
                        throw new IllegalArgumentException("Can only force wires of the same logic width");
+               // this can add the same wire multiple times, but maybe there is a weird configuration where it is neccessary, due to race
+               // conditions, to force the same wire twice.
                if (inverted)
                        wiresToForceInverted.add(wire);
                else
@@ -75,16 +86,26 @@ public class WireForcingAtomicHighLevelStateHandler implements AtomicHighLevelSt
                logicWidth = 0;
        }
 
+       public List<ModelWire> getWiresToForce()
+       {
+               return wiresToForceUnmodifiable;
+       }
+
+       public List<ModelWire> getWiresToForceInverted()
+       {
+               return wiresToForceInvertedUnmodifiable;
+       }
+
        @Override
        public Object getHighLevelState()
        {
                BitVector result = BitVector.of(Bit.ZERO, logicWidth);
-               for (GUIWire wire : wiresToForceInverted)
-                       if (wire.hasLogicModelBinding())
+               for (ModelWire wire : wiresToForceInverted)
+                       if (wire.hasCoreModelBinding())
                                result = result.or(wire.getWireValues());
                result = result.not();
-               for (GUIWire wire : wiresToForce)
-                       if (wire.hasLogicModelBinding())
+               for (ModelWire wire : wiresToForce)
+                       if (wire.hasCoreModelBinding())
                                result = result.and(wire.getWireValues());
                return result;
        }
@@ -97,12 +118,12 @@ public class WireForcingAtomicHighLevelStateHandler implements AtomicHighLevelSt
                        vector = BitVector.of((Bit) newState);
                else
                        vector = (BitVector) newState;
-               for (GUIWire wire : wiresToForce)
-                       if (wire.hasLogicModelBinding())
+               for (ModelWire wire : wiresToForce)
+                       if (wire.hasCoreModelBinding())
                                wire.forceWireValues(vector);
                vector = vector.not();
-               for (GUIWire wire : wiresToForceInverted)
-                       if (wire.hasLogicModelBinding())
+               for (ModelWire wire : wiresToForceInverted)
+                       if (wire.hasCoreModelBinding())
                                wire.forceWireValues(vector);
        }