Shop OBEX P1 Docs P2 Docs Learn Events
Cogs vs Hub (Newbie question) — Parallax Forums

Cogs vs Hub (Newbie question)

jmspaggijmspaggi Posts: 629
edited 2010-04-13 06:07 in Propeller 1
Hi all,

I have some troubles to understand how to use the Hub wih the cogs. I think I understand how it's working, with the 7 to 22 clocks, based on the documentation. My concerne is when 2 cogs try to access at the same time.

Based on figure 1-3 page 25, if cog 0 try to get the Hub, it will get it at system clock 0. Lets say it wants to write $FF at $1234. This will be done by System Clock 7. Now, cog 1 wants to get the hub also and writes $EE at $1234. It will get the hub at system clock 2 (Hub Clock 1) and will finish at System Clock 9. This mean we will have 2 cogs, at the same time (System Clock 2 to System Clock System Clcok 7), trying to write at the same place.

So does it means I need to implement a mechanisme on the code side to avoid read/write at the same time by 2 different cogs? Using a semaphore (LOCKNEW) also take 7 to 22 clocks. Which mean the issue is the same, while cog0 is puting the semaphore, cog1 can access the hub and do operation, while cog0 thought it's going to be locked.

Should I reserve some range of memory per cog, to be sure they are not writing at the same time?

Or will the 2 write operations been "buffered", which mean the hub will process the $FF, then the $EE with no issue and I will get $EE at the end?

Also, is there a way to transfert flags between 2 cogs without using the hub?

Thanks,

