In this unit, you will learn how to add interrupt and exception support to your multicycle CPU design. For additional information, please refer section 5.6 and appendix A in the Hennessy and Patterson textbook. Note: you will only be implementing a subset of the exception and interrupt functionality of the MIPS architecture. Therefore, use this page as your definitive source of information regarding this unit.
Exceptions and Interrupts defined
Exceptions and interrupts are unexpected events that disrupt the normal flow of instruction execution. An exception is an unexpected event from within the processor. An interrupt is an unexpected event from outside the processor. You are to implement exception and interrupt handling in your multicycle CPU design.
When an exception or interrupt occurs, the hardware begins executing code that performs an action in response to the exception. This action may involve killing a process, outputting a error message, communicating with an external device, or horribly crashing the entire computer system by initiating a “Blue Screen of Death” and halting the CPU. The instructions responsible for this action reside in the operating system kernel, and the code that performs this action is called the interrupt handler code. You can think of handler code as an operating system subroutine. After the handler code is executed, it may be possible to continue execution after the instruction where the execution or interrupt occurred.
For your project, there are three events that will trigger an exception: arithmetic overflow, undefined instruction, and system call.
Arithmetic overflow occurs during the execution of an add, addi, or sub instruction. If the result of the computation is too large or too small to hold in the result register, the Overflow output of the ALU will become high during the execute state. This event triggers an exception.
Undefined instruction occurs when an unknown instruction is fetched. This exception is caused by an instruction in the IR that has an unknown opcode or an R-type instruction that has an unknown function code.
System call occurs when the processor executes a syscall instruction. Syscall instructions are used to implement operating system services (functions).
We also want to have to ability to service external interrupts. This is useful if a device external to the processor
needs attention. To do this, we’ll add 2 pins to the processor. The first pin, called IRQ (interrupt request), will be
an input that will allow an external device to interrupt the processor. Since we don’t want the processor to service any
external interrupts before it is finished executing the current instruction, we may have to make the external device
wait for several clock cycles. Because of this, we need a way to tell the external device that we’ve serviced its
interrupt. We’ll solve this problem by adding the second pin, called IACK (interrupt acknowledge), that will be an
output. The following waveform defines the timing for external interrupt requests.
What to do when an exception or interrupt occurs
When an exception or interrupt occurs, your processor may perform the following actions:
- move the current PC into another register, call the EPC
- record the reason for the exception in the Cause register
- automatically disable further interrupts or execptions from occuring, by left-shifting the Status register
- change control (jump) to a hardwired exception handler address
To return from a handler, your processor may perform the following actions:
- move the contents of the EPC register to the PC.
- re-enable interrupts and exceptions, by right-shifting the Status register
Dealing with multiple types of exceptions and interrupts
In a situation where multiple types of exceptions and interrupts can occur, there must be a mechanism in place where different handler code can be executed for different types of events. In general, there are two methods for handling this problem: polled interrupts and vectored interrupts.
- The processor can branch to a certain address that begins a sequence of instructions that check the cause of the exception and branch to handler code for the type of exception encountered. This is called polled exception handling.
- The processor can branch to a different address for each type of exception. Each exception address is separated by only one word. A jump instruction is placed at each of these addresses that forces the processor to jump to the handler code for each type of exception. This method is called vectored exception handling.
MIPS uses the first method (polled interrupts), so we’ll implement exception handling that way. So, in our case, all exceptions will cause the processor to jump to a “hardwired” instruction address. A sequence of instructions starting at this address will check the cause of the exception and act accordingly. We will set this address to 00000004 (in hex). Also, we’ll need to use the Cause register to record the cause of the exception or interrupt before jumping to the handler code.
The Cause register is a 32-bit register, but only certain fields on that register will be used. Bits 1 down to 0 will be set to describe the cause of the last interrupt/exception. The following table codes the interrupt/exception causes:
|01||IBUS||Instruction bus error (invalid instruction)|
Disabling interrupts and exceptions
We require a way to disable interrupts and exceptions. This is necessary to prevent exceptions and interrupts from
occuring during handler execution. In order to be able to do this, we need an additional register that can be used to
mask exception and interrupt types. This is called the Status register.
The status register is also a 32-bit register. It too, only has certain fields that are used by the processor. Bits 3 down to 0 will define masks for the three types of interrupts/exceptions. If an interrupt/exception occurs when its mask bit is current set to 0, then the interrupt/exception will be ignored. The mask bits are used according to the following table:
Control for exceptions
You will need to add control and datapaths to support exceptions and interrupts. When an exception or interrupt occurs, the following must be done:
EPC <= PC Cause <= (cause code for event) Status <= Status << 4 PC <= (handler address)
To return from an exception or datapath, the following must be done:
PC <= EPC Status <= Status >> 4
You will also have to add control to support four additional instructions, mfc0, mtc0, syscall, and rte.
Additional instructions needed
Several instructions must be added to your instruction set in order to use the interrupt/exception functionality of your processor. These instructions are mfc0 rt,rd and mtc0 rd,rt, which stand for “move from coprocessor 0” and “move from coprocessor 0”. The new registers that facilite interrupt and exception handling, Status, Cause, and EPC, can be accessed via these instructions. These new instructions transfer data between the exception registers and the general-purpose registers. Also, you will need the syscall instruction. These instructions are encoded in the following way:
Executes a system call. The system call number should be set in register $v0 prior to executing the system call.
Return from exception.
mfc0 rd, rt
Moves data from coprocessor 0 register rt to general purpose register rd.
mtc0 rd, rt
Moves data from general purpose register rt to coprocessor 0 register rd.
The following table defines coprocessor 0’s register set:
|Register name||Register number||Usage|
|Status||12||Interrupt mask and enable bits|
|EPC||14||Register containing the following address of the instruction where the exception occurred|