No, the DRVH instruction was executed but should have been executed in the "next" step like the SKIPF variant did.
Oh! I think I get what you are saying. An active SKIP disables interrupts, including the debug interrupt. Therefore, a pending debug interrupt should trigger on the instruction immediately after the last skipped instruction, which would be the DRVH instructions. In the case of SKIP, the interrupt occurred after DRVH. But, in the case of SKIPF, it interrupted correctly (prior to DRVH). Is that correct?
There's a two-cog/no-CORDIC image for the Prop123_A9 board in there, as well as a new PNut.exe which fixes the problem with AUGS/AUGD working with _RET_.
SKIPF and EXECF can now work in hub space, too, but they revert to cancelling instructions, like SKIP does. This matters for EXECF only if a subsequent branch gets you into hub memory, while there are still skip bits queued. This way, SKIPF/EXECF code could run faster in the cog/LUT space, but still works in hub space.
Chip
No joy with _ret_ and AUGD and WRLUT playing together.
dat org
or dirb,##$ffff
call #op1
rdlut ax,#0
or outb,ax
call #op2
rdlut ax,#0
or outb,ax
call #op3
rdlut ax,#0
or outb,ax
outh #33
here jmp #here
op1 _ret_ wrlut #1,#0 'ok
op2 wrlut ##$8000,#0 'ok
ret
op3 _ret_ wrlut ##$4000,#0 'returns ok but wrlut cancelled
ax res 1
That worked, but is that intentional? I don't see a mention of this in the documentation or the instruction list.
Here's from the spreadsheet:
EEEE 11110NN NNN NNNNNNNNN NNNNNNNNN AUGS #N
Queue N to be used as upper 23 bits for next #S occurrence, so that the next 9-bit #S will be augmented to 32 bits.
AUGS/AUGD have 23 bits of operand. They get tacked on above the 9-bit #S/#D of the next instruction using #S/#D.
Ah.... Sorry! I see what you were getting at. I made the assembler just grab bits 31..9 of the operand for AUGS/AUGD. I figured it would be easier to use. I need to do something about the spreadsheet explanation, though.
either way, why? if someone is explicitly using AUGx, shouldn't they know what the value should be? Why make this one instruction work differently from all others?
edit: Never mind. Chip's update in the spreadsheet is clear enough. No need to dwell on this...
Ozpropdev, have you tried SKIPF in hub memory? It should work just like SKIP, cancelling instructions. Only v17a does it. I might make another release soon just to update this minor issue, but it could wait a little bit, in case some problems are discovered.
Ozpropdev, have you tried SKIPF in hub memory? It should work just like SKIP, cancelling instructions. Only v17a does it. I might make another release soon just to update this minor issue, but it could wait a little bit, in case some problems are discovered.
I'm seeing problems going from cog to hub using SKIPF.
Aside from that, things are executing way faster than I understand. It seems that there is no rest cycle after a branch using SKIPF. It's hitting every needful instruction, anyway:
I can't figure out how those JMPs are back-to-back. It looks like they are jumping directly to the address PLUS the needed skips! There's no time for that! In the above example, everything between the SKIPF and the JMP #$ took only 12 clocks.
Here's my guess: it's because the jmp is relative. As soon as jmp #cogy is loaded in the pipeline, the instruction pointer is incremented by 3 because of the three skipped instructions (it has no idea that a branch is about to occur). If it weren't for the jump instruction, the next instruction to be executed would be drvh #33. In fact, I would expect you'd see this instruction in the pipeline. But as soon as the pipelined JMP instruction is executed, it adds 3 which is jmp $cogx. The drvh #33 in the pipeline would be cancelled, of course.
But, if I am right, then this means that absolute branches will fail. In those cases, you cannot increment the IP until after the branch, or else you will end up skipping the wrong instructions that followed the branch.
Edit: I finally got a chance to test this theory. Given the following code (note the absolute jumps)
skipf #%01011101
drvh #32 ' skip[0]
jmp #\cogy ' executed
' <= skip[4..2]
drvh #33 ' loaded by skip[5], then cancelled by jmp
drvh #33 ' loaded in place of skip[5] by jmp, executed
drvh #34 ' skip[6]
drvh #35 ' executed (skip no longer active)
jmp #\cogx ' executed
drvh #36 ' executed
drvh #37 ' executed
jmp #$
I assume this is only an issue with the fast skip, as I'm guessing that the slow skip doesn't touch the instruction pointer.
I suggest the following:
* Allow only slow skips to continue after a jump. This works with both relative and absolute jumps (I assume).
* For fast skips, cancel if a jump is encountered. In order to do this, instead of modifying the instruction pointer directly, maintain a separate look-ahead counter (LC) that's driven by the skip pattern. The fetched instruction address will be IP+LC, except when it's a branch. In that case, it's just IP and skip is cancelled. When fast skip is not enabled, LC will just be zero.
Given that, the rules would be:
SKIP : works with all execution modes and branch addressing modes
SKIPF : works with COG execution mode, cancelled if branch
EXECF : JMP first, then enable SKIPF
SKIP : works with all execution modes and branch addressing modes
SKIPF : works with COG execution mode, cancelled if branch
EXECF : JMP first, then enable SKIPF
Chip did mention he had a case where SKIPF over branch was useful, but maybe he only tested that with relative jumps ?
Guess it comes down to what is simplest - fixing ABS, or patching SKIPF ?
SKIP : works with all execution modes and branch addressing modes
SKIPF : works with COG execution mode, cancelled if branch
EXECF : JMP first, then enable SKIPF
Chip did mention he had a case where SKIPF over branch was useful, but maybe he only tested that with relative jumps ?
Guess it comes down to what is simplest - fixing ABS, or patching SKIPF ?
But fix it how? By the point that the absolute jump occurs, the crucial skip bits will have been shifted out of the skip mask. The only reason it happens to work for relative jumps is because it doesn't matter (mathematically) whether you skip-then-branch or branch-then-skip. Except, in the case of branch-then-skip, you're back to slow skips.
Seairth, you are right! I thought it was working differently, by design. Indeed, the absolute JMPs cause it to fail. I will study more what you wrote. This is kind of a mind-bender.
Comments
Oh! I think I get what you are saying. An active SKIP disables interrupts, including the debug interrupt. Therefore, a pending debug interrupt should trigger on the instruction immediately after the last skipped instruction, which would be the DRVH instructions. In the case of SKIP, the interrupt occurred after DRVH. But, in the case of SKIPF, it interrupted correctly (prior to DRVH). Is that correct?
I believe I fixed the problem. Try this:
https://drive.google.com/file/d/0B9NbgkdrupkHUEZ3VExnN0VZZXc/view?usp=sharing
There's a two-cog/no-CORDIC image for the Prop123_A9 board in there, as well as a new PNut.exe which fixes the problem with AUGS/AUGD working with _RET_.
SKIPF and EXECF can now work in hub space, too, but they revert to cancelling instructions, like SKIP does. This matters for EXECF only if a subsequent branch gets you into hub memory, while there are still skip bits queued. This way, SKIPF/EXECF code could run faster in the cog/LUT space, but still works in hub space.
Maybe you could check that out.
SKIP looks good now, works as expected.
Super! I had erred on the side of caution, at first, because I wasn't completely sure.
No joy with _ret_ and AUGD and WRLUT playing together.
Woops, sorry! I modified the assembler, but didn't recompile the main app. Try this:
https://drive.google.com/file/d/0B9NbgkdrupkHcTkwOE1ac3hlT1U/view?usp=sharing
V17b fixed issue with ret_/augd/wrlt combination.
Looking good. :cool:
and changed it to
the AUGD gets encoded as FF800000 instead of FF800040.
That worked, but is that intentional? I don't see a mention of this in the documentation or the instruction list.
Pnut ignores the lower 9 bits for AUGx instructions.
Here's from the spreadsheet:
AUGS/AUGD have 23 bits of operand. They get tacked on above the 9-bit #S/#D of the next instruction using #S/#D.
Ah.... Sorry! I see what you were getting at. I made the assembler just grab bits 31..9 of the operand for AUGS/AUGD. I figured it would be easier to use. I need to do something about the spreadsheet explanation, though.
Ah, thanks. I didn't see this, at first.
edit: Never mind. Chip's update in the spreadsheet is clear enough. No need to dwell on this...
Hold off on the compile for a bit.
Some weirdness with SKIPF in cog now.
I'll get back to you.
Edit: Doh! My bad, V17b is working correctly.
How about SKIPF branching from cog to hub and back again with a skip pattern?
This worked Ok.
SKIPF from cog to hub and back
How about one more instruction between 'cogx' and 'here', and testing one-bits out to that instruction? How they behave around the jumps is important.
I'm maybe pushing my luck here but this nearly worked!
Seems to have got out of step in the last stage.
I am breaking the riles...
I changed the augmented immediate D
Edit: Scratch the above theory.
SKIP works fine in the above example.
SKIPF nearly works except for the second hub snippet.
Aside from that, things are executing way faster than I understand. It seems that there is no rest cycle after a branch using SKIPF. It's hitting every needful instruction, anyway:
Here is what the pipeline sees:
I can't figure out how those JMPs are back-to-back. It looks like they are jumping directly to the address PLUS the needed skips! There's no time for that! In the above example, everything between the SKIPF and the JMP #$ took only 12 clocks.
But, if I am right, then this means that absolute branches will fail. In those cases, you cannot increment the IP until after the branch, or else you will end up skipping the wrong instructions that followed the branch.
Edit: I finally got a chance to test this theory. Given the following code (note the absolute jumps)
I am getting:
I assume this is only an issue with the fast skip, as I'm guessing that the slow skip doesn't touch the instruction pointer.
I suggest the following:
* Allow only slow skips to continue after a jump. This works with both relative and absolute jumps (I assume).
* For fast skips, cancel if a jump is encountered. In order to do this, instead of modifying the instruction pointer directly, maintain a separate look-ahead counter (LC) that's driven by the skip pattern. The fetched instruction address will be IP+LC, except when it's a branch. In that case, it's just IP and skip is cancelled. When fast skip is not enabled, LC will just be zero.
Given that, the rules would be:
SKIP : works with all execution modes and branch addressing modes
SKIPF : works with COG execution mode, cancelled if branch
EXECF : JMP first, then enable SKIPF
Guess it comes down to what is simplest - fixing ABS, or patching SKIPF ?
Notice the long column with all #, making it harder to see labels.
More conventional/standard assemblers would support this
But fix it how? By the point that the absolute jump occurs, the crucial skip bits will have been shifted out of the skip mask. The only reason it happens to work for relative jumps is because it doesn't matter (mathematically) whether you skip-then-branch or branch-then-skip. Except, in the case of branch-then-skip, you're back to slow skips.