A Slashdot topic has this quote:
“It takes 4200 picojoules to move 64 bits from DRAM to registers while it only takes 100 picojoules to do a double-precision floating point operation. It’s over 40x more energy to move the data than to actually operate on it. What most people would assume is that most of that 4200 picojoules is being used in going off-chip, but in reality, about 60% of that energy usage is being consumed by the on-chip cache hierarchy because of all of the extra gates and wires on the chip that the electrons go through. We are removing that 60%.”
It seems external DRAM costs a lot of power when using traditional caching. Funnily, that has been reasonably obvious just from reading specs. I always struggled as to why.
Sorry - somehow the js editor would only let me post within the quote!
Upon reflection, let's leave the locks exactly the same, with the same instructions, as in the P1, but let's have more of them. 16 at a minimum, 32 would not hurt.
As Dave mentioned above, one is theoretically enough, but it requires everything be aware of the single locks management method.
With 16, each cog could theoretically provide a service that could be atomically ineracted with by every cog - simply & quickly.
wonder if a 32 bit long dual port register mapped into lower hub would work as lock bits with a special atomic hub lock instruction.
This way you could just read or write normally, or using the special LOCK instruction set/clear a lock bit with WC returning the original but setting. Because of the dual port nature of this register, in the one clock we would read the bit of the register as well as writing the desired value.
Interrupts could possibly be added to this although I am unsure how this would be applied. Note you could have more than 32 bits.
It probably would not require any extra hub buss bits if implemented this way.
Can some of you explain why it would be good to have a LOCKGET D/# instruction that just reads a LOCK state? These 16 signals come into every cog now and could be easily read without needing any hub interaction.
The problem with just reading them is that they could change abruptly. Simultaneous reading and writing via LOCKSET/LOCKCLR in the hub is where the meaningful action occurs.
We could add an instruction to do this, but I just need to be convinced that it would be useful.
Sorry! I jumped in late, and was trying to catch up.
I like the interrupts as you propose them.
What I meant was:
LOCKGET would obtain the lock, and return a state (was lock busy/did I have to wait)
LOCKFREE would release it.
Similar to what is on the P1, except no automatic lock number allocation (which I never used)
I am perfectly happy with the P1 locks, other than wanting at least 16 locks.
The reason I suggested paring down to two instructions is that some posters wanted to get rid of locks altogether.
Chip was proposing 16 locks anyway.
Even though I have never used them, they are simple to use if required. So I don't suggest they be removed unless there is something to replace them.
Yeah, he's got one per COG at present, linked into the HUB logic. Now, the signals go into the COG as well. Likely interrupt source, but maybe for something else too.
I think we should leave them, and Chip's last request was really to add a mode to use them more like flags and not locks. Chip is very unlikely to pull 'em. They offer a unique feature, and they are there now. It's a freebie to keep, and a cost or loss to remove.
Honestly, to avoid confusion and insure that locks actually do behave like locks, adding that functionality probably doesn't make sense.
But, Searth (sp?) was building a case for it. Maybe he's got a bit more to add. I didn't quite understand where he was headed on that one.
@Bill Henning, when you do a quote, take a moment to drop a few, or just one new line into the comment box, then position the cursor at top of the box, or in the middle of the new lines if you want text pre and post quote, then use the quote button.
The script drops the quote in OK, but doesn't offer you a place to make edits outside of the quote. I think Parallax is working on it, but that's the short term workaround for quoted posts.
For a while now, Chip has been building toward an FPGA image. Where it's obvious, he's just knocking it out, or dealing with the layout team. When it gets to a place where he's wanting some input or other, he's getting it here, then continuing on.
That's why I said he was busy. The interrupt dialog played out, and it made sense to just finish it up, and continue on. And you can see it played out from our dialog. We sort of reach a point where it's been said, we aren't feeling like we need to add much, and it's up to him to take all that and go.
The lock question is unresolved, so he popped up again to see about that one. And if you trace back, it was left dangling. That case for lock state is just hanging out there, no clear use case on it.
Soon, if not already, the ROM and other pieces needed to get an image, pnut, etc... will need to get done, and then we are really close!
Oy. I just now caught up. Unfortunately, too busy with work to respond fully to the LOCKGET query. So, leave LOCKxxx as it currently is (no new instructions) and get the FPGA image wrapped up. We can take this conversation back up later.
I've got the rest of the event system implemented. Events can be captured in flags, polled, waited on, and used as interrupt sources. Here are the event-related instructions:
SETPER D/# set 32-bit period for timer eventSETEDG D/# set 2-bit edge and 6-bit pin/lock for edge eventSETCRW D/# set 2 x 4-bit locations for cog-long-read/write eventsSETBRK D/# set 20-bit address for breakpoint event
GETINT get interrupt-event flag into C, clear flagGETPER get timer-event flag into C, clear flagGETEDG get edge-event flag into C, clear flagGETXRO get transfer-rollover-event flag into C, clear flagGETFBW get fast-block-wrap-event flag into C, clear flagGETCRD get cog-long-read-event flag into C, clear flagGETCWR get cog-long-write-event flag into C, clear flagGETBRK get breakpoint-event flag into C, clear flag
WAITINT wait for interrupt event, WC=1 for timeout using QWAITPER wait for timer event, WC=1 for timeout using QWAITEDG wait for edge event, WC=1 for timeout using QWAITXRO wait for transfer-rollover event, WC=1 for timeout using QWAITFBW wait for fast-block-wrap event, WC=1 for timeout using QWAITCRD wait for cog-long-read event, WC=1 for timeout using QWAITCWR wait for cog-long-write event, WC=1 for timeout using Q
SETINT0 D/# set 3-bit interrupt 0 modeSETINT1 D/# set 3-bit interrupt 1 modeSETINT2 D/# set 3-bit interrupt 2 mode
BLOCKI block interruptsALLOWI allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin 1 = lock
%EE: 00 = any edge %EE: 01 = pos edge %EE: 10 = neg edge %EE: 11 = any edge
%PPPPPP: pin number %xxPPPP: lock number
Look's very nice.
And open for very advanced programing on memory handlers / IO
to transfer data betwen mem-mem else mem-I/O
Thanks
I've got the rest of the event system implemented. Events can be captured in flags, polled, waited on, and used as interrupt sources. Here are the event-related instructions:
SETPER D/# set 32-bit period for timer eventSETEDG D/# set 2-bit edge and 6-bit pin/lock for edge eventSETCRW D/# set 2 x 4-bit locations for cog-long-read/write eventsSETBRK D/# set 20-bit address for breakpoint event
GETINT get interrupt-event flag into C, clear flagGETPER get timer-event flag into C, clear flagGETEDG get edge-event flag into C, clear flagGETXRO get transfer-rollover-event flag into C, clear flagGETFBW get fast-block-wrap-event flag into C, clear flagGETCRD get cog-long-read-event flag into C, clear flagGETCWR get cog-long-write-event flag into C, clear flagGETBRK get breakpoint-event flag into C, clear flag
WAITINT wait for interrupt event, WC=1 for timeout using QWAITPER wait for timer event, WC=1 for timeout using QWAITEDG wait for edge event, WC=1 for timeout using QWAITXRO wait for transfer-rollover event, WC=1 for timeout using QWAITFBW wait for fast-block-wrap event, WC=1 for timeout using QWAITCRD wait for cog-long-read event, WC=1 for timeout using QWAITCWR wait for cog-long-write event, WC=1 for timeout using Q
SETINT0 D/# set 3-bit interrupt 0 modeSETINT1 D/# set 3-bit interrupt 1 modeSETINT2 D/# set 3-bit interrupt 2 mode
BLOCKI block interruptsALLOWI allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin 1 = lock
%EE: 00 = any edge %EE: 01 = pos edge %EE: 10 = neg edge %EE: 11 = any edge
%PPPPPP: pin number %xxPPPP: lock number
Chip,
Shouldn't the SETCRW etc be Hub addresses and not Cog addresses???
I've got the rest of the event system implemented. Events can be captured in flags, polled, waited on, and used as interrupt sources. Here are the event-related instructions:
SETPER D/# set 32-bit period for timer eventSETEDG D/# set 2-bit edge and 6-bit pin/lock for edge eventSETCRW D/# set 2 x 4-bit locations for cog-long-read/write eventsSETBRK D/# set 20-bit address for breakpoint event
GETINT get interrupt-event flag into C, clear flagGETPER get timer-event flag into C, clear flagGETEDG get edge-event flag into C, clear flagGETXRO get transfer-rollover-event flag into C, clear flagGETFBW get fast-block-wrap-event flag into C, clear flagGETCRD get cog-long-read-event flag into C, clear flagGETCWR get cog-long-write-event flag into C, clear flagGETBRK get breakpoint-event flag into C, clear flag
WAITINT wait for interrupt event, WC=1 for timeout using QWAITPER wait for timer event, WC=1 for timeout using QWAITEDG wait for edge event, WC=1 for timeout using QWAITXRO wait for transfer-rollover event, WC=1 for timeout using QWAITFBW wait for fast-block-wrap event, WC=1 for timeout using QWAITCRD wait for cog-long-read event, WC=1 for timeout using QWAITCWR wait for cog-long-write event, WC=1 for timeout using Q
SETINT0 D/# set 3-bit interrupt 0 modeSETINT1 D/# set 3-bit interrupt 1 modeSETINT2 D/# set 3-bit interrupt 2 mode
BLOCKI block interruptsALLOWI allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin 1 = lock
%EE: 00 = any edge %EE: 01 = pos edge %EE: 10 = neg edge %EE: 11 = any edge
%PPPPPP: pin number %xxPPPP: lock number
@Bill Henning, when you do a quote, take a moment to drop a few, or just one new line into the comment box, then position the cursor at top of the box, or in the middle of the new lines if you want text pre and post quote, then use the quote button.
The script drops the quote in OK, but doesn't offer you a place to make edits outside of the quote. I think Parallax is working on it, but that's the short term workaround for quoted posts.
With the default enabled, you just need to make sure you've covered all cases where a failure, mis-wired something, etc. doesn't prevent you from coming up from a reset/power-off. If the ROM will have known always good vectors in place at reset, you're ok. If they are volatile on reset, then you can't enable interrupts until you've had a chance to set the vectors.
Plus a default of "disabled" makes it more Propellerish when it starts up. You only get the interrupt features if you ask for them by setting vectors and enabling them. What you don't enable, never exists!
Chip,
Shouldn't the SETCRW etc be Hub addresses and not Cog addresses???
I've got the rest of the event system implemented. Events can be captured in flags, polled, waited on, and used as interrupt sources. Here are the event-related instructions:
SETPER D/# set 32-bit period for timer eventSETEDG D/# set 2-bit edge and 6-bit pin/lock for edge eventSETCRW D/# set 2 x 4-bit locations for cog-long-read/write eventsSETBRK D/# set 20-bit address for breakpoint event
GETINT get interrupt-event flag into C, clear flagGETPER get timer-event flag into C, clear flagGETEDG get edge-event flag into C, clear flagGETXRO get transfer-rollover-event flag into C, clear flagGETFBW get fast-block-wrap-event flag into C, clear flagGETCRD get cog-long-read-event flag into C, clear flagGETCWR get cog-long-write-event flag into C, clear flagGETBRK get breakpoint-event flag into C, clear flag
WAITINT wait for interrupt event, WC=1 for timeout using QWAITPER wait for timer event, WC=1 for timeout using QWAITEDG wait for edge event, WC=1 for timeout using QWAITXRO wait for transfer-rollover event, WC=1 for timeout using QWAITFBW wait for fast-block-wrap event, WC=1 for timeout using QWAITCRD wait for cog-long-read event, WC=1 for timeout using QWAITCWR wait for cog-long-write event, WC=1 for timeout using Q
SETINT0 D/# set 3-bit interrupt 0 modeSETINT1 D/# set 3-bit interrupt 1 modeSETINT2 D/# set 3-bit interrupt 2 mode
BLOCKI block interruptsALLOWI allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin 1 = lock
%EE: 00 = any edge %EE: 01 = pos edge %EE: 10 = neg edge %EE: 11 = any edge
%PPPPPP: pin number %xxPPPP: lock number
Woops! Poor choice of words on my part. By "cog long address" I meant "long address in hub that a cog reads/writes". I should have just said "Nth hub long", or something.
No, because interrupts are initially off and do not need blocking, and then when you turn them on, you''ll want them to work without needing an additional instruction, ALLOWI.
SETINTx is the enable/disable of each interrupt.
I think of BLOCKI and ALLOWI as being "begin critical section" and "end critical section" but that comes from my Windows coding background.
I cleaned up that description I posted earlier. This is much more accurate about how things work:
Event-related instructions
SETPER D/# - set 32-bit period for recurring timer event
SETEDG D/# - set 2-bit edge and 6-bit pin/lock number for edge event
SETRWL D/# - set two 4-bit long indexes for universal RDLONG/WRLONG events
SETBRK D/# - set 20-bit address for breakpoint event
GETINT - get interrupt-event flag into C, clear flag
GETPER - get timer-event flag into C, clear flag
GETEDG - get edge-event flag into C, clear flag
GETXRO - get transfer-rollover-event flag into C, clear flag
GETFBW - get fast-block-wrap-event flag into C, clear flag
GETRDL - get RDLONG-event flag into C, clear flag
GETWRL - get WRLONG-event flag into C, clear flag
GETBRK - get breakpoint-event flag into C, clear flag
WAITINT - wait for interrupt event, WC=1 for timeout using Q
WAITPER - wait for timer-event flag, clear flag, WC=1 for timeout using Q
WAITEDG - wait for edge-event flag, clear flag, WC=1 for timeout using Q
WAITXRO - wait for transfer-rollover-event flag, clear flag, WC=1 for timeout using Q
WAITFBW - wait for fast-block-wrap-event flag, clear flag, WC=1 for timeout using Q
WAITRDL - wait for RDLONG-event flag, clear flag, WC=1 for timeout using Q
WAITWRL - wait for WRLONG-event flag, clear flag, WC=1 for timeout using Q
SETINT0 D/# - set 3-bit mode for interrupt 0
SETINT1 D/# - set 3-bit mode for interrupt 1
SETINT2 D/# - set 3-bit mode for interrupt 2
BLOCKI - block interrupts
ALLOWI - allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin
1 = lock
%EE: 00 = any edge
%EE: 01 = pos edge
%EE: 10 = neg edge
%EE: 11 = any edge
%PPPPPP: pin number
%xxPPPP: lock number
Getting events isolated from interrupts really made things flow. Polling and waiting were practically free, then.
There's a lot of instructions there, but just a little core logic fed by 8-to-1 mux's. All those GETxxx/WAITxxx instructions are actually ONE machine-language instruction with differing mux-control bits in its D field. It's like a peacock - little brain, but big feathers with lots of eyes.
But @mmm,
without access to the pins your restricted code can do nothing. The main point of code in a micro controller is to control pins to do something.
Sure - some sort of settable memory limit for COGS might be a good idea. It would prevent cogs from destroying main hub memory. But no access to pins make a COG useless.
my 2 cents.
Mike
because you use block elsewhere, a better name and clearer description would help those who are not native English speakers.
I think BLOCK prevents or defers or pauses or ignores interrupts - then, the details matter :
Are pending flags responded to on ALLOWI, or are they discarded, and only those after ALLOWI acted on ?
because you use block elsewhere, a better name and clearer description would help those who are not native English speakers.
I think BLOCK prevents or defers or pauses or ignores interrupts - then, the details matter :
Are pending flags responded to on ALLOWI, or are they discarded, and only those after ALLOWI acted on ?
Interrupts are still gathered after BLOCKI and then responded to after ALLOWI.
I think 'defer' is the most descriptive word: DEFERI. Makes a wierd-looking instruction, though. IDEFER would be better, but that doesn't work for IALLOW. We need another word for 'allow' that starts with a consonant. IPERMIT? IDEFER and IPERMIT sound first-person and lawyerly. I agree about the conflict with the word BLOCK. Maybe the fast hub read/write block should be termed a FRAME with 'reload' rather than a BLOCK with 'wrap'.
Comments
“It takes 4200 picojoules to move 64 bits from DRAM to registers while it only takes 100 picojoules to do a double-precision floating point operation. It’s over 40x more energy to move the data than to actually operate on it. What most people would assume is that most of that 4200 picojoules is being used in going off-chip, but in reality, about 60% of that energy usage is being consumed by the on-chip cache hierarchy because of all of the extra gates and wires on the chip that the electrons go through. We are removing that 60%.”
It seems external DRAM costs a lot of power when using traditional caching. Funnily, that has been reasonably obvious just from reading specs. I always struggled as to why.
Full article - http://www.theplatform.net/2015/07/22/supercomputer-chip-startup-scores-funding-darpa-contract/
I'm gonna guess he's chucked out most forms of protection and virtualisation.
Sorry - somehow the js editor would only let me post within the quote!
Upon reflection, let's leave the locks exactly the same, with the same instructions, as in the P1, but let's have more of them. 16 at a minimum, 32 would not hurt.
As Dave mentioned above, one is theoretically enough, but it requires everything be aware of the single locks management method.
With 16, each cog could theoretically provide a service that could be atomically ineracted with by every cog - simply & quickly.
Cluso99 said:
LOCKS
wonder if a 32 bit long dual port register mapped into lower hub would work as lock bits with a special atomic hub lock instruction.
This way you could just read or write normally, or using the special LOCK instruction set/clear a lock bit with WC returning the original but setting. Because of the dual port nature of this register, in the one clock we would read the bit of the register as well as writing the desired value.
Interrupts could possibly be added to this although I am unsure how this would be applied. Note you could have more than 32 bits.
It probably would not require any extra hub buss bits if implemented this way.
The problem with just reading them is that they could change abruptly. Simultaneous reading and writing via LOCKSET/LOCKCLR in the hub is where the meaningful action occurs.
We could add an instruction to do this, but I just need to be convinced that it would be useful.
Sorry! I jumped in late, and was trying to catch up.
I like the interrupts as you propose them.
What I meant was:
LOCKGET would obtain the lock, and return a state (was lock busy/did I have to wait)
LOCKFREE would release it.
Similar to what is on the P1, except no automatic lock number allocation (which I never used)
I am perfectly happy with the P1 locks, other than wanting at least 16 locks.
The reason I suggested paring down to two instructions is that some posters wanted to get rid of locks altogether.
Even though I have never used them, they are simple to use if required. So I don't suggest they be removed unless there is something to replace them.
I think we should leave them, and Chip's last request was really to add a mode to use them more like flags and not locks. Chip is very unlikely to pull 'em. They offer a unique feature, and they are there now. It's a freebie to keep, and a cost or loss to remove.
Honestly, to avoid confusion and insure that locks actually do behave like locks, adding that functionality probably doesn't make sense.
But, Searth (sp?) was building a case for it. Maybe he's got a bit more to add. I didn't quite understand where he was headed on that one.
The script drops the quote in OK, but doesn't offer you a place to make edits outside of the quote. I think Parallax is working on it, but that's the short term workaround for quoted posts.
For a while now, Chip has been building toward an FPGA image. Where it's obvious, he's just knocking it out, or dealing with the layout team. When it gets to a place where he's wanting some input or other, he's getting it here, then continuing on.
That's why I said he was busy. The interrupt dialog played out, and it made sense to just finish it up, and continue on. And you can see it played out from our dialog. We sort of reach a point where it's been said, we aren't feeling like we need to add much, and it's up to him to take all that and go.
The lock question is unresolved, so he popped up again to see about that one. And if you trace back, it was left dangling. That case for lock state is just hanging out there, no clear use case on it.
Soon, if not already, the ROM and other pieces needed to get an image, pnut, etc... will need to get done, and then we are really close!
Just thought I would share what I'm seeing.
SETPER D/# set 32-bit period for timer eventSETEDG D/# set 2-bit edge and 6-bit pin/lock for edge eventSETCRW D/# set 2 x 4-bit locations for cog-long-read/write eventsSETBRK D/# set 20-bit address for breakpoint event
GETINT get interrupt-event flag into C, clear flagGETPER get timer-event flag into C, clear flagGETEDG get edge-event flag into C, clear flagGETXRO get transfer-rollover-event flag into C, clear flagGETFBW get fast-block-wrap-event flag into C, clear flagGETCRD get cog-long-read-event flag into C, clear flagGETCWR get cog-long-write-event flag into C, clear flagGETBRK get breakpoint-event flag into C, clear flag
WAITINT wait for interrupt event, WC=1 for timeout using QWAITPER wait for timer event, WC=1 for timeout using QWAITEDG wait for edge event, WC=1 for timeout using QWAITXRO wait for transfer-rollover event, WC=1 for timeout using QWAITFBW wait for fast-block-wrap event, WC=1 for timeout using QWAITCRD wait for cog-long-read event, WC=1 for timeout using QWAITCWR wait for cog-long-write event, WC=1 for timeout using Q
SETINT0 D/# set 3-bit interrupt 0 modeSETINT1 D/# set 3-bit interrupt 1 modeSETINT2 D/# set 3-bit interrupt 2 mode
BLOCKI block interruptsALLOWI allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin 1 = lock
%EE: 00 = any edge %EE: 01 = pos edge %EE: 10 = neg edge %EE: 11 = any edge
%PPPPPP: pin number %xxPPPP: lock number
SETCRW %RRRR_WWWW
%RRRR: cog-long-read-event address %0000_0000_0000_00RR_RR00 %WWWW: cog-long-write-event address %0000_0000_0000_00WW_WW00
SETINTx %MMM
%MMM: 000 = off 001 = timer interrupt 010 = edge interrupt 011 = transfer-rollover interrupt 100 = fast-block-wrap interrupt 101 = cog-long-read interrupt 110 = cog-long-write interrupt 111 = breakpoint interrupt
Look's very nice.
And open for very advanced programing on memory handlers / IO
to transfer data betwen mem-mem else mem-I/O
Thanks
I've got the rest of the event system implemented. Events can be captured in flags, polled, waited on, and used as interrupt sources. Here are the event-related instructions:
SETPER D/# set 32-bit period for timer eventSETEDG D/# set 2-bit edge and 6-bit pin/lock for edge eventSETCRW D/# set 2 x 4-bit locations for cog-long-read/write eventsSETBRK D/# set 20-bit address for breakpoint event
GETINT get interrupt-event flag into C, clear flagGETPER get timer-event flag into C, clear flagGETEDG get edge-event flag into C, clear flagGETXRO get transfer-rollover-event flag into C, clear flagGETFBW get fast-block-wrap-event flag into C, clear flagGETCRD get cog-long-read-event flag into C, clear flagGETCWR get cog-long-write-event flag into C, clear flagGETBRK get breakpoint-event flag into C, clear flag
WAITINT wait for interrupt event, WC=1 for timeout using QWAITPER wait for timer event, WC=1 for timeout using QWAITEDG wait for edge event, WC=1 for timeout using QWAITXRO wait for transfer-rollover event, WC=1 for timeout using QWAITFBW wait for fast-block-wrap event, WC=1 for timeout using QWAITCRD wait for cog-long-read event, WC=1 for timeout using QWAITCWR wait for cog-long-write event, WC=1 for timeout using Q
SETINT0 D/# set 3-bit interrupt 0 modeSETINT1 D/# set 3-bit interrupt 1 modeSETINT2 D/# set 3-bit interrupt 2 mode
BLOCKI block interruptsALLOWI allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin 1 = lock
%EE: 00 = any edge %EE: 01 = pos edge %EE: 10 = neg edge %EE: 11 = any edge
%PPPPPP: pin number %xxPPPP: lock number
SETCRW %RRRR_WWWW
%RRRR: cog-long-read-event address %0000_0000_0000_00RR_RR00 %WWWW: cog-long-write-event address %0000_0000_0000_00WW_WW00
SETINTx %MMM
%MMM: 000 = off 001 = timer interrupt 010 = edge interrupt 011 = transfer-rollover interrupt 100 = fast-block-wrap interrupt 101 = cog-long-read interrupt 110 = cog-long-write interrupt 111 = breakpoint interrupt
Shouldn't the SETCRW etc be Hub addresses and not Cog addresses???
I've got the rest of the event system implemented. Events can be captured in flags, polled, waited on, and used as interrupt sources. Here are the event-related instructions:
SETPER D/# set 32-bit period for timer eventSETEDG D/# set 2-bit edge and 6-bit pin/lock for edge eventSETCRW D/# set 2 x 4-bit locations for cog-long-read/write eventsSETBRK D/# set 20-bit address for breakpoint event
GETINT get interrupt-event flag into C, clear flagGETPER get timer-event flag into C, clear flagGETEDG get edge-event flag into C, clear flagGETXRO get transfer-rollover-event flag into C, clear flagGETFBW get fast-block-wrap-event flag into C, clear flagGETCRD get cog-long-read-event flag into C, clear flagGETCWR get cog-long-write-event flag into C, clear flagGETBRK get breakpoint-event flag into C, clear flag
WAITINT wait for interrupt event, WC=1 for timeout using QWAITPER wait for timer event, WC=1 for timeout using QWAITEDG wait for edge event, WC=1 for timeout using QWAITXRO wait for transfer-rollover event, WC=1 for timeout using QWAITFBW wait for fast-block-wrap event, WC=1 for timeout using QWAITCRD wait for cog-long-read event, WC=1 for timeout using QWAITCWR wait for cog-long-write event, WC=1 for timeout using Q
SETINT0 D/# set 3-bit interrupt 0 modeSETINT1 D/# set 3-bit interrupt 1 modeSETINT2 D/# set 3-bit interrupt 2 mode
BLOCKI block interruptsALLOWI allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin 1 = lock
%EE: 00 = any edge %EE: 01 = pos edge %EE: 10 = neg edge %EE: 11 = any edge
%PPPPPP: pin number %xxPPPP: lock number
SETCRW %RRRR_WWWW
%RRRR: cog-long-read-event address %0000_0000_0000_00RR_RR00 %WWWW: cog-long-write-event address %0000_0000_0000_00WW_WW00
SETINTx %MMM
%MMM: 000 = off 001 = timer interrupt 010 = edge interrupt 011 = transfer-rollover interrupt 100 = fast-block-wrap interrupt 101 = cog-long-read interrupt 110 = cog-long-write interrupt 111 = breakpoint interrupt
That worked like a charm.
@Bill Henning, when you do a quote, take a moment to drop a few, or just one new line into the comment box, then position the cursor at top of the box, or in the middle of the new lines if you want text pre and post quote, then use the quote button.
The script drops the quote in OK, but doesn't offer you a place to make edits outside of the quote. I think Parallax is working on it, but that's the short term workaround for quoted posts.
that looks good.
Plus a default of "disabled" makes it more Propellerish when it starts up. You only get the interrupt features if you ask for them by setting vectors and enabling them. What you don't enable, never exists!
Shouldn't the SETCRW etc be Hub addresses and not Cog addresses???
I've got the rest of the event system implemented. Events can be captured in flags, polled, waited on, and used as interrupt sources. Here are the event-related instructions:
SETPER D/# set 32-bit period for timer eventSETEDG D/# set 2-bit edge and 6-bit pin/lock for edge eventSETCRW D/# set 2 x 4-bit locations for cog-long-read/write eventsSETBRK D/# set 20-bit address for breakpoint event
GETINT get interrupt-event flag into C, clear flagGETPER get timer-event flag into C, clear flagGETEDG get edge-event flag into C, clear flagGETXRO get transfer-rollover-event flag into C, clear flagGETFBW get fast-block-wrap-event flag into C, clear flagGETCRD get cog-long-read-event flag into C, clear flagGETCWR get cog-long-write-event flag into C, clear flagGETBRK get breakpoint-event flag into C, clear flag
WAITINT wait for interrupt event, WC=1 for timeout using QWAITPER wait for timer event, WC=1 for timeout using QWAITEDG wait for edge event, WC=1 for timeout using QWAITXRO wait for transfer-rollover event, WC=1 for timeout using QWAITFBW wait for fast-block-wrap event, WC=1 for timeout using QWAITCRD wait for cog-long-read event, WC=1 for timeout using QWAITCWR wait for cog-long-write event, WC=1 for timeout using Q
SETINT0 D/# set 3-bit interrupt 0 modeSETINT1 D/# set 3-bit interrupt 1 modeSETINT2 D/# set 3-bit interrupt 2 mode
BLOCKI block interruptsALLOWI allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin 1 = lock
%EE: 00 = any edge %EE: 01 = pos edge %EE: 10 = neg edge %EE: 11 = any edge
%PPPPPP: pin number %xxPPPP: lock number
SETCRW %RRRR_WWWW
%RRRR: cog-long-read-event address %0000_0000_0000_00RR_RR00 %WWWW: cog-long-write-event address %0000_0000_0000_00WW_WW00
SETINTx %MMM
%MMM: 000 = off 001 = timer interrupt 010 = edge interrupt 011 = transfer-rollover interrupt 100 = fast-block-wrap interrupt 101 = cog-long-read interrupt 110 = cog-long-write interrupt 111 = breakpoint interrupt
Woops! Poor choice of words on my part. By "cog long address" I meant "long address in hub that a cog reads/writes". I should have just said "Nth hub long", or something.
No, because interrupts are initially off and do not need blocking, and then when you turn them on, you''ll want them to work without needing an additional instruction, ALLOWI.
It is exciting!!
IMHO, going this way gets us most of what "hot" did, and that is compelling. Whatever teething pains we may have are going to be so worth it.
Go Chip!
I think of BLOCKI and ALLOWI as being "begin critical section" and "end critical section" but that comes from my Windows coding background.
Event-related instructions
SETPER D/# - set 32-bit period for recurring timer event
SETEDG D/# - set 2-bit edge and 6-bit pin/lock number for edge event
SETRWL D/# - set two 4-bit long indexes for universal RDLONG/WRLONG events
SETBRK D/# - set 20-bit address for breakpoint event
GETINT - get interrupt-event flag into C, clear flag
GETPER - get timer-event flag into C, clear flag
GETEDG - get edge-event flag into C, clear flag
GETXRO - get transfer-rollover-event flag into C, clear flag
GETFBW - get fast-block-wrap-event flag into C, clear flag
GETRDL - get RDLONG-event flag into C, clear flag
GETWRL - get WRLONG-event flag into C, clear flag
GETBRK - get breakpoint-event flag into C, clear flag
WAITINT - wait for interrupt event, WC=1 for timeout using Q
WAITPER - wait for timer-event flag, clear flag, WC=1 for timeout using Q
WAITEDG - wait for edge-event flag, clear flag, WC=1 for timeout using Q
WAITXRO - wait for transfer-rollover-event flag, clear flag, WC=1 for timeout using Q
WAITFBW - wait for fast-block-wrap-event flag, clear flag, WC=1 for timeout using Q
WAITRDL - wait for RDLONG-event flag, clear flag, WC=1 for timeout using Q
WAITWRL - wait for WRLONG-event flag, clear flag, WC=1 for timeout using Q
SETINT0 D/# - set 3-bit mode for interrupt 0
SETINT1 D/# - set 3-bit mode for interrupt 1
SETINT2 D/# - set 3-bit mode for interrupt 2
BLOCKI - block interrupts
ALLOWI - allow interrupts - default
SETEDG %L_EE_PPPPPP
%L: 0 = pin
1 = lock
%EE: 00 = any edge
%EE: 01 = pos edge
%EE: 10 = neg edge
%EE: 11 = any edge
%PPPPPP: pin number
%xxPPPP: lock number
SETRWL %RRRR_WWWW
%RRRR: RDLONG-event address %0000_0000_0000_00RR_RR00
%WWWW: WRLONG-event address %0000_0000_0000_00WW_WW00
SETINT0/SETINT1/SETINT2 %MMM
%MMM: 000 = disable interrupt - default
001 = enable timer-event interrupt
010 = enable edge-event interrupt
011 = enable transfer-rollover-event interrupt
100 = enable fast-block-wrap-event interrupt
101 = enable RDLONG-event interrupt
110 = enable WRLONG-event interrupt
111 = enable breakpoint-event interrupt
Nice work Chip. I'm feeling very good about this feature.
There's a lot of instructions there, but just a little core logic fed by 8-to-1 mux's. All those GETxxx/WAITxxx instructions are actually ONE machine-language instruction with differing mux-control bits in its D field. It's like a peacock - little brain, but big feathers with lots of eyes.
without access to the pins your restricted code can do nothing. The main point of code in a micro controller is to control pins to do something.
Sure - some sort of settable memory limit for COGS might be a good idea. It would prevent cogs from destroying main hub memory. But no access to pins make a COG useless.
my 2 cents.
Mike
BLOCKI - block interrupts
ALLOWI - allow interrupts - default
because you use block elsewhere, a better name and clearer description would help those who are not native English speakers.
I think BLOCK prevents or defers or pauses or ignores interrupts - then, the details matter :
Are pending flags responded to on ALLOWI, or are they discarded, and only those after ALLOWI acted on ?
BLOCKI - block interrupts
ALLOWI - allow interrupts - default
because you use block elsewhere, a better name and clearer description would help those who are not native English speakers.
I think BLOCK prevents or defers or pauses or ignores interrupts - then, the details matter :
Are pending flags responded to on ALLOWI, or are they discarded, and only those after ALLOWI acted on ?
Interrupts are still gathered after BLOCKI and then responded to after ALLOWI.
I think 'defer' is the most descriptive word: DEFERI. Makes a wierd-looking instruction, though. IDEFER would be better, but that doesn't work for IALLOW. We need another word for 'allow' that starts with a consonant. IPERMIT? IDEFER and IPERMIT sound first-person and lawyerly. I agree about the conflict with the word BLOCK. Maybe the fast hub read/write block should be termed a FRAME with 'reload' rather than a BLOCK with 'wrap'.