The RISC Concept
Both RISC and MIPS were developed from the realization that the vast majority of programs did not use the vast majority of a processor's instructions. In one calculation it was found that the entire Unix system, when compiled, used only 30% of the available instructions on the Motorola 68000. Much of the circuitry in the m68k, and similar designs, was dedicated to decoding these instructions which were never being used. The RISC idea was to include only those instructions that were really used, using those transistors to speed the system up instead.
To do this, RISC concentrated on adding many more registers, small bits of memory holding temporary values that can be accessed at zero cost. This contrasts with normal main memory, which might take several cycles to access. By providing more registers, and making sure the compilers actually used them, programs should run much faster. Additionally the speed of the processor would be more closely defined by its clock speed, because less of its time would be spent waiting for memory accesses. Transistor for transistor, a RISC design would outperform a conventional CPU, hopefully by a lot.
On the downside, the instructions being removed were generally performing several "sub-instructions". For instance, the ADD
instruction of a traditional design would generally come in several flavours, one that added the numbers in two registers and placed it in a third, another that added numbers found in main memory and put the result in a register, etc. The RISC designs, on the other hand, included only a single flavour of any particular instruction, the ADD
, for instance, would always use registers for all operands. This forced the programmer to write additional instructions to load the values from memory, if needed, making a RISC program "less dense".
In the era of expensive memory this was a real concern, notably because memory was also much slower than the CPU. Since a RISC design's ADD
would actually require four instructions (two loads, an add, and a save), the machine would have to do much more memory access to read the extra instructions, potentially slowing it down considerably. This was offset to some degree by the fact that the new designs used what was then a very large instruction word of 32-bits, allowing small constants to be folded directly into the instruction instead of having to be loaded separately. Additionally, the results of one operation are often used soon after by another, so by skipping the write to memory and storing the result in a register, the program did not end up much larger, and could in theory run much faster. For instance, a string of instructions carrying out a series of mathematical operations might require only a few loads from memory, while the majority of the numbers being used are either loaded in the instructions themselves, or intermediate values in the registers.
But to the casual observer, it was not clear whether or not the RISC concept would improve performance, or even make it worse. The only way to be sure was to actually simulate it, and in test after test, every simulation showed an enormous overall benefit in performance from this design.
Where the two projects, RISC and MIPS, differed was in the handling of the registers. MIPS simply added lots of them and left it to the compilers to make use of them. RISC, on the other hand, added circuitry to the CPU to "help" the compiler. RISC used the concept of register windows, in which the entire "register file" was broken down into blocks, allowing the compiler to "see" one block for global variables, and another for local variables.
The idea was to make one particularly common instruction, the procedure call, extremely easy to implement in the compilers. Almost all computer languages use a system known as an activation record or stack frame that contains the address of who called it, the data that was passed in, and any results that need to be returned. In the vast majority of cases these frames are small, typically with three or less inputs and one or no outputs. In the Berkeley design, then, the entire procedure stack would most likely fit entirely within the register window.
In this case the call into and return from a procedure is simple and extremely fast. A single instruction is called to set up a new block of registers, operands passed in on the "low end" of the new frame, and then the code jumps into the procedure. On return, the results are placed in the frame at the same end, and the code exits. The register windows are set up to overlap at the ends, meaning that the results from the call simply "appear" in the window of the code that called it, with no data having to be copied. Thus the common procedure call did not have to interact with main memory, greatly speeding it up.
On the downside, this approach meant that procedures with large numbers of local variables were problematic, and ones with less led to registers -an expensive resource- being wasted. It was Stanford's work on compilers that led them to ignore the register window concept, believing that a smart compiler could make better use of the registers than a fixed system in hardware.
Read more about this topic: Berkeley RISC
Famous quotes containing the word concept:
“The concept of a mental state is primarily the concept of a state of the person apt for bringing about a certain sort of behaviour.”
—David Malet Armstrong (b. 1926)