FlexBasic.....For "COG"
Mickster
Posts: 2,698
in Propeller 2
Anyone figured out how to use this?
I only get compiler complaints. I suspect that there is some kind of initialization that I'm missing.
Comments
Here's an example:
There are significant restrictions on functions placed in COG and LUT memory; see the general compiler documentation for details. In particular, the functions should be leaf functions (not call any other functions... in theory they could call other COG or LUT functions, but the compiler doesn't allow that yet).
Hmmm, I may have spoken too soon about the leaf function restriction... it looks like that was lifted a while ago.
But I can't just launch something like this, right?
If I'm reading Eric correctly, it doesn't start a separate task. The
for "cog"
feature is just a way to specify routine to be compiled for cogexec rather than the default hubexec.Correct.
The code @Mickster posted will jump into Addup() and never return, as Addup() runs in the same cog that has called it. But if you spawn Addup() into its own cog (with its own stack pace, etc) the code will run as intended, with the value of cogtest being printed every 200 mS.
Right. FOR "COG" means the function is to be placed in COG memory (and FOR "LUT" means it is to be placed in LUT memory) but the function will still run in the same cog as the rest of the program. To start a new cog you need to use the CPU pseudo-function:
Oh yeah, I already have a couple of these happening but I misunderstood it to be like running a routine permanently in only cog memory. Like, with the P1; in cog-mode you get the full 20MIPS but only 4 or 5 MIPS using LMM (?)
All correct. But it's the same cog as was being used to execute in LMM, just like one cog that executes hubexec or cogexec. Your main program is using a cog, and a subroutine/function, in hubexec or cogexec, is still running on the same cog unless a new cog is explicitly launched. Prop1 with LMM is same in this respect.
@evanh Understood, many thanks
The difference isn't that extreme in P2 mode, plus FlexBasic already caches loops in COG memory (which further reduces the penalty). So generally it's fine to run code in HUB memory. But if you want extra reliable timing, or have a very frequently used function, then FOR "COG" and FOR "LUT" may be useful. And of course you can combine them with CPU -- that is, if you want a subroutine to run permanently in another cog and be in internal memory in that cog, make the subroutine FOR "COG" or FOR "LUT" and then launch it in the new cog with a CPU command.
Hi Eric,
Been trying to make this work but the compiler complains that the sub needs to be in hub memory.
Don't suppose you have an example, please?
Also, from the manual:
What exactly is "noinline"?
Craig
D'oh, I forgot about that restriction. But to work around it is straightforward, just have a small stub function that launches the COG/LUT function, e.g.:
I'll see if I can make the compiler generate that stub automatically if necessary.
It says the function/subroutine should never be made inline. Normally if the routine is small, or is only called from one place, the compiler expands it in place instead of creating a CALL instruction. For example, in code like:
the generated assembly will be exactly the same as if you had written
because the "incr" function is simple enough that the compiler can just do it "in place". If you specify that "incr" is
FOR "noinline"
then instead the generated assembly will contain a subroutine for incr and the code will include a CALL.@ersmith
Perfect 🤓.... Many thanks 👍😎👍
Craig