[Libre-soc-bugs] [Bug 1210] New: sv.bc branching to incorrect address in Vertical-First mode

bugzilla-daemon at libre-soc.org bugzilla-daemon at libre-soc.org
Fri Nov 17 15:08:19 GMT 2023


            Bug ID: 1210
           Summary: sv.bc branching to incorrect address in Vertical-First
           Product: Libre-SOC's first SoC
           Version: unspecified
          Hardware: PC
                OS: Windows
            Status: CONFIRMED
          Severity: enhancement
          Priority: ---
         Component: Source Code
          Assignee: lkcl at lkcl.net
          Reporter: andrey at technepisteme.xyz
                CC: libre-soc-bugs at lists.libre-soc.org
   NLnet milestone: ---

While experimenting with sv.bc in Vertical-First, I discovered an issue where a
branch is not take (although the condition for the branch is met).

Example test case created in a branch:

Code (With PC/NIA):
00 "setvl 0, 0, %d, 1, 1, 1" % maxvl, # VL = MAXVL = 2, vf=1
04 "sv.cmpi *cr0, 1, *10, 0x10", # compare reg val with immediate
0c "sv.bc 0, *2, 0x10", # jmp if CTR!=0 AND reg  not equal to imm
14 "svstep. 27, 1, 0",
18 "bc 4, 3, -0x14", # CR_BI=0, jump to start of loop (sv.cmpi)
1c "or 0, 0, 0", # jump to here if terminate VF loop early

Initial value for CTR=MAXVL=2, GPR['10'] = 0x20.

Running the simulator and looking at the log output, I can see that
- sv.cmpi generates the correct CR0 bits (GPR['10'] > 0x10)
  Positive (GT) bit set, Zero (EQ) bit cleared
- sv.bc: since BO=0, CTR should decrement, and branch if CTR!=0 AND CR_BI=0.
  CTR is decremented correctly.
  The branch should be taken as the EQ bit of CR0 is cleared.
- NIA should be 0x1c (0x0c + 0x10), the final nop (or 0, 0, 0).
  BUT instead NIA is set to 0x14 (svstep., the next insn)
  The 'bc' instruction jumps back to the start of the loop.

In this example, the code should never reach svstep, because the processor
would branch early. Because of this CTR should remain as 1 (because the second
iteration around the loop wouldn't happen).

Checking the NIA value using python debugger (pdb)

- Breakpoints set in
  - decoder/isa/generated/svbranch.py, at the start of op_sv_bc()
  - caller.py:
    - at call(#l1961)
    - yield from self.do_nia(asmop, ins_name, rc_en, ffirst_hit) (#l2362)

Stepping through the code I got the following:
- Running test up to where the auto-generated function op_sv_bc() starts:
  - CTR is subtracted correctly
  - ctr_ok true, cond_ok true, test_branch=1, thus NIA will be updated
  - LR not updated, correct behaviour
- Then continuing to run until the yield from self.do_nia
  - before the yield, the self.namespace['NIA'] is correctly set to 0x1c
- Stepping inside self.do_nia:
  - Not in ffirst mode, thus take the else path
  - Going into self.check_step_increment():
    - self.allow_next_step_inc is false
    - self.is_svp64_mode is true (make sense)
    - return value by yielding from self.svstate_post_inc():
      - svstate_post_inc() has a default argument of vf=0
      - The current SVSTATE vfirst value is compared against the input vf
      - if (vf=0 and vfirst=1), NIA is updated().

- There are two places in caller.py where svstate_post_inc() is called.
  In both places, only the required argument 'insn_name' is given,
  vf remains as 0. This is what causes NIA after sv.bc to be 0x14,
  instead of 0x1c.

(Haven't found relevant bugs to include in 'blocks' or 'see also', adding bug
#994 as 'see also' as it is related to addresses.)

You are receiving this mail because:
You are on the CC list for the bug.

More information about the libre-soc-bugs mailing list