wrpgpr fails at certain conditions

This topic contains 7 replies, has 2 voices, and was last updated by  Petko 4 months, 2 weeks ago.

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #55086

    Petko
    Member

    Hello guys.

    In my project, based on PIC32MZ (EF), i make extensive use of nearly all available shadow register sets. While switching them back and forth i stumbled upon something that looks like a bug in the MIPS core. The code in question is:


    mtc0 v1,c0_srsctl
    ehb

    wrpgpr v0,s2
    mtc0 s1,c0_srsctl
    ehb

    The above happens in a syscall, so i first change PSS to whatever register set i want to write to, and then restore the original PSS value. If the above executes as per the documentation i should end up with ‘v0’ equal to ‘s2’ in the register set pointed to by ‘v1’. What actually happens is that ‘wrpgpr’ reliably(*) writes in the PSS pointed to by ‘s1’, which is in the _next_ instruction.

    Adding ‘ehb’ or even a single ‘nop’ between ‘wrpgpr’ and ‘mtc0’ seems to fix the issue. The above behavior is not documented so it took me a while to figure out what happens. I am not overly familiar with the MIPS pipeline, but it looks to me that ‘wrpgpr’ takes more than one cycle to complete and the subsequent ‘mtc0’ finishes before it. In this particular case these two instructions create a dependency, which the core does not detect. The presence or absence of the last ‘ehb’ does not seem to make any difference.

    (*) This happens each time i execute a particular code sequence. A few smaller and simpler test cases that i wrote does not hit the bug.

    2 users thanked author for this post.
    #55090

    Petko
    Member

    Forgot to mention that TLB and both L1 caches (in write back with write allocate mode) are on. This may help explain the strangeness.

    1 user thanked author for this post.
    #55731

    ChrisImgtec
    Moderator
    #55735

    Petko
    Member

    Hey Chris. Thanks for the reply.

    This is how i read table 2.9: If there’s mtc0 to SRSCtl(pss) the _next_ instruction should not be rd/wrpgpr. IOW the hazard continues into the future few clocks.

    In my code example the hazard appears to happen _back_ in time. wrpgpr fails if the _following_ instruction is mtc0. I realized that this issue manifests itself more reliably if there’s a long loop before wrpgpr.

    My (maybe naive) take on the problem is this: wrpgpr depends on SRSCtl(pss) just as mtc0 to the same location. For some reason and at certain conditions (cpu pipeline feature) wrpgpr executes after the following instruction. If the next instruction happen to be “mtc0 SRSCtl(pss)” we hit the race.

    All execution hazards are supposed to affect the following instruction. In this case it appears that execution hazard may also affects the _preceding_ instruction.

    thanks,
    Petko

    1 user thanked author for this post.
    #56031

    ChrisImgtec
    Moderator

    Hi Petko,

    Sorry for not getting back to you sooner I had some thinking to do about this and it does seem strange. I’m reaching out to the designers and will get back to you.

    Chris

    #56032

    Petko
    Member

    Thanks Chris. I’ve worked around the issue, but I am really curious about what the designers have to say. 🙂

    cheers,
    Petko

    #56033

    ChrisImgtec
    Moderator

    The designers said the right thing to do for this version of the processor is ehb or nop or another instruction between the wrpgpr and access to srsctl.

    Chris

    #56044

    Petko
    Member

    I figured that much, but was hoping for a little bit more details. 🙂 I prefer ‘ehb’ as it gives better pipeline protection against execution hazards.

    Offtopic: is there M6250 based device i can buy to play with?

    thanks,
    Petko

Viewing 8 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic.