Shop OBEX P1 Docs P2 Docs Learn Events
PASM - How cogs are loaded — Parallax Forums

PASM - How cogs are loaded

lanternfishlanternfish Posts: 366
edited 2012-11-16 12:33 in Propeller 1
The subject line would appear to be a statement when in fact I have a question (or two) that need answering.

If I load a SPIN/PASM program like this:
PUB Main
 {Launch COG's}

  coginit(3, @InitCOG3, 0) 'Launch COG 3
  coginit(2, @InitCOG2, 0) 'Launch COG 2
  coginit(1, @InitCOG1, 0) 'Launch COG 1
  coginit(0, @InitCOG0, 0) '(Re)Launch COG 0

CON
 _clkmode = xtal1 + pll16x
 _xinfreq = 5_000_000

DAT
  {COG0 Code Block}

  COG0 PASM here

  {COG1 Code Block}

  COG1 PASM here

  {COG2 Code Block}

  COG2 PASM here

  {COG3 Code Block}

  COG3 PASM here

  {Other Code Blocks Here}

I observe that the COG 0 has all the code; the COG 1 is loaded with code from the second block on; and so on to the COG 3 only having its block of code.

Q1. Is this standard?

Q2. If not, how do I only get each COGs specific code to load only to that COG?

Clearly I have misread or overlooked another obvious piece of info.

Cheers

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2010-11-30 17:10
    I observe that the COG 0 has all the code; the COG 1 is loaded with code from the second block on; and so on to the COG 3 only having its block of code.

    Q1. Is this standard?

    Q2. If not, how do I only get each COGs specific code to load only to that COG?

    I wouldn't call it standard, it's just the way it is. The internal loader always executes 512 rdlongs (blanking the last 16). Side effect is that data after your effective code block ends up in the cog as well. So either your code doesn't care what's in the unused area (usually occupied by res) or you have to clear it yourself (e.g. if you want to place an array there).
  • localrogerlocalroger Posts: 3,451
    edited 2010-11-30 17:23
    Seconding what kuroneko said. Coginit loads 512 longs into the cog whether you need them or not. The assumption is that if you needed them, you would have defined contents for them, and if you don't you don't care that they contain garbage. If you use a single DAT area so all the cog images are grouped together, you get a nice clean concatenation such as you describe, but you can't count on that; you could find Spin bytecode or the contents of var areas in those upper longs of cog RAM. The proptool simply doesn't care what's hanging off the end of your PASM image that might get written there.
  • lanternfishlanternfish Posts: 366
    edited 2010-11-30 20:12
    A-ha! Not sure if I have read this anywhere. Certainly not as succinctly. Thanks
  • Heater.Heater. Posts: 21,230
    edited 2010-11-30 20:43
    Don't forget that the code for Cogs 1, 2 and 3 probably won't work without an "ORG 0" statement at the beginning of each block.
  • AleAle Posts: 2,363
    edited 2010-12-01 02:30
    kuroneko wrote: »
    (usually occupied by _res_)

    Note: This is not correct. res only creates a placeholder with the name and address. It does not occupies anything.
  • AleAle Posts: 2,363
    edited 2010-12-01 02:32
    Heater. wrote: »
    Don't forget that the code for Cogs 1, 2 and 3 probably won't work without an "ORG 0" statement at the beginning of each block.

    Because addresses will be forced to start at the ORG's value... be aware of this small but common mistake ! (at least I forgot plenty).
  • kuronekokuroneko Posts: 3,623
    edited 2010-12-01 04:44
    Ale wrote: »
    Note: This is not correct. res only creates a placeholder with the name and address. It does not occupies anything.

    Minor misunderstanding, occupied probably being the wrong word. I should have said used by. Does that sound better to you?

    That said, res does live in the unused area so it does occupy it ;)
  • localrogerlocalroger Posts: 3,451
    edited 2010-12-01 06:01
    Here's a little trick I often use with ORG to recycle cog ram used only on startup:

    org 0
    jmp #initlabel
    maincode
    {usual pasm code}
    initlabel
    {init code}
    jmp #maincode
    fit 496
    org initlabel
    {res statements}
    fit 496

    This automatically overlays uninitialized storage on top of init code without a lot of thinking about where everything ends up.
  • AleAle Posts: 2,363
    edited 2010-12-01 08:06
    kuroneko: res does not "reserve" space... nor does it occupy it. Only creates the labels with such address, a concept a little bit different than what long for instance does :).
  • Dave HeinDave Hein Posts: 6,347
    edited 2010-12-01 08:38
    I think a "res n" statement is equivalent to "org $ + n". It just increases the assembler's program counter by n longs. It doesn't allocate any memory, so the next instruction will follow immediately after the previous instruction in memory. It seems like it's main purpose is to be used in conjunction with the "fit" statement. Of course, it's really not needed if the space is accounted for in the "fit" statement, such as in "fit 496 - n".
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2010-12-01 09:15
    Chip's vocaltract object is instructive in how a pasm cog can be loaded in a way that saves space in hub memory. That object needs a fast inline multiplication and cordic routines, and those being inline of course take up a lot of longs in a repeating pattern. Instead of writing it all out in the code, vocaltract REServes the addresses where that code needs to go, and then at run time, during COG initialization, pasm code generates the inline code from a stub pattern and places it at the RES addresses. The result is that the vocaltract pasm occupies far less hub space than it would have if the code had been written out in full.
  • edited 2012-11-16 12:33
    The Propeller Manual states that, when assembly code is launched, "496 longs of the DAT block's content" are copied to the cog and not 512 longs as was previously mentioned. This will preserve the last 16 longs which are the special purpose registers.

    Sandy
Sign In or Register to comment.