Shop OBEX P1 Docs P2 Docs Learn Events
Propeller First Step — Parallax Forums

Propeller First Step

jmspaggijmspaggi Posts: 629
edited 2010-04-21 12:55 in Propeller 1
Hi all,

I just received my prop and I'm trying to play with it.

I did a home made PASM version of Fibo. It can probably been improved, but I was able to do something at least.

Now, I have one question.

Here is the code

{{
fibo.spin
}}
con
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000
var
  long Table[noparse][[/noparse]64>>2] ' 64 bytes ... keep var data all the same type so addresses are contiguous
obj
  sx : "FullDuplexSerial"
PUB Main | n, t1, t2
  sx.start(31,30,0,115200)
  waitcnt(clkfreq+cnt)
  sx.str(string($d,"Spin FIBO Test",$d))
  repeat n from 0 to 24
    sx.str(string($d,"FIBO "))
    sx.dec(n)
    t1 := cnt/1000000
    Table[noparse][[/noparse]0] := n
    cognew(@Fibo, @Table)
    t2 := cnt/1000000
    sx.str(string(" = "))
    sx.dec(result)
    sx.tx(" ")
    sx.dec((t2-t1)*1_000_000/(clkfreq/1000))
    sx.str(string("ms"))
DAT
        org 0
Fibo    mov FibResult, #0 ' So far, result is 0
        mov tptr, par
        mov TabAddr, tptr ' tabadr contains table pointer
        mov TopAddr, tptr ' topadr contains top of the table
        jmp #MLoop

MLoop   rdbyte Temp, TopAddr ' Read the value on the stack
        cmp Temp, #2 wc,wz       ' Do we have 2 or less in the stack?6
IF_A    jmp #Above
        add FibResult, #1      ' Yes. So add 1.
        cmp TopAddr, TabAddr wc, wz ' Is there still work on the stack?
IF_E    jmp #End
        sub TopAddr, #1
        jmp #MLoop         ' And continue

Above   sub Temp, #1
        wrbyte Temp, TopAddr
        add TopAddr, #1
        sub Temp, #1
        jmp #MLoop2

End     wrbyte FibResult, TabAddr
        cogid Temp
        cogstop Temp
        ret

FibResult long 0
Temp long 0
TabAddr long 0 ' Storage for table address
TopAddr long 0 ' Top of the storage address
tptr long 0 ' use RES only at end of cog pasm code




How can I wait for the cog to complete in order to read the result? Because if I run this code, it will create cog1 to 7 very quickly, then fail to create a new code. And I will never see the results, and they will all try to use the same array to store the stack, and so on. Also, I'm not 100% sure for the cogit and cogstop lines.

So do I have a way to check the cog status in a repeat loop in my Spin code?

Thanks,

JM

