On Wednesday, 26 August 2015 05:53:18 UTC+1, rickman wrote:
> The register thread made me realize that one of the greatest
> accomplishments of the GA144 is not any of the typically quoted features
> of the inter-processor communications or the small CPU size. It is the
> fact that programming the processor is made so much simpler by not
> having *interrupts*. Interrupts make the design of any processor
> significantly more complex, not to mention the software.
I can imagine that interrupts do indeed make the hardware side
more complex. Regarding the software side, you might be interested
in the approach taken by Texas Instruments in the 1970s with their
990/x line of mini computers.
The 9900/x mini's had a CPU that was originally built from discrete
logic, like most of the minis back then (PDPs etc) on plug in boards.
Later on it was integrated into a single chip in the form of the
TMS9900 and decscendants.
The TMS9900 has a unique architecture: It has 16 general purpose
registers, but, uniquely, the registers do not reside on the chip.
The registers are in regular RAM, and can be anywhere. The CPU
only has three on-board registers: PC (program counter), ST (status
register) and WP (workspace pointer).
Using the LWPI instruction, (Load Workspace Pointer) you can have
as many sets of 16 registers as you have memory for. They can even
overlap if that's what you want to do. Certain instructions, for
example BLWP (branch and load workspace pointer) allow you to
specify an address to branch to, and critically, an address from
which the 16 registers will be taken from in RAM. Thusly,
subroutines can each have their own set of registers - meaning the
registers effectively become local variables.
Interrupts on the 9900 are programmed using vectors. Some locations
in memory are reserved for vectors. So, when a level 4 interrupt
(for example) comes in, the processor reads the level 4 vector.
In that vector are two pointers: The address of an interrupt
service routine, and the address of the registers for that ISR.
Thusly, interrupts are very fast indeed - no registers need to
be pushed to stacks in order to save their contents - the ISR
(every ISR) can have its own register workspace. Same for subroutines.
Even better, when an interrupt occurs, or a subroutine is called
using BLWP, three registers in the *new* workspace are loaded with:
Previous contents of program counter (for returning from ISR or SR)
Previous contents of status register
Previous address of register set
So, having serviced your interrupt, or finished your subroutine,
you can return, seamlessly, back to your main program. The entire
previous context of the machine is restored instantly. The contents
of the registers stay where they were: in RAM.
Using this technique, routines can call routines, that call routines
that call routines, each having their own register set, and if
an interrupt arrives while it's all happening, the programmer makes
precisely no effort at all. Just let it happen. It'll all unwind
itself.
It's a brilliant architecture (in practice, the implementation
used in the 9900 could be better, it was massively improved in
the TMS9995) that actually makes the silicon a lot simpler.
Move the registers off the chip into memory. You won't get
the fastest performance using that technique (you have to go
out on the address and data busses (obviously) to fetch your
registers), but you can get a nice simple design and programming
it is like falling off a log!
Mark