allow small decimal opcodes
[soc.git] / src / soc / decoder / power_decoder.py
index 028de9b3b0f78cc488096ff74a2c57a458a75f77..ace1ae280c6334bc9ca30b17c3da0379ef949d06 100644 (file)
@@ -1,6 +1,6 @@
 """Cascading Power ISA Decoder
 
-License: LGPLv3
+License: LGPLv3+
 
 # Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
@@ -92,13 +92,14 @@ from nmigen import Module, Elaboratable, Signal, Cat, Mux
 from nmigen.cli import rtlil
 from soc.decoder.power_enums import (Function, Form, MicrOp,
                                      In1Sel, In2Sel, In3Sel, OutSel,
-                                     RC, LdstLen, LDSTMode, CryIn, get_csv,
+                                     SVEXTRA, SVEtype, SVPtype,  # Simple-V
+                                     RC, LdstLen, LDSTMode, CryIn,
                                      single_bit_flags, CRInSel,
                                      CROutSel, get_signal_name,
                                      default_values, insns, asmidx)
 from soc.decoder.power_fields import DecodeFields
 from soc.decoder.power_fieldsn import SigDecode, SignalBitRange
-
+from soc.decoder.power_svp64 import SVP64RM
 
 # key data structure in which the POWER decoder is specified,
 # in a hierarchical fashion
@@ -118,12 +119,20 @@ power_op_types = {'function_unit': Function,
                   'internal_op': MicrOp,
                   'form': Form,
                   'asmcode': 8,
+                  'SV_Etype': SVEtype,
+                  'SV_Ptype': SVPtype,
                   'in1_sel': In1Sel,
                   'in2_sel': In2Sel,
                   'in3_sel': In3Sel,
                   'out_sel': OutSel,
                   'cr_in': CRInSel,
                   'cr_out': CROutSel,
+                  'sv_in1': SVEXTRA,
+                  'sv_in2': SVEXTRA,
+                  'sv_in3': SVEXTRA,
+                  'sv_out': SVEXTRA,
+                  'sv_cr_in': SVEXTRA,
+                  'sv_cr_out': SVEXTRA,
                   'ldst_len': LdstLen,
                   'upd': LDSTMode,
                   'rc_sel': RC,
@@ -137,6 +146,14 @@ power_op_csvmap = {'function_unit': 'unit',
                    'in2_sel': 'in2',
                    'in3_sel': 'in3',
                    'out_sel': 'out',
+                   'sv_in1': 'sv_in1',
+                   'sv_in2': 'sv_in2',
+                   'sv_in3': 'sv_in3',
+                   'sv_out': 'sv_out',
+                   'sv_cr_in': 'sv_cr_in',
+                   'sv_cr_out': 'sv_cr_out',
+                   'SV_Etype': 'SV_Etype',
+                   'SV_Ptype': 'SV_Ptype',
                    'cr_in': 'CR in',
                    'cr_out': 'CR out',
                    'ldst_len': 'ldst len',
@@ -152,6 +169,25 @@ def get_pname(field, pname):
     return "%s_%s" % (pname, field)
 
 
+class PatternOpcode(str):
+    pass
+
+
+def parse_opcode(opcode, opint=True):
+    assert opint
+    if isinstance(opcode, (int, PatternOpcode)):
+        return opcode
+    assert isinstance(opcode, str)
+    if len(opcode) > 4 or '-' in opcode:
+        # all binary numbers must start with 0b
+        assert opcode.startswith('0b')
+    if '-' not in opcode:
+        opcode = int(opcode, 0)
+    else:
+        opcode = PatternOpcode(opcode[2:])
+    return opcode
+
+
 class PowerOp:
     """PowerOp - a dynamic class that stores (subsets of) CSV rows of data
     about a PowerISA instruction.  this is a "micro-code" expanded format
@@ -206,6 +242,7 @@ class PowerOp:
             if field not in power_op_csvmap:
                 continue
             csvname = power_op_csvmap[field]
+            print(field, ptype, csvname, row)
             val = row[csvname]
             if csvname == 'upd' and isinstance(val, int):  # LDSTMode different
                 val = ptype(val)
@@ -298,9 +335,7 @@ class PowerDecoder(Elaboratable):
         mask = self.suffix_mask(d)
         print("mask", hex(mask))
         for row in d.opcodes:
-            opcode = row['opcode']
-            if d.opint and '-' not in opcode:
-                opcode = int(opcode, 0)
+            opcode = parse_opcode(row['opcode'], d.opint)
             key = opcode & mask
             opcode = opcode >> d.suffix
             if key not in divided:
@@ -336,7 +371,7 @@ class PowerDecoder(Elaboratable):
                     bitsel = (d.suffix+d.bitsel[0], d.bitsel[1])
                     sd = Subdecoder(pattern=None, opcodes=row,
                                     bitsel=bitsel, suffix=None,
-                                    opint=False, subdecoders=[])
+                                    opint=True, subdecoders=[])
                     mname = get_pname("dec_sub%d" % key, self.pname)
                     subdecoder = PowerDecoder(width=32, dec=sd,
                                               name=mname,
@@ -363,9 +398,7 @@ class PowerDecoder(Elaboratable):
                     case_does_something = True
                 eq += seqs
                 for row in d.opcodes:
-                    opcode = row['opcode']
-                    if d.opint and '-' not in opcode:
-                        opcode = int(opcode, 0)
+                    opcode = parse_opcode(row['opcode'], d.opint)
                     if not row['unit']:
                         continue
                     if self.row_subsetfn:
@@ -475,6 +508,7 @@ class TopPowerDecoder(PowerDecoder):
     def elaborate(self, platform):
         m = PowerDecoder.elaborate(self, platform)
         comb = m.d.comb
+        # sigh duplicated in SVP64PowerDecoder
         # raw opcode in assumed to be in LE order: byte-reverse it to get BE
         raw_le = self.raw_opcode_in
         l = []
@@ -513,6 +547,11 @@ def create_pdecode(name=None, col_subset=None, row_subset=None):
     subsetting of the PowerOp decoding is possible by setting col_subset
     """
 
+    # some alteration to the CSV files is required for SV so we use
+    # a class to do it
+    isa = SVP64RM()
+    get_csv = isa.get_svp64_csv
+
     # minor 19 has extra patterns
     m19 = []
     m19.append(Subdecoder(pattern=19, opcodes=get_csv("minor_19.csv"),
@@ -533,6 +572,8 @@ def create_pdecode(name=None, col_subset=None, row_subset=None):
                    opint=True, bitsel=(0, 2), suffix=None, subdecoders=[]),
         Subdecoder(pattern=62, opcodes=get_csv("minor_62.csv"),
                    opint=True, bitsel=(0, 2), suffix=None, subdecoders=[]),
+        Subdecoder(pattern=22, opcodes=get_csv("minor_22.csv"),
+                   opint=True, bitsel=(1, 5), suffix=None, subdecoders=[]),
     ]
 
     # top level: extra merged with major
@@ -541,7 +582,7 @@ def create_pdecode(name=None, col_subset=None, row_subset=None):
     dec.append(Subdecoder(pattern=None, opint=True, opcodes=opcodes,
                           bitsel=(26, 32), suffix=None, subdecoders=pminor))
     opcodes = get_csv("extra.csv")
-    dec.append(Subdecoder(pattern=None, opint=False, opcodes=opcodes,
+    dec.append(Subdecoder(pattern=None, opint=True, opcodes=opcodes,
                           bitsel=(0, 32), suffix=None, subdecoders=[]))
 
     return TopPowerDecoder(32, dec, name=name, col_subset=col_subset,