TAQOZ Reloaded - SWITCH statement cannot be run by more than one cog
In the Taqoz source code, I've been trying to fix a problem caused by long 'uswitch' being located in Hub memory, rather than where it should be in COG memory. If two or more COGS attempt to use a SWITCH statement simultaneously, then a race condition exists on the value stored at 'uswitch' and one or other SWITCH constructs will misbehave.
I'm looking for help to fix this as my knowledge of Taqoz source code and assembly language is limited. Here's what I've tried - assembling using flexprop 5.9.9 using this source code.
I add a new long 'cswitch' to COG memory:-
txpin long tx_pin pinreg long 0 ' PIN - access via PIN operation' cswitch long 0 ' storage for the SWITCH selection u ACC long 0 ' accumulator register cleared to zero before instruction' xx x long 0
I substitute for words _SWITCH and SWFETCH:-
' ************** CASE STATEMENTS *********************8 { ' SWITCH ( val -- ) _SWITCH word rg+uswitch,STOREX+ex ' SWITCH@ ( -- val ) SWFETCH word rg+uswitch,FETCHX+ex ' Peter's original words } _SWITCH word cswitch,STOREX+ex SWFETCH word cswitch,FETCHX+ex ' New words cause Taqoz boot to fail or other hiccups
I've tried a number of different phrases but haven't hit on the right one over several days. the problem could do with a fresh pair of eyes!
Comments
Hi Bob,
I had a look into this now.
Are you really sure, that switch does not work properly????
As far as I understand this, uswitch resides at offset $01c+regptr of a "register area" in hub ram, at $200....$3ff.
regptr is a cog resident pointer, which points to the register area of this cog. So it is intended and possible to let each cog have it's own "private register area".
What I did not find, is the startup code of each cog, which would set regptr to different hub locations for each cog. There is some code that seems to reset the contents of the first 8? register variables depending on the cogid.
Line 5140:
IDLE word INITSTKS
word ATID,_8,ERASE ' clear this cog's task registers
Line 5170:
' initialize task registers
' free memory backup
word rg+0,w+$100,ERASE ' init task registers'
Peter has used the wording "tasks" sometimes instead of cog. (?)
Perhaps Peter wanted to be open to introduce several tasks per cog.
I don't think, that it is a good idea to introduce new cog register variables in cog memory, because this will shift everything in the precious coq memory space!!! It will change codes of cog code and so on. Some things are hardcoded in this source code like erasing exactly 8 memory locations in the code above.
Instead you already have introduced LUT variables, so if the original idea of Peter to separate the registers via regptr really does not work, I would strongly recommend to use a position in LUT for this!!!!
I would also recommend to just define new versions of switch and case and not alter the original source code, because it seems to be rather hard to understand everything of it, at least for me.
To your original question how to access cog memory directly:
Have you tried something like:
SWFETCH word w+cswitch,COGFETCH+ex
But as said, do only alter cog ram, if you really know what you are doing.....
Christof
OK, I verified, different cogs do really use the same hub location for uswitch, so regptr is not initalised properly. I don't know what other effects will this have, because it means that all of these "user variables" are shared too. At least all printing will be affected, because BASE is global then too.
Hi @"Christof Eb." , thanks for looking into this. I had a skype call with Peter Jakacki this morning and he confirms that uswitch should be a cog ram variable, not hub ram. He is going to change it in a future release.
As it stands, the details of running TAQOZ on more than one cog at the same time is not well documented - today I'm adding what I've learned in the glossary., which I'll reissue soon at v61.
Cheers Bob
Peter Jakacki could tell me in the source code:-
'regptr' (located in COG ram) contains the start address of a block of Hub Variables. These are the variables headed 'variables.p2a'. On switch on, COG 0 sets 'regptr' = $200. So 'temp' is at $200+0, 'uemit' at $200+32 and so on. Let's dump it:-
So at $200+38 is stored 0A 0A, the current number base, stored in variable 'base'.
The preferred way of reading the Hub Variables is by using REG. e.g. the current number base is 38 REG C@ .B
If we start another cog running Taqoz by using RUN, RUN: etc. we may need it to set up a new Hub Variable block for itself to avoid race conditions like we currently have with uswitch.
We can do that by getting the new COG to:-
1. Copy the COG 0 Hub Variables to a new hub location
2. Setting regptr to point to the new hub location
The new cog would have to execute something like:-
On the other hand, if all you want the new COG to do is read smartpins and read/write from hub ram, then a new Hub Variable Block may not be needed.
Sadly all a bit messy - e.g. it's not easy for the programmer to determine when a new block is needed.
@bob_g4bby
Hi, I have now found, that there is a rather simple way to patch the words SWITCH and CASE@ so that they now use a variable in LUT. Taqoz will then use the new words. And as LUT is private to each cog, SWITCH can then be used in parallel.
@"Christof Eb."
That works well, good solution! May I put your patch in the glossary in the BRANCHING section?
Cheers, Bob
Yes, Your glossary is the the best place to find such things.
Cheers, Christof