Comments

  • jmspaggijmspaggi Posts: 629
    edited 2010-04-20 20:00
    2nd version [noparse];)[/noparse]

    {{
    fibo.spin
    }}
    con
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    var
      long Table[noparse][[/noparse]64>>2] ' 64 bytes ... keep var data all the same type so addresses are contiguous
    obj
      sx : "FullDuplexSerial"
    PUB Main | n, t1, t2
      sx.start(31,30,0,115200)
      waitcnt(clkfreq+cnt)
      sx.str(string($d,"Spin FIBO Test JMS",$d))
      repeat n from 2 to 24
        Table[noparse][[/noparse]0] := n
        sx.str(string($d,"FIBO "))
        sx.dec(Table[noparse][[/noparse]0])
        t1 := cnt/1000000
        cognew(@Fibo, @Table)
        repeat while Table[noparse][[/noparse]0] == n
        t2 := cnt/1000000
        sx.str(string(" = "))
        sx.dec(Table[noparse][[/noparse]0])
        sx.tx(" ")
        sx.dec((t2-t1)*1_000_000/(clkfreq/1000))
        sx.str(string("ms"))
      cogstop(cogid)
    DAT
            org 0
    Fibo    mov FibResult, #0 ' So far, result is 0
            mov tptr, par
            mov TabAddr, tptr ' tabadr contains table pointer
            mov TopAddr, tptr ' topadr contains top of the table
            'mov Temp, #5
            'wrbyte Temp, TopAddr
    
    MLoop   rdbyte Temp, TopAddr ' Read the value on the stack
    MLoop2  cmp Temp, #2 wc,wz       ' Do we have 2 or less in the stack?6
    IF_A    jmp #Above
            add FibResult, #1      ' Yes. So add 1.
            cmp TopAddr, TabAddr wc, wz ' Is there still work on the stack?
    IF_E    jmp #End
            sub TopAddr, #1
            jmp #MLoop         ' And continue
    
    Above   sub Temp, #1
            wrbyte Temp, TopAddr
            add TopAddr, #1
            sub Temp, #1
            jmp #MLoop2
    
    End     wrbyte FibResult, TabAddr
            cogid Temp
            cogstop Temp
            ret
    
    FibResult long 0
    Temp long 0
    TabAddr long 0 ' Storage for table address
    TopAddr long 0 ' Top of the storage address
    tptr long 0 ' use RES only at end of cog pasm code
    
    



    I found a way to wait for the cog to complet, but it's not always working. There should be a better way to do that.

    Also, this code is not working [noparse]:([/noparse]

    FIBO 2 = 1 0ms 
    FIBO 3 = 2 0ms 
    FIBO 4 = 3 0ms 
    FIBO 5 = 517 0ms 
    FIBO 6 = 520 0ms
    FIBO 7 = 131597 0ms
    FIBO 8 = 131605 0ms
    
    



    It's working for 0 to 4, but not above that. I tried in pProppelerSim just the ASM code, and it's working fine [noparse]:([/noparse] So I don't really understand why it's not working there.

    Any clue?

    Thanks,

    JM
  • jazzedjazzed Posts: 11,803
    edited 2010-04-20 20:18
    @JM,

    Normally we want to start one COG one time and post messages to it about what needs to be done.

    You could use two variables in this case: one called "doit", the other called "number".

    var
      long doit   ' mailbox
      long number ' parameter
    
    


    So, in spin where your cognew is now, you set number := fibonumber, then set doit := non-zero.

    In your PASM you "Spin" waiting for "doit" to be non-zero, read the number, calculate, store the result back to number, and set doit to zero. In Spin, you wait for doit to be zero before advancing to the next spin statement.

    You can figure out the rest.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    May the road rise to meet you; may the sun shine on your back.
    May you create something useful, even if it's just a hack.
  • jmspaggijmspaggi Posts: 629
    edited 2010-04-20 21:38
    Ok I see. I will update it.

    My final goal is to use all the COGs on that. So I will have to define more than one doit...

    Anyway, I will first make this one working before doing another one [noparse];)[/noparse]

    Anyclue why FIBO 5 is giving me a so big number when fibo 1 to 4 are working fine?

    JM
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-21 02:38
    jmspaggi said...
    Anyclue why FIBO 5 is giving me a so big number when fibo 1 to 4 are working fine?
    Beats me. But your 2nd try source (after fixing the wait condition below cognew, 5 == 5) works for me until 13, fn(14) exeeds a byte but as you only return a byte value from PASM you get the wrong result. Anyway, why do you complicate things in your PASM section? All you need is a simple loop adding numbers ...

    re: fn(14), even returning a long doesn't help. So there is one more worm who didn't make it back to the can ...

    Post Edited (kuroneko) : 4/21/2010 2:56:34 AM GMT
  • jmspaggijmspaggi Posts: 629
    edited 2010-04-21 11:24
    Hi Kuroneko,

    Here is a version which return a long, but it's still not return the right value.

    I have also try to modify the exit condition, but it's never exiting the loop now [noparse];)[/noparse]

    Can you point me what's rong with this peace?

    Also, I built the code this way becayse my final goal is to tun it on multi-cogs. So I want to have more than one cog ready/writing the stack.

    Thanks,

    JM

    {{
    fibo.spin
    }}
    con
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    var
      long done
      long Table[noparse][[/noparse]64] ' 64 bytes ... keep var data all the same type so addresses are contiguous
    obj
      sx : "FullDuplexSerial"
    PUB Main | n, t1, t2
      sx.start(31,30,0,115200)
      waitcnt(clkfreq+cnt)
      sx.str(string($d,"Spin FIBO Test JMS",$d))
      repeat n from 2 to 24
        Table[noparse][[/noparse]0] := n
        sx.str(string($d,"FIBO "))
        sx.dec(Table[noparse][[/noparse]0])
        t1 := cnt/1000000
        done := 0
        cognew(@Fibo, @done)
        repeat while done == 0
        t2 := cnt/1000000
        sx.str(string(" = "))
        sx.dec(Table[noparse][[/noparse]0])
        sx.tx(" ")
        sx.dec((t2-t1)*1_000_000/(clkfreq/1000))
        sx.str(string("ms"))
      cogstop(cogid)
    DAT
            org 0
    Fibo    mov FibResult, #0 ' So far, result is 0
            mov tptr, par
            mov _Done, tptr
            add tptr, #4
            mov TabAddr, tptr ' tabadr contains table pointer
            mov TopAddr, tptr ' topadr contains top of the table
    
    MLoop   rdbyte Temp, TopAddr ' Read the value on the stack
    MLoop2  cmp Temp, #2 wc,wz       ' Do we have 2 or less in the stack?6
    IF_A    jmp #Above
            add FibResult, #1      ' Yes. So add 1.
            cmp TopAddr, TabAddr wc, wz ' Is there still work on the stack?
    IF_E    jmp #End
            sub TopAddr, #1
            jmp #MLoop         ' And continue
    
    Above   sub Temp, #1
            wrbyte Temp, TopAddr
            add TopAddr, #1
            sub Temp, #1
            jmp #MLoop2
    
    End     wrlong FibResult, TabAddr
            wrlong _Done, #1
            cogid Temp
            cogstop Temp
            ret
    
    _Done long 0
    FibResult long 0
    Temp long 0
    TabAddr long 0 ' Storage for table address
    TopAddr long 0 ' Top of the storage address
    tptr long 0 ' use RES only at end of cog pasm code
    
    
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-21 12:16
    jmspaggi said...
    Here is a version which return a long, but it's still not return the right value.

    I have also try to modify the exit condition, but it's never exiting the loop now [noparse];)[/noparse]
    This one works for me with a minor change.

    wrlong _Done, #1
    


    is backwards. Try this

    wrlong $, _Done
    


    The $ refers to the current instruction i.e. wrlong which is not equal null which is the important bit. Then it produces the same results as my version (SPIN or PASM).
    You said...
    Also, I built the code this way becayse my final goal is to tun it on multi-cogs. So I want to have more than one cog ready/writing the stack.
    What, you mean run fibonacci on multiple cogs? Or run stuff in general? You run out of bit space anyway (~50) so it seems a bit of a waste [noparse]:)[/noparse]
  • jmspaggijmspaggi Posts: 629
    edited 2010-04-21 12:45
    I always do the mistake with wrlong, wrbyte, rd* and so on [noparse]:([/noparse]

    Also, why using
    wrlong $, _Done
    
    



    instead of
    wrlong #1, _Done
    
    



    ? Is it faster? Of it's the state of the art to do such update?

    For the multi cog, it's more for me a way to try, learn, do mistakes, investigate and so on. Fibo is the only think I found to far for that [noparse];)[/noparse] Later, I will try to find some other usefull thinkg to do. But I'm missing ideas.

    Thanks,

    JM
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-21 12:52
    jmspaggi said...
    Also, why using

    wrlong $, _Done
    
    


    instead of

    wrlong #1, _Done
    
    



    ? Is it faster? Of it's the state of the art to do such update?
    Have you tried compiling the second version? You can't have immediate (#) values in the destination slot. So the only chance is to refer to some data value you have to setup. Or you have a register you know contains #1. There are lots of different ways of doing that but if the only qualification required is <>0 then any register will do. It's just a shortcut, nothing sinister. And they both take 8 cycles + hub sync delay (0..15).
  • jmspaggijmspaggi Posts: 629
    edited 2010-04-21 12:55
    Ok! Got it!

    I have so much to learn with PASM and SPIN...

    Thanks again!

    JM
Sign In or Register to comment.