Simulated Toy Machine
Architecture for projects for Computer Systems Organization II, section 3.
The Simulated Toy Machine (STM) is a simulation of an extremely simple
machine architecture. We will assign projects that involve
involve extending the operating system for this toy machine.
Warning:
There are some misleading aspects to this toy machine,
as compared to real machines.
Unlike any conceivable real operating system, the "operating system"
for STM is not resident in the simulated machine; rather, it
is part of the simulator. This is why, for instance, the STM
does not need interrupts; in effect, control reverts to the "operating
system" after every instruction.
Another unrealistic aspect of the STM is
that it makes no attempt to model blocking a process for I/O.
It is critical to keep such differences
in mind when you try to relate your experiences with STM
to real operating systems.
Basic Architecture
The basic architecture of the STM contains
- 1 Meg of RAM, organized as an 18 bit address space with 4 byte words.
- 16 user addressible registers. R0 is the program counter.
- A base and limit register, to support address translations with
variable length partitions. User processes can neither read nor write
the base and limit registers.
That's it.
Machine language --- STML
Strictly speaking, there's no need for you to care about
the detail structure of STML. We will provide the code to execute STML
instructions.
Each instruction in STML is a 32-bit word, organized as follows: (bits
are numbered from low-order to high-order; thus bit 0 is the lowest order
bit.)
- Bits 0-3: Op code.
- Bits 4-7: First register argument
- Bits 8-25: Depending on the op code, either an address or a sequence
of additional register arguments, in 4 bit chunks from low-order to high-order.
- Bits 26-31: Unused.
The op codes are as follows:
Op code | Abbreviation | Args | Meaning
|
0 | LOA | RA, AD | Load the value at AD into RA
|
1 | STO | RA, AD | Store the value at RA into AD
|
2 | CPR | RA, RB | Copy RB into RA
|
3 | LOI | RA, RB | RB holds the address of AD. Load the
value of AD into RA.
|
4 | STI | RA, RB | RA holds the address of AD. Store the
value in RB into AD.
|
5 | ADD | RA, RB, RC | RC = RA + RB
|
6 | SUB | RA, RB, RC | RC = RA - RB
|
7 | MUL | RA, RB, RC | RC = RA * RB
|
8 | DIV | RA, RB, RC, RD | RC = RA / RB; RD = RA % RB.
|
9 | ICR | RA | RA++
|
10 | DCR | RA | RA--
|
11 | GTR | RA, RB, RC | RC = (RA > RB)
|
12 | JMP | RA, AD | Jump to AD. (RA is unused).
|
13 | IFZ | RA, AD | If (RA == 0) then goto AD.
|
14 | JMI | RA | RA holds the address of AD. Jump to AD.
|
15 | TRP | | Trap to the kernel.
|
Note: The arithmetic operations are all integer. An instruction that has
two or more identical register arguments may have unexpected results.
Thus, for example, the hexadecimal value 0x11B0 consists of the opcode
0, the register value 0xB == 11, and the address 0x11 = 17, so
it indicates the instruction to load address 17 to register R11.
System calls
A user process executes a system call by executing an instruction of
the form "TRP". The value of register R15 indicates the nature of the system
call, as follows:
- R15 == 0. Terminate. The process halts.
-
R15 == 1. Input. Read an integer from standard input.
The value of the integer read is
returned to the process in register R14. R13 is returned as 1 if an integer
has been read and 0 if the end-of-file is reached. Any non-integer value
in standard input causes an error.
- R15 == 2. Output. Print on a new line to standard output in decimal
the value of the integer held in register R14.
- Project 2 will involve defining other trap codes, for forking
and for manipulating semaphores.
STML source files
A code file in STML has the following form:
- Line 1: Name of the process.
- Line 2: Size of the memory needed (including code, data, and variable
space.)
- Lines 3 onward: 1 instruction or data item per line, expressed as
an integer starting at the beginning of the line. Any line that does
not start with a digit is ignored.
Anything following the first integer on the line is ignored, and
may be used for comments.
You may assume that the STML file is correctly formatted.
Basic STM interpreter
A basic STM interpreter for a single process is available in
stm.c
The program is executed with the following command line:
stm* [-b BASE] [-d DEBUGGING-LEVEL] [-m MAX] sml-file
where
- The optional argument "-b BASE" may be used with an integer value
for BASE to indicate where in memory the process partition should start.
Default value = 0.
- The optional argument "-d DEBUG" sets the level of debugging output:
Default value = 0.
- If DEBUG == 0, then the only output is that required by the STML code.
- If DEBUG == 1, then each time a TRP instruction is executed, the
program prints out the name of the process, the address of the instruction,
and the value of the R15 register.
- If DEBUG == 2, then each time any other instruction is executed,
the program prints out the name of the process, the address, op-code,
and arguments of the instruction.
- The optional argument "-m MAX" ensures that
your STM interpreter executes at most MAX number of instructions.
This may be useful for debugging.
- "sml-file" is the file containing the sml code.
The "-b", "-d", and "-m" flags may be given in any order; the file name
must be the last argument on the line.
The execution of the STM follows the standard "fetch-execute" cycle:
- 1. The instruction at the address contained in the PC is retrieved.
(The PC holds the relative address.)
- 2. The PC is incremented.
- 3. The instruction is executed.
Execution continues until either the process intentionally terminates,
or aborts due to an error, or reaches the specified maximum number of
instructions.
Address translation: The addresses in STML are all relative
addresses. The base register holds the starting address of the process,
and the physical address is equal to the relative address plus the
base register. The limit register holds the size of the partition.
Any relative address that is less than 0 or greater than or equal to
the value of the limit register causes an error.
Errors: Any runtime error causes termination of the process.
The following list includes all possible runtime errors:
- Arithmetic errors: Overflow and divide by 0.
- Address errors: Relative address is not within bounds.
- PC increment error: Incrementing the PC causes its value to
fall outside the partition.
- Reading error: A non-integer is encountered in reading the input; or
an attempt to read past end-of-file.
All these errors except overflow are caught by the STM interpreter,
which exits smoothly. I am doubtful that there is any easy way to catch
overflow errors that will work on all systems. Therefore, these
are not intercepted, and will cause the STM interpreter to abort.