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