The What and Why of zEnterprise Millicode
Most people in the mainframe community have heard the term millicode, but what is it? The short answer is it’s a form of microcode—one of the greatest ideas in computer engineering. Millicode embodies a very clever refinement of the basic idea.
First, let’s start by defining microcode, which is a layer of hardware-level instructions involved in the implementation of higher-level machine code instructions. This means microcode is a set of instructions in a simple architecture used to implement the instructions of a more complex architecture.
Microcode was originally a simpler method of developing the control logic for a computer. Complex logic can be implemented with a sequence of simpler microcode instructions. Because it’s essentially a program, logic errors can be fixed with a reload without making any actual hardware changes. Microcode patches can be used to work around errors in the hardware during development or even in the field.
An important part of the mainframe’s history, microcode enables machines with differing internal designs and built on different hardware technologies to present a single architecture to software. Its introduction was a major contributor to the success of the IBM mainframe architecture in becoming the de facto standard for large-scale computers. Microcode made it all possible.
A Very Brief History of Microcode
IBM used microcode to create a full line of IBM System/360 processors in the mid-1960s, covering wide ranges of price and performance. They were built on different circuit technologies yet able to run the same programs. Prior to S/360, each computer was basically a one-off with its own unique instruction set. Programs written to run on one computer would not run on the next version. As a result, programs needed to be constantly rewritten, or at least recompiled, to run on the newer, faster machines. It’s hard to make progress in that sort of environment. On the other hand, it’s been said that the IBM mainframe platform has amassed more than $3 billion worth of software over the decades, all of which is able to run on the latest IBM zEnterprise* System server.
Microcode can be used to enable an inexpensive low-end machine to look at software just like an expensive high-end computer. An example of this from the S/360 era was the Model 30. Physically, the Model 30 was an 8-bit machine with 8-bit registers and 8-bit data paths. The architected general-purpose registers were not hardware registers at all, but actually resided in core memory. Yet, by using microcode in a read-only store (ROS), the Model 30 presented the full basic S/360 architecture—in which the registers and operations are defined—as if it were a 32-bit machine.
Programs developed on a Model 30 would run on an S/360 Model 75, which was a high-performance machine with nearly everything implemented in hardware. Customers could buy the next model up and not have to make changes to their software. Other machines in the S/360 line implemented the simpler, more performance-sensitive S/360 instructions in hardware and the more complex, less performance-sensitive instructions in microcode. In a sense, these machines were actually two machines—the native S/360 processor and the microcode processor—cooperating to present the complete S/360 architecture to software.
Obviously, this was a brilliant idea, and it’s had a profound effect on computer design since its conception in 1953 by M.V. Wilkes.
The Advantages of Millicode
From the days of the S/360 until the mid-1990s, most computers were designed as a symbiosis between a native processor and microcode processor. A good example of this design is one of the early complementary metal-oxide semiconductor (CMOS) processors called the IBM System/390* 9672 G3. It used a type of microcode very similar to familiar machine language instructions, but the microcode architecture was much simpler than the target S/390* architecture. Most of the frequently used simple instructions were implemented directly in hardware. The more complex functions were implemented in microcode that ran on a distinct microcode processor, which acted somewhat like a coprocessor. The microcode programs were executed from special memory.
Because more microcode existed than could fit into the special microcode memory, the microcode for some instructions had to be paged in from regular memory before execution. This was a reasonable design but not for very high performance.
The next IBM mainframe processor, the IBM S/390 9672 G4, was quite different. It had a lot of microcode but no distinct microcode processor. It ran the microcode on the native processor and eliminated the need to design and build a separate microcode processor. The microcode language was a subset of the S/390 architecture—of course with some additions—so the microcode of this processor, being of a higher level than typical microcode, was dubbed millicode.
Besides the elimination of the separate microcode processor, there’s another great advantage to running millicode on the native processor. A large amount of time and money go into the design and fabrication of the native engine to achieve maximum performance. The System z* processor of the latest zEnterprise System, the z196, is a high-frequency, superscalar, out-of-order instruction processor with four levels of processor cache. The complexity of the z196 is nearly beyond comprehension. Since the millicode is executed just like normal z/Architecture* code, it benefits from this performance optimization. By contrast, microcode processors of the past were always much simpler and slower than the native processor they worked with. Therefore, they were getting comparatively slower with each processor generation.
Of course, for the millicode to do its job while running on the native processor, some additional hardware has to be added to that processor. It must have an additional execution mode, called millimode, to execute it. This requires distinct registers (general purpose, access and control registers), an instruction address register, and other special registers. There must be additional instructions available only in millimode, for example, to move values between the architected and millicode registers, and to control hardware capabilities not available through the architected instruction set. When millicode is entered to execute an instruction, the hardware also does some initialization processing, like simple validity checking and setting up millicode registers.
comments powered by