split out base,offset in register decoding for elwidth overrides to work
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 8 Oct 2022 20:14:24 +0000 (21:14 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 8 Oct 2022 20:14:24 +0000 (21:14 +0100)
previously, calculating the register number was fine, it was straight
64-bit reg indexed.  however elwidths are *part-way* through registers
(packed) so need to compute the reg differently

src/openpower/decoder/decode2execute1.py
src/openpower/decoder/isa/caller.py
src/openpower/decoder/power_decoder2.py
src/openpower/test/alu/svp64_cases.py

index 767d84967ff40b6e86ae4d89ded535ad5998427a..40c90b9e3c0bd9fa647e7524ef0af5a7a7ba6c60 100644 (file)
@@ -30,6 +30,26 @@ class Data(Record):
         return [self.data, self.ok]
 
 
+class SVP64Reg(Record):
+
+    def __init__(self, width, name):
+        name_ok = "%s_ok" % name
+        name_offs = "%s_offs" % name
+        name_base = "%s_base" % name
+        layout = ((name, width), (name_offs, width),
+                  (name_base, width), (name_ok, 1))
+        Record.__init__(self, layout)
+        self.data = getattr(self, name) # convenience
+        self.base = getattr(self, name_base) # convenience
+        self.offs = getattr(self, name_offs) # convenience
+        self.ok = getattr(self, name_ok) # convenience
+        self.data.reset_less = True # grrr
+        self.reset_less = True # grrr
+
+    def ports(self):
+        return [self.data, self.ok]
+
+
 class IssuerDecode2ToOperand(RecordObject):
     """IssuerDecode2ToOperand
 
@@ -107,11 +127,11 @@ class Decode2ToExecute1Type(RecordObject):
 
         if asmcode:
             self.asmcode = Signal(asmlen, reset_less=True) # only for simulator
-        self.write_reg = Data(7, name="rego")
-        self.write_ea = Data(7, name="ea") # for LD/ST in update mode
-        self.read_reg1 = Data(7, name="reg1")
-        self.read_reg2 = Data(7, name="reg2")
-        self.read_reg3 = Data(7, name="reg3")
+        self.write_reg = SVP64Reg(7, name="rego")
+        self.write_ea = SVP64Reg(7, name="ea") # for LD/ST in update mode
+        self.read_reg1 = SVP64Reg(7, name="reg1")
+        self.read_reg2 = SVP64Reg(7, name="reg2")
+        self.read_reg3 = SVP64Reg(7, name="reg3")
         self.write_spr = Data(SPR, name="spro")
         self.read_spr1 = Data(SPR, name="spr1")
         #self.read_spr2 = Data(SPR, name="spr2") # only one needed
index 1cdc1327eee00fd32b2ae742be1efb95d452717e..4842cda1e1a3030f5a69d46e9e497ae81b3c32b5 100644 (file)
@@ -122,9 +122,10 @@ class GPR(dict):
         for i in range(len(regfile)):
             self[i] = SelectableInt(regfile[i], 64)
 
-    def __call__(self, ridx):
+    def __call__(self, ridx, is_vec=False, offs=0, elwidth=64):
         if isinstance(ridx, SelectableInt):
             ridx = ridx.value
+        log("GPR call", ridx, "isvec", is_vec, "offs", offs, "elwid", elwidth)
         return self[ridx]
 
     def set_form(self, form):
@@ -1113,7 +1114,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
                                'undefined': undefined,
                                'mode_is_64bit': True,
                                'SO': XER_bits['SO'],
-                               'XLEN': 64  # elwidth overrides, later
+                               'XLEN': 64  # elwidth overrides
                                })
 
         # update pc to requested start point
@@ -1187,7 +1188,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
     def memassign(self, ea, sz, val):
         self.mem.memassign(ea, sz, val)
 
-    def prep_namespace(self, insn_name, formname, op_fields):
+    def prep_namespace(self, insn_name, formname, op_fields, xlen):
         # TODO: get field names from form in decoder*1* (not decoder2)
         # decoder2 is hand-created, and decoder1.sigform is auto-generated
         # from spec
@@ -1224,6 +1225,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         self.namespace['XER'] = self.spr['XER']
         self.namespace['CA'] = self.spr['XER'][XER_bits['CA']].value
         self.namespace['CA32'] = self.spr['XER'][XER_bits['CA32']].value
+        self.namespace['XLEN'] = xlen
 
         # add some SVSTATE convenience variables
         vl = self.svstate.vl
@@ -1693,12 +1695,26 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             self.update_pc_next()
             return
 
+        # get elwidths, defaults to 64
+        xlen = 64
+        ew_src = 64
+        ew_dst = 64
+        if self.is_svp64_mode:
+            ew_src = yield self.dec2.rm_dec.ew_src
+            ew_dst = yield self.dec2.rm_dec.ew_dst
+            ew_src = 8 << (3-int(ew_src)) # convert to bitlength
+            ew_dst = 8 << (3-int(ew_dst)) # convert to bitlength
+            xlen = max(ew_src, ew_dst)
+            log("elwdith", ew_src, ew_dst)
+        log("XLEN:", self.is_svp64_mode, xlen)
+
         # look up instruction in ISA.instrs, prepare namespace
         if ins_name == 'pcdec': # grrrr yes there are others ("stbcx." etc.)
             info = self.instrs[ins_name+"."]
         else:
             info = self.instrs[ins_name]
-        yield from self.prep_namespace(ins_name, info.form, info.op_fields)
+        yield from self.prep_namespace(ins_name, info.form, info.op_fields,
+                                       xlen)
 
         # preserve order of register names
         input_names = create_args(list(info.read_regs) +
@@ -1766,7 +1782,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         # main input registers (RT, RA ...)
         inputs = []
         for name in input_names:
-            regval = (yield from self.get_input(name))
+            regval = (yield from self.get_input(name, ew_src))
             log("regval name", name, regval)
             inputs.append(regval)
 
@@ -2003,7 +2019,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             else:
                 self.namespace['D'] = imm
 
-    def get_input(self, name):
+    def get_input(self, name, ew_src):
         # using PowerDecoder2, first, find the decoder index.
         # (mapping name RA RB RC RS to in1, in2, in3)
         regnum, is_vec = yield from get_pdecode_idx_in(self.dec2, name)
@@ -2020,10 +2036,10 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         if not self.is_svp64_mode or not self.pred_src_zero:
             log('reading reg %s %s' % (name, str(regnum)), is_vec)
             if name in fregs:
-                reg_val = SelectableInt(self.fpr(regnum))
+                reg_val = SelectableInt(self.fpr(regnum, is_vec, ew_src))
                 log("read reg %d: 0x%x" % (regnum, reg_val.value))
             elif name is not None:
-                reg_val = SelectableInt(self.gpr(regnum))
+                reg_val = SelectableInt(self.gpr(regnum, is_vec, ew_src))
                 log("read reg %d: 0x%x" % (regnum, reg_val.value))
         else:
             log('zero input reg %s %s' % (name, str(regnum)), is_vec)
index 1ad9a52fdb3b19a81ec4905cdaf8e5e490a52c09..5e7b03706bcaf3396e54ed78fcca641ab159853d 100644 (file)
@@ -1379,11 +1379,13 @@ class PowerDecode2(PowerDecodeSubset):
                         comb += step.eq((selectstep*(subvl+1))+subselect)
                     # reverse gear goes the opposite way
                     with m.If(self.rm_dec.reverse_gear):
-                        comb += to_reg.data.eq(offs+svdec.reg_out+(vmax-1-step))
+                        comb += to_reg.offs.eq(offs+(vmax-1-step))
                     with m.Else():
-                        comb += to_reg.data.eq(offs+step+svdec.reg_out)
+                        comb += to_reg.offs.eq(offs+step)
                 with m.Else():
-                    comb += to_reg.data.eq(offs+svdec.reg_out)
+                    comb += to_reg.offs.eq(offs)
+                comb += to_reg.base.eq(svdec.reg_out)
+                comb += to_reg.data.eq(to_reg.base + to_reg.offs)
 
             # SVP64 in/out fields
             comb += in1_svdec.idx.eq(self.op_get("sv_in1"))  # reg #1 (in1_sel)
@@ -1436,11 +1438,13 @@ class PowerDecode2(PowerDecodeSubset):
                     # reverse gear goes the opposite way
                     with m.If(self.rm_dec.reverse_gear):
                         roffs = offs+(vl-1-step)
-                        comb += to_reg.data.eq(roffs+imp_reg_out)
+                        comb += e.write_ea.data.eq(roffs)
                     with m.Else():
-                        comb += to_reg.data.eq(offs+step+imp_reg_out)
+                        comb += e.write_ea.data.eq(offs+step)
                 with m.Else():
-                    comb += to_reg.data.eq(offs+imp_reg_out)
+                    comb += e.write_ea.offs.eq(offs)
+                comb += e.write_ea.base.eq(imp_reg_out)
+                comb += e.write_ea.data.eq(e.write_ea.base + e.write_ea.offs)
                 # ... but write to *second* output
                 comb += self.o2_isvec.eq(imp_isvec)
                 comb += o2_svdec.idx.eq(self.op_get("sv_out"))
index 86ad4be10e456bad46043768ef357ea78107bd17..5c7b5efe8c00e74cd4129fbe613505d8198a3d01 100644 (file)
@@ -9,9 +9,9 @@ from copy import deepcopy
 class SVP64ALUElwidthTestCase(TestAccumulatorBase):
 
     def case_1_sv_add_ew8(self):
-        """>>> lst = ['sv.add/ew=8 *1, *5, *9']
+        """>>> lst = ['sv.add/w=8 *1, *5, *9']
         """
-        isa = SVP64Asm(['sv.add *1, *5, *9'])
+        isa = SVP64Asm(['sv.add/w=8 *1, *5, *9'])
         lst = list(isa)
         print("listing", lst)