There will be an instruction 'TSHARE D/#' to enable/disable the timer interrupt. If D/# is zero, the timer interrupt is disabled; otherwise, D/# will set the number of clocks that the interrupt occurs on (ie #200 means every 200 clocks). Two other instructions TLOCK/TFREE can be used to prevent the interrupt from occurring within a block of code. When the timer rolls under and reloads, a bit is set which gets cleared as soon as the 'LINK' instruction can be issued.
Cool.
So the range of this is 9b on immediate, and 32b using (any?) register, and the counting register & signal bit are hidden ?
If the jitter can be removed, this could also be used to generate Beeps, and Sync, saving timers for more important things.
Could even be used for refresh timing, on the new HyperRAM
Addit : Can a better name be found for LINK instruction ? Opcode names work better, if they describe what the opcode actually does.
The text suggests this is a SAVEJMP - saves PC.Flags to specified D, and Jumps.
cgracey said:
About the reverse subtract and compare instructions SUBR/CMPR: they are really useful for processing CNT values, where you want CNT minus a register into the register. They make code a lot tighter in those cases.
Excellent example. Same can be done with the counters when de-accumulating ADC readings.
So after x clocks, link gets inserted into the new instruction stream?
Seems very simple.
I don't know how to make it any simpler.
With only a few instructions in the interrupt handler, you could make a task switcher. The most practical value may be running medium-bandwidth scheduled tasks concurrently with your main program. It would be a shame to spend whole cogs on handling what could be done better in periodic, timed interrupts. It's just cheap multitasking.
Just watching on the sidelines without trying to jump into the "melee" but I like it when you are working through a problem and get to this point, it really means you've nailed it in regards to the Propeller "design philosophy" if I may call it that. Although I may be missing some of the finer details but I can see this scheme working well without introducing unnecessary complexity (and time) while maintaining the streamlined simplicity of a multi-core architecture. Looking forward to jumping back into the P2 seat again.
So after x clocks, link gets inserted into the new instruction stream?
Seems very simple.
I don't know how to make it any simpler.
With only a few instructions in the interrupt handler, you could make a task switcher. The most practical value may be running medium-bandwidth scheduled tasks concurrently with your main program. It would be a shame to spend whole cogs on handling what could be done better in periodic, timed interrupts. It's just cheap multitasking.
What happens if you are in a WAITxxx? Or must you use only non-blocking instructions?
Edit: now that I think about this, it doesn't matter. The LINK would still be inserted after X instructions, whether any of them block or not.
There will be an instruction 'TSHARE D/#' to enable/disable the timer interrupt. If D/# is zero, the timer interrupt is disabled; otherwise, D/# will set the number of clocks that the interrupt occurs on (ie #200 means every 200 clocks). Two other instructions TLOCK/TFREE can be used to prevent the interrupt from occurring within a block of code. When the timer rolls under and reloads, a bit is set which gets cleared as soon as the 'LINK' instruction can be issued.
Cool.
So the range of this is 9b on immediate, and 32b using (any?) register, and the counting register & signal bit are hidden ?
If the jitter can be removed, this could also be used to generate Beeps, and Sync, saving timers for more important things.
Could even be used for refresh timing, on the new HyperRAM
Addit : Can a better name be found for LINK instruction ? Opcode names work better, if they describe what the opcode actually does.
The text suggests this is a SAVEJMP - saves PC.Flags to specified D, and Jumps.
I second what Peter said, and share your belief it's a shame to blow a COG when we've had the experiences we did on the hot chip. Those COGS were basically super duper uber COGS. Doing this means we get nice bit of that utility without any real addition in complexity.
Good call Chip. I'm eager to dig in and write some code.
Really ? Google finds shiploads of Web links, and object file Linker reference, and if I dig deep enough I can find a Branch-link (BL) opcode mentioned, and that name I can understand, but LINK alone?, seems quite obscure, to me and google..
There will be an instruction 'TSHARE D/#' to enable/disable the timer interrupt. If D/# is zero, the timer interrupt is disabled; otherwise, D/# will set the number of clocks that the interrupt occurs on (ie #200 means every 200 clocks). Two other instructions TLOCK/TFREE can be used to prevent the interrupt from occurring within a block of code. When the timer rolls under and reloads, a bit is set which gets cleared as soon as the 'LINK' instruction can be issued.
Cool.
So the range of this is 9b on immediate, and 32b using (any?) register, and the counting register & signal bit are hidden ?...
So after x clocks, link gets inserted into the new instruction stream?
Seems very simple.
I don't know how to make it any simpler.
With only a few instructions in the interrupt handler, you could make a task switcher. The most practical value may be running medium-bandwidth scheduled tasks concurrently with your main program. It would be a shame to spend whole cogs on handling what could be done better in periodic, timed interrupts. It's just cheap multitasking.
What happens if you are in a WAITxxx? Or must you use only non-blocking instructions?
Edit: now that I think about this, it doesn't matter. The LINK would still be inserted after X instructions, whether any of them block or not.
The link will be inserted when everything's moving again. There is going to be jitter, but if you don't execute instructions that hold things up, it will be minimal.
Link IS what the instruction does. Not literally. I suppose the difference is like calling shl something like multiply2 (which I know of at least one CPU used in arcade games that did), rather than the strictly functional shift all bits left mnemonic.
Link is nice and short. The mnemonic for what it actually does would be obtuse and hard to remember, IMHO.
There will be an instruction 'TSHARE D/#' to enable/disable the timer interrupt. If D/# is zero, the timer interrupt is disabled; otherwise, D/# will set the number of clocks that the interrupt occurs on (ie #200 means every 200 clocks). Two other instructions TLOCK/TFREE can be used to prevent the interrupt from occurring within a block of code. When the timer rolls under and reloads, a bit is set which gets cleared as soon as the 'LINK' instruction can be issued.
Cool.
So the range of this is 9b on immediate, and 32b using (any?) register, and the counting register & signal bit are hidden ?
If the jitter can be removed, this could also be used to generate Beeps, and Sync, saving timers for more important things.
Could even be used for refresh timing, on the new HyperRAM
Addit : Can a better name be found for LINK instruction ? Opcode names work better, if they describe what the opcode actually does.
The text suggests this is a SAVEJMP - saves PC.Flags to specified D, and Jumps.
FYI LINK has been used for 45+ years
It seems that the MIPS "jal" would be more accurate. How about JMPLNK?
Really ? Google finds shiploads of Web links, and object file Linker reference, and if I dig deep enough I can find a Branch-link (BL) opcode mentioned, (& also jump and link = jal) and those names I can understand, but LINK used alone?, seems quite obscure, to me, and google..
Really ? Google finds shiploads of Web links, and object file Linker reference, and if I dig deep enough I can find a Branch-link (BL) opcode mentioned, (& also jump and link) and those names I can understand, but LINK used alone?, seems quite obscure, to me, and google..
68000 instruction set has a LINK. Not the same thing, though.
Really ? Google finds shiploads of Web links, and object file Linker reference, and if I dig deep enough I can find a Branch-link (BL) opcode mentioned, and that name I can understand, but LINK alone?, seems quite obscure, to me and google..
I try to avoid giving instructions names that the programmer might want to use symbolically. I agree that LINK is very generic and would cause reserved-word troubles. If we rename it to TLINK or something, the problem is solved.
What happens if you are in a WAITxxx? Or must you use only non-blocking instructions?
Edit: now that I think about this, it doesn't matter. The LINK would still be inserted after X instructions, whether any of them block or not.
Chip mentioned some instructions do block the branch & link insertion, with REP looking like the biggest (possible) impact.
With the exception of REP, the other blocking opcodes seem to be paired. Jitter levels are still unclear.
Since some wise conditions will apply, preventing non interruptible code being broken by the muxing of 'LINK $1F4,$1F5 WC,WZ', wouldn't be interesting to have some means to enable the adjusting of the timer value, just before leaving the interrupt service routine, thus preserving the predictability of the occurence of the next interrupt?
One way to achieve the correction could be a readable 32 bit "almost free" running timer, zeroed by the first main interrupt timer roll under, blocked from being cleared otherwise.
Sure, the execution of the 'TSHARE D/#' also zeroes it, and resets the lock that prevents it from being affected by the roll under of the main one.
That way, one can read the secondary timer and evaluate the total elapsed time since the first roll under, i. e., the event that flagged the need of muxing a LINK instruction, and regain control of almost any sequence, knowing how many were skipped/lost by the inherent jitter of conditionally serviced timer interrupts.
I know that will not cover all possibilities, since there could be some long REP iteration running, whose intrinsic delay will almost kill any useful predictability, but sure, those cases almost cry for the need of having a separated COG, to run without compromise.
Look at the cases put above. Instructions are atomic.
There isn't jitter when there is an ordinary instruction in play. mov, shl, etc...
1) If AUGS/AUGD have executed and their values are waiting for an instruction, don't interrupt.
This makes sense, because the instruction to follow needs to have it's values modified for program intent to play out correctly. Consider this an atomic instruction pair. Could be a few instructions worth of wait here, if I am remember AUGS and AUGD correctly. Edit: Chip clarified below.
2) If ALTDS is executing, the next instruction must be allowed to execute, as well.
3) If REP is active, wait for it to finish iterating.
4)
Some interrupt inhibitors would be needed to allow critical segments to
complete without interruption: TLOCK/TFREE. Interrupt code wouldn't
ever be interrupted, unless the timer setting was too aggressive.
Jitter could be one additional instruction, or a few thousand of them in the case of REP, or a few or maybe one in the AUGD/S case above.
Clearly, there will be tradeoffs with this. Basically, this really is an instruction insert that needs to be completely transparent to the program. Another way to think of it, is the running program has priority to complete whatever instruction needs completed before moving to the next one, and the next one could be the inserted one.
What happens if you are in a WAITxxx? Or must you use only non-blocking instructions?
Edit: now that I think about this, it doesn't matter. The LINK would still be inserted after X instructions, whether any of them block or not.
Chip mentioned some instructions do block the branch & link insertion, with REP looking like the biggest (possible) impact.
With the exception of REP, the other blocking opcodes seem to be paired. Jitter levels are still unclear.
That makes sense. Any of these approaches would be subject to jitter, I think.
Actually, this whole timer thing could open up other interesting possibilities unrelated to general multitasking. For instance, suppose that you wanted to output a PWM signal while also doing other things (let's ignore the smart pins for a moment). You could use the timer for this!
1. Set up initial LINK destination and a really short delay.2. The cog then inserts the LINK.3. In the link, toggle the pin and set a new delay. Then LINK back to the prior routine.4. Repeat from #2.
I suspect this would be very useful for protocols like I2C and CANBUS, which need to both assert a signal and "simultaneously" test the pin to see if someone else is also asserting a signal.
Of course, it may be that the smart pins will make some of this unnecessary, but it's nice to know that the timer would have more than one use case.
In case there's any confusion, once the interrupt is turned on, it fires on the timer rollunder, each time, repeating indefinitely on every Nth clock. It may take a few clocks before the LINK can be inserted in each instance, but the next interrupt will be on time, without any accumulated error. The only jitter is the varying number of clocks it may take before the LINK can be inserted. In most cases, there is no delay, at all. In the case of ALTDS/AUGD/AUGS, there will be one or two clocks (if both AUGD and AUGS are being used). The big jitter will be coming from the caching involved for hub exec. That could be upwards of 20 clocks! If you want tight timing, execute from the cog. If you don't care about timing, you can have both your mainline and interrupt code in the hub.
Nice, so just never max out the code time allocation. Code it best, fast case, and it will get done when it needs to get done. It just might not start right on time.
That makes sense. Any of these approaches would be subject to jitter, I think.
Actually, this whole timer thing could open up other interesting possibilities unrelated to general multitasking. For instance, suppose that you wanted to output a PWM signal while also doing other things (let's ignore the smart pins for a moment). You could use the timer for this!
1. Set up initial LINK destination and a really short delay.2. The cog then inserts the LINK.3. In the link, toggle the pin and set a new delay. Then LINK back to the prior routine.4. Repeat from #2.
That's why the jitter cases matter.
REP I can see has a 'use other forms' avoidance, but the other cases look to be paired due to some buried queue mechanism. If they are always 2 opcode cycles then jitter removal in all but REP looks doable.
- basically, the Branch & Link always takes 2 opcode cycles, one of which may be a packer.
That makes sense. Any of these approaches would be subject to jitter, I think.
Actually, this whole timer thing could open up other interesting possibilities unrelated to general multitasking. For instance, suppose that you wanted to output a PWM signal while also doing other things (let's ignore the smart pins for a moment). You could use the timer for this!
1. Set up initial LINK destination and a really short delay.2. The cog then inserts the LINK.3. In the link, toggle the pin and set a new delay. Then LINK back to the prior routine.4. Repeat from #2.
That's why the jitter cases matter.
REP I can see has a 'use other forms' avoidance, but the other cases look to be paired due to some buried queue mechanism. If they are always 2 opcode cycles then jitter removal in all but REP looks doable.
- basically, the Branch & Link always takes 2 opcode cycles, one of which may be a packer.
Here's how you could effectively make it jitter free:
Once in the interrupt, do a WAITCNT to the next clock you really want. The WAITCNT would wind up waiting ~5 (the minimum) to ~25 (allowing for hub exec caching and LINK execution) clocks. Then, you would be exactly where you need to be without any jitter.
I try to avoid giving instructions names that the programmer might want to use symbolically. I agree that LINK is very generic and would cause reserved-word troubles. If we rename it to TLINK or something, the problem is solved.
Given I can find Branch-link (BL) usage & also jump and link = jal, as existing industry usage, it would seem least confusing to follow those leads ?
The Prop already uses jump terminology over Branch, so that points to JMPLINK or maybe JMPL
hehe, Maybe.... however the objective here is to try to reduce the culture shock & confusion for users of other MCUs, coming into the P2.
There is plenty enough about P2 to confuse, without adding obscure names into the mix.
I try to avoid giving instructions names that the programmer might want to use symbolically. I agree that LINK is very generic and would cause reserved-word troubles. If we rename it to TLINK or something, the problem is solved.
Given I can find Branch-link (BL) usage & also jump and link = jal, as existing industry usage, it would seem least confusing to follow those leads ?
The Prop already uses jump terminology over Branch, so that points to JMPLINK or maybe JMPL
It is like a JMP, but it leaves the return address in a register. Seems to me that leaving the return address happens before the JMP, in the mind of the programmer, since it can't go back and do anything after the flying leap. It's like it writes a note and leaves it somewhere before it leaves, to later return. A single word that isn't CALL or JMP seems needed. LINK serves that role, in that it's unique. It took me a while to get used to, though. There could be something better, I suppose. I hear what you are saying, anyway. JMPLINK sounds like you are jumping to some link, not that you are linking your jump. LINKJMP would be more accurate, to me.
It is like a JMP, but it leaves the return address in a register. Seems to me that leaving the return address happens before the JMP, in the mind of the programmer, since it can't go back and do anything after the flying leap. It's like it writes a note and leaves it somewhere before it leaves, to later return. A single word that isn't CALL or JMP seems needed. LINK serves that role, in that it's unique. It took me a while to get used to, though. There could be something better, I suppose. I hear what you are saying, anyway. JMPLINK sounds like you are jumping to some link, not that you are linking your jump. LINKJMP would be more accurate, to me.
I can follow the details of operation, but a user is more interested in what the opcode does, and the primary result is the Branch/Jump, which is why the industry norm is to put that first.
Someone scanning an ASM listing will see JMP and JMPL and know they are fundamentally similar, differing in the house-keeping details.
Comments
There will be an instruction 'TSHARE D/#' to enable/disable the timer interrupt. If D/# is zero, the timer interrupt is disabled; otherwise, D/# will set the number of clocks that the interrupt occurs on (ie #200 means every 200 clocks). Two other instructions TLOCK/TFREE can be used to prevent the interrupt from occurring within a block of code. When the timer rolls under and reloads, a bit is set which gets cleared as soon as the 'LINK' instruction can be issued.
Cool.
So the range of this is 9b on immediate, and 32b using (any?) register, and the counting register & signal bit are hidden ?
If the jitter can be removed, this could also be used to generate Beeps, and Sync, saving timers for more important things.
Could even be used for refresh timing, on the new HyperRAM
Addit : Can a better name be found for LINK instruction ? Opcode names work better, if they describe what the opcode actually does.
The text suggests this is a SAVEJMP - saves PC.Flags to specified D, and Jumps.
cgracey said:
About the reverse subtract and compare instructions SUBR/CMPR: they are really useful for processing CNT values, where you want CNT minus a register into the register. They make code a lot tighter in those cases.
Excellent example. Same can be done with the counters when de-accumulating ADC readings.
Seems very simple.
Seems very simple.
I don't know how to make it any simpler.
With only a few instructions in the interrupt handler, you could make a task switcher. The most practical value may be running medium-bandwidth scheduled tasks concurrently with your main program. It would be a shame to spend whole cogs on handling what could be done better in periodic, timed interrupts. It's just cheap multitasking.
I don't know how to make it any simpler.
Just watching on the sidelines without trying to jump into the "melee" but I like it when you are working through a problem and get to this point, it really means you've nailed it in regards to the Propeller "design philosophy" if I may call it that. Although I may be missing some of the finer details but I can see this scheme working well without introducing unnecessary complexity (and time) while maintaining the streamlined simplicity of a multi-core architecture. Looking forward to jumping back into the P2 seat again.
Seems very simple.
I don't know how to make it any simpler.
With only a few instructions in the interrupt handler, you could make a task switcher. The most practical value may be running medium-bandwidth scheduled tasks concurrently with your main program. It would be a shame to spend whole cogs on handling what could be done better in periodic, timed interrupts. It's just cheap multitasking.
What happens if you are in a WAITxxx? Or must you use only non-blocking instructions?
Edit: now that I think about this, it doesn't matter. The LINK would still be inserted after X instructions, whether any of them block or not.
There will be an instruction 'TSHARE D/#' to enable/disable the timer interrupt. If D/# is zero, the timer interrupt is disabled; otherwise, D/# will set the number of clocks that the interrupt occurs on (ie #200 means every 200 clocks). Two other instructions TLOCK/TFREE can be used to prevent the interrupt from occurring within a block of code. When the timer rolls under and reloads, a bit is set which gets cleared as soon as the 'LINK' instruction can be issued.
Cool.
So the range of this is 9b on immediate, and 32b using (any?) register, and the counting register & signal bit are hidden ?
If the jitter can be removed, this could also be used to generate Beeps, and Sync, saving timers for more important things.
Could even be used for refresh timing, on the new HyperRAM
Addit : Can a better name be found for LINK instruction ? Opcode names work better, if they describe what the opcode actually does.
The text suggests this is a SAVEJMP - saves PC.Flags to specified D, and Jumps.
FYI LINK has been used for 45+ years
Good call Chip. I'm eager to dig in and write some code.
FYI LINK has been used for 45+ years
Really ? Google finds shiploads of Web links, and object file Linker reference, and if I dig deep enough I can find a Branch-link (BL) opcode mentioned, and that name I can understand, but LINK alone?, seems quite obscure, to me and google..
There will be an instruction 'TSHARE D/#' to enable/disable the timer interrupt. If D/# is zero, the timer interrupt is disabled; otherwise, D/# will set the number of clocks that the interrupt occurs on (ie #200 means every 200 clocks). Two other instructions TLOCK/TFREE can be used to prevent the interrupt from occurring within a block of code. When the timer rolls under and reloads, a bit is set which gets cleared as soon as the 'LINK' instruction can be issued.
Cool.
So the range of this is 9b on immediate, and 32b using (any?) register, and the counting register & signal bit are hidden ?...
That's all correct.
Seems very simple.
I don't know how to make it any simpler.
With only a few instructions in the interrupt handler, you could make a task switcher. The most practical value may be running medium-bandwidth scheduled tasks concurrently with your main program. It would be a shame to spend whole cogs on handling what could be done better in periodic, timed interrupts. It's just cheap multitasking.
What happens if you are in a WAITxxx? Or must you use only non-blocking instructions?
Edit: now that I think about this, it doesn't matter. The LINK would still be inserted after X instructions, whether any of them block or not.
The link will be inserted when everything's moving again. There is going to be jitter, but if you don't execute instructions that hold things up, it will be minimal.
Link is nice and short. The mnemonic for what it actually does would be obtuse and hard to remember, IMHO.
There will be an instruction 'TSHARE D/#' to enable/disable the timer interrupt. If D/# is zero, the timer interrupt is disabled; otherwise, D/# will set the number of clocks that the interrupt occurs on (ie #200 means every 200 clocks). Two other instructions TLOCK/TFREE can be used to prevent the interrupt from occurring within a block of code. When the timer rolls under and reloads, a bit is set which gets cleared as soon as the 'LINK' instruction can be issued.
Cool.
So the range of this is 9b on immediate, and 32b using (any?) register, and the counting register & signal bit are hidden ?
If the jitter can be removed, this could also be used to generate Beeps, and Sync, saving timers for more important things.
Could even be used for refresh timing, on the new HyperRAM
Addit : Can a better name be found for LINK instruction ? Opcode names work better, if they describe what the opcode actually does.
The text suggests this is a SAVEJMP - saves PC.Flags to specified D, and Jumps.
FYI LINK has been used for 45+ years
It seems that the MIPS "jal" would be more accurate. How about JMPLNK?
FYI LINK has been used for 45+ years
Really ? Google finds shiploads of Web links, and object file Linker reference, and if I dig deep enough I can find a Branch-link (BL) opcode mentioned, (& also jump and link = jal) and those names I can understand, but LINK used alone?, seems quite obscure, to me, and google..
FYI LINK has been used for 45+ years
Really ? Google finds shiploads of Web links, and object file Linker reference, and if I dig deep enough I can find a Branch-link (BL) opcode mentioned, (& also jump and link) and those names I can understand, but LINK used alone?, seems quite obscure, to me, and google..
68000 instruction set has a LINK. Not the same thing, though.
FYI LINK has been used for 45+ years
Really ? Google finds shiploads of Web links, and object file Linker reference, and if I dig deep enough I can find a Branch-link (BL) opcode mentioned, and that name I can understand, but LINK alone?, seems quite obscure, to me and google..
I try to avoid giving instructions names that the programmer might want to use symbolically. I agree that LINK is very generic and would cause reserved-word troubles. If we rename it to TLINK or something, the problem is solved.
What happens if you are in a WAITxxx? Or must you use only non-blocking instructions?
Edit: now that I think about this, it doesn't matter. The LINK would still be inserted after X instructions, whether any of them block or not.
Chip mentioned some instructions do block the branch & link insertion, with REP looking like the biggest (possible) impact.
With the exception of REP, the other blocking opcodes seem to be paired. Jitter levels are still unclear.
Since some wise conditions will apply, preventing non interruptible code being broken by the muxing of 'LINK $1F4,$1F5 WC,WZ', wouldn't be interesting to have some means to enable the adjusting of the timer value, just before leaving the interrupt service routine, thus preserving the predictability of the occurence of the next interrupt?
One way to achieve the correction could be a readable 32 bit "almost free" running timer, zeroed by the first main interrupt timer roll under, blocked from being cleared otherwise.
Sure, the execution of the 'TSHARE D/#' also zeroes it, and resets the lock that prevents it from being affected by the roll under of the main one.
That way, one can read the secondary timer and evaluate the total elapsed time since the first roll under, i. e., the event that flagged the need of muxing a LINK instruction, and regain control of almost any sequence, knowing how many were skipped/lost by the inherent jitter of conditionally serviced timer interrupts.
I know that will not cover all possibilities, since there could be some long REP iteration running, whose intrinsic delay will almost kill any useful predictability, but sure, those cases almost cry for the need of having a separated COG, to run without compromise.
Hope it helps more than encumbers.
Henrique
There isn't jitter when there is an ordinary instruction in play. mov, shl, etc...
1) If AUGS/AUGD have executed and their values are waiting for an instruction, don't interrupt.
This makes sense, because the instruction to follow needs to have it's values modified for program intent to play out correctly. Consider this an atomic instruction pair. Could be a few instructions worth of wait here, if I am remember AUGS and AUGD correctly. Edit: Chip clarified below.
2) If ALTDS is executing, the next instruction must be allowed to execute, as well.
3) If REP is active, wait for it to finish iterating.
4)
Some interrupt inhibitors would be needed to allow critical segments to
complete without interruption: TLOCK/TFREE. Interrupt code wouldn't
ever be interrupted, unless the timer setting was too aggressive.
Jitter could be one additional instruction, or a few thousand of them in the case of REP, or a few or maybe one in the AUGD/S case above.
Clearly, there will be tradeoffs with this. Basically, this really is an instruction insert that needs to be completely transparent to the program. Another way to think of it, is the running program has priority to complete whatever instruction needs completed before moving to the next one, and the next one could be the inserted one.
What happens if you are in a WAITxxx? Or must you use only non-blocking instructions?
Edit: now that I think about this, it doesn't matter. The LINK would still be inserted after X instructions, whether any of them block or not.
Chip mentioned some instructions do block the branch & link insertion, with REP looking like the biggest (possible) impact.
With the exception of REP, the other blocking opcodes seem to be paired. Jitter levels are still unclear.
That makes sense. Any of these approaches would be subject to jitter, I think.
Actually, this whole timer thing could open up other interesting possibilities unrelated to general multitasking. For instance, suppose that you wanted to output a PWM signal while also doing other things (let's ignore the smart pins for a moment). You could use the timer for this!
1. Set up initial LINK destination and a really short delay.2. The cog then inserts the LINK.3. In the link, toggle the pin and set a new delay. Then LINK back to the prior routine.4. Repeat from #2.
I suspect this would be very useful for protocols like I2C and CANBUS, which need to both assert a signal and "simultaneously" test the pin to see if someone else is also asserting a signal.
Of course, it may be that the smart pins will make some of this unnecessary, but it's nice to know that the timer would have more than one use case.
That makes sense. Any of these approaches would be subject to jitter, I think.
Actually, this whole timer thing could open up other interesting possibilities unrelated to general multitasking. For instance, suppose that you wanted to output a PWM signal while also doing other things (let's ignore the smart pins for a moment). You could use the timer for this!
1. Set up initial LINK destination and a really short delay.2. The cog then inserts the LINK.3. In the link, toggle the pin and set a new delay. Then LINK back to the prior routine.4. Repeat from #2.
That's why the jitter cases matter.
REP I can see has a 'use other forms' avoidance, but the other cases look to be paired due to some buried queue mechanism. If they are always 2 opcode cycles then jitter removal in all but REP looks doable.
- basically, the Branch & Link always takes 2 opcode cycles, one of which may be a packer.
That makes sense. Any of these approaches would be subject to jitter, I think.
Actually, this whole timer thing could open up other interesting possibilities unrelated to general multitasking. For instance, suppose that you wanted to output a PWM signal while also doing other things (let's ignore the smart pins for a moment). You could use the timer for this!
1. Set up initial LINK destination and a really short delay.2. The cog then inserts the LINK.3. In the link, toggle the pin and set a new delay. Then LINK back to the prior routine.4. Repeat from #2.
That's why the jitter cases matter.
REP I can see has a 'use other forms' avoidance, but the other cases look to be paired due to some buried queue mechanism. If they are always 2 opcode cycles then jitter removal in all but REP looks doable.
- basically, the Branch & Link always takes 2 opcode cycles, one of which may be a packer.
Here's how you could effectively make it jitter free:
Once in the interrupt, do a WAITCNT to the next clock you really want. The WAITCNT would wind up waiting ~5 (the minimum) to ~25 (allowing for hub exec caching and LINK execution) clocks. Then, you would be exactly where you need to be without any jitter.
I try to avoid giving instructions names that the programmer might want to use symbolically. I agree that LINK is very generic and would cause reserved-word troubles. If we rename it to TLINK or something, the problem is solved.
Given I can find Branch-link (BL) usage & also jump and link = jal, as existing industry usage, it would seem least confusing to follow those leads ?
The Prop already uses jump terminology over Branch, so that points to JMPLINK or maybe JMPL
hehe, Maybe.... however the objective here is to try to reduce the culture shock & confusion for users of other MCUs, coming into the P2.
There is plenty enough about P2 to confuse, without adding obscure names into the mix.
I try to avoid giving instructions names that the programmer might want to use symbolically. I agree that LINK is very generic and would cause reserved-word troubles. If we rename it to TLINK or something, the problem is solved.
Given I can find Branch-link (BL) usage & also jump and link = jal, as existing industry usage, it would seem least confusing to follow those leads ?
The Prop already uses jump terminology over Branch, so that points to JMPLINK or maybe JMPL
It is like a JMP, but it leaves the return address in a register. Seems to me that leaving the return address happens before the JMP, in the mind of the programmer, since it can't go back and do anything after the flying leap. It's like it writes a note and leaves it somewhere before it leaves, to later return. A single word that isn't CALL or JMP seems needed. LINK serves that role, in that it's unique. It took me a while to get used to, though. There could be something better, I suppose. I hear what you are saying, anyway. JMPLINK sounds like you are jumping to some link, not that you are linking your jump. LINKJMP would be more accurate, to me.
It is like a JMP, but it leaves the return address in a register. Seems to me that leaving the return address happens before the JMP, in the mind of the programmer, since it can't go back and do anything after the flying leap. It's like it writes a note and leaves it somewhere before it leaves, to later return. A single word that isn't CALL or JMP seems needed. LINK serves that role, in that it's unique. It took me a while to get used to, though. There could be something better, I suppose. I hear what you are saying, anyway. JMPLINK sounds like you are jumping to some link, not that you are linking your jump. LINKJMP would be more accurate, to me.
I can follow the details of operation, but a user is more interested in what the opcode does, and the primary result is the Branch/Jump, which is why the industry norm is to put that first.
Someone scanning an ASM listing will see JMP and JMPL and know they are fundamentally similar, differing in the house-keeping details.