From 83a3212c234c413e8e5b670a18840f0a8a7f7190 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 26 Aug 2022 15:40:01 +0100 Subject: [PATCH] add setvl unit tests for overflow condition. TODO, update spec to match: when VL attempted to be set > MAXVL --- openpower/isa/simplev.mdwn | 10 +- src/openpower/decoder/isa/caller.py | 21 +-- .../decoder/isa/test_caller_setvl.py | 123 ++++++++++++++++++ 3 files changed, 143 insertions(+), 11 deletions(-) diff --git a/openpower/isa/simplev.mdwn b/openpower/isa/simplev.mdwn index 6169c2e3..b19e3af6 100644 --- a/openpower/isa/simplev.mdwn +++ b/openpower/isa/simplev.mdwn @@ -31,6 +31,7 @@ Pseudo-code: if _RT != 0 then RT <- [0]*57 || step else + overflow <- 0b0 VLimm <- SVi + 1 # set or get MVL if ms = 1 then MVL <- VLimm[0:6] @@ -38,14 +39,19 @@ Pseudo-code: # set or get VL if vs = 0 then VL <- SVSTATE[7:13] else if _RA != 0 then - if (RA) >u 0b1111111 then VL <- 0b1111111 + if (RA) >u 0b1111111 then + VL <- 0b1111111 + overflow <- 0b1 else VL <- (RA)[57:63] else if _RA != 0 then VL <- (RA)[57:63] else if _RT = 0 then VL <- VLimm[0:6] - else if CTR >u 0b1111111 then VL <- 0b1111111 + else if CTR >u 0b1111111 then + VL <- 0b1111111 + overflow <- 0b1 else VL <- CTR[57:63] # limit VL to within MVL if VL >u MVL then + overflow <- 0b1 VL <- MVL SVSTATE[0:6] <- MVL SVSTATE[7:13] <- VL diff --git a/src/openpower/decoder/isa/caller.py b/src/openpower/decoder/isa/caller.py index 854d7849..bb928aba 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -935,7 +935,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers): so = so | ov self.spr['XER'][XER_bits['SO']] = so - def handle_comparison(self, outputs, cr_idx=0): + def handle_comparison(self, outputs, cr_idx=0, overflow=None): out = outputs[0] assert isinstance(out, SelectableInt), \ "out zero not a SelectableInt %s" % repr(outputs) @@ -951,7 +951,9 @@ class ISACaller(ISACallerHelper, ISAFPHelpers): positive = SelectableInt(out > 0, 1) negative = SelectableInt(out < 0, 1) SO = self.spr['XER'][XER_bits['SO']] - log("handle_comparison SO", SO) + log("handle_comparison SO overflow", SO, overflow) + if overflow is not None and overflow == 1: + SO = SelectableInt(1, 1) cr_field = selectconcat(negative, positive, zero, SO) log("handle_comparison cr_field", self.cr, cr_idx, cr_field) self.crl[cr_idx].eq(cr_field) @@ -1412,14 +1414,15 @@ class ISACaller(ISACallerHelper, ISAFPHelpers): if carry_en: yield from self.handle_carry_(inputs, results, already_done) + # check if one of the regs was named "overflow" + overflow = None + if info.write_regs: + for name, output in zip(output_names, results): + if name == 'overflow': + overflow = output + if not self.is_svp64_mode: # yeah just no. not in parallel processing # detect if overflow was in return result - overflow = None - if info.write_regs: - for name, output in zip(output_names, results): - if name == 'overflow': - overflow = output - if hasattr(self.dec2.e.do, "oe"): ov_en = yield self.dec2.e.do.oe.oe ov_ok = yield self.dec2.e.do.oe.ok @@ -1437,7 +1440,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers): rc_en = yield self.dec2.e.do.rc.rc if rc_en and ins_name not in ['svstep']: regnum, is_vec = yield from get_pdecode_cr_out(self.dec2, "CR0") - self.handle_comparison(results, regnum) + self.handle_comparison(results, regnum, overflow) # any modified return results? if info.write_regs: diff --git a/src/openpower/decoder/isa/test_caller_setvl.py b/src/openpower/decoder/isa/test_caller_setvl.py index 45ff3578..3b2097cf 100644 --- a/src/openpower/decoder/isa/test_caller_setvl.py +++ b/src/openpower/decoder/isa/test_caller_setvl.py @@ -97,6 +97,129 @@ class DecoderTestCase(FHDLTestCase): self.assertEqual(CR0[CRFields.GT], 1) self.assertEqual(CR0[CRFields.SO], 0) + def test_3_setvl_overflow_rc1(self): + lst = SVP64Asm(["setvl. 5, 4, 5, 0, 1, 1", + ]) + lst = list(lst) + + # SVSTATE (in this case, MAXVL=5) which is going to get erased by setvl + # r4 (RA) is 4. and Rc=1. therefore, CR0 should be set to GT + svstate = SVP64State() + svstate.maxvl = 5 # MAXVL + print ("SVSTATE", bin(svstate.asint())) + + initial_regs = [0] * 32 + initial_regs[4] = 1000 # much greater than MAXVL + + with Program(lst, bigendian=False) as program: + sim = self.run_tst_program(program, svstate=svstate, + initial_regs=initial_regs) + print ("SVSTATE after", bin(sim.svstate.asint())) + print (" vl", bin(sim.svstate.vl)) + print (" mvl", bin(sim.svstate.maxvl)) + print (" srcstep", bin(sim.svstate.srcstep)) + print (" dststep", bin(sim.svstate.dststep)) + print (" vfirst", bin(sim.svstate.vfirst)) + self.assertEqual(sim.svstate.vl, 5) + self.assertEqual(sim.svstate.maxvl, 5) + self.assertEqual(sim.svstate.srcstep, 0) + self.assertEqual(sim.svstate.dststep, 0) + self.assertEqual(sim.svstate.vfirst, 0) + print(" gpr4", sim.gpr(4)) + self.assertEqual(sim.gpr(4), SelectableInt(1000, 64)) # unmodified + print(" gpr5", sim.gpr(5)) + self.assertEqual(sim.gpr(5), SelectableInt(5, 64)) # equal to MAXVL + CR0 = sim.crl[0] + print(" CR0", bin(CR0.get_range().value)) + self.assertEqual(CR0[CRFields.EQ], 0) + self.assertEqual(CR0[CRFields.LT], 0) + self.assertEqual(CR0[CRFields.GT], 1) + self.assertEqual(CR0[CRFields.SO], 1) + + def test_4_setvl_max_overflow_rc1(self): + """this should set overflow even though VL gets set to MAXVL + at its limit of 127 (0b1111111) + """ + lst = SVP64Asm(["setvl. 5, 4, 127, 0, 1, 1", + ]) + lst = list(lst) + + # SVSTATE (in this case, MAXVL=5) which is going to get erased by setvl + # r4 (RA) is 4. and Rc=1. therefore, CR0 should be set to GT + svstate = SVP64State() + svstate.maxvl = 5 # MAXVL + print ("SVSTATE", bin(svstate.asint())) + + initial_regs = [0] * 32 + initial_regs[4] = 1000 # much greater than MAXVL + + with Program(lst, bigendian=False) as program: + sim = self.run_tst_program(program, svstate=svstate, + initial_regs=initial_regs) + print ("SVSTATE after", bin(sim.svstate.asint())) + print (" vl", bin(sim.svstate.vl)) + print (" mvl", bin(sim.svstate.maxvl)) + print (" srcstep", bin(sim.svstate.srcstep)) + print (" dststep", bin(sim.svstate.dststep)) + print (" vfirst", bin(sim.svstate.vfirst)) + self.assertEqual(sim.svstate.vl, 127) + self.assertEqual(sim.svstate.maxvl, 127) + self.assertEqual(sim.svstate.srcstep, 0) + self.assertEqual(sim.svstate.dststep, 0) + self.assertEqual(sim.svstate.vfirst, 0) + print(" gpr4", sim.gpr(4)) + self.assertEqual(sim.gpr(4), SelectableInt(1000, 64)) # unmodified + print(" gpr5", sim.gpr(5)) + self.assertEqual(sim.gpr(5), SelectableInt(127, 64)) # eq. MAXVL + CR0 = sim.crl[0] + print(" CR0", bin(CR0.get_range().value)) + self.assertEqual(CR0[CRFields.EQ], 0) + self.assertEqual(CR0[CRFields.LT], 0) + self.assertEqual(CR0[CRFields.GT], 1) + self.assertEqual(CR0[CRFields.SO], 1) + + def test_5_setvl_max_rc1(self): + """this should not set when VL gets set to MAXVL + at its limit of 127 (0b1111111) + """ + lst = SVP64Asm(["setvl. 5, 4, 127, 0, 1, 1", + ]) + lst = list(lst) + + # SVSTATE (in this case, MAXVL=5) which is going to get erased by setvl + # r4 (RA) is 4. and Rc=1. therefore, CR0 should be set to GT + svstate = SVP64State() + svstate.maxvl = 5 # MAXVL + print ("SVSTATE", bin(svstate.asint())) + + initial_regs = [0] * 32 + initial_regs[4] = 127 # exactly equal to MAXVL + + with Program(lst, bigendian=False) as program: + sim = self.run_tst_program(program, svstate=svstate, + initial_regs=initial_regs) + print ("SVSTATE after", bin(sim.svstate.asint())) + print (" vl", bin(sim.svstate.vl)) + print (" mvl", bin(sim.svstate.maxvl)) + print (" srcstep", bin(sim.svstate.srcstep)) + print (" dststep", bin(sim.svstate.dststep)) + print (" vfirst", bin(sim.svstate.vfirst)) + self.assertEqual(sim.svstate.vl, 127) + self.assertEqual(sim.svstate.maxvl, 127) + self.assertEqual(sim.svstate.srcstep, 0) + self.assertEqual(sim.svstate.dststep, 0) + self.assertEqual(sim.svstate.vfirst, 0) + print(" gpr4", sim.gpr(4)) + self.assertEqual(sim.gpr(4), SelectableInt(127, 64)) # unmodified + print(" gpr5", sim.gpr(5)) + self.assertEqual(sim.gpr(5), SelectableInt(127, 64)) # eq. MAXVL + CR0 = sim.crl[0] + print(" CR0", bin(CR0.get_range().value)) + self.assertEqual(CR0[CRFields.EQ], 0) + self.assertEqual(CR0[CRFields.LT], 0) + self.assertEqual(CR0[CRFields.GT], 1) + self.assertEqual(CR0[CRFields.SO], 0) + def test_svstep_1(self): lst = SVP64Asm(["setvl 0, 0, 10, 1, 1, 1", # actual setvl (VF mode) "setvl 0, 0, 1, 1, 0, 0", # svstep -- 2.30.2