add PowerDecoder condition switches (untested, doesnt break anything)
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 24 Jun 2021 18:19:26 +0000 (19:19 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 24 Jun 2021 18:19:26 +0000 (19:19 +0100)
src/openpower/decoder/power_decoder.py

index 8d7fcfa921b1dbbee1e5dc65303338818861bd16..517748de5a63a9661371ece038016c8059722589 100644 (file)
@@ -319,9 +319,13 @@ class PowerDecoder(Elaboratable):
     the constructor is called.  all quite messy.
     """
 
-    def __init__(self, width, dec, name=None, col_subset=None, row_subset=None):
+    def __init__(self, width, dec, name=None, col_subset=None,
+                       row_subset=None, conditions=None):
+        if conditions is None:
+            conditions = {}
         self.actually_does_something = False
         self.pname = name
+        self.conditions = conditions
         self.col_subset = col_subset
         self.row_subsetfn = row_subset
         if not isinstance(dec, list):
@@ -335,6 +339,22 @@ class PowerDecoder(Elaboratable):
                 d.suffix = None
         self.width = width
 
+        # create some case statement condition patterns for matching
+        # a single condition.  "1----" for the first condition,
+        # "-1----" for the 2nd etc.
+        # also create a matching ordered list of conditions, for the switch,
+        # which will Cat() them together
+        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] = case
+            cswitch.append(conditions[ckey])
+        self.cswitch = cswitch
+
     def suffix_mask(self, d):
         return ((1 << d.suffix) - 1)
 
@@ -475,9 +495,25 @@ class PowerDecoder(Elaboratable):
                 with m.Switch(switch):
                     for key, eqs in cases.items():
                         with m.Case(key):
-                            comb += eqs
+                            # "conditions" are a further switch statement
+                            if isinstance(eqs, dict):
+                                self.condition_switch(m, eqs)
+                            else:
+                                comb += eqs
         return m
 
+    def condition_switch(self, m, cases):
+        """against the global list of "conditions", having matched against
+        bits of the opcode, we FINALLY now have to match against some
+        additional "conditions".  this is because there can be **MULTIPLE**
+        entries for a given opcode match. here we discern them.
+        """
+        comb = m.d.comb
+        with m.Switch(Cat(*self.ccswitch)):
+            for ckey, eqs in cases.items():
+                with m.Case(self.ccases[key]):
+                    comb += eqs
+
     def ports(self):
         return [self.opcode_in] + self.op.ports()
 
@@ -490,8 +526,10 @@ class TopPowerDecoder(PowerDecoder):
     (reverses byte order).  See V3.0B p44 1.11.2
     """
 
-    def __init__(self, width, dec, name=None, col_subset=None, row_subset=None):
-        PowerDecoder.__init__(self, width, dec, name, col_subset, row_subset)
+    def __init__(self, width, dec, name=None, col_subset=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])
         self.fields.create_specs()
         self.raw_opcode_in = Signal.like(self.opcode_in, reset_less=True)