Shop OBEX P1 Docs P2 Docs Learn Events
COGINIT not working if code not reloaded? - Fixed — Parallax Forums

COGINIT not working if code not reloaded? - Fixed

bob_g4bbybob_g4bby Posts: 485
edited 2025-12-20 12:47 in PASM2/Spin2 (P2)

I wanted to measure the time difference between
1. starting a cog with cog ram load
2. restarting the cog, no cog ram load
The code below does (1) but (2) fails. What have I done wrong, please, I'm going round in circles?

DAT ORG

        getct startcycle
        getct cycles
        sub cycles, startcycle          ' cycles ends up = 2
        cogid cog_id
        debug("Measurement overhead in ", udec_long(cycles))

loadandstart
        getct startcycle
        setq ptra_val
        coginit #COGEXEC+1, #@cog1start
        waitatn
        getct cycles
        sub cycles, startcycle
        debug("Time to load and start cog 1 in ", udec_long(cycles))

juststart
        getct startcycle
        setq ptra_val
        coginit #%1_0_0001, #@cog1start     ' E=1 don't reload cogram; N=0 target cog is V; V=1 cog1 is target
        waitatn
        getct cycles
        sub cycles, startcycle
        debug("Time to just restart cog 1 in ", udec_long(cycles))
        cogstop #0

cog1start
        cogatn #1
        cogstop #1

startcycle      res         1
cycles          res         1
cog_id          res         1
ptra_val        res         1

