Pasm catch 22 - passing an address
Beau Schwabe
Posts: 6,568
Attached is an example code of an idea I'm tossing around.
The concept is for an LMM approach by moving blocks of code from a larger (external) source.
With the attached code it could be made to work entirely within the launched cog the way that it is.
The area labeled "Instruction Data" is basically an area that gets self modified from the "Entry" area, where the "Entry" area reads from an external source and moves external data into the "InstructionData" section ... at the end of the "InstructionData" section you jump back, by way of the very last section of code not being modified, up to the "Entry" section where another block of code gets read in.
In theory, this should work... I don't care about speed in this case, just loading blocks of executable code at a specific location.
The catch 22 is that I can't quite figure out a way
to send information back from Pasm to the original Spin that called it without loosing my current 'par' being used as a program counter pointer.
Perhaps there is a more elegant way to do this and I need to have a non-blonde moment of clarity.
Unless !! (I might have answered my own question here) ... any data modified IS actually in COG 0 where the Spin code had originally launched the Pasm. That would mean that the PASM code is working from a copy but the address that's pointed to, actually whats modified, resides in COG 0 with the Spin that launched the Pasm in the first place.
That's ok also... I Think... the Pasm code would then just do a COGINT within the Pasm that points to the modified address (I have that), and wait until that code block has completed (a flag and cog termination at the end).
Some more tests to confirm where the modified data would be, but here is some test code for now...
The concept is for an LMM approach by moving blocks of code from a larger (external) source.
With the attached code it could be made to work entirely within the launched cog the way that it is.
The area labeled "Instruction Data" is basically an area that gets self modified from the "Entry" area, where the "Entry" area reads from an external source and moves external data into the "InstructionData" section ... at the end of the "InstructionData" section you jump back, by way of the very last section of code not being modified, up to the "Entry" section where another block of code gets read in.
In theory, this should work... I don't care about speed in this case, just loading blocks of executable code at a specific location.
The catch 22 is that I can't quite figure out a way
to send information back from Pasm to the original Spin that called it without loosing my current 'par' being used as a program counter pointer.
Perhaps there is a more elegant way to do this and I need to have a non-blonde moment of clarity.
Unless !! (I might have answered my own question here) ... any data modified IS actually in COG 0 where the Spin code had originally launched the Pasm. That would mean that the PASM code is working from a copy but the address that's pointed to, actually whats modified, resides in COG 0 with the Spin that launched the Pasm in the first place.
That's ok also... I Think... the Pasm code would then just do a COGINT within the Pasm that points to the modified address (I have that), and wait until that code block has completed (a flag and cog termination at the end).
Some more tests to confirm where the modified data would be, but here is some test code for now...
PUB PAsm cognew(@Entry,@InstructionData) DAT Entry mov temp, par '<- Par in this case holds the address of ' InstructionData 'ALL remarked, returns the LED pattern for 'the source field for 'Line A' below ' add temp, #4 'unremarked, returns the LED pattern for 'the source field for 'Line B' below ' add temp, #8 'unremarked, returns the LED pattern for 'the source field for 'Line C' below which 'in this case is the long offset from org 0 'can be confirmed with F9 and selecting 'temp' rdlong temp, temp '<-- Get value in address(temp) and replace 'temp with the value '----------------------------------------------------------------------- ' This just gets the pattern out to the LEDs mov dira, LEDmask shl temp, #16 mov outa, temp '----------------------------------------------------------------------- ' Endless Loop NoEnd jmp #NoEnd '----------------------------------------------------------------------- ' This stuff is never reached by running the Assembly code but ' is able to be read at instruction level InstructionData mov temp, #%11001100 ''<- Line A sub temp, #%11001111 ''<- Line B or temp, temp ''<- Line C LEDmask long %00000000_11111111_00000000_00000000 temp long 0
Comments
I am experimenting with something similar.... but I don't understand your problem. Perhaps because my approah is different an my mindset does not follow your technique.
I have numerous tiny assembler programs (only simple driver and serial I/O types so far) residing in HubRam. I have my multi threading scheduler loaded an running in a cog. It then starts a tiny (8 or so instructions) loader that loads (about 1 instruction per uSec) a desired driver from Hub to any (relocatable) location into the cog. At the conclusion of the load (typically only a few tens of uSecs) the loaded program launches itself through the scheduler.
In this manner any program running in the cog can trigger the load and simultaneous execution of any other piece of code, (or multiple instances of it) that is written to co-operate with the multi threading scheduler.
Although my tests so far have loaded from HubRam, it could equally well load from external or SD ram.
So far this works great, as a program that gets swapped in runs at full cog speed. There is a very short (a few longs) header at the front of the loaded program that gives particulars about the program, such as length, port assignments etc. So some SPIN program has the ability to configure details about the cog program.
Once this concept is refined. very large programs should be possible as sections just get swapped in as required. Obviously this concept can be spawned into as many cogs as desired.
The only use I have for the PAR is to tell the loader where in Hub to find the header for all the load details.
Is this somewhat similar to your efforts??
Cheers,
Peter (pjv)
It's more of a personal academic challenge ... I was able to do some tests, and because of the suggested use of 'coginit' it sort of puts you back where you started... thus the catch 22.
1) I need to pass arguments between Spin and Pasm
2) I need to dynamically determine an Address (not the contents, the actual address) from Pasm within Pasm
I can easily do one or the other but not both at the same time. If I could figure that out I think I could achieve what I am after. ... Should be simple, one would think.