The case for a reset from pin to COG
I'd like to make a case for having a an interrupt or reset in our COGs:
It is often stated that the Propeller does not need interrupts. Is intentionally designed without interrupts. That interrupts upset deterministic behaviour and that anything you can do with interrupts can be done with more COGs.
This is a line of reasoning that I have always had sympathy for. But is it just possible that there are some situations where a means of interrupting a COG from a pin, or only just simply resetting it's program counter, would be useful if not essential?
Consider:
You have a stream of bits or bytes or whatever coming in at speed. Each bit or byte is read when some clock pin transitions or perhaps just by free running at the sample rate. As per the serial or USB drivers. So we are either doing waitpeq looking for the clock, or waiting on a time count or just constructing a loop that has the correct length in time to sample in the right places.
Now we add to this another signal, call it "synch" or "reset" or "start" or whatever. The purpose of which is to indicate that the interface should be reset, or another block transfer is starting immediately (aborting the current one). So now we have to read this synch signal as well as our data bits, at the same speed as the data b
It is often stated that the Propeller does not need interrupts. Is intentionally designed without interrupts. That interrupts upset deterministic behaviour and that anything you can do with interrupts can be done with more COGs.
This is a line of reasoning that I have always had sympathy for. But is it just possible that there are some situations where a means of interrupting a COG from a pin, or only just simply resetting it's program counter, would be useful if not essential?
Consider:
You have a stream of bits or bytes or whatever coming in at speed. Each bit or byte is read when some clock pin transitions or perhaps just by free running at the sample rate. As per the serial or USB drivers. So we are either doing waitpeq looking for the clock, or waiting on a time count or just constructing a loop that has the correct length in time to sample in the right places.
Now we add to this another signal, call it "synch" or "reset" or "start" or whatever. The purpose of which is to indicate that the interface should be reset, or another block transfer is starting immediately (aborting the current one). So now we have to read this synch signal as well as our data bits, at the same speed as the data b
Comments
You want everything in the processor right? Then design one yourself, that solves problems. Or you can buy one from microchip or another another name that makes complex microcontrollers that require 500 pages of reading material to use (not that the propeller chip's manual is small).
However,·your case is a pretty good reason to add the feaure. But instead why not just increase the speed of the propeller chip and keep its internal operation simple? Increasing the speed would solve the problem without drastically changing all the current gate configuration designs.
But...
I acutally kinda like the idea, maybe there could be a 32 bit register with the bottom 5 bits indexing the pin to have an interrupt on. The next 9 bits to be what to set the PC to, and maybe the rest of the bits controlling the what kind of operation will trigger the interrupt.
That would be kinda cool. But on the other hand you would lose one long from the cog ram.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
Increasing the speed of the Prop will of course solve many problems of the nature I describe above however I do have an application in mind where no matter what the speed one would always be left thinking "that's nice but what a shame I have waste 25 or 50 percent of it's speed checking a pin for the lack of a simple interrupt or reset"
Specifically I was thinking of the Prop as RAM idea that I posted on another thread recently. Here we want to clock address, data and command bytes between Props as fast as possible whilst at the same time having an initiate or sync or reset signal that causes the remote end of the link to reset its state ready for new commands.
Now somewhere in the Prop there must already be logic to reset the COGs program counter. How hard would it be in Prop II, say, to get that reset driven by a pin.
Of course, thinking now, the Prop as RAM idea boils down to an inter COG communication problem, between Props or within a single Prop. Many have already voiced a desire for a lightning fast solution to that issue.
It never really occurred to me before that the Prop has no individual resets for it's CPUs. Without having to reload the whole thing. The Prop is weird in so many ways[noparse]:)[/noparse]
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Your point is valid, but you could solve the problem with software. Using an additional cog to monitor the Sync signal and also function as an interrupt, you can invoke a COGINIT to another cog by obtaining the COGID of interest. The COGINIT command can be used to start a new cog, or restart an active cog. You may also choose to use the COGSTOP in lieu of a cog reset depending on the circumstance. Keep in mind the number of clocks required for these HUB instructions. To keep valid Sync points it may be necessary to pass the Counter value into the cog being reset, so that it can compare to the "live" Counter value and make necessary adjustments.
A similar scheme can also be applied to "break-out" of an endless wait instruction after a certain time interval has elapsed.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
1) It must be slow, having to stop and reload an entire COG.
2) It breaks by heart to use a whole 32 bit CPU for such a simple task! I need all the COGs I can get.
What I'm fishing for here is something very simple that uses as few gates and interconnects on chip as possible, that provides a substantial benefit for it's implementation effort/cost, is of general purpose use, and fits within the overall Propeller philosophy. It's only a reset after all.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
With COGINIT, you don't need to reload the entire COG. If you set the bit 3 of the Destination address to a Zero instead of a ONE, then the COG will simply reset. Because the COGINIT is a HUB instruction it can take anywhere from 7 to 22 clocks and that's what you might need to lookout for depending on your application.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Where is that documented? The manual describes bit 3 of the destination value as the NEW bit. If set to 1, the instruction does a COGNEW operation. If set to 0, the instruction does a COGINIT operation using a specific cog. I don't see anything that can instruct the hub to skip the reload of the cog's memory (which takes about 100us).
That's new to me as well! That makes building a supervisor cog more attractive.
BTW Heater: Such a COG could be doing other stuff, depending on the latency requirements.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
Safety Tip: Life is as good as YOU think it is!
Perhaps I'm mis-interpreting it, but I'm looking at the book (hard-copy) on page 366-367
"Propeller Assembly’s COGINIT instruction can be used to start a new cog or restart an active cog."
"If the third field bit is clear (0), the Hub will start or restart cog identified by the Destination's fourth field, bits 2:0."
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 2/2/2009 8:03:48 PM GMT
As for "wishing", for sure one can wish ones self into a whole ball of complication.
However I'm not actually wishing for interrupts here. A simple reset would do. In fact it is logically equivalent to and conceptually as simple as the suggested method of using a COG to to restart another COG. Except that instead of using a whole 32 bit CPU to crack a nut it uses a hand full of gates. That's not so much to wish for, is it?
Anyway, we have what we have and as potatohead says the "interrupting" COG could have other functions so things are not so bad.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
I assume "start" has to load code and get the thing running. But does restart also reload the code or just reset the PC.
Thinking about it I get the idea it reloads otherwise all those instructions that have modified themselves will be in a chaotic state!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
From the Manual:
"The third field, bit 3, should be set (1) if a new cog should be started, or cleared (0) if a
specific cog should be started or restarted."
and
"If the third field bit is set (1), the Hub will start the next available (lowest-numbered inactive)
cog and return that cog’s ID in Destination (if the WR effect is specified).
If the third field bit is clear (0), the Hub will start or restart the cog identified by Destination’s
fourth field, bits 2:0."
The bit simply designates if a specific cog is started or restarted. "Started" meaning the cog is currently stopped, or "restarted" meaning the cog is not currently stopped..
So, I'd like to restate my case for a simple pin to RESET feature that simply jams the COGs program counter back to zero as fast as possible?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
As an aside, the book says that waitpne does not write a result. So I thought I'd try forcing it with a wr. This would be very handy for two things: 1) automatically updating the compare value with the new state for detecting subsequent changes, and 2) providing the actual state value at the time of the compare that one can read without having to reread the pins four clocks later and to wonder if they changed again in the interim. It didn't work, though, and I'm a bit surprised by the omission.
-Phil
I'm not an expert in PASM at all but
somewhere in your code you have a jump-command anyway
How about using the PHSA-register as the destination-field of some kind of a jump-command
which changes to the reset-adress as soon as a positive edge arrives on a PIN ???
(by setting up the right countermode and the right frqa-value)
Maybe this requires a jump to and from the PHSA-modified jump
would that be fast enough ?
best regards
Stefan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
If, for example, it means that the timing of a cog's operations is determined only by those operations themselves, and is unaffected by other cogs, that's untrue if it interacts with other cogs in nearly any conceivable way.· And if·cogs don't interact, the very real benefits of multiprocessing seem lost.
If it means that event timing can easily (or at all) be kept coherent among multiple cogs, it's barely true but very difficult.· Every program that does anything useful, after all,·is a loop, big or small.· Timing can be kept coherent only if (1) all loops in various cogs have the same length (in machine cycles), and (2) the loop lengths can't change, which in turn means no conditional jumps.· Pretty confining!· Without these two conditions, the time between one cog's reaching some particular one of its instructions, and another cog's reaching some particular one of its instructions, is a random number.· Coherency would be useful, but that's not coherency, and it doesn't seem to me to meet any conceivable definition of determinacy, either.· Nor, as some people speak of it, "determinancy", whatever that may be.
On the other hand, coherency is easy to achieve in an interrupt-driven structure.· A routine running in such·a machine can be written with absolute assurance of the timing between an external event (that causes an interrupt) and the execution of the routine that handles it.· It's predictable within a cycle or two, and often exactly.· But if a separate processor (a cog) must loop and loop to recheck for the external event (a pin going high, say), then this timing becomes incoherent because the external event may occur at any time in the loop, from just after the instruction that checks, through the looping stuff, right up through the instruction just before the test, and for that matter the test itself.· Since interrupts don't have to loop to respond, interrupts can be faster and simpler.
Interrupts can be faster and simpler, but if there is much context to be saved (on a stack as in some machines, or in save areas as in IBM mainframes), they can be faster, though in my view not more complex.· In the Propeller there is essentially no context to be saved, for there are no registers -- so coherency would be easy if there were interrupts.
But back to my original query:· what exactly do you mean when you speak of "deterministic timing".· Can you define it, or is it merely advertising hype?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
I still think interupts are a good option especially 1 waitpeq interupt that is optionaly engaged.
There is the program counter, the flags, state of counters are three I can think of off hand. Of those, the PC and flags would have to go somewhere, for an interrupt right? Otherwise, code that depends on a flag state would break, if interrupted. At a minimum the flags are important context, given the conditional execution of all the instructions.
IMHO, that's part of the determinism as well. The state of the CPU is known and can be depended on being known for a given body of code.
There is also the pipeline. To me, that's like a register. If a loop is written for the pipe, but is interrupted, the pipe may not then be valid.
When we go down this path, it then is not really possible to determine what a given set of code will do timing wise.
I like the reset the COG deal personally. That, plus a jump table then puts the burden of sorting out the state issues on the programmer, and I think that's also part of the Propeller determinism definition. If we are doing stuff in software, then we do as much as we can with software, knowing the state of the chip is consistent.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
Safety Tip: Life is as good as YOU think it is!
Determinacy, as a useful concept in Propeller programming, means that one is able to control to within one clock cycle (in absolute or relative terms) when a given instruction will execute and to within a clock cycle or less when a pin or pins will change state. The Propeller's architecture includes multiple useful constructs for achieving this kind of determinacy. Among them are:
1. Conditional execution on an instruction-by-instruction basis. This eliminates the necessity for many conditional jumps, which, as you point out, can potentially affect loop timing.
2. The waitcnt instruction, which permits instruction timing granularity to within one clock (1/4 of most instruction times) and allows easy resynchronization when feature #1 cannot be used to advantage.
3. The waitvid instruction, which permits output timing granularity to within not only less than one processor clock but to a time base (PLL) completely separate from the processor clock.
4. The waitpeq and waitpne instructions, which permit timing relative to an external event to within one processor clock.
5. Predictable timing for hub accesses, which allows interprocess communication without disrupting loop timiing. (Any objection that hub access times are indeterminate holds only for the first encounter within an otherwise tightly-timed loop.)
These features don't just comprise a bag of handy but randomly assorted tools but arise from a coherent vision of what a deterministic, multiprocessor architecture should look like. By contrast, to suggest that interrupts simply be tacked onto the Propeller would render moot many of these features, since none could be depended upon to provide the fine-grained timing predictability it does now. This is not to say that interrupts have no place in microcontroller programming or that they add unnecessary complexity to other architectures, particularly those with single processors. On the contrary, they permit these other architectures to simulate a multiprocessor controller via asynchronous cycle-sharing. I will assert that interrupts would do more harm than good in the Propeller's case, though, since it was designed so cohesively to function well without them. Moreover (and I might be going out on a limb here), I would claim that any supposed requirement for interrupts in the Propeller could be addressed more simply by refactoring to achieve the desired behavior without them.
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 2/3/2009 6:26:53 AM GMT
Frankly, I was just interested in the preserve state element of the discussion. At this time, I'm working on nothing that would require an interrupt be in play.
The notion of state extends beyond registers, in the sense of an accumulator, index registers, etc...
Prop II will make more use of these, what I will call, implied registers. We don't address them, but their state is a factor in the program.
A while back I wrote that such a thing, like an interrupt, or funky HUB access schemes, bolted on now would be a kludge, and that scaling the kludge equals a mess. After sorting out this discussion, it is these state issues that do that! And that's why the interrupt discussion is messy. That mess trickles down to silicon, bugs, design cycle time and heat. All of these things are hard costs. On the other hand grey matter costs generally can be paid, then enjoyed repeatedly and shared! Just curious where that balance goes. The balance struck in the Prop is a very interesting one, from that perspective.
Be all of that as it may, I think the COG reset without reload deal would probably fit with how the Prop is currently engineered to function best.
Edit: There are multiple levels to work on with a Prop also. If one was doing LMM code, the COG kernel could provide the facilities, such as stack, interrupt, etc.. The cost is raw speed however. Just thought I would note that. At the next level of speed and instruction set capability, this LMM option is highly likely to be far more attractive than it is right now.
So then, we would have the supervisor COG model, requiring some re-factoring to make work where interrupts do now at times, and we would have the COG as CPU model as well.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
Safety Tip: Life is as good as YOU think it is!
Post Edited (potatohead) : 2/3/2009 4:04:08 PM GMT
Yes interupts in there normal use would be bad for determinism. Reset if enabled on peq would not.
-Phil
The ability to enable or disable the interupt is a must. another method would be to have one long set aside as the jump address. $FFFFFFFF is set to disable any value from 0 to 411 is enable
While I'm unconvinced that determionacy by that definition is actually achieved, nor that it is a particularly useful thing to achieve in any case, still it's a great help to have a definition for a word so frequently used.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
The pipeline, also, is not a program context, and in any case is surely thrown away on any branch in most machines -- perhaps only on a successful branch in some.· I'm a little curious, though only a little, to know under what circumstances the pipeline is flushed in the Prop.
Still, the Propeller, because it has no general-purpose registers and no (hardware) stacks, would be perhaps the easiest machine I've seen in which to handle an interrupt.· But given a choice I'd rather have index registers, at least, than anything else we've discussed -- and a call instruction that didn't modify storage, or at any rate didn't modify instructions in the stored program.· And the ability for a cog to execute instructions in hub storage.· And, and, and ...
I persist in my conclusion, too, that not having interrupts forces one to dedicate whole processors (cogs) to tasks that might (with interrupts) be handled (depending on what's being handled) by a thousandth of a processor.·
Idly I wonder, since this discussion is very general, why they're called cogs.· Every airplane I've flown, if it had a propeller, had one with blades.· Never flew one that had cogs, although I think there were some Ratier electric variable-pitch propellers in the 1940s that may have had cogs, or toothed gears,·somewhere in the pitch-change mechanism.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
Unfortunately the propeller is close enough to being all things to all men that it is getting pushed to the limits of what can be achieved.
I know (and see what you're saying) about the efficiency (and power, and speed) of interupts, but I see the propellor as more useful in the "scan"
or Step Sequence (finite state machine) modes.
As a scanning machine, the behavior is absolutely deterministic. Absolutely. Because it is built like PLC's (good ones) have been built for years,
it takes as long to process the logic every time it is swept, the IF_C/Z not C not Z structure allows the building of a completely deterministic block.
PLC's are not fast, 50-100 scans a second is generally fine, but they are solid on that "deterministic" idea, the prop can be too.
If speed is critical, then an alternative is to use it as a finite state machine (I still call them step sequencers), in which case response is as fast as
interrupt driven, and very "deterministic", it will do what it is told to do. BUT, it will only do what it is told to do.
At the moment the Prop seems to be doing a myriad of the "lines of code" type activities, with jumps and loops of an inderteminate nature. Once the
jumps and loops are in, it is inderterminate. That's why PLC's exist. There is nothing in real time control that the Propellor wouldn't be capable of,
but as a graphics, number crunching, high speed communicator of database machine we're really off it's original target playing field.
Chip clearly meant to build a machine with a very deterministic potential, but added all sorts of extra possibilities to allow it venture out of it's native
cave, and these get used, and there are considerations when doing so.