Comments

  • evanhevanh Posts: 17,009

    I didn't try to solve exactly which part was at fault, I just did a general cleanup.

    Output when compiled with Flexspin:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  Measurement overhead in cycles = 2
    Cog1  INIT $0000_006C $0000_0001 load
    Cog0  Time to load and start cog 1 in cycles = 22_571
    Cog1  INIT $0000_006C $0000_0001 jump
    Cog0  Time to just restart cog 1 in cycles = 22_851
    
    CON
        _xtlfreq = 20_000_000
        _clkfreq = 100_000_000
    
    
    DAT     ORG
            asmclk
            getct startcycle
            getct cycles
            sub cycles, startcycle          ' cycles ends up = 2
            cogid cog_id
            decod ptra_val, cog_id
            debug("Measurement overhead in ", udec_long(cycles))
    
    loadandstart
            getct startcycle
            setq ptra_val
            coginit #COGEXEC_NEW, #@cogruntest
            waitatn
            getct cycles
            sub cycles, startcycle
            debug("Time to load and start cog 1 in ", udec_long(cycles))
    
    juststart
            getct startcycle
            setq ptra_val
            coginit #HUBEXEC_NEW, #@cogruntest
            waitatn
            getct cycles
            sub cycles, startcycle
            debug("Time to just restart cog 1 in ", udec_long(cycles))
            cogstop #0
    
    cogruntest
            cogatn ptra
            cogid pa
            cogstop pa
    
    
    startcycle      res         1
    cycles          res         1
    cog_id          res         1
    ptra_val        res         1
    
  • evanhevanh Posts: 17,009

    Problem with the measuring is Debug adds a massive overhead to each cog's startup time.

  • @bob_g4bby, please check the code from thread Questions about PASM2 and register allocation. It measures the startup time of a cog without debugger. It should be easy to modify it to measure what you want.

  • evanhevanh Posts: 17,009

    @Kaio said:
    ... It measures the startup time of a cog without debugger. It should be easy to modify it to measure what you want.

    Bob,
    Remember to turn off debugging to eliminate its overhead.

  • @bob_g4bby said:
    I wanted to measure the time difference between
    1. starting a cog with cog ram load
    2. restarting the cog, no cog ram load
    The code below does (1) but (2) fails. What have I done wrong, please, I'm going round in circles?

    I think the problem is that (2) starts the Cog in HUBEXEC mode, however the start address is below $400 so it is actually a Cog/Lut exec mode, and since the previous start loaded uninitialized hub content, it executes random instructions.

    The fix should be
    coginit #%1_0_0001, #0 ' E=1 don't reload cogram; N=0 target cog is V; V=1 cog1 is target
    The start address 0 restarts the Cog with whatever the ram holds at the time.

    This is the debug output with the modify:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  Measurement overhead in cycles = 2
    Cog1  INIT $0000_0050 $0000_0000 load
    Cog0  Time to load and start cog 1 in cycles = 34_267
    Cog1  INIT $0000_0000 $0000_0000 jump
    Cog0  Time to just restart cog 1 in cycles = 33_755
    

    The difference is exactly 512, the clock cycles needed to load the full Cog ram.

    I have added a counter to the Cog1 code to see if the HUBEXEC start reuses the Cog ram and looks correct:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  Measurement overhead in cycles = 2
    Cog1  INIT $0000_0050 $0000_0000 load
    Cog1  counter = 0
    Cog0  Time to load and start cog 1 in cycles = 51_861
    Cog1  INIT $0000_0000 $0000_0000 jump
    Cog1  counter = 1
    Cog0  Time to just restart cog 1 in cycles = 51_349
    

    This is the modified code:

    DAT
                    org
    
                    getct   startcycle
                    getct   cycles
                    sub     cycles, startcycle                      ' cycles ends up = 2
                    cogid   cog_id
                    debug("Measurement overhead in ", udec_long(cycles))
    
    loadandstart
                    getct   startcycle
                    setq    ptra_val
                    coginit #COGEXEC + 1, #@cog1start
                    waitatn
                    getct   cycles
                    sub     cycles, startcycle
                    debug("Time to load and start cog 1 in ", udec_long(cycles))
    
    juststart
                    getct   startcycle
                    setq    ptra_val
                    coginit #HUBEXEC + 1, #0                 ' E=1 don't reload cogram; N=0 target cog is V; V=1 cog1 is target
                    waitatn
                    getct   cycles
                    sub     cycles, startcycle
                    debug("Time to just restart cog 1 in ", udec_long(cycles))
                    cogstop #0
    
    cog1start
                    debug(udec(counter))
                    add     counter, #1
                    cogatn  #1
                    cogstop #1
    
    counter         long    0
    
    startcycle      res     1
    cycles          res     1
    cog_id          res     1
    ptra_val        res     1
    

    Hope this is correct.

  • Thanks everyone, instant explanations, how good is that?! I now appreciate the addressing mistake I made in the 2nd COGINIT. The code starting with code1start is loaded into cogram at 0, so the next COGINIT needs to restart at cog ram 0.

    I was expecting 'load and start' to take a bit of time, but would expect 'just start' to be quite quick, which it isn't in my debug dependent code. So like @Kaio says, you can't make a true measurement with debug active - I'll look at the code you've recommended.

  • evanhevanh Posts: 17,009

    @macca said:
    I think the problem is that (2) starts the Cog in HUBEXEC mode, however the start address is below $400 so it is actually a Cog/Lut exec mode, and since the previous start loaded uninitialized hub content, it executes random instructions.

    Huh, yeah, mine wasn't working correctly either.

    Updated output with corrected code placement:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  Measurement overhead in cycles = 2
    Cog1  INIT $0000_0400 $0000_0001 load
    Cog0  Time to load and start cog 1 in cycles = 22_579
    Cog1  INIT $0000_0400 $0000_0001 jump
    Cog0  Time to just restart cog 1 in cycles = 22_089
    

    Hubexec is 490 ticks quicker.

    CON
        _xtlfreq = 20_000_000
        _clkfreq = 100_000_000
    
    
    DAT
            ORG     0
            asmclk
            getct startcycle
            getct cycles
            sub cycles, startcycle          ' cycles ends up = 2
            cogid cog_id
            decod ptra_val, cog_id
            debug("Measurement overhead in ", udec_long(cycles))
    
    loadandstart
            getct startcycle
            setq ptra_val
            coginit #COGEXEC_NEW, ##@cogruntest
            waitatn
            getct cycles
            sub cycles, startcycle
            debug("Time to load and start cog 1 in ", udec_long(cycles))
    
    juststart
            getct startcycle
            setq ptra_val
            coginit #HUBEXEC_NEW, ##@cogruntest
            waitatn
            getct cycles
            sub cycles, startcycle
            debug("Time to just restart cog 1 in ", udec_long(cycles))
            cogstop #0
    
    startcycle      res         1
    cycles          res         1
    cog_id          res         1
    ptra_val        res         1
    
    
    DAT
            ORGH    $400
            ORG     0
    cogruntest
            cogatn ptra
            cogid pa
            cogstop pa
    
Sign In or Register to comment.