JM

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2010-04-10 14:30
    jmspaggi said...
    Or will the 2 write operations been "buffered", which mean the hub will process the $FF, then the $EE with no issue and I will get $EE at the end?
    No buffering takes place. The cog writing first sets the location to $FF, then 2 clocks later it gets set to $EE. Simple as that. Meaning when cog 0 writes and cog 1 reads, the latter would get the $FF (provided cog 1 accesses the hub in the same window or later).

    Post Edited (kuroneko) : 4/10/2010 2:37:48 PM GMT
  • jmspaggijmspaggi Posts: 629
    edited 2010-04-10 15:21
    Hi Kuroneko,

    How does it work for the semaphores? If the 2 cogs try to get it a the same time, is there a risk they will both have it since the memory will not be updated when the 2nd cog will try to get it?

    JM
  • potatoheadpotatohead Posts: 10,261
    edited 2010-04-10 17:23
    The access is round robin, meaning that won't happen at the core write it, read it PASM level. COG x will have completed it's work before COG y gets a shot at it. That's always true. However, your program might involve some more advanced conditions, that run above that basic timing, and that's where the semaphores could be used. I don't think I've seen them used all that often, as a simple flag can do that for a lot of cases.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!
    8x8 color 80 Column NTSC Text Object
    Safety Tip: Life is as good as YOU think it is!
  • Mike GreenMike Green Posts: 23,101
    edited 2010-04-10 17:40
    A read or write access of the hub is indivisible in that you can read a byte, word, or long or write a byte, word, or long without worrying about some other cog getting in there in the middle of an operation. There is no indivisible read/modify/write operation though. You can't increment a hub location without the risk that some other cog will change that location between the time that the value is fetched and the time that the incremented value is stored. That's where the semaphores (locks) come in. The test and set or test and clear operation done by LOCKSET or LOCKCLR is indivisible and these can be used to protect more complex shared memory situations.

    You rarely see these used because most shared memory situations involve buffers and buffer pointers and these situations can be designed so that only one cog changes the value (pointer) even though another cog will use that value (pointer). Most important is that, even if the writing cog is updating the pointer while the other cog is referencing it, there's no harm done because the only error that will occur is that the buffer will appear less full to the 2nd cog and the 2nd cog can catch up on a later cycle after the writing pointer is updated.

    This is called the single producer / single consumer case in multiprogramming and is one of the few situations that's theoretically (and practically) valid without using semaphores.
  • potatoheadpotatohead Posts: 10,261
    edited 2010-04-10 18:06
    I'm a bit confused on this.

    If timing is factored in, both single producer, multiple consumer, and single consumer, multiple producer don't require the locks. Happens on video drivers all the time.

    To me, that's one of very positive elements of the propeller. Timing is known for a lot of cases, and it's simple, meaning the time based cases end up used more than they would in a system where it's all just concurrent multiprocessing.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!
    8x8 color 80 Column NTSC Text Object
    Safety Tip: Life is as good as YOU think it is!
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-04-10 18:31
    Even single producer/single consumer cases might require sync. Let's say you want to do a GPS logger. The producer simply writes the position to a memory location and the SD writer logs that content to a SD card. Without sync it can happen that during write of the longitude the latitude is updated by the GPS COG. So, you can end up with a log entry which consits of a longitude/latitude-pair that don't belong together.
    It can even be worse and the first digits of one number are old measuerement and the following digits are already from a later measurement.

    That's what also happens in case of different subsystems write to the screen-buffer of the video driver. It will show a mixture of old and new content. But as the refresh rate of the video driver is fairly high, you will not recognize that. That's why locks are not necessary for the video driver.
  • potatoheadpotatohead Posts: 10,261
    edited 2010-04-10 18:34
    Got it. That makes great sense, thanks [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!
    8x8 color 80 Column NTSC Text Object
    Safety Tip: Life is as good as YOU think it is!
  • Cluso99Cluso99 Posts: 18,071
    edited 2010-04-11 04:01
    Just to restate what others have said, but in a different way...
    • The following occurs in a loop, each access below is 2 clocks
      • Cog 0 gets hub access (for read or write, byte/word/long)
      • Cog 1 gets hub access
      • Cog 2
      • Cog 3
      • Cog 4
      • Cog 5
      • Cog 6
      • Cog 7
    • Now the loop repeats again.

    Now the other thing is that the cog may or may not be ready when it gets it's access cycle (once every 16 clocks). That is why we say it is 7-22 clocks because the instruction takes 6+1 clocks to execute and then waits for it's access. If it just missed it's access it has to wait a further 15 clocks so 6+1+15=22 clocks. If it does not use it's access cycle, the hub access cycle (2 clocks) is lost.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
    · Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
  • jmspaggijmspaggi Posts: 629
    edited 2010-04-11 23:21
    Thanks all regarding all your replies.

    So now, how to apply this situation to the Semaphors?

    If one cog can read/write just before the 2nd one read/write the same location, do we have a risk to have 2 cogs asking for a semaphor with 2 clocks interval, and been assigned the same one?

    Because when cog0 will ask for the semaphor, he will look at the first one available, then get (write) it. But the time he write it, the 2nd code will read and see that the same semaphore is available? No?

    Also, is there a way for a cog to read only without waiting for the hub to be assigned? I only want to read a bit. So I don't really care if another cog if writing/reading it.

    Thanks,

    JM
  • Mike GreenMike Green Posts: 23,101
    edited 2010-04-11 23:43
    1) Once a semaphore is "checked out" by one cog (LOCKNEW), it's never given to another cog. It must be returned to the hub (LOCKRET). The semaphores don't enforce anything further. You have to build waits into your code. What a semaphore does is to provide your program with an indivisible "test and set" or "test and clear" operation which allow one cog to grab a resource like a memory location without any other cog being able to grab the same resource at the same time.

    2) A cog cannot access the hub memory until its access "slot" comes up. Whenever a cog attempts to access the hub memory at a time other than its assigned "slot", the hub forces the cog to wait until the cog's "slot" occurs. There are no exceptions.
  • jmspaggijmspaggi Posts: 629
    edited 2010-04-11 23:56
    Super, perfect for the semaphores. Look likt it's working like in unix. I was wondering because of what we discussed above for the memory.

    Regarding the "shared" memory, I think I will use OUTB for that since I just need 8 bits to be shared between the cogs. My goal is to have a register which keep a status of each cog stat. So when a cog ends, it will put the realted bit at 0. and when it starts, it puts the status at 1. So each cog can have a status of the other cogs without waiting 7-22 cycles.

    It's only my 3rd day with Propeller, so maybe I'm not going the right way, but at least I'm trying [noparse];)[/noparse]

    Thanks again for sharing your knowledge.

    JM
  • Cluso99Cluso99 Posts: 18,071
    edited 2010-04-12 00:24
    You cannot use OUTB. It is not implemented as internal bits accessible to each hub.

    Most likely you will not use semaphores either. Take a look at FullDuplexSerial for how we pass characters in a buffer.

    If you pass a group of parameters, then the last parameter passed is a flag - either set or cleared. The other cog(s) wait for the flag, take the data and then clear or set the flag. Simple.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
    · Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
  • heaterheater Posts: 3,370
    edited 2010-04-12 07:46
    MagIO2: Your case of a single producer/single consumer exchanging GPS data will fail as you have stated it.

    For sure when the producer is writing a bunch of LONGs (say) and the consumer is reading them there is a chance for the consumer to see old and new data mixed up.

    But that is not how you would implement it. Rather one would have a flag that the producer sets when it has written the data. The consumer will wait for that flag to become set before reading the data and then unset the flag. Similarly the producer must wait for the flag to be unset before it writes.

    In this way producer and consumer are prevented from simultaneous access to the data buffer. No locks are required.

    More complex buffering can be done with cyclic buffers and "head" and "tail" pointers. See full duplex serial for example.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • jazzedjazzed Posts: 11,803
    edited 2010-04-12 22:11
    heater said...
    ...
    But that is not how you would implement it. Rather one would have a flag that the producer sets when it has written the data. The consumer will wait for that flag to become set before reading the data and then unset the flag. Similarly the producer must wait for the flag to be unset before it writes.

    In this way producer and consumer are prevented from simultaneous access to the data buffer. No locks are required.

    More complex buffering can be done with cyclic buffers and "head" and "tail" pointers. See full duplex serial for example.
    I'm so glad you said that. There is a time and place for everything, but usually locks are not necessary ....

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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.
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-04-13 06:07
    In my post I only talked about synchronizing the access to the string - which not necessarily meant lock.

    So, a lock is not necessary ... true ... but why not? And my example only should point out that you very soon have to make sure that 2 COGs sharing the same memory have to be programmed in a style that assures data-integrity. This also implies that usually 1 byte, 1 word or 1 long access is foolproof in a one consumer, one producer environment.

    But let's detail/change the scope a bit - still talking about a one consumer/one producer scenario:
    Say the GPS receiver sends the string periodically. And the GPS COG reads it continuously. And it copies the parsed result (e.g. converting the GPS string to float) to the shared memory. Maybe the consumer has more to do than just wait for the GPS data. So, depending on the current state it might want to skip some GPS readings. In your implementation this would stop the GPS COG writing new values to the shared memory because the flag is no more changed.

    GPS COG:
    1. receive string
    2. parse string
    3. wait for lock/get lock
    4. update shared variables
    5. free lock
    6. goto 1.

    Consumer COG:
    1. Do whatever needs to be done
    2. If new GPS coordinates are needed: wait for lock/get lock
    3. read value
    4. free lock
    5. continue with 1.

    Making the part between get lock and free lock as short as possible ensures that no COG has to wait to long.

    In other words: using a lock decouples the COGs. Using a flag means one COG affects the other far more. Using a lock only affects the COG in case the lock is already reserved.

    Post Edited (MagIO2) : 4/13/2010 6:13:44 AM GMT
Sign In or Register to comment.