syscalls: support generic system calls
[openpower-isa.git] / src / openpower / decoder / power_decoder.py
index e3b2e9321ba4b381fb716de8071d6c119801f731..81fc1db071117c5a1f03e739ba698dae05f0426d 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: LGPL-3-or-later
 """Cascading Power ISA Decoder
 
 License: LGPLv3+
@@ -91,12 +92,14 @@ from collections import namedtuple, OrderedDict
 from nmigen import Module, Elaboratable, Signal, Cat, Mux, Const
 from nmigen.cli import rtlil, verilog
 from openpower.decoder.power_enums import (Function, Form, MicrOp,
-                                     In1Sel, In2Sel, In3Sel, OutSel,
-                                     SVEXTRA, SVEtype, SVPtype,  # Simple-V
-                                     RC, LdstLen, LDSTMode, CryIn,
-                                     single_bit_flags, CRInSel,
-                                     CROutSel, get_signal_name,
-                                     default_values, insns, asmidx)
+                                           In1Sel, In2Sel, In3Sel, OutSel,
+                                           SVEXTRA, SVMode, # Simple-V
+                                           SVEType, SVPType, # Simple-V
+                                           RCOE, LdstLen, LDSTMode, CryIn,
+                                           single_bit_flags, CRInSel,
+                                           CROutSel, get_signal_name,
+                                           default_values, insns, asmidx,
+                                           asmlen)
 from openpower.decoder.power_fields import DecodeFields
 from openpower.decoder.power_fieldsn import SigDecode, SignalBitRange
 from openpower.decoder.power_svp64 import SVP64RM
@@ -111,7 +114,7 @@ Subdecoder = namedtuple(  # fix autoformatter
      "opcodes",    # a dictionary of minor patterns to find
      "opint",      # true => the pattern must not be in "10----11" format
      # the bits (as a range) against which "pattern" matches
-     "bitsel",
+     "bitsel",     # should be in MSB0 order but isn't! it's LSB0. um.
      "suffix",     # shift the opcode down before decoding
      "subdecoders"  # list of further subdecoders for *additional* matches,
      # *ONLY* after "pattern" has *ALSO* been matched against.
@@ -120,9 +123,10 @@ Subdecoder = namedtuple(  # fix autoformatter
 power_op_types = {'function_unit': Function,
                   'internal_op': MicrOp,
                   'form': Form,
-                  'asmcode': 8,
-                  'SV_Etype': SVEtype,
-                  'SV_Ptype': SVPtype,
+                  'asmcode': asmlen,
+                  'SV_Etype': SVEType,
+                  'SV_Ptype': SVPType,
+                  'SV_mode': SVMode,
                   'in1_sel': In1Sel,
                   'in2_sel': In2Sel,
                   'in3_sel': In3Sel,
@@ -138,7 +142,7 @@ power_op_types = {'function_unit': Function,
                   'sv_cr_out': SVEXTRA,
                   'ldst_len': LdstLen,
                   'upd': LDSTMode,
-                  'rc_sel': RC,
+                  'rc_sel': RCOE,
                   'cry_in': CryIn
                   }
 
@@ -158,10 +162,12 @@ power_op_csvmap = {'function_unit': 'unit',
                    'sv_cr_out': 'sv_cr_out',
                    'SV_Etype': 'SV_Etype',
                    'SV_Ptype': 'SV_Ptype',
+                   'SV_mode': 'SV_mode',
                    'cr_in': 'CR in',
                    'cr_out': 'CR out',
                    'ldst_len': 'ldst len',
                    'upd': 'upd',
+                   'rsrv': 'rsrv',  # atomic operation
                    'rc_sel': 'rc',
                    'cry_in': 'cry in',
                    }
@@ -245,7 +251,7 @@ class PowerOp:
             if field not in power_op_csvmap:
                 continue
             csvname = power_op_csvmap[field]
-            # log(field, ptype, csvname, row)
+            log("_eq", field, ptype, csvname, row)
             val = row[csvname]
             if csvname == 'upd' and isinstance(val, int):  # LDSTMode different
                 val = ptype(val)
@@ -258,8 +264,8 @@ class PowerOp:
         # process the comment field, strip out "equals" for FP
         if "=" in asmcode:
             asmcode = asmcode.split("=")[-1]
-            log ("asmcode stripping =", asmcode,
-                    asmcode in asmidx, hasattr(self, "asmcode"))
+            log("asmcode stripping =", asmcode,
+                asmcode in asmidx, hasattr(self, "asmcode"))
         if hasattr(self, "asmcode") and asmcode in asmidx:
             res.append(self.asmcode.eq(asmidx[asmcode]))
         for bit in single_bit_flags:
@@ -320,11 +326,12 @@ class PowerDecoder(Elaboratable):
     """
 
     def __init__(self, width, dec, name=None, col_subset=None,
-                       row_subset=None, conditions=None):
+                 row_subset=None, conditions=None):
         if conditions is None:
             # XXX conditions = {}
