PB-127 Firmware Development Systems A Survey Nov80
PB-127 Firmware Development Systems A Survey Nov80
PB-127 Firmware Development Systems A Survey Nov80
A Survey
by
Peter Kornerup
DAIMI PB-127
November 1980
Peter Kornerup
Abstract:
The firmware development was for a long time intimately connected with the
design of the processor, as was the debugging of the microprograms with the
debugging of the processor hardware. With diode matrices, or most other
discrete read-only memory technology for storing the microprogram, it does not
seem reasonable to debug the host processor by special microprograms, before
the microprogram realizing the target architecture is "loaded", in particular since
the latter anyway was going to be the only "program" ever to run on the host.
The most essential tool for firmware development is some sort of translator,
assembler or compiler, which to a varying degree can relieve the programmer of
the burden of the detailed task of expressing the program in terms of field
encodings of the primitive operations. Besides introducing symbolic opcodes
and labelling, microassemblers most often furthermore are used to "hide away"
certain peculiarities of the underlying architecture. E.g. assemblers were often
used to handle the ackward addressing and instruction allocation caused by the
2
The protection and integrity of ordinary user programs are secured through the
system, which also provides an ·environment of facilities to call upon. This
environment has been created through interpretation on top of the hardware,
which allows the system to monitor and supervise the user program. In
contrast, the microprogram has to execute in an environment which provides
little or no protection, where in general the available support is very limited, and
communication with the "user" (i.e. the firmware-programmer) is either
restricted to lights and switches or may be severely hampered by the layers of
system above the firmware (unless of course specific tools are available, e.g. a
firmware debugger). Also I/O in general may be complicated, either because it
has to be handled at a very low level, or because it has to go through the
ordinary system I/O routines (i.e. calls have to "go upwards").
With the advent of bit-slice technology, history has repeated itself. This
technology may be used to architecture "ordinary" microprogrammable
processors, i.e. intended to realize a .target architecture through interpretation.
However, microprogrammed bit-sliced control units may be used directly in
various controllers, requiring complicated sequencing. For such purposes the
"firmware level" becomes "the applications level", and the firmware host will in
general be designed more or less from scratch for each application. This is
almost the same situation as the one faced in the desing of the early
microprogrammed processors, except for the fact that the "building blocks" of
3
the hardware design today are LSI circuits, whose level of functionality assures
more homogeneity across designs.
In either of these situations, the firmware of such control units will most often
be fixed in ROM storage. Design, development, testing and verification of the
firmware will have to take place in some way or other external to the final
system, where the firmware is going to reside. Since the firmware host
architecture changes from one application to the next, support systems will
have to be parameterizable to amortize their cost, and reduce the time needed
to create support for the individual design situation.
In the rest of this paper we will discuss firmware development and test systems,
based on actual systems. First we will treat user-microprogram mabie systems,
where apparently most progress has been made. One particular sytem, the
RIKKE-MATHILDA system at Aarhus will be described to some depth, as it has
not been reported on before. A sample of other development systems will then
be surveyed, to illustrate complementary facilities.
and MATHILDA may hence view WS as 128K-16 bit or 32K-64 bit respectively,
and may communicate through WS, as well as through direct 16 bit
connections (with busy/done flags). The disk-system is also connected to one
of the WS ports, acting as a data-channel, but transfers can only be initiated
from RIKKE.
The hardware has evolved over a long period, starting with the construction of
RIKKE in 1972-73, as a prototype of the MATHILDA design. With some design
changes MATHILDA was constructed and became available early 76, together
with WS. Later the disk system and the block-transfer capability on WS has
been added, just as a number of minor updates on RIKKE and additions to
MATHILDA have been made.
5
It was at an early stage decided to use the language BCPL [16] as the vehicle
for systems programming on RIKKE, and a firmware interpreter for a-code (an
intermediate language for BCPL) was implemented on RIKKE late 1973 [24].
Supported by the I/O Nucleus [12]. the RIKKE as was developed (based on
the Oxford as [21]) into a versatile single user operating system with a
sophisticated file system. A variety of other firmware interpreters have been
developed for experimental purposes, including lately a "twin-interpreter"
supporting pure concurrency in Concurrent Pascal, running on the combination
RIKKE-MATHILDA-WS. A Pascal-supporting interpreter on RIKKE, utilizing
MATH I LOA as a functional unit for non-standard arithmetic [11], is about to be
completed. Experiments with migration of operating system functions have
been performed in connection with the disk-drivers [23], with primitives for a
relational database system [2], and a string search operator in the editor.
Except for some very first hardware test programs, a" firmware for RIKKE and
MATHILDA has been developed using the microassembler MARIA (existing in
two versions) and in most cases debugged on the (batch) simulators for RIKKE
and MATHILDA. Assemblers and simulators are implemented in BCPL,
originally in 1973 on a CDC 6400, but later transferred to the departmental
DEC10 System [22], as we" as to a number of other installations to be used as a
teaching and research tool in other departments.
The MARIA microassembler provides the same sort of facilities that are usually
found in ordinary assemblers,but does not contain macrofacilities. Datapath
transfer is specified as an assignment with a possible shift specification. The
list of mops is free format, and their ordering is immaterial. Since some mops
may be represented in anyone of two or three fields, the assembler also has the
task of "shuffling" around with such mops to make the whole list fit. Mops
which specify load-actions with a source selection are specified as assignments,
which are then represented as a combination of the load action and a setting of
the proper source selection bits of the instruction. Also if the source is
specified as the current microinstruction, i.e. as a literal, that constant is
assembled into the proper field (and that field is marked as non-executable).
The third part of the microinstruction specifies the sequencing part in the form
of an if-then-else construction, with suitable defaults if not "a" the power" is
needed. The hardware provides the conditional selection among two
address-computations (rather than addresses), whose binary specification is
quite tricky and sometimes interrelated. A task of the assembler is to cover up
such details, and, as in general, to detect resource conflicts.
The simulators perform faithful simulations of the processors, but only crude
simulations of I/O, since they do not attempt to simulate timings of the devices.
The simulators operate in "batch mode", and devices are simulated by files.
The RIKKE simulator only provides simulation of some of the early physi.cal
devices, as most user microprograms utilize the I/O nucleus. As the only
"device" with which MATHILDA can communicate is RIKKE, corresponding
files are provided, however there is no possibility to run the simulators of RIKKE
and MATHILDA in parallel. The simulators provide a tracing of the user
microprogram program counter as the default. All other output from simulators
has to be specified in the source program to the assembler by means of
"display" pseudo-instructions. The range of a display statement is the (static)
interval from its occurrence in the source, until the next one is encountered.
The display pseudo-instruction does not immediately specify what is to be
dumped on output, it only references a "table" pseudo-instruction. In this way
it is fairly easy to insert and delete the display statements in appropriate places.
The table definitions, containing the details 'of which resources are to be
dumped, then have to appear only once, and can be collected in one place.
An interactive simulator for the MATH I LDA processor has been implemented
(,>n a Multics system but has so far not been transported to Aarhus, as the
implementation heavily relies on the Multics file system (segments).
The philosophy of the RIM system is to let the firmware programmer construct
in BCPL (the system language) the environment in which the firmware is to
exist. A few standard routines available allows the user on RIKKE to load and
execute microcode in RIKKE, as well as in MATHILDA, and to communicate
with the microcode.
The primitives for the control of microcode in "RIKKE are provided by the
following three BCPL functions:
SetupRikkeCS
LoadRikkeCS
CaliRikkeCS
the first of which just initializes a table, used by the control store allocation
(recall that it is a single-user system). LoadRikkeCS takes a filename as
parameter (assumed to be a file containing assembled microcode) and performs
the specified resource initializations and loading of microcode into control store.
It returns (as the value of the function) entrypoint information if the call was
successful, otherwise an error condition.
When microcode has been successfully loaded into RIKKE control store, it can
be repeatedly invoked by calls of the form:
function call to the BCPL level. Of course, nothing prevents the microcode
from accessing other parts of the communications vector, nor to interpret it in
any way it wants, e.g. to use its contents as pointers to other data. The
transfer to and from registers is just provided to facilitate the implementation of
firmware routines with a minimal need for parameter transfer.
If the firmware called upon is an interpreter for another virtual machine, its
address space may be disjoint from that of the BCPL program. The interpreter
and the BCPL program may communicate as coroutines, since the interpreter
may call back and request a service from the BCPL level system, in the
following way. The interpreter returns to the BCPL level with a "result"
(contents of OS), which specifies what service is wanted (and possibly
parameters in the communications vector) and after the BCPL level has
performed the requested action, it calls upon the interpreter again (possibly
returning results of the action in the communication area).
The routines provided for loading and calling upon firmware in MATHILDA are
basically equivalent, except for the differences caused by the asynchronous
operation of the caller and callee:
SetupMatCS
LoadMatCS
CaliMatCS
Matldle
InMat64
The setup and ·Ioading is completely equivalent to the RIKKE routines, but
CaliMatCS differs in that it only invokes MATHILDA (assumed idle) and then
immediately returns to the BCPL system (i.e. it does not wait for a result),
allowing RIKKE to continue operation. The communications area consists of 64
bit words, i.e. they have to be handled by the BCPL system as four 16 bit
words. The Matldle function allows testing MATHILDA for completion, in
which case InMat64 can read the contents of OS, and the communications area
may be interpreted safely by the BCPL system. Notice that since operation of
RIKKE and MATHILDA is asynchronous, any communication through the
9
In tre Utah system the LOADER simulates the effect of a compiler, and creates
such a codefile. It is possible to specify to the LOADER initializations of
scratch pad registers, and the static data-area of the microprogram, together
with file specifications. Notice that such initializations may differ from one
invocation of some microcode, to another invocation of the same (shared)
code. However if all invocations require some common scratchpad
initializations, all codefiles must contain the proper data.
The only firmware debugging tool which seems to be available at Utah is the
tracing facility, which is a physical machine equivalent of the facilities found in
non-interactive (batch-type) simulators. .
One of the very early microprogrammable processors which was designed for
and was marketed as a user microprogrammable system, is the Standard
Computer Corporation MLP900, the basic component of the PRIM system [8] at
the USC, Information Sciences Institute in Los Angeles. The MLP900 is
running under the control of the PRIM system on a DEC10, and is accessible on
the ARPA network.
users running under PRIM, as well as other processes running under the TENEX
system on the DEC10.
The TENEX system is based on a virtual memory system, and the MLP900 has
been modified to contain an equivalent memory address translator, allowing a
PRIM process in the DEC10 and its subordinate emulator in the MLP900 to
share the same virtual memory. Also the MLP900 has been modified to be able
to run in a priviledged state at the firmware level. A small resident firmware
operating system in the MLP900 (the microvisor) is responsible for switching
among emulators and handles service requests from emulators, as well as page
faults, to be served by the MLP driver and TENEX on the DEC10.
As seen from the user, the PRIM system acts as the interface to firmware under
development, as well as to the emulator user. In its exec-state, the PRIM
system allows the user to define the environment of an emulator (Le. its target
machine), e.g. to associate target machine devices with DEC10 physical devices
or files, to save target environments for later use, or to restore such
environments.
From the exec-state the user can enter the debug-state, which can operate as a
target-independent system for debugging the emulator, as well as the target
machine defined by the emulator. A particular feature is the possibility to
associate with breakpoints "break-time programs" who are invoked at the
breakpoint, thus allowing tracing and monitoring automatically.
In the third state, the execute-state, control is in the emulator. The user
terminal can only interact through "intervention characters" (e.g. a defined
break), unless the terminal has been "mounted" as a device on the target
machine. The TTY can act as one target input device only, but possibly as
several output devices.
Emulators are created outside the PRIM system, as well as target code may be
compiled in the standard TENEX environment. In the exec-state the
environment is defined, possibly including appropriate symbol tables for the
debugger, in the form of tables to be used by the PRIM system. In particular
tables describing completed emulators, make new target systems available as
tools to be used by other users.
Both the B1700/1800 and the PRIM systems have been organized to support
the development of emulators, and to facilitate the inclusion of new target
machines in the environment of the common user. In contrast other
development systems have been reported where the systems are organized as
12
Another and more flexible approach has been reported in [9]. A CAL Data 135
is used as the host of an .emulated PDP11/45, which supports the C-Ianguage
and the UNIX operating system [18]. A few unassigned opcodes have been
used to add the primitives necessary to load and call upon user developed
firmware, and these primitives have been made available in C also. The system
distinguishes between static (resident) and dynamic (overlaid) firmware, where
user created microcode falls in the second category, and is referenced through
the file system.' The system works much the same way as the RIKKE system
does, and seems well suited to the migration of primitives into firmware. It has
been used to improve the efficiency of C and UNIX by microcoding the
function-enter and -exit operations. However it is not apparent that the system
can be used to (and is intended to) support complete emulators and their target
machines.
The paper also contains a discussion of the objectives, and the tools which
should be available in such a system. The author seems particularly concerned
that it should be possible to "authorize" firmware through a validation routine,
before it can be included and called upon. However it does not seem very likely
that this process can be automated in the foreseable future, as the present state
of affairs for "ordinary" systems programs (e.g. operating systems) may
indicate. The work on verification of firmware may take us part of the way, but
assuring that a microprogram is realizing the functionality it is supposed to is
one thing, but to prove that it is harmless to its environment is quite different.
Any proof or verification of a program is based upon some formal specification
of the (virtual) machine on which it is supposed to run, and if the program is
"correct" it is (of course) only accessing resources of the specified machine.
But since the specified machine may not be-completely equivalent to the actual,
and resources in general will be shared, interference from a harmful program (or
user) may still occur, unless the whole system can be proven correct [16].
Some interesting work on verification of firmware, based on host and target
machine descriptions in a hardware decription language ISPS, has been
reported in [3].
13
In this section we will restrict the discussion to the development of firmware for
systems whose underlying hardware architecture changes from one system to
the next, i.e. where the control unit is designed to fit a particular application. It
might be a control unit of a bit-sliced processor, or that of a more general
controller, where the firmware is to reside in ROM storage.
By nature, some sort of cross support is needed when developing firmware for
ROM based control. As demonstrated in the previous sections, cross support
for firmware development may be very advantageous. During development,
the read-only control store can be substituted by an equivalent writeable
storage, which can be loaded from the supporting system. With suitable
monitoring of the control unit under debugging, and possibly by some
simulation of the environment of the unit, the development system can be
utilized for debugging and testing of the firmware before it is being" cast" into
its final ROM storage. Such systems have been commercially available for use
with standard microprocessors, to develop software which is to end up in ROM
storage for a particular fixed application.
The obvious problem with such "on-line" tools is the limited amount of
knowledge the development system has on the system under construction.
The minimal knowledge required, in a system as discussed above, is
information on the structure of the control store, i.e. its width and length.
During debugging, any reference to the (simulated) control store has to be
checked against the set of defined breakpoints, to check for the break
condition. If this is performed in software obviously this may cause problems in
time-critical applications, but could possibly be avoided using a set of hardware
comparators (e.g. a small associative memory).
In order that the debugging system can inform the user on the state of the
system, suitable probes may be connected to provide a feed-back of
information. However such a solution does not seem more flexible than adding
display-panels to the system under debugging. There will probably be major
parts of the state vector of the system which will be inaccessible for
interrogation, unless special-purpose display firmware is developed, loaded into
control store, and called upon during debugging. And it does not seem very
likely that such display firmware routines can be constructed automatically,
even if the development system has a very detailed knowledge on the system
under testing. The same problem arises with respect to interactive corrections
of the state vector during debugging.
The most advanced development and test. systems have so far been pure
"off-line" systems, based on simulation of the system under design, and
implemented on medium to large scale computer systems. In [15) a
microassembler and simulator generator system has been described. It does
not use a hardware description language (HDL), but an ordinary programming
language Simula, which is used to build descriptions of the hardware
components, which in turn are used in a description of a system. Simula is a
discrete event simulation language, and as such well suited for a proper
15
simulation of the system under design. The simulation could possibly even
include the environment, with proper timing. With a library of component
descriptions, the individual architecture design may be simulated, and can be
checked out before physical construction.
5. Conclusions
The most serious problem with improving the tools for user microprogrammable
systems is to handle the problems of horizontal instructions and parallelism in
compilation and verification of firmware. Another problem is in the protection
of innocent users and systems against malevolent firmware (or programmers),
where the hosts usually provide little or no facilities for protection or
virtualization.
References
[16] G.J. Popek, D.A. Farber: "A Model for Verification of Data Security
in Operating Systems".
CACM vol. 21, no. 9 (1978).