From 429050209dee387d52ebcfc5ab3538ea645d7cdb Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sat, 8 Oct 2022 21:14:24 +0100 Subject: [PATCH] split out base,offset in register decoding for elwidth overrides to work 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 | 30 ++++++++++++++++++---- src/openpower/decoder/isa/caller.py | 32 ++++++++++++++++++------ src/openpower/decoder/power_decoder2.py | 16 +++++++----- src/openpower/test/alu/svp64_cases.py | 4 +-- 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/openpower/decoder/decode2execute1.py b/src/openpower/decoder/decode2execute1.py index 767d8496..40c90b9e 100644 --- a/src/openpower/decoder/decode2execute1.py +++ b/src/openpower/decoder/decode2execute1.py @@ -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 diff --git a/src/openpower/decoder/isa/caller.py b/src/openpower/decoder/isa/caller.py index 1cdc1327..4842cda1 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -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) diff --git a/src/openpower/decoder/power_decoder2.py b/src/openpower/decoder/power_decoder2.py index 1ad9a52f..5e7b0370 100644 --- a/src/openpower/decoder/power_decoder2.py +++ b/src/openpower/decoder/power_decoder2.py @@ -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")) diff --git a/src/openpower/test/alu/svp64_cases.py b/src/openpower/test/alu/svp64_cases.py index 86ad4be1..5c7b5efe 100644 --- a/src/openpower/test/alu/svp64_cases.py +++ b/src/openpower/test/alu/svp64_cases.py @@ -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) -- 2.30.2