From: Luke Kenneth Casson Leighton Date: Sun, 15 Aug 2021 16:05:16 +0000 (+0100) Subject: sv.bc test jumping to wrong location (offset 0xc not 0x8) X-Git-Tag: xlen-bcd~130 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c3b9973df8edcb1f6c1583c2da693336af7d1921;p=openpower-isa.git sv.bc test jumping to wrong location (offset 0xc not 0x8) fix sv.bc/all test, and sv.bc pseudocode, to early-exit if one CR test fails, but also not branch just because *one* test succeeds. --- diff --git a/openpower/isa/svbranch.mdwn b/openpower/isa/svbranch.mdwn index 0c15a04d..bbc5aeda 100644 --- a/openpower/isa/svbranch.mdwn +++ b/openpower/isa/svbranch.mdwn @@ -54,6 +54,7 @@ Pseudo-code: SVSTATE[7:13] <- (srcstep+1) else SVSTATE[7:13] <- srcstep+1 + end_loop <- 0b1 # XXX if svstep_mode then # XXX SVSTATE.srcstep = new_srcstep # actual branch @@ -61,8 +62,17 @@ Pseudo-code: else M <- 32 if ¬BO[2] then CTR <- CTR - 1 ctr_ok <- BO[2] | ((CTR[M:63] != 0) ^ BO[3]) + test_branch <- 0b1 + if ALL then + # in ALL mode only try branching at end of loop + if ¬end_loop then + test_branch <- 0b0 + # test early-exit. ALL will exit if cond_ok fails + if ¬cond_ok then + end_loop <- 0b1 + test_branch <- 0b0 lr_ok <- LRu - if ctr_ok & cond_ok then + if test_branch & ctr_ok & cond_ok then if AA then NIA <-iea EXTS(BD || 0b00) else NIA <-iea CIA + EXTS(BD || 0b00) lr_ok <- 0b1 diff --git a/src/openpower/decoder/isa/caller.py b/src/openpower/decoder/isa/caller.py index 157d4598..0c1a8730 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -799,7 +799,9 @@ class ISACaller: bc_snz = (mode & SVP64MODE.BC_SNZ) != 0 bc_vsb = yield self.dec2.rm_dec.bc_vsb bc_lru = yield self.dec2.rm_dec.bc_lru + bc_gate = yield self.dec2.rm_dec.bc_gate sz = yield self.dec2.rm_dec.pred_sz + self.namespace['ALL'] = SelectableInt(bc_gate, 1) self.namespace['VSb'] = SelectableInt(bc_vsb, 1) self.namespace['LRu'] = SelectableInt(bc_lru, 1) self.namespace['VLSET'] = SelectableInt(bc_vlset, 1) @@ -1019,7 +1021,8 @@ class ISACaller: if not self.respect_pc: self.fake_pc += 4 - log("execute one, CIA NIA", self.pc.CIA.value, self.pc.NIA.value) + log("execute one, CIA NIA", hex(self.pc.CIA.value), + hex(self.pc.NIA.value)) def get_assembly_name(self): # TODO, asmregs is from the spec, e.g. add RT,RA,RB @@ -1581,6 +1584,7 @@ class ISACaller: # this is our Sub-Program-Counter loop from 0 to VL-1 pre = False post = False + nia_update = True if self.allow_next_step_inc: log("SVSTATE_NEXT: inc requested, mode", self.svstate_next_mode, self.allow_next_step_inc) @@ -1598,7 +1602,7 @@ class ISACaller: else: if self.allow_next_step_inc == 2: log ("SVSTATE_NEXT: read") - yield from self.svstate_post_inc(ins_name) + nia_update = (yield from self.svstate_post_inc(ins_name)) else: log ("SVSTATE_NEXT: post-inc") # use actual src/dst-step here to check end, do NOT @@ -1638,7 +1642,7 @@ class ISACaller: self.svstate.vfirst = 0 elif self.is_svp64_mode: - yield from self.svstate_post_inc(ins_name) + nia_update = (yield from self.svstate_post_inc(ins_name)) else: # XXX only in non-SVP64 mode! # record state of whether the current operation was an svshape, @@ -1647,7 +1651,8 @@ class ISACaller: # to interrupt in between. sigh. self.last_op_svshape = asmop == 'svremap' - self.update_pc_next() + if nia_update: + self.update_pc_next() def SVSTATE_NEXT(self, mode, submode): """explicitly moves srcstep/dststep on to next element, for @@ -1796,18 +1801,18 @@ class ISACaller: svp64_is_vector = (out_vec or in_vec) else: svp64_is_vector = out_vec + # check if this was an sv.bc* and if so did it succeed + if self.is_svp64_mode and insn_name.startswith("sv.bc"): + end_loop = self.namespace['end_loop'] + log("branch %s end_loop" % insn_name, end_loop) + if end_loop.value: + self.svp64_reset_loop() + self.update_pc_next() + return False if svp64_is_vector and srcstep != vl-1 and dststep != vl-1: self.svstate.srcstep += SelectableInt(1, 7) self.svstate.dststep += SelectableInt(1, 7) self.namespace['SVSTATE'] = self.svstate - # check if this was an sv.bc* and if so did it succeed - if self.is_svp64_mode and insn_name.startswith("sv.bc"): - end_loop = self.namespace['end_loop'] - log("branch %s end_loop" % insn_name, end_loop) - if end_loop.value: - self.svp64_reset_loop() - self.update_pc_next() - return True # not an SVP64 branch, so fix PC (NIA==CIA) for next loop # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64) # this way we keep repeating the same instruction (with new steps) @@ -1871,6 +1876,8 @@ def inject(): log("args[0]", args[0].namespace['CIA'], args[0].namespace['NIA'], args[0].namespace['SVSTATE']) + if 'end_loop' in func_globals: + log("args[0] end_loop", func_globals['end_loop']) args[0].namespace = func_globals #exec (func.__code__, func_globals) diff --git a/src/openpower/decoder/isa/test_caller_svp64_bc.py b/src/openpower/decoder/isa/test_caller_svp64_bc.py index 65ba1b70..53780400 100644 --- a/src/openpower/decoder/isa/test_caller_svp64_bc.py +++ b/src/openpower/decoder/isa/test_caller_svp64_bc.py @@ -51,13 +51,13 @@ class DecoderTestCase(FHDLTestCase): self.assertEqual(sim.gpr(10), SelectableInt(0x1235, 64)) def test_sv_branch_cond(self): - for i in [0, 10]: #[0, 10]: + for i in [0, 10]: #, 10]: #[0, 10]: lst = SVP64Asm( [f"addi 1, 0, {i}", # set r1 to i f"addi 2, 0, {i}", # set r2 to i "cmpi cr0, 1, 1, 10", # compare r1 with 10 and store to cr0 "cmpi cr1, 1, 2, 10", # compare r2 with 10 and store to cr1 - "sv.bc 12, 2.v, 0x8", # beq 0x8 - + "sv.bc 12, 2.v, 0xc", # beq 0xc - # branch if r1 equals 10 to the nop below "addi 3, 0, 0x1234", # if r1 == 10 this shouldn't execute "or 0, 0, 0"] # branch target @@ -77,6 +77,33 @@ class DecoderTestCase(FHDLTestCase): else: self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64)) + def test_sv_branch_cond_all(self): + for i in [7, 8, 9]: + lst = SVP64Asm( + [f"addi 1, 0, {i+1}", # set r1 to i + f"addi 2, 0, {i}", # set r2 to i + "cmpi cr0, 1, 1, 8", # compare r1 with 10 and store to cr0 + "cmpi cr1, 1, 2, 8", # compare r2 with 10 and store to cr1 + "sv.bc/all 12, 1.v, 0xc", # bgt 0xc - branch if BOTH + # r1 AND r2 greater 8 to the nop below + "addi 3, 0, 0x1234", # if tests fail this shouldn't execute + "or 0, 0, 0"] # branch target + ) + lst = list(lst) + + # SVSTATE (in this case, VL=2) + svstate = SVP64State() + svstate.vl = 2 # VL + svstate.maxvl = 2 # MAXVL + print ("SVSTATE", bin(svstate.asint())) + + with Program(lst, bigendian=False) as program: + sim = self.run_tst_program(program, svstate=svstate) + if i == 9: + self.assertEqual(sim.gpr(3), SelectableInt(0, 64)) + else: + self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64)) + def tst_sv_add_cr(self): """>>> lst = ['sv.add. 1.v, 5.v, 9.v' ] diff --git a/src/openpower/sv/trans/svp64.py b/src/openpower/sv/trans/svp64.py index 96f9e71d..45b292b4 100644 --- a/src/openpower/sv/trans/svp64.py +++ b/src/openpower/sv/trans/svp64.py @@ -783,8 +783,8 @@ class SVP64Asm: sv_mode = ((bc_svstep << SVP64MODE.MOD2_MSB) | (bc_vlset << SVP64MODE.MOD2_LSB) | (bc_snz << SVP64MODE.BC_SNZ)) - srcwid = (bc_brc << 1) | bc_vsb - destwid = (bc_all << 1) | bc_lru + srcwid = (bc_vsb << 1) | bc_lru + destwid = (bc_lru << 1) | bc_all else: