From ca2b8c6635688dc113356bde3ddb80d0fa5149f7 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Mon, 5 Jul 2021 17:28:31 +0100 Subject: [PATCH] add svremap manual instruction (Primary Opcode 22, sandbox) --- openpower/isa/simplev.mdwn | 20 ++-- openpower/isatables/fields.text | 3 + src/openpower/decoder/isa/caller.py | 18 ++++ .../decoder/isa/test_caller_svp64_matrix.py | 91 +++++++++++++++++++ src/openpower/decoder/power_enums.py | 1 + src/openpower/decoder/pseudo/parser.py | 3 +- src/openpower/sv/trans/svp64.py | 17 +++- 7 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 src/openpower/decoder/isa/test_caller_svp64_matrix.py diff --git a/openpower/isa/simplev.mdwn b/openpower/isa/simplev.mdwn index bb84625e..ec47d0f7 100644 --- a/openpower/isa/simplev.mdwn +++ b/openpower/isa/simplev.mdwn @@ -37,7 +37,7 @@ Special Registers Altered: SVM-Form -* svstate SVxd, SVyd, SVzd, SVRM +* svremap SVxd, SVyd, SVzd, SVRM Pseudo-code: @@ -46,13 +46,21 @@ Pseudo-code: SVSHAPE1[0:31] <- [0] * 32 SVSHAPE2[0:31] <- [0] * 32 SVSHAPE3[0:31] <- [0] * 32 - # set up FRT and FRB + # set up template in SVSHAPE0, then copy to 1-3 SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim - SVSHAPE3[0:5] <- (0b0 || SVxd) # xdim + SVSHAPE0[6:11] <- (0b0 || SVyd) # ydim + SVSHAPE0[12:17] <- (0b0 || SVzd) # zdim + SVSHAPE0[28:29] <- 0b11 # skip z + # copy + SVSHAPE1[0:31] <- SVSHAPE0[0:31] + SVSHAPE2[0:31] <- SVSHAPE0[0:31] + SVSHAPE3[0:31] <- SVSHAPE0[0:31] # set up FRA - SVSHAPE0[0:5] <- (0b0 || SVxd) # xdim - SVSHAPE0[6:11] <- (0b0 || SVyd) # ydim - SVSHAPE0[18:20] <- 0b010 # permute y,x,z + SVSHAPE1[18:20] <- 0b001 # permute x,z,y + SVSHAPE1[28:29] <- 0b01 # skip z + # FRC + SVSHAPE2[18:20] <- 0b001 # permute x,z,y + SVSHAPE2[28:29] <- 0b11 # skip y Special Registers Altered: diff --git a/openpower/isatables/fields.text b/openpower/isatables/fields.text index a46299e8..542429dc 100644 --- a/openpower/isatables/fields.text +++ b/openpower/isatables/fields.text @@ -770,6 +770,9 @@ SVyd (11:15) Simple-V "REMAP" y-dimension size Formats: SVM + SVzd (16:20) + Simple-V "REMAP" z-dimension size + Formats: SVM SX,S (28,6:10) Fields SX and S are concatenated to specify a VSR to be used as a source. diff --git a/src/openpower/decoder/isa/caller.py b/src/openpower/decoder/isa/caller.py index f7561a78..06abbf28 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -74,6 +74,10 @@ REG_SORT_ORDER = { "TAR": 0, "MSR": 0, "SVSTATE": 0, + "SVSHAPE0": 0, + "SVSHAPE1": 0, + "SVSHAPE2": 0, + "SVSHAPE3": 0, "CA": 0, "CA32": 0, @@ -584,6 +588,11 @@ class ISACaller: self.gpr = GPR(decoder2, self, self.svstate, regfile) self.fpr = GPR(decoder2, self, self.svstate, fpregfile) self.spr = SPR(decoder2, initial_sprs) # initialise SPRs before MMU + for i in range(4): + sname = 'SVSHAPE%d' % i + if sname not in self.spr: + self.spr[sname] = SVSHAPE(0) + # "raw" memory self.mem = Mem(row_bytes=8, initial_mem=initial_mem) self.imem = Mem(row_bytes=4, initial_mem=initial_insns) @@ -623,6 +632,10 @@ class ISACaller: 'NIA': self.pc.NIA, 'CIA': self.pc.CIA, 'SVSTATE': self.svstate.spr, + 'SVSHAPE0': self.spr['SVSHAPE0'], + 'SVSHAPE1': self.spr['SVSHAPE1'], + 'SVSHAPE2': self.spr['SVSHAPE2'], + 'SVSHAPE3': self.spr['SVSHAPE3'], 'CR': self.cr, 'MSR': self.msr, 'undefined': undefined, @@ -1054,6 +1067,11 @@ class ISACaller: illegal = False name = 'setvl' + # and svremap not being supported by binutils (.long) + if asmop.startswith('svremap'): + illegal = False + name = 'svremap' + # sigh also deal with ffmadds not being supported by binutils (.long) if asmop == 'ffmadds': illegal = False diff --git a/src/openpower/decoder/isa/test_caller_svp64_matrix.py b/src/openpower/decoder/isa/test_caller_svp64_matrix.py new file mode 100644 index 00000000..4a9c3f38 --- /dev/null +++ b/src/openpower/decoder/isa/test_caller_svp64_matrix.py @@ -0,0 +1,91 @@ +from nmigen import Module, Signal +from nmigen.back.pysim import Simulator, Delay, Settle +from nmutil.formaltest import FHDLTestCase +import unittest +from openpower.decoder.isa.caller import ISACaller +from openpower.decoder.power_decoder import (create_pdecode) +from openpower.decoder.power_decoder2 import (PowerDecode2) +from openpower.simulator.program import Program +from openpower.decoder.isa.caller import ISACaller, SVP64State +from openpower.decoder.selectable_int import SelectableInt +from openpower.decoder.orderedset import OrderedSet +from openpower.decoder.isa.all import ISA +from openpower.decoder.isa.test_caller import Register, run_tst +from openpower.sv.trans.svp64 import SVP64Asm +from openpower.consts import SVP64CROffs +from copy import deepcopy +from openpower.decoder.helpers import fp64toselectable +from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE + +class DecoderTestCase(FHDLTestCase): + + def _check_regs(self, sim, expected): + for i in range(32): + self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64)) + + def test_sv_remap(self): + """>>> lst = ["svremap 2, 2, 3, 0" + ] + """ + lst = SVP64Asm(["svremap 2, 2, 3, 0" + ]) + lst = list(lst) + + fprs = [0] * 32 + if False: + av = [7.0, -9.8, 2.0, -32.3] # first half of array 0..3 + bv = [-2.0, 2.0, -9.8, 32.3] # second half of array 4..7 + coe = [-1.0, 4.0, 3.1, 6.2] # coefficients + res = [] + # work out the results with the twin mul/add-sub + for i, (a, b, c) in enumerate(zip(av, bv, coe)): + fprs[i+2] = fp64toselectable(a) + fprs[i+6] = fp64toselectable(b) + fprs[i+10] = fp64toselectable(c) + mul = a * c + t = a + mul + u = b - mul + t = DOUBLE2SINGLE(fp64toselectable(t)) # convert to Power single + u = DOUBLE2SINGLE(fp64toselectable(u)) # from double + res.append((t, u)) + print ("FFT", i, "in", a, b, "coeff", c, "mul", + mul, "res", t, u) + + # SVSTATE (in this case, VL=12, to cover all of matrix) + svstate = SVP64State() + svstate.vl[0:7] = 12 # VL + svstate.maxvl[0:7] = 12 # MAXVL + print ("SVSTATE", bin(svstate.spr.asint())) + + with Program(lst, bigendian=False) as program: + sim = self.run_tst_program(program, svstate=svstate, + initial_fprs=fprs) + print ("spr svshape0", sim.spr['SVSHAPE0']) + print ("spr svshape1", sim.spr['SVSHAPE1']) + print ("spr svshape2", sim.spr['SVSHAPE2']) + print ("spr svshape3", sim.spr['SVSHAPE3']) + # confirm that the results are as expected + #for i, (t, u) in enumerate(res): + # self.assertEqual(sim.fpr(i+2), t) + # self.assertEqual(sim.fpr(i+6), u) + + def run_tst_program(self, prog, initial_regs=None, + svstate=None, + initial_mem=None, + initial_fprs=None): + if initial_regs is None: + initial_regs = [0] * 32 + simulator = run_tst(prog, initial_regs, mem=initial_mem, + initial_fprs=initial_fprs, + svstate=svstate) + + print ("GPRs") + simulator.gpr.dump() + print ("FPRs") + simulator.fpr.dump() + + return simulator + + +if __name__ == "__main__": + unittest.main() diff --git a/src/openpower/decoder/power_enums.py b/src/openpower/decoder/power_enums.py index 1b658639..67f81c3b 100644 --- a/src/openpower/decoder/power_enums.py +++ b/src/openpower/decoder/power_enums.py @@ -505,6 +505,7 @@ def get_spr_enum(full_file): this saves drastically on the size of the regfile """ short_list = {'PIDR', 'DAR', 'PRTBL', 'DSISR', 'SVSRR0', 'SVSTATE', + 'SVSTATE0', 'SVSTATE1', 'SVSTATE2', 'SVSTATE3', 'SPRG0_priv', 'SPRG1_priv', 'SPRG2_priv', 'SPRG3_priv', 'SPRG3' } diff --git a/src/openpower/decoder/pseudo/parser.py b/src/openpower/decoder/pseudo/parser.py index ed9fae79..6b11359c 100644 --- a/src/openpower/decoder/pseudo/parser.py +++ b/src/openpower/decoder/pseudo/parser.py @@ -726,7 +726,8 @@ class PowerParser: if self.include_ca_in_write: if name in ['CA', 'CA32']: self.write_regs.add(name) - if name in ['CR', 'LR', 'CTR', 'TAR', 'FPSCR', 'MSR', 'SVSTATE']: + if name in ['CR', 'LR', 'CTR', 'TAR', 'FPSCR', 'MSR', + 'SVSTATE', 'SVSHAPE0', 'SVSHAPE1', 'SVSHAPE2', 'SVSHAPE3']: self.special_regs.add(name) self.write_regs.add(name) # and add to list to write p[0] = ast.Name(id=name, ctx=ast.Load()) diff --git a/src/openpower/sv/trans/svp64.py b/src/openpower/sv/trans/svp64.py index 64888594..bf192028 100644 --- a/src/openpower/sv/trans/svp64.py +++ b/src/openpower/sv/trans/svp64.py @@ -196,6 +196,19 @@ class SVP64Asm: yield ".long 0x%x" % insn return + # and svremap + if opcode == 'svremap': + insn = 22 << (31-5) # opcode 22, bits 0-5 + fields = list(map(int, fields)) + insn |= fields[0] << (31-10) # SVxd , bits 6-10 + insn |= fields[1] << (31-15) # SVyd , bits 11-15 + insn |= fields[2] << (31-16) # SVzd , bits 16-20 + insn |= fields[3] << (31-21) # SVRM , bits 21-25 + insn |= 0b00001 << (31-30) # XO , bits 26..30 + log ("svremap", bin(insn)) + yield ".long 0x%x" % insn + return + # identify if is a svp64 mnemonic if not opcode.startswith('sv.'): yield insn # unaltered @@ -890,7 +903,8 @@ def asm_process(): for line in lines: ls = line.split("#") # identify macros - if ls[0].strip().startswith("setvl"): + op = ls[0].strip() + if op.startswith("setvl") or op.startswith("svremap"): ws, line = get_ws(ls[0]) lst = list(isa.translate_one(ls[0].strip(), macros)) lst = '; '.join(lst) @@ -953,6 +967,7 @@ if __name__ == '__main__': #'sv.lhzbr 5.v, 11(9.v), 15', #'sv.lwzbr 5.v, 11(9.v), 15', 'sv.ffmadds 6.v, 2.v, 4.v, 6.v', + 'svremap 2, 2, 3, 0', ] isa = SVP64Asm(lst, macros=macros) print ("list", list(isa)) -- 2.30.2