pass SPR MicroOp to MMU function unit
[soc.git] / src / soc / decoder / power_decoder2.py
index 72b0e24662c25cf81b917c6f91b029c560b5ce9f..bfe9eda4d3a29f6f6f37a3d4248248fcff6d0c90 100644 (file)
@@ -889,7 +889,16 @@ class PowerDecodeSubset(Elaboratable):
 
         # set up instruction type
         # no op: defaults to OP_ILLEGAL
-        comb += self.do_copy("insn_type", self.op_get("internal_op"))
+        if self.fn_name=="MMU":
+            # mmu is special case: needs SPR opcode as well
+            mmu0 = self.mmu0_spr_dec
+            with m.If(((mmu0.dec.op.internal_op == MicrOp.OP_MTSPR) |
+                       (mmu0.dec.op.internal_op == MicrOp.OP_MFSPR))):
+                comb += self.do_copy("insn_type", mmu0.op_get("internal_op"))
+            with m.Else():
+                comb += self.do_copy("insn_type", self.op_get("internal_op"))
+        else:
+            comb += self.do_copy("insn_type", self.op_get("internal_op"))
 
         # function unit for decoded instruction: requires minor redirect
         # for SPR set/get
@@ -1269,6 +1278,53 @@ class PowerDecode2(PowerDecodeSubset):
         comb += self.do_copy("cia", self.state.pc, True)  # copy of PC "state"
 
 
+# SVP64 Prefix fields: see https://libre-soc.org/openpower/sv/svp64/
+# identifies if an instruction is a SVP64-encoded prefix, and extracts
+# the 24-bit SVP64 context (RM) if it is
+class SVP64PowerDecoder(Elaboratable):
+
+    def __init__(self):
+        self.opcode_in = Signal(32, reset_less=True)
+        self.raw_opcode_in = Signal.like(self.opcode_in, reset_less=True)
+        self.is_svp64_mode = Signal(1, reset_less=True)
+        self.svp64_rm = Signal(24, reset_less=True)
+        self.bigendian = Signal(reset_less=True)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+        # sigh copied this from TopPowerDecoder
+        # raw opcode in assumed to be in LE order: byte-reverse it to get BE
+        raw_le = self.raw_opcode_in
+        l = []
+        for i in range(0, 32, 8):
+            l.append(raw_le[i:i+8])
+        l.reverse()
+        raw_be = Cat(*l)
+        comb += self.opcode_in.eq(Mux(self.bigendian, raw_be, raw_le))
+
+        # start identifying if the incoming opcode is SVP64 prefix)
+        major = Signal(6, reset_less=True)
+
+        comb += major.eq(self.opcode_in[26:32])
+        comb += self.is_svp64_mode.eq((major == Const(1, 6)) & # EXT01
+                                      self.opcode_in[31-7] & # identifier
+                                      self.opcode_in[31-9])  # bits
+
+        # now grab the 24-bit ReMap context bits,
+        rmfields = [6, 8] + list(range(10,32)) # SVP64 24-bit RM
+        l = []
+        for idx in rmfields:
+            l.append(self.opcode_in[32-idx])
+        with m.If(self.is_svp64_mode):
+            comb += self.svp64_rm.eq(Cat(*l))
+
+        return m
+
+    def ports(self):
+        return [self.opcode_in, self.raw_opcode_in, self.is_svp64_mode,
+                self.svp64_rm, self.bigendian]
+
 def get_rdflags(e, cu):
     rdl = []
     for idx in range(cu.n_src):
@@ -1280,6 +1336,10 @@ def get_rdflags(e, cu):
 
 
 if __name__ == '__main__':
+    svp64 = SVP64PowerDecoder()
+    vl = rtlil.convert(svp64, ports=svp64.ports())
+    with open("svp64_dec.il", "w") as f:
+        f.write(vl)
     pdecode = create_pdecode()
     dec2 = PowerDecode2(pdecode)
     vl = rtlil.convert(dec2, ports=dec2.ports() + pdecode.ports())