Added MnemonicFamilyBuilder and set most Mnemonics to 'X' by default
[Mograsim.git] / plugins / net.mograsim.machine / src / net / mograsim / machine / mi / parameters / MnemonicFamily.java
1 package net.mograsim.machine.mi.parameters;
2
3 import java.util.Arrays;
4 import java.util.LinkedList;
5 import java.util.List;
6 import java.util.Map;
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.machine.mi.parameters.MicroInstructionParameter.ParameterType;
12
13 public class MnemonicFamily implements ParameterClassification
14 {
15         private final Mnemonic[] values;
16         private final Mnemonic defaultValue;
17         private final String[] stringValues;
18         private Map<String, Mnemonic> byText;
19         private int vectorLength;
20
21         MnemonicFamily(String defaultValueName, MnemonicPair... values)
22         {
23                 this.values = new Mnemonic[values.length];
24                 this.stringValues = new String[values.length];
25
26                 setup(values);
27
28                 int defaultValueIndex = -1;
29                 for (int i = 0; i < values.length; i++)
30                         if (stringValues[i].equals(defaultValueName))
31                         {
32                                 defaultValueIndex = i;
33                                 break;
34                         }
35                 this.defaultValue = this.values[defaultValueIndex];
36         }
37
38         private void setup(MnemonicPair[] values)
39         {
40                 for (int i = 0; i < values.length; i++)
41                 {
42                         this.values[i] = createMnemonic(values[i], i);
43                         this.stringValues[i] = values[i].name;
44                 }
45                 if (values.length == 0)
46                         vectorLength = 0;
47                 else
48                 {
49                         vectorLength = values[0].value.length();
50                         for (int i = 1; i < values.length; i++)
51                                 if (values[i].value.length() != vectorLength)
52                                         throw new IllegalArgumentException("MnemonicFamily is not of uniform vector length!");
53                 }
54                 byText = Arrays.stream(this.values).collect(Collectors.toMap(m -> m.getText(), m -> m));
55                 if (values.length != byText.keySet().size())
56                         throw new IllegalArgumentException("MnemonicFamily contains multiple Mnemonics with the same name!");
57         }
58
59         private Mnemonic createMnemonic(MnemonicPair mnemonicPair, int ordinal)
60         {
61                 return new Mnemonic(mnemonicPair.name, mnemonicPair.value, this, ordinal);
62         }
63
64         public Mnemonic[] values()
65         {
66                 return values.clone();
67         }
68
69         public Mnemonic get(int ordinal)
70         {
71                 return values[ordinal];
72         }
73
74         public Mnemonic get(String text)
75         {
76                 return byText.get(text);
77         }
78
79         @Override
80         public MicroInstructionParameter getDefault()
81         {
82                 return defaultValue;
83         }
84
85         public boolean contains(Mnemonic m)
86         {
87                 if (m != null)
88                         return m.owner == this;
89                 return false;
90         }
91
92         public boolean contains(String value)
93         {
94                 return byText.keySet().contains(value);
95         }
96
97         public int size()
98         {
99                 return values.length;
100         }
101
102         public int getVectorLength()
103         {
104                 return vectorLength;
105         }
106
107         @Override
108         public boolean conforms(MicroInstructionParameter param)
109         {
110                 return ParameterClassification.super.conforms(param) && (param instanceof Mnemonic ? contains((Mnemonic) param) : false);
111         }
112
113         @Override
114         public ParameterType getExpectedType()
115         {
116                 return ParameterType.MNEMONIC;
117         }
118
119         @Override
120         public int getExpectedBits()
121         {
122                 return vectorLength;
123         }
124
125         public String[] getStringValues()
126         {
127                 return stringValues.clone();
128         }
129
130         @Override
131         public int hashCode()
132         {
133                 final int prime = 31;
134                 int result = 1;
135                 result = prime * result + Arrays.hashCode(values);
136                 return result;
137         }
138
139         @Override
140         public boolean equals(Object obj)
141         {
142                 return this == obj;
143         }
144
145         @Override
146         public Mnemonic parse(String toParse)
147         {
148                 Mnemonic parsed = get(toParse);
149                 if (parsed == null)
150                         throw new UnknownMnemonicException(toParse);
151                 return parsed;
152         }
153
154         public static class MnemonicPair
155         {
156                 public final String name;
157                 public final BitVector value;
158
159                 public MnemonicPair(String name, BitVector value)
160                 {
161                         this.name = name;
162                         this.value = value;
163                 }
164         }
165
166         public static class MnemonicFamilyBuilder
167         {
168                 private final List<MnemonicPair> pairs;
169                 private final int bits;
170                 private String defaultValue;
171
172                 public MnemonicFamilyBuilder(int bits)
173                 {
174                         this.pairs = new LinkedList<>();
175                         this.bits = bits;
176                 }
177
178                 public MnemonicFamilyBuilder addX()
179                 {
180                         pairs.add(new MnemonicPair("X", BitVector.of(Bit.ZERO, bits)));
181                         return this;
182                 }
183
184                 public MnemonicFamilyBuilder add(MnemonicPair... pairs)
185                 {
186                         this.pairs.addAll(List.of(pairs));
187                         return this;
188                 }
189
190                 /**
191                  * Adds a name with its corresponding value to the {@link MnemonicFamily}
192                  * 
193                  * @return this {@link MnemonicFamilyBuilder}
194                  */
195                 public MnemonicFamilyBuilder add(String name, BitVector value)
196                 {
197                         add(new MnemonicPair(name, value));
198                         return this;
199                 }
200
201                 /**
202                  * Adds names with their corresponding values to the {@link MnemonicFamily}
203                  * 
204                  * @param names  The names to be added to the {@link MnemonicFamily}
205                  * @param values The values as {@link BitVector}s
206                  * @return this {@link MnemonicFamilyBuilder}
207                  */
208                 public MnemonicFamilyBuilder add(String name, long value)
209                 {
210                         add(new MnemonicPair(name, BitVector.from(value, bits)));
211                         return this;
212                 }
213
214                 /**
215                  * Adds names with their corresponding values to the {@link MnemonicFamily}
216                  * 
217                  * @param names  The names to be added to the {@link MnemonicFamily}
218                  * @param values The values as {@link BitVector}s
219                  * @return this {@link MnemonicFamilyBuilder}
220                  */
221                 public MnemonicFamilyBuilder add(String names[], BitVector[] values)
222                 {
223                         if (names.length != values.length)
224                                 throw new IllegalArgumentException("Cannot add Mnemonics! Amount of names does not match amount of values!");
225                         for (int i = 0; i < names.length; i++)
226                                 add(new MnemonicPair(names[i], values[i]));
227                         return this;
228                 }
229
230                 /**
231                  * Adds names with their corresponding values (converted to a BitVector) to the {@link MnemonicFamily}
232                  * 
233                  * @param names  The names to be added to the {@link MnemonicFamily}
234                  * @param values The values to be converted to {@link BitVector}s with a given amount of {@link MnemonicFamilyBuilder#bits}
235                  * @return this {@link MnemonicFamilyBuilder}
236                  */
237                 public MnemonicFamilyBuilder add(String names[], long values[])
238                 {
239                         if (names.length != values.length)
240                                 throw new IllegalArgumentException("Cannot add Mnemonics! Amount of names does not match amount of values!");
241                         for (int i = 0; i < names.length; i++)
242                                 add(new MnemonicPair(names[i], BitVector.from(values[i], bits)));
243                         return this;
244                 }
245
246                 /**
247                  * Adds names to the {@link MnemonicFamily}; The corresponding {@link BitVector} value to a name is the value of its index
248                  * 
249                  * @param names The names to be added to the {@link MnemonicFamily}
250                  * @return this {@link MnemonicFamilyBuilder}
251                  */
252                 public MnemonicFamilyBuilder add(String... names)
253                 {
254                         for (int i = 0; i < names.length; i++)
255                                 add(names[i], i);
256                         return this;
257                 }
258
259                 /**
260                  * Sets the name of the default {@link Mnemonic} of this {@link MnemonicFamily}
261                  */
262                 public MnemonicFamilyBuilder setDefault(String defaultValue)
263                 {
264                         this.defaultValue = defaultValue;
265                         return this;
266                 }
267
268                 /**
269                  * Sets the name of the default {@link Mnemonic} of this {@link MnemonicFamily} to "X"
270                  */
271                 public MnemonicFamilyBuilder setXDefault()
272                 {
273                         this.defaultValue = "X";
274                         return this;
275                 }
276
277                 public MnemonicFamily build()
278                 {
279                         return new MnemonicFamily(defaultValue, pairs.toArray(new MnemonicPair[pairs.size()]));
280                 }
281         }
282 }