-            conditions = {'SVP64BREV': Const(0, 1),
-                         }
+            conditions = {
+                          'SVP64FFT': Const(0, 1),
+                          }
         self.actually_does_something = False
         self.pname = name
         self.conditions = conditions
@@ -354,15 +361,15 @@ class PowerDecoder(Elaboratable):
     def find_conditions(self, opcodes):
         # look for conditions, create dictionary entries for them
         # sorted by opcode
-        rows = OrderedDict() # start as a dictionary, get as list (after)
+        rows = OrderedDict()  # start as a dictionary, get as list (after)
         for row in opcodes:
             condition = row['CONDITIONS']
             opcode = row['opcode']
             if condition:
                 # check it's expected
                 assert (condition in self.conditions or
-                       (condition[0] == '~' and
-                        condition[1:] in self.conditions)), \
+                        (condition[0] == '~' and
+                         condition[1:] in self.conditions)), \
                     "condition %s not in %s" % (condition, str(conditions))
                 if opcode not in rows:
                     rows[opcode] = {}
@@ -371,7 +378,7 @@ class PowerDecoder(Elaboratable):
                 # check it's unique
                 assert opcode not in rows, \
                     "opcode %s already in rows for %s" % \
-                                        (opcode, self.pname)
+                    (opcode, self.pname)
                 rows[opcode] = row
         # after checking for conditions, get just the values (ordered)
         return list(rows.values())
@@ -456,7 +463,7 @@ class PowerDecoder(Elaboratable):
                     # get the FIRST item (will be the same opcode), and it
                     # had BETTER have the same unit and also pass other
                     # row subset conditions.
-                    if 'opcode' not in row: # must be a "CONDITIONS" dict...
+                    if 'opcode' not in row:  # must be a "CONDITIONS" dict...
                         is_conditions = True
                         _row = row[list(row.keys())[0]]
                     else:
@@ -489,7 +496,8 @@ class PowerDecoder(Elaboratable):
 
         #print("submodules", self.pname, submodules)
 
-        gc.collect()
+        # GC collection is really slow and shouldn't be needed
+        # gc.collect()
         return self.actually_does_something
 
     def handle_subdecoders(self, switch_case, submodules, d):
@@ -509,9 +517,9 @@ class PowerDecoder(Elaboratable):
                                           col_subset=self.col_subset,
                                           row_subset=self.row_subsetfn,
                                           conditions=self.conditions)
-                log ("subdecoder", mname, subdecoder)
+                log("subdecoder", mname, subdecoder)
                 if not subdecoder.tree_analyse():  # doesn't do anything
-                    log ("analysed, DELETING", mname)
+                    log("analysed, DELETING", mname)
                     del subdecoder
                     continue                      # skip
                 submodules[mname] = subdecoder
