Memory mapped I/O
In order to study exceptions and interrupts we will use the Mips 32 simulator
Mars. All instructions will be written for and tested using Mars but you
should be able to use the Spim simulator if you prefer.
Mips system architecture
A Mips processor consists of an integer processing unit (the CPU) and a
collection of coprocessors that perform ancillary tasks or operate on other
types of data such as floating-point numbers.
Both Mars and Spim
simulates two coprocessors:
- Coprocessor 0 handles exceptions and interrupts.
- Coprocessor 1 is the floating-point unit.
Integer arithmetic and logical operations are executed directly by the CPU.
Floating point operations are executed by Coprocessor 1. Coprocessor 0 are used
do manage exceptions and interrupts.
Receiver and transmitter
Mars simulates one I/O device: a memory-mapped console on which a
program can read and write characters. The terminal device consists of two
independent units: a receiver and a transmitter.
- The receiver reads characters typed on the keyboard.
- The transmitter display characters on the console.
The receiver and transmitter are completely independent. This means, for example, that
characters typed at the keyboard are not automatically echoed on the display.
Instead, a program must explicit echo a character by reading it from the receiver and
writing it to the transmitter.
To execute a Mips program memory must be allocated. The Mips computer can
address 4 Gbyte of memory, from address
0x0000 0000 to
0xffff ffff. User memory
is limited to locations below
0x7fff ffff. In the below figure the layout of the
memory allocated to a Mips program is shown.
The purpose of the various memory segments:
- The user level code is stored in the text segment.
- Static data (data know at compile time) use by the user program is stored
in the data segment.
- Dynamic data (data allocated during runtime) by the user program is stored
in the heap.
- The stack is used by the user program to store temporary data during for
example subroutine calls.
- Kernel level code (exception and interrupt handlers) are stored in the
kernel text segment.
- Static data used by the kernel is stored in the kernel data segment.
- Memory mapped registers for IO devices are stored in the memory mapped IO
Memory-mapped terminal device
A program controls the terminal with four memory-mapped device registers.
Memory-mapped means that each register appears as a special memory location. In
this sense, these are not real registers but simply words (32 bit) values stored
The Receiver Control register is at memory location
0xffff0000. Only two of its
bits are actually used.
Bit 0 is called ready:
- If it is1, it means that a character has arrived from the keyboard but has not
yet been read from the Receiver Data register.
- The ready bit is read-only: writes to it are ignored.
- The ready bit changes from 0 to 1 when a character is typed at the key- board,
and it changes from 1 to 0 when the character is read from the Receiver Data
Bit 1 is the keyboard interrupt enable bit:
- This bit may be both read and written by a program.
- The interrupt enable is initially 0.
- If it is set to 1 by a program, the terminal requests an interrupt at hardware
level 1 whenever a character is typed and the ready bit becomes 1. However,
for the interrupt to affect the processor, interrupts must also be enabled in
the Status register.
- All other bits of the Receiver Control register are unused.
The second terminal device register is the Receiver Data register at memory
- The low-order 8 bits of this register contain the last character typed at the
keyboard. All other bits contain 0s.
- This register is read-only and changes only when a new character is typed at
- Reading the Receiver Data register resets the ready bit in the Receiver
Control register to 0.
- The value in this register is undefined if the Receiver Control register is 0.
The third terminal device register is the Transmitter Control register at memory
0xffff0008. Only the low-order 2 bits of this register are used. They
behave much like the corresponding bits of the Receiver Control register.
Bit 0 is called ready:
- This bit is read-only.
- If this bit is 1, the transmitter is ready to accept a new character for output.
- If it is 0, the transmitter is still busy writing the previous character.
Bit 1 is the interrupt enable bit:
- This bit is readable and writable.
- If this bit is set to 1, then the terminal requests an interrupt at hardware
level 0 whenever the transmitter is ready for a new character and the ready
bit becomes 1.
The final device register is the Transmitter Data register at memory address
Only the least 8 significant bits (the least significant byte) are used:
- When a value is written into this location, its low-order 8 bits (i.e., an
ASCII character) are sent to the console.
- When the Transmitter Data register is written, the ready bit in the
Transmitter Control register is reset to 0. This bit stays 0 until enough time
has elapsed to transmit the character to the terminal; then the ready bit
becomes 1 again.
- The Transmitter Data register should only be written when the ready bit of the
Transmitter Control register is 1. If the transmitter is not ready, writes to
the Transmitter Data register are ignored (the write appears to succeed but
the character is not output).
In a physical computer sending a character to the terminal doesn’t happen
instantly, the operation takes some time to complete.
The simulators Mars and SPIM measures time by counting the number executed instructions
, not in real clock time. After writing a character to the receiver data register, this means that the transmitter does not
become ready again until the processor executes a fixed number of instructions.
If you stop the simulation and look at the ready bit, it will not change. However,
if you let the simulation continue, the bit eventually changes back to 1.
Assemblers, Linkers, and the SPIM Simulator