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