@@ -573,7 +581,7 @@ class TopPowerDecoder(PowerDecoder):
     """
 
     def __init__(self, width, dec, name=None, col_subset=None,
-                                   row_subset=None, conditions=None):
+                 row_subset=None, conditions=None):
         PowerDecoder.__init__(self, width, dec, name,
                               col_subset, row_subset, conditions)
         self.fields = df = DecodeFields(SignalBitRange, [self.opcode_in])
@@ -648,12 +656,12 @@ class TopPowerDecoder(PowerDecoder):
 # PRIMARY FUNCTION SPECIFYING ALTERNATIVE SVP64 POWER DECODER
 
 def create_pdecode_svp64_ldst(name=None, col_subset=None, row_subset=None,
-                   include_fp=False):
+                              include_fp=False):
     """create_pdecode - creates a cascading hierarchical POWER ISA decoder
 
     subsetting of the PowerOp decoding is possible by setting col_subset
     """
-    log ("create_pdecode_svp64_ldst", name, col_subset, row_subset, include_fp)
+    log("create_pdecode_svp64_ldst", name, col_subset, row_subset, include_fp)
 
     # some alteration to the CSV files is required for SV so we use
     # a class to do it
@@ -665,7 +673,7 @@ def create_pdecode_svp64_ldst(name=None, col_subset=None, row_subset=None,
         Subdecoder(pattern=58, opcodes=get_csv("svldst_minor_58.csv"),
                    opint=True, bitsel=(0, 2), suffix=None, subdecoders=[]),
         # nope - needs 4-in regs
-        #Subdecoder(pattern=62, opcodes=get_csv("svldst_minor_62.csv"),
+        # Subdecoder(pattern=62, opcodes=get_csv("svldst_minor_62.csv"),
         #           opint=True, bitsel=(0, 2), suffix=None, subdecoders=[]),
     ]
 
@@ -673,14 +681,14 @@ def create_pdecode_svp64_ldst(name=None, col_subset=None, row_subset=None,
     if False and include_fp:
         pminor.append(
             Subdecoder(pattern=63, opcodes=get_csv("minor_63.csv"),
-                                 opint=False, bitsel=(1, 11), suffix=None,
-                                 subdecoders=[]),
-            )
+                       opint=False, bitsel=(1, 11), suffix=None,
+                       subdecoders=[]),
+        )
         pminor.append(
             Subdecoder(pattern=59, opcodes=get_csv("minor_59.csv"),
-                                 opint=False, bitsel=(1, 11), suffix=None,
-                                 subdecoders=[]),
-            )
+                       opint=False, bitsel=(1, 11), suffix=None,
+                       subdecoders=[]),
+        )
 
     # top level: extra merged with major
     dec = []
@@ -700,8 +708,10 @@ def create_pdecode(name=None, col_subset=None, row_subset=None,
     """create_pdecode - creates a cascading hierarchical POWER ISA decoder
 
     subsetting of the PowerOp decoding is possible by setting col_subset
