Unit 4a: Exception and Interrupt handling in the MIPS architecture

Introduction

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.

Exceptions: Types

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).

Interrupts

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.


Figure 1: Timing diagram for external interrupts

What to do when an exception or interrupt occurs

When an exception or interrupt occurs, your processor may perform the following actions:

To return from a handler, your processor may perform the following actions:

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.

  1. 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.
  2. 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.

Cause register

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:

Number

Name

Description

00

INT

External Interrupt

01

IBUS

Instruction bus error (invalid instruction)

10

OVF

Arithmetic overflow

11

SYSCALL

System call

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.

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:

Bit

Interrupt/exception

3

INT

2

IBUS

1

OVF

0

SYSCALL

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.


Figure 2: Example top-level block diagram with exception handling hardware added. Note: this design doesn't include the Status register and doesn't use the Cause register the same way we are.

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:

syscall

Executes a system call. The system call number should be set in register $v0 prior to executing the system call.

31-26

25-6

5-0

000000

00000000000000000000

001100

rfe

Return from exception.

31-26

25

24-6

5-0

010000

1

0000000000000000000

010000

mfc0 rd, rt

Moves data from coprocessor 0 register rt to general purpose register rd.

31-26

25-21

20-16

15-11

10-0

010000

00000

rt

rd

00000000000

mtc0 rd, rt

Moves data from general purpose register rt to coprocessor 0 register rd.

31-26

25-21

20-16

15-11

10-0

010000

00100

rt

rd

00000000000

The following table defines coprocessor 0's register set:

Register name

Register number

Usage

Status

12

Interrupt mask and enable bits

Cause

13

Exception type

EPC

14

Register containing the following address of the instruction where the exception occurred