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