+
+    NOTE (sigh) the bitsel patterns are in LSB0 order, they should be MSB0
     """
-    log ("create_pdecode", name, col_subset, row_subset, include_fp)
+    log("create_pdecode", name, col_subset, row_subset, include_fp)
 
     # some alteration to the CSV files is required for SV so we use
     # a class to do it
@@ -711,11 +721,11 @@ def create_pdecode(name=None, col_subset=None, row_subset=None,
     # minor 19 has extra patterns
     m19 = []
     m19.append(Subdecoder(pattern=19, opcodes=get_csv("minor_19.csv"),
-                          opint=True, bitsel=(1, 11), suffix=None,
+                          opint=False, bitsel=(1, 11), suffix=None,
                           subdecoders=[]))
     # XXX problem with sub-decoders (can only handle one),
     # sort this another time
-    #m19.append(Subdecoder(pattern=19, opcodes=get_csv("minor_19_00000.csv"),
+    # m19.append(Subdecoder(pattern=19, opcodes=get_csv("minor_19_00000.csv"),
     #                      opint=True, bitsel=(1, 6), suffix=None,
     #                      subdecoders=[]))
 
@@ -723,7 +733,7 @@ def create_pdecode(name=None, col_subset=None, row_subset=None,
     pminor = [
         m19,
         Subdecoder(pattern=30, opcodes=get_csv("minor_30.csv"),
-                   opint=True, bitsel=(1, 5), suffix=None, subdecoders=[]),
+                   opint=False, bitsel=(1, 5), suffix=None, subdecoders=[]),
         Subdecoder(pattern=31, opcodes=get_csv("minor_31.csv"),
                    opint=True, bitsel=(1, 11), suffix=0b00101, subdecoders=[]),
         Subdecoder(pattern=58, opcodes=get_csv("minor_58.csv"),
@@ -731,21 +741,25 @@ def create_pdecode(name=None, col_subset=None, row_subset=None,
         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=[]),
+                   opint=False, bitsel=(0, 11), suffix=None, subdecoders=[]),
+        Subdecoder(pattern=5, opcodes=get_csv("minor_5.csv"),
+                   opint=True, bitsel=(0, 11), suffix=None, subdecoders=[]),
+        Subdecoder(pattern=4, opcodes=get_csv("minor_4.csv"),
+                   opint=True, bitsel=(0, 6), suffix=None, subdecoders=[]),
     ]
 
     # FP 63L/H decoders. TODO: move mffsfamily to separate subdecoder
     if include_fp:
         pminor.append(
             Subdecoder(pattern=63, opcodes=get_csv("minor_63.csv"),
-                                 opint=False, bitsel=(1, 11), suffix=None,
-                                 subdecoders=[]),
-            )
+                       opint=False, bitsel=(1, 11), suffix=None,
+                       subdecoders=[]),
+        )
         pminor.append(
             Subdecoder(pattern=59, opcodes=get_csv("minor_59.csv"),
-                                 opint=False, bitsel=(1, 11), suffix=None,
-                                 subdecoders=[]),
-            )
+                       opint=False, bitsel=(1, 11), suffix=None,
+                       subdecoders=[]),
+        )
 
     # top level: extra merged with major
     dec = []
@@ -760,6 +774,30 @@ def create_pdecode(name=None, col_subset=None, row_subset=None,
                            row_subset=row_subset,
                            conditions=conditions)
 
+# test function from
+# https://github.com/apertus-open-source-cinema/naps/blob/9ebbc0/naps/soc/cli.py#L17
+
+
+def fragment_repr(original):
+    from textwrap import indent
+    attrs_str = "\n"
+    for attr in ['ports', 'drivers', 'statements', 'attrs',
+                 'generated', 'flatten']:
+        attrs_str += f"{attr}={repr(getattr(original, attr))},\n"
+
+    domains_str = "\n"
+    for name, domain in original.domains.items():
+        # TODO: this is not really sound because domains could be non local
+        domains_str += f"{name}: {domain.name}\n"
+    attrs_str += f"domains={{{indent(domains_str, '  ')}}},\n"
+
+    children_str = "\n"
+    for child, name in original.subfragments:
+        children_str += f"[{name}, {fragment_repr(child)}]\n"
+    attrs_str += f"children=[{indent(children_str, '  ')}],\n"
+
+    return f"Fragment({indent(attrs_str, '  ')})"
+
 
 if __name__ == '__main__':
 
@@ -768,12 +806,14 @@ if __name__ == '__main__':
 
         def rowsubsetfn(opcode, row):
             log("row_subset", opcode, row)
-            return row['unit'] == 'LDST'
+            return row['unit'] in ['LDST', 'FPU']
 
-        conditions = {'SVP64BREV': Signal(name="svp64brev", reset_less=True),
-                     }
+        conditions = {
+                      'SVP64FFT': Signal(name="svp64fft", reset_less=True),
+                      }
         pdecode = create_pdecode(name="rowsub",
                                  col_subset={'opcode', 'function_unit',
+                                             'asmcode',
                                              'in2_sel', 'in3_sel'},
                                  row_subset=rowsubsetfn,
                                  include_fp=True,
@@ -786,15 +826,23 @@ if __name__ == '__main__':
         with open("row_subset_decoder.v", "w") as f:
             f.write(vl)
 
-        exit(0)
-
         # col subset
 
-        pdecode = create_pdecode(name="fusubset", col_subset={'function_unit'})
+        pdecode = create_pdecode(name="fusubset", col_subset={'function_unit'},
+                                 conditions=conditions)
         vl = rtlil.convert(pdecode, ports=pdecode.ports())
         with open("col_subset_decoder.il", "w") as f:
             f.write(vl)
 
+        from nmigen.hdl.ir import Fragment
+        elaborated = Fragment.get(pdecode, platform=None)
+        elaborated_repr = fragment_repr(elaborated)
+        print(elaborated_repr)
+
+        exit(0)
+
+        exit(0)
+
     # full decoder
     pdecode = create_pdecode(include_fp=True)
     vl = rtlil.convert(pdecode, ports=pdecode.ports())