Shop OBEX P1 Docs P2 Docs Learn Events
Pre-check for waitcnt? — Parallax Forums

Pre-check for waitcnt?

mparkmpark Posts: 1,305
edited 2009-01-12 05:56 in Propeller 1
I have some cog code that occasionally runs long and causes waitcnt to stall for a minute 'cuz it's missed the boat.
I thought I'd try to skip the waitcnt if cnt has already passed the target value. This is what I have so far; what do you think of it?
              mov       temp, cntTarget
              sub       temp, cnt
              cmps      temp, #10               wc, wz
        if_b  jmp       #:skipWaitcnt
              
              waitcnt   cntTarget, cntPeriod
:skipWaitcnt



The 10 is just a number I pulled out of my... head. Anyone know what the correct value is? I figure it shouldn't be too big, because I don't want to skip the waitcnt unnecessarily, but it has to be big enough to account for the extra instructions leading up to waitcnt.

What I'd really like to do is figure out why my %$# code runs long in the first place, but after chasing it for a day I'm ready to put in this stopgap and move on. Unfortunately I have lost all faith in my ability to reason about waitcnt and timing, so I'd appreciate less bleary eyes checking me on this little snippet.

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2009-01-11 19:14
    You don't want to use CMPS. That's a signed compare and CNT is treated as a 32 bit unsigned value. Use CMP instead. I'd use at least 20 for the value to compare. The SUB, CMP, and JMP will take 4 clock cycles each (or slightly less from the fetch of the CNT value) and the WAITCNT will take at least 5 clocks. You could shorten this a little by eliminating the JMP and making the WAITCNT conditional.
  • mparkmpark Posts: 1,305
    edited 2009-01-11 19:42
    But I'm not comparing aginst cnt, I'm comparing against (cntTarget - cnt) which is signed, no?

    Good points about 20 and making waitcnt conditional (slaps forehead).
  • Mike GreenMike Green Posts: 23,101
    edited 2009-01-11 20:00
    cntTarget is an unsigned 32 bit number. CNT is an unsigned 32 bit number. When you subtract them, you still have a 32 bit unsigned number. You need to do an unsigned compare. Try some examples.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-01-11 20:39
    With all due respect to Mike, I think cmps is the way to go. Consider the following examples:

      Target           CNT       Target - CNT    CMP #$0A   CMPS #$0A   Desired Action
    $2000_0010     $2000_0000     $0000_0010      NC NZ       NC  NZ       WAITCNT
    $2000_0010     $2000_0006     $0000_000A      NC  Z       NC   Z       WAITCNT
    $2000_0010     $2000_0007     $0000_0009       C NZ        C  NZ        Skip
    $2000_0010     $2000_0011     $FFFF_FFFF      NC NZ        C  NZ        Skip
    
    
    


    cmp will only return the desired carry when CNT hasn't yet passed Target but is very close. cmps also handles the case where CNT has already passed Target.

    -Phil

    Addendum:
    One thing to note is that cmps will work only when your timed interval is less than $8000_0000 (about 27 seconds). To encompass the entire 53-second interval, you will need something like this:

                  mov       temp,target
                  sub       temp,cnt wc
            if_nc cmp       temp,#LIMIT wc
            if_nc waitcnt   target,interval        
    
    
    


    At least I think that's correct. I still need to work through some examples.

    Post Edited (Phil Pilgrim (PhiPi)) : 1/11/2009 8:50:55 PM GMT
  • mparkmpark Posts: 1,305
    edited 2009-01-12 05:31
    Thanks Phil (and yes, mad respect for Mike Green).

    Your addendum is giving me a headache. I may be misunderstanding your scenario, but I think there's a problem here.
    After "sub temp, cnt wc", C means "cnt passed target up to 27 seconds ago" and NC means "cnt will hit target in 27 seconds or less". Of course, because of modular arithmetic, C also means "cnt will hit target between 27 and 54 seconds from now".

    If I set target to 50 seconds from now and then do my work, and it only takes say 10 seconds, I'll hit the sub instruction with 40 seconds to go before cnt reaches target, so sub will set C (the second meaning, but there's no way to tell) and the waitcnt will be skipped, thus exiting prematurely.


    Edit: Never mind, I was thinking subs, not sub. I gotta stop trying to think about this stuff.

    Post Edited (mpark) : 1/12/2009 5:42:58 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-01-12 05:56
    mpark said...
    Your addendum is giving me a headache.
    Yeah, me too! Sorry, it's not right. I knew there was still a possible range issue, and it's something I dashed off too quickly, thinking I could solve it. But in thinking more about it, there really is no solution. The problem is endemic to modular arithmetic. If target - CNT were $8000_0000, say, does this mean that we have $8000_0000 more clocks to wait, or have we passed the target by $8000_0000? There's just no way to tell, which reduces the effective timing interval to 27 seconds in principle.

    -Phil
Sign In or Register to comment.