Serializing now serializes everything; among many other things:
[Mograsim.git] / net.mograsim.logic.model / src / net / mograsim / logic / model / snippets / highlevelstatehandlers / standard / atomic / WireForcingAtomicHighLevelStateHandler.java
1 package net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.atomic;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Map;
6 import java.util.function.Function;
7 import java.util.stream.Collectors;
8
9 import net.mograsim.logic.core.types.Bit;
10 import net.mograsim.logic.core.types.BitVector;
11 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
12 import net.mograsim.logic.model.model.wires.GUIWire;
13 import net.mograsim.logic.model.serializing.IdentifierGetter;
14 import net.mograsim.logic.model.snippets.SnippetDefinintion;
15 import net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.HighLevelStateHandlerContext;
16 import net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.StandardHighLevelStateHandlerSnippetSuppliers;
17
18 public class WireForcingAtomicHighLevelStateHandler implements AtomicHighLevelStateHandler
19 {
20         private SubmodelComponent component;
21         private int logicWidth;
22         private final List<GUIWire> wiresToForce;
23         private final List<GUIWire> wiresToForceInverted;
24
25         public WireForcingAtomicHighLevelStateHandler(HighLevelStateHandlerContext context)
26         {
27                 this(context, null);
28         }
29
30         public WireForcingAtomicHighLevelStateHandler(HighLevelStateHandlerContext context, WireForcingAtomicHighLevelStateHandlerParams params)
31         {
32                 this.component = context.component;
33                 this.wiresToForce = new ArrayList<>();
34                 this.wiresToForceInverted = new ArrayList<>();
35                 if (params != null)
36                 {
37                         Map<String, GUIWire> wiresByName = component.submodel.getWiresByName();
38                         setWiresToForce(params.wiresToForce.stream().map((Function<String, GUIWire>) wiresByName::get).collect(Collectors.toList()),
39                                         params.wiresToForceInverted.stream().map((Function<String, GUIWire>) wiresByName::get).collect(Collectors.toList()));
40                 }
41         }
42
43         public void set(List<GUIWire> wiresToForce, List<GUIWire> wiresToForceInverted)
44         {
45                 setWiresToForce(wiresToForce, wiresToForceInverted);
46         }
47
48         public void setWiresToForce(List<GUIWire> wiresToForce, List<GUIWire> wiresToForceInverted)
49         {
50                 clearWiresToForce();
51                 for (GUIWire wire : wiresToForce)
52                         addWireToForce(wire, false);
53                 for (GUIWire wire : wiresToForceInverted)
54                         addWireToForce(wire, true);
55         }
56
57         public void addWireToForce(GUIWire wire, boolean inverted)
58         {
59                 if (component.submodel.getWiresByName().get(wire.name) != wire)
60                         throw new IllegalArgumentException("Can only force wires belonging to the parent component of this handler");
61                 if (logicWidth < 1)
62                         logicWidth = wire.logicWidth;
63                 else if (wire.logicWidth != logicWidth)
64                         throw new IllegalArgumentException("Can only force wires of the same logic width");
65                 if (inverted)
66                         wiresToForceInverted.add(wire);
67                 else
68                         wiresToForce.add(wire);
69         }
70
71         public void clearWiresToForce()
72         {
73                 wiresToForce.clear();
74                 wiresToForceInverted.clear();
75                 logicWidth = 0;
76         }
77
78         @Override
79         public Object getHighLevelState()
80         {
81                 BitVector result = BitVector.of(Bit.ZERO, logicWidth);
82                 for (GUIWire wire : wiresToForceInverted)
83                         if (wire.hasLogicModelBinding())
84                                 result = result.or(wire.getWireValues());
85                 result = result.not();
86                 for (GUIWire wire : wiresToForce)
87                         if (wire.hasLogicModelBinding())
88                                 result = result.and(wire.getWireValues());
89                 return result;
90         }
91
92         @Override
93         public void setHighLevelState(Object newState)
94         {
95                 BitVector vector;
96                 if (newState instanceof Bit)
97                         vector = BitVector.of((Bit) newState);
98                 else
99                         vector = (BitVector) newState;
100                 for (GUIWire wire : wiresToForce)
101                         if (wire.hasLogicModelBinding())
102                                 wire.forceWireValues(vector);
103                 vector = vector.not();
104                 for (GUIWire wire : wiresToForceInverted)
105                         if (wire.hasLogicModelBinding())
106                                 wire.forceWireValues(vector);
107         }
108
109         @Override
110         public WireForcingAtomicHighLevelStateHandlerParams getParamsForSerializing(IdentifierGetter idGetter)
111         {
112                 WireForcingAtomicHighLevelStateHandlerParams params = new WireForcingAtomicHighLevelStateHandlerParams();
113                 params.wiresToForce = wiresToForce.stream().map(w -> w.name).collect(Collectors.toList());
114                 params.wiresToForceInverted = wiresToForceInverted.stream().map(w -> w.name).collect(Collectors.toList());
115                 return params;
116         }
117
118         public static class WireForcingAtomicHighLevelStateHandlerParams
119         {
120                 public List<String> wiresToForce;
121                 public List<String> wiresToForceInverted;
122         }
123
124         static
125         {
126                 StandardHighLevelStateHandlerSnippetSuppliers.atomicHandlerSupplier.setSnippetSupplier(
127                                 WireForcingAtomicHighLevelStateHandler.class.getCanonicalName(),
128                                 SnippetDefinintion.create(WireForcingAtomicHighLevelStateHandlerParams.class, WireForcingAtomicHighLevelStateHandler::new));
129         }
130 }