Fixed performance issue with tables
[Mograsim.git] / net.mograsim.machine / src / net / mograsim / machine / mi / parameters / MnemonicFamily.java
index 3724a42..54c275b 100644 (file)
@@ -4,34 +4,108 @@ import java.util.Arrays;
 import java.util.Map;
 import java.util.stream.Collectors;
 
+import net.mograsim.logic.core.types.BitVector;
 import net.mograsim.machine.mi.parameters.MicroInstructionParameter.ParameterType;
 
 public class MnemonicFamily implements ParameterClassification
 {
        private final Mnemonic[] values;
-       private final Map<String, Mnemonic> byText;
-       private final int vectorLenght;
+       private final String[] stringValues;
+       private Map<String, Mnemonic> byText;
+       private int vectorLength;
        
-       public MnemonicFamily(Mnemonic... values)
+       public MnemonicFamily(String... names)
        {
-               this.values = values;
+               this.values = new Mnemonic[names.length];
+               this.stringValues = new String[names.length];
+               BitVector[] values = new BitVector[names.length];
+               int bits = (int) Math.ceil(Math.log(names.length));
+               for(int i = 0; i < names.length; i++)
+               {
+                       values[i] = BitVector.from(i, bits);
+               }
+               
+               setup(names, values);
+       }
+       
+       public MnemonicFamily(String[] names, long[] values, int bits)
+       {
+               if(names.length != values.length)
+                       throw new IllegalArgumentException();
+               this.values = new Mnemonic[values.length];
+               this.stringValues = new String[values.length];
+               BitVector[] vectors = new BitVector[values.length];
+               
+               for(int i = 0; i < vectors.length; i++)
+               {
+                       vectors[i] = BitVector.from(values[i], bits);
+               }
+               
+               setup(names, vectors);
+       }
+       
+       public MnemonicFamily(String[] names, BitVector[] values)
+       {
+               if(names.length != values.length)
+                       throw new IllegalArgumentException();
+               this.values = new Mnemonic[values.length];
+               this.stringValues = new String[values.length];
+               
+               setup(names, values);
+       }
+       
+       public MnemonicFamily(MnemonicPair... values)
+       {
+               this.values = new Mnemonic[values.length];
+               this.stringValues = new String[values.length];
+               
+               setup(values);
+       }
+       
+       private void setup(String[] names, BitVector[] values)
+       {
+               MnemonicPair[] mnemonics = new MnemonicPair[values.length];
+               for(int i = 0; i < values.length; i++)
+                       mnemonics[i] = new MnemonicPair(names[i], values[i]);
+               setup(mnemonics);
+       }
+       
+       private void setup(MnemonicPair[] values)
+       {
+               for(int i = 0; i < values.length; i++)
+               {
+                       this.values[i] = createMnemonic(values[i], i);
+                       this.stringValues[i] = values[i].name;
+               }
                if(values.length == 0)
-                       vectorLenght = 0;
+                       vectorLength = 0;
                else
                {
-                       vectorLenght = values[0].getValue().length();
+                       vectorLength = values[0].value.length();
                        for(int i = 1; i < values.length; i++)
-                               if(values[i].getValue().length() != vectorLenght)
+                               if(values[i].value.length() != vectorLength)
                                        throw new IllegalArgumentException("MnemonicFamily is not of uniform vector length!");
                }
-               byText = Arrays.stream(values).collect(Collectors.toMap(m -> m.getText(), m -> m));
+               byText = Arrays.stream(this.values).collect(Collectors.toMap(m -> m.getText(), m -> m));
+               if(values.length != byText.keySet().size())
+                       throw new IllegalArgumentException("MnemonicFamily contains multiple Mnemonics with the same name!");
        }
-       
-       public Mnemonic[] getValues()
+
+       private Mnemonic createMnemonic(MnemonicPair mnemonicPair, int ordinal)
+       {
+               return new Mnemonic(mnemonicPair.name, mnemonicPair.value, this, ordinal);
+       }
+
+       public Mnemonic[] values()
        {
                return values.clone();
        }
        
+       public Mnemonic get(int ordinal)
+       {
+               return values[ordinal];
+       }
+       
        public Mnemonic get(String text)
        {
                return byText.get(text);
@@ -40,11 +114,16 @@ public class MnemonicFamily implements ParameterClassification
        public boolean contains(Mnemonic m)
        {
                if(m != null)
-                       return m.equals(byText.get(m.getText()));
+                       return m.owner == this;
                else
                        return false;
        }
        
+       public boolean contains(String value)
+       {
+               return byText.keySet().contains(value);
+       }
+       
        public int size()
        {
                return values.length;
@@ -52,13 +131,13 @@ public class MnemonicFamily implements ParameterClassification
        
        public int getVectorLength()
        {
-               return vectorLenght;
+               return vectorLength;
        }
 
        @Override
        public boolean conforms(MicroInstructionParameter param)
        {
-               return param instanceof Mnemonic ? contains((Mnemonic) param) : false;
+               return ParameterClassification.super.conforms(param) && (param instanceof Mnemonic ? contains((Mnemonic) param) : false);
        }
 
        @Override
@@ -66,4 +145,51 @@ public class MnemonicFamily implements ParameterClassification
        {
                return ParameterType.MNEMONIC;
        }
+
+       @Override
+       public int getExpectedBits()
+       {
+               return vectorLength;
+       }
+
+       public String[] getStringValues()
+       {
+               return stringValues.clone();
+       }
+       
+       @Override
+       public int hashCode()
+       {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + Arrays.hashCode(values);
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj)
+       {
+               return this == obj;
+       }
+       
+       @Override
+       public Mnemonic parse(String toParse)
+       {
+               Mnemonic parsed = get(toParse);
+               if(parsed == null)
+                       throw new UnknownMnemonicException(toParse);
+               return parsed;
+       }
+
+       public static class MnemonicPair
+       {
+               public final String name;
+               public final BitVector value;
+               
+               public MnemonicPair(String name, BitVector value)
+               {
+                       this.name = name;
+                       this.value = value;
+               }
+       }
 }