1 package net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.atomic;
3 import java.math.BigInteger;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.HashMap;
9 import java.util.function.Consumer;
11 import net.mograsim.logic.core.types.Bit;
12 import net.mograsim.logic.core.types.BitVector;
13 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
14 import net.mograsim.logic.model.serializing.IdentifyParams;
15 import net.mograsim.logic.model.snippets.SnippetDefinintion;
16 import net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.StandardHighLevelStateHandlerSnippetSuppliers;
18 public class BitVectorSplittingAtomicHighLevelStateHandler implements AtomicHighLevelStateHandler
20 private final SubmodelComponent component;
21 private final List<String> vectorPartTargets;
22 private final List<String> vectorPartTargetsUnmodifiable;
23 private final List<Integer> vectorPartLengthes;
24 private final List<Integer> vectorPartLengthesUnmodifiable;
25 private BitVector minimalValue;
26 private BigInteger minimalValueBigInteger;
27 private BitVector maximalValue;
28 private BigInteger maximalValueBigInteger;
31 private final Map<Consumer<Object>, Consumer<Object>> targetListeners;
33 public BitVectorSplittingAtomicHighLevelStateHandler(SubmodelComponent component)
35 this(component, null);
38 public BitVectorSplittingAtomicHighLevelStateHandler(SubmodelComponent component,
39 BitVectorSplittingAtomicHighLevelStateHandlerParams params)
41 this.component = component;
42 this.vectorPartTargets = new ArrayList<>();
43 this.vectorPartTargetsUnmodifiable = Collections.unmodifiableList(vectorPartTargets);
44 this.vectorPartLengthes = new ArrayList<>();
45 this.vectorPartLengthesUnmodifiable = Collections.unmodifiableList(vectorPartLengthes);
47 this.targetListeners = new HashMap<>();
51 setVectorParts(params.vectorPartTargets, params.vectorPartLengthes);
52 setRange(params.minimalValue, params.maximalValue);
56 public void set(List<String> targets, List<Integer> lengthes, BitVector minimalValue, BitVector maximalValue)
58 setVectorParts(targets, lengthes);
59 setRange(minimalValue, maximalValue);
62 public void addVectorPart(String target, int length)
64 vectorPartTargets.add(target);
65 vectorPartLengthes.add(length);
66 this.length += length;
69 public void clearVectorParts()
71 vectorPartTargets.clear();
72 vectorPartLengthes.clear();
76 private void setVectorParts(List<String> targets, List<Integer> lengthes)
79 if (targets.size() != lengthes.size())
80 throw new IllegalArgumentException("Targets list and lengthes list have different sizes");
81 vectorPartTargets.addAll(targets);
82 vectorPartLengthes.addAll(lengthes);
83 length += lengthes.stream().mapToInt(Integer::intValue).sum();
86 @SuppressWarnings("null") // explicit checks for null are in place
87 public void setRange(BitVector minimalValue, BitVector maximalValue)
89 boolean minIsNull = minimalValue == null;
90 if (minIsNull != (maximalValue == null))
91 throw new IllegalArgumentException("minimalValue and maximalValue must either both be null or both non-null");
94 if (!minimalValue.isBinary())
95 throw new IllegalArgumentException("minimalValue is not binary");
96 if (!maximalValue.isBinary())
97 throw new IllegalArgumentException("maximalValue is not binary");
98 this.minimalValueBigInteger = minimalValue.getUnsignedValue();
99 this.maximalValueBigInteger = maximalValue.getUnsignedValue();
101 this.minimalValue = minimalValue;
102 this.maximalValue = maximalValue;
105 public BitVector getMinimalValue()
110 public BitVector getMaximalValue()
115 public List<String> getVectorPartTargets()
117 return vectorPartTargetsUnmodifiable;
120 public List<Integer> getVectorPartLenghtes()
122 return vectorPartLengthesUnmodifiable;
126 public Object getHighLevelState()
128 BitVector result = BitVector.of();
129 for (int partIndex = 0; partIndex < vectorPartTargets.size(); partIndex++)
131 Object subStateUncasted = component.getHighLevelState(vectorPartTargets.get(partIndex));
132 BitVector vectorPart;
133 if (subStateUncasted instanceof Bit)
134 vectorPart = BitVector.of((Bit) subStateUncasted);
136 vectorPart = (BitVector) subStateUncasted;
137 if (vectorPart.length() != vectorPartLengthes.get(partIndex))
138 throw new IllegalArgumentException(
139 "Incorrect vector part length: " + vectorPart.length() + "; expected " + vectorPartLengthes.get(partIndex));
140 result = result.concat(vectorPart);
146 public void setHighLevelState(Object newState)
148 BitVector newStateCasted = (BitVector) newState;
149 if (newStateCasted.length() != length)
150 throw new IllegalArgumentException("Incorrect vector length: " + newStateCasted.length() + "; expected " + length);
151 // TODO what for non-binary values?
152 if (minimalValue != null && newStateCasted.isBinary())
154 BigInteger newStateBigInteger = newStateCasted.getUnsignedValue();
155 if (newStateBigInteger.compareTo(minimalValueBigInteger) < 0 || newStateBigInteger.compareTo(maximalValueBigInteger) > 0)
156 throw new IllegalArgumentException(
157 "Value out of range: should be in " + minimalValue + " - " + maximalValue + "; was " + newState);
159 for (int partIndex = 0, bitIndex = 0; partIndex < vectorPartTargets.size(); partIndex++)
161 int vectorPartLength = vectorPartLengthes.get(partIndex);
162 BitVector vectorPart = newStateCasted.subVector(bitIndex, bitIndex + vectorPartLength);
163 component.setHighLevelState(vectorPartTargets.get(partIndex), vectorPart);
164 bitIndex += vectorPartLength;
169 public void addListener(Consumer<Object> stateChanged)
171 if (targetListeners.get(stateChanged) != null)
172 // this listener is/was already registered
175 Consumer<Object> targetListener = o -> stateChanged.accept(getHighLevelState());
176 targetListeners.put(stateChanged, targetListener);
178 for (String target : vectorPartTargets)
179 component.addHighLevelStateListener(target, targetListener);
183 public void removeListener(Consumer<Object> stateChanged)
185 Consumer<Object> targetListener = targetListeners.get(stateChanged);
186 if (targetListener == null)
187 // this listener is/was not registered
190 for (String target : vectorPartTargets)
191 component.removeHighLevelStateListener(target, targetListener);
195 public String getIDForSerializing(IdentifyParams idParams)
197 return "bitVectorSplitting";
201 public BitVectorSplittingAtomicHighLevelStateHandlerParams getParamsForSerializing(IdentifyParams idParams)
203 BitVectorSplittingAtomicHighLevelStateHandlerParams params = new BitVectorSplittingAtomicHighLevelStateHandlerParams();
204 params.vectorPartTargets = new ArrayList<>(vectorPartTargets);
205 params.vectorPartLengthes = new ArrayList<>(vectorPartLengthes);
206 params.minimalValue = minimalValue;
207 params.maximalValue = maximalValue;
211 public static class BitVectorSplittingAtomicHighLevelStateHandlerParams
213 public List<String> vectorPartTargets;
214 public List<Integer> vectorPartLengthes;
215 public BitVector minimalValue;
216 public BitVector maximalValue;
221 StandardHighLevelStateHandlerSnippetSuppliers.atomicHandlerSupplier
222 .setSnippetSupplier(BitVectorSplittingAtomicHighLevelStateHandler.class.getCanonicalName(), SnippetDefinintion.create(
223 BitVectorSplittingAtomicHighLevelStateHandlerParams.class, BitVectorSplittingAtomicHighLevelStateHandler::new));