add a quick logic test of astor tree-dump
[openpower-isa.git] / src / openpower / decoder / power_decoder.py
index 4fe3d7e6add3ccf3bd4a64ddd03ec3e01e287737..250cb9b2878796acb5abc3730595e2dbed8d9d3b 100644 (file)
@@ -88,15 +88,16 @@ Top Level:
 
 import gc
 from collections import namedtuple, OrderedDict
-from nmigen import Module, Elaboratable, Signal, Cat, Mux
-from nmigen.cli import rtlil
+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)
+                                     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
@@ -120,7 +121,7 @@ Subdecoder = namedtuple(  # fix autoformatter
 power_op_types = {'function_unit': Function,
                   'internal_op': MicrOp,
                   'form': Form,
-                  'asmcode': 8,
+                  'asmcode': asmlen,
                   'SV_Etype': SVEtype,
                   'SV_Ptype': SVPtype,
                   'in1_sel': In1Sel,
@@ -323,8 +324,8 @@ class PowerDecoder(Elaboratable):
                        row_subset=None, conditions=None):
         if conditions is None:
             # XXX conditions = {}
-            conditions = {'SVP64BREV': 0,
-                          '~SVP64BREV': 1,
+            conditions = {'SVP64BREV': Const(0, 1),
+                          'SVP64FFT': Const(0, 1),
                          }
         self.actually_does_something = False
         self.pname = name
@@ -351,13 +352,6 @@ class PowerDecoder(Elaboratable):
         self.ccases = {}
         self.ckeys = list(conditions.keys())
         self.ckeys.sort()
-        cswitch = []
-        for i, ckey in enumerate(self.ckeys):
-            case = ['-'] * len(self.ckeys)
-            case[i] = '1'
-            self.ccases[ckey] = ''.join(case)
-            cswitch.append(conditions[ckey])
-        self.cswitch = cswitch
 
     def find_conditions(self, opcodes):
         # look for conditions, create dictionary entries for them
@@ -368,7 +362,9 @@ class PowerDecoder(Elaboratable):
             opcode = row['opcode']
             if condition:
                 # check it's expected
-                assert condition in self.conditions, \
+                assert (condition in self.conditions or
+                       (condition[0] == '~' and
+                        condition[1:] in self.conditions)), \
                     "condition %s not in %s" % (condition, str(conditions))
                 if opcode not in rows:
                     rows[opcode] = {}
@@ -434,7 +430,8 @@ class PowerDecoder(Elaboratable):
                     subdecoder = PowerDecoder(width=32, dec=sd,
                                               name=mname,
                                               col_subset=self.col_subset,
-                                              row_subset=self.row_subsetfn)
+                                              row_subset=self.row_subsetfn,
+                                              conditions=self.conditions)
                     if not subdecoder.tree_analyse():
                         del subdecoder
                         continue
@@ -479,6 +476,7 @@ class PowerDecoder(Elaboratable):
                     if is_conditions:
                         switch_case[opcode] = {}
                         for k, crow in row.items():
+                            # log("ordered", k, crow)
                             switch_case[opcode][k] = self.op._eq(crow)
                     else:
                         switch_case[opcode] = self.op._eq(row)
@@ -511,7 +509,8 @@ class PowerDecoder(Elaboratable):
                 subdecoder = PowerDecoder(self.width, dec,
                                           name=mname,
                                           col_subset=self.col_subset,
-                                          row_subset=self.row_subsetfn)
+                                          row_subset=self.row_subsetfn,
+                                          conditions=self.conditions)
                 log ("subdecoder", mname, subdecoder)
                 if not subdecoder.tree_analyse():  # doesn't do anything
                     log ("analysed, DELETING", mname)
@@ -553,9 +552,14 @@ class PowerDecoder(Elaboratable):
         entries for a given opcode match. here we discern them.
         """
         comb = m.d.comb
-        with m.Switch(Cat(*self.cswitch)):
-            for ckey, eqs in cases.items():
-                with m.Case(self.ccases[ckey]):
+        cswitch = []
+        ccases = []
+        for casekey, eqs in cases.items():
+            if casekey.startswith('~'):
+                with m.If(~self.conditions[casekey[1:]]):
+                    comb += eqs
+            else:
+                with m.If(self.conditions[casekey]):
                     comb += eqs
 
     def ports(self):
@@ -636,7 +640,10 @@ class TopPowerDecoder(PowerDecoder):
         return m
 
     def ports(self):
-        return [self.raw_opcode_in, self.bigendian] + PowerDecoder.ports(self)
+        res = [self.raw_opcode_in, self.bigendian] + PowerDecoder.ports(self)
+        for condition in self.conditions.values():
+            res.append(condition)
+        return res
 
 
 #############################################################
@@ -691,7 +698,7 @@ def create_pdecode_svp64_ldst(name=None, col_subset=None, row_subset=None,
 # PRIMARY FUNCTION SPECIFYING THE FULL POWER DECODER
 
 def create_pdecode(name=None, col_subset=None, row_subset=None,
-                   include_fp=False):
+                   include_fp=False, conditions=None):
     """create_pdecode - creates a cascading hierarchical POWER ISA decoder
 
     subsetting of the PowerOp decoding is possible by setting col_subset
@@ -752,7 +759,30 @@ def create_pdecode(name=None, col_subset=None, row_subset=None,
                           bitsel=(0, 32), suffix=None, subdecoders=[]))
 
     return TopPowerDecoder(32, dec, name=name, col_subset=col_subset,
-                           row_subset=row_subset)
+                           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__':
@@ -762,24 +792,43 @@ if __name__ == '__main__':
 
         def rowsubsetfn(opcode, row):
             log("row_subset", opcode, row)
-            return row['unit'] == 'FPU'
+            return row['unit'] in ['LDST', 'FPU']
 
+        conditions = {'SVP64BREV': Signal(name="svp64brev", reset_less=True),
+                      'SVP64FFT': Signal(name="svp64fft", reset_less=True),
+                     }
         pdecode = create_pdecode(name="rowsub",
                                  col_subset={'opcode', 'function_unit',
-                                             'form'},
+                                              'asmcode',
+                                             'in2_sel', 'in3_sel'},
                                  row_subset=rowsubsetfn,
-                                 include_fp=True)
+                                 include_fp=True,
+                                 conditions=conditions)
         vl = rtlil.convert(pdecode, ports=pdecode.ports())
         with open("row_subset_decoder.il", "w") as f:
             f.write(vl)
 
+        vl = verilog.convert(pdecode, ports=pdecode.ports())
+        with open("row_subset_decoder.v", "w") as f:
+            f.write(vl)
+
         # 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())
@@ -791,3 +840,5 @@ if __name__ == '__main__':
     vl = rtlil.convert(pdecode, ports=pdecode.ports())
     with open("decoder_svp64.il", "w") as f:
         f.write(vl)
+
+