4289808dcd2a04e698d886680da169dd5e781b9c
[Mograsim.git] / plugins / net.mograsim.logic.model / src / net / mograsim / logic / model / snippets / highlevelstatehandlers / standard / atomic / BitVectorSplittingAtomicHighLevelStateHandler.java
1 package net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.atomic;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.function.Consumer;
9
10 import net.mograsim.logic.core.types.Bit;
11 import net.mograsim.logic.core.types.BitVector;
12 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
13 import net.mograsim.logic.model.serializing.IdentifyParams;
14 import net.mograsim.logic.model.snippets.SnippetDefinintion;
15 import net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.StandardHighLevelStateHandlerSnippetSuppliers;
16
17 public class BitVectorSplittingAtomicHighLevelStateHandler implements AtomicHighLevelStateHandler
18 {
19         private final SubmodelComponent component;
20         private final List<String> vectorPartTargets;
21         private final List<String> vectorPartTargetsUnmodifiable;
22         private final List<Integer> vectorPartLengthes;
23         private final List<Integer> vectorPartLengthesUnmodifiable;
24         private int length;
25
26         private final Map<Consumer<Object>, Consumer<Object>> targetListeners;
27
28         public BitVectorSplittingAtomicHighLevelStateHandler(SubmodelComponent component)
29         {
30                 this(component, null);
31         }
32
33         public BitVectorSplittingAtomicHighLevelStateHandler(SubmodelComponent component,
34                         BitVectorSplittingAtomicHighLevelStateHandlerParams params)
35         {
36                 this.component = component;
37                 this.vectorPartTargets = new ArrayList<>();
38                 this.vectorPartTargetsUnmodifiable = Collections.unmodifiableList(vectorPartTargets);
39                 this.vectorPartLengthes = new ArrayList<>();
40                 this.vectorPartLengthesUnmodifiable = Collections.unmodifiableList(vectorPartLengthes);
41
42                 this.targetListeners = new HashMap<>();
43
44                 if (params != null)
45                         setVectorParts(params.vectorPartTargets, params.vectorPartLengthes);
46         }
47
48         public void set(List<String> targets, List<Integer> lengthes)
49         {
50                 setVectorParts(targets, lengthes);
51         }
52
53         public void addVectorPart(String target, int length)
54         {
55                 vectorPartTargets.add(target);
56                 vectorPartLengthes.add(length);
57                 this.length += length;
58         }
59
60         public void clearVectorParts()
61         {
62                 vectorPartTargets.clear();
63                 vectorPartLengthes.clear();
64                 length = 0;
65         }
66
67         private void setVectorParts(List<String> targets, List<Integer> lengthes)
68         {
69                 clearVectorParts();
70                 if (targets.size() != lengthes.size())
71                         throw new IllegalArgumentException("Targets list and lengthes list have different sizes");
72                 vectorPartTargets.addAll(targets);
73                 vectorPartLengthes.addAll(lengthes);
74                 length += lengthes.stream().mapToInt(Integer::intValue).sum();
75         }
76
77         public List<String> getVectorPartTargets()
78         {
79                 return vectorPartTargetsUnmodifiable;
80         }
81
82         public List<Integer> getVectorPartLenghtes()
83         {
84                 return vectorPartLengthesUnmodifiable;
85         }
86
87         @Override
88         public Object getHighLevelState()
89         {
90                 BitVector result = BitVector.of();
91                 for (int partIndex = 0; partIndex < vectorPartTargets.size(); partIndex++)
92                 {
93                         Object subStateUncasted = component.getHighLevelState(vectorPartTargets.get(partIndex));
94                         BitVector vectorPart;
95                         if (subStateUncasted instanceof Bit)
96                                 vectorPart = BitVector.of((Bit) subStateUncasted);
97                         else
98                                 vectorPart = (BitVector) subStateUncasted;
99                         if (vectorPart.length() != vectorPartLengthes.get(partIndex))
100                                 throw new IllegalArgumentException(
101                                                 "Incorrect vector part length: " + vectorPart.length() + "; expected " + vectorPartLengthes.get(partIndex));
102                         result = result.concat(vectorPart);
103                 }
104                 return result;
105         }
106
107         @Override
108         public void setHighLevelState(Object newState)
109         {
110                 BitVector newStateCasted = (BitVector) newState;
111                 if (newStateCasted.length() != length)
112                         throw new IllegalArgumentException("Incorrect vector length: " + newStateCasted.length() + "; expected " + length);
113                 for (int partIndex = 0, bitIndex = 0; partIndex < vectorPartTargets.size(); partIndex++)
114                 {
115                         int vectorPartLength = vectorPartLengthes.get(partIndex);
116                         BitVector vectorPart = newStateCasted.subVector(bitIndex, bitIndex + vectorPartLength);
117                         component.setHighLevelState(vectorPartTargets.get(partIndex), vectorPart);
118                         bitIndex += vectorPartLength;
119                 }
120         }
121
122         @Override
123         public void addListener(Consumer<Object> stateChanged)
124         {
125                 if (targetListeners.get(stateChanged) != null)
126                         // this listener is/was already registered
127                         return;
128
129                 Consumer<Object> targetListener = o -> stateChanged.accept(getHighLevelState());
130                 targetListeners.put(stateChanged, targetListener);
131
132                 for (String target : vectorPartTargets)
133                         component.addHighLevelStateListener(target, targetListener);
134         }
135
136         @Override
137         public void removeListener(Consumer<Object> stateChanged)
138         {
139                 Consumer<Object> targetListener = targetListeners.get(stateChanged);
140                 if (targetListener == null)
141                         // this listener is/was not registered
142                         return;
143
144                 for (String target : vectorPartTargets)
145                         component.removeHighLevelStateListener(target, targetListener);
146         }
147
148         @Override
149         public String getIDForSerializing(IdentifyParams idParams)
150         {
151                 return "bitVectorSplitting";
152         }
153
154         @Override
155         public BitVectorSplittingAtomicHighLevelStateHandlerParams getParamsForSerializing(IdentifyParams idParams)
156         {
157                 BitVectorSplittingAtomicHighLevelStateHandlerParams params = new BitVectorSplittingAtomicHighLevelStateHandlerParams();
158                 params.vectorPartTargets = new ArrayList<>(vectorPartTargets);
159                 params.vectorPartLengthes = new ArrayList<>(vectorPartLengthes);
160                 return params;
161         }
162
163         public static class BitVectorSplittingAtomicHighLevelStateHandlerParams
164         {
165                 public List<String> vectorPartTargets;
166                 public List<Integer> vectorPartLengthes;
167         }
168
169         static
170         {
171                 StandardHighLevelStateHandlerSnippetSuppliers.atomicHandlerSupplier
172                                 .setSnippetSupplier(BitVectorSplittingAtomicHighLevelStateHandler.class.getCanonicalName(), SnippetDefinintion.create(
173                                                 BitVectorSplittingAtomicHighLevelStateHandlerParams.class, BitVectorSplittingAtomicHighLevelStateHandler::new));
174         }
175 }