Hades logoHades applet banner
TinyMips interrupts demo

applet icon

The image above shows a thumbnail of the interactive Java applet embedded into this page. Unfortunately, your browser is not Java-aware or Java is disabled in the browser preferences. To start the applet, please enable Java and reload this page. (You might have to restart the browser.)

Circuit Description

UNDER CONSTRUCTION This applet demonstrates the concepts of interrupt handling on the MIPS (R3000) series. The hardware structure used for this applet consists of the processor, some glue logic, and a single RAM component that stores both the program and the data generated during program execution. A few switches allow you to interactively generate interrupts via the five interrupt-input pins INT0..INT4 provided by the processor. The counter-compare interrupt (INT5) is demonstrated in the next applet.

Exceptions and Interrupts on the MIPS architecture

Basic interrupt service routine

By software convention, registers k0 and k1 (r26 and r27) are reserved for kernel and supervisor software. Whenever the hardware detects an external interXXXXX the corresponding bits are set in the CAUSE register of the system coprocessor (coprocessor 0). Unlike several other microprocessors, the MIPS architecture does not include the so-called vectored interrupts, Instead, the interrupt handler routine will usually check the ExcCode bit field in the CAUSE register and then dispatch to the corresponding subroutine. Due to a clever organization of the ExcCode bit field, this requires only very few machine instructions. Assuming that the memory locations pointed to by interrupt_table are initialized with the start addresses of the interrupt handler routines for the different software and hardware interrupts, the following code is sufficient to decode the exception cause and jump to the corresponding subroutine. Here, we assume that registers t1 and t2 are available for the exception handler:

  mfc0  t1, C0_CAUSE
  nop
  and   t2, t1, 0x3f
  lw    t2, interrupt_table(t2)
  nop
  jr    t2
  ...

Naturally, most exception routines will require more than just two registers (k0, k1). This means that the exception routine must first save the contents of the registers to a special reserved location in memory, and later restore those register contents before returning from the exception handler. A separate exception handler stack is required when nested exceptions are to be used, or when exception handler routines are allowed to call libary subroutines. In this demo, we reserve and use the memory region in the range of

  0x.XXXX.YYYY - 0x.XXXX.ZZZZ
for the exception handler subroutines. The following code, taken from Dominic&nbps;Sweetman: See Mips Run, is the quintessential MIPS exception handler routine. It simply increments a counter value stored in main memory each time an exception is generated:

  .set noreorder
  .set noat
xcptgen:
  la	k0, xcptcount	# get address of counter
  lw	k1, 0(k0)	# load counter value
  nop                   # load delay
  addu  k1, 1           # increment counter
  sw    k1, 0(k0)       # store new value
  mfc0  k0, C0_EPC      # get EPC 
  nop                   # load delay (mfc0 slow)
  j     k0              # return to program
  rfe                   # restore from exception
                        #  in branch delay slot

The program uses the same idea, but manages a set of eight counters for each of the different exceptions. The base address of those counters is set to 0x.XXXX.ZZZZ. The main program first initializes those counters to zero, then enters a main loop that just incremements another counter value.

You can now click the input switches to generate interrupts. A rising-edge on any of the interrupt inputs of the TinyMipsCop0 processor will set the corresponding interrupt bit in the status register, and the interrupt will be handled as soon as possible. The interrupt handler will first disable further interrupts, then clear the corresponding interrupt pending bit, increment the corresponding counter, re-enable interrupts, and then re-enter the main program.

Usage

Wait until the applet is loaded. You can now open the memory-editor (via popup > edit) The memory editor highlights the last read operation in green color, and the last write operation in cyan color, which allows you to easily watch the program execution. Note that the address bus of the standard RAM component is connected to a subset of the MIPS address bus, namely RAM_ADDR[15:0] = MIPS_ADDR[17:2]. Therefore, MIPS addresses or pointer values have to be divided by 4 to get the actual physical address inside the RAM. For example, the MIPS pointer value 0x00000200 used as the start address of the sieve array corresponds to the RAM address 0x00000080.

If you want to change the simulation speed, just select 'edit' on the clock-generator component, then edit the value of the clock-generator 'period' property, and select 'apply' (and 'ok' to close the clock-generator config dialog).

Similarly, open the TinyMips user-interface window (via popup > edit) to watch the register contents during the program execution.

The binary program running on the processor was compiled and linked with the GNU gcc (2.7.2.3) and binutils cross-compiler toolchain on a Linux x86 host, with the final ELF loading and relocation done via the Hades Elf2rom tool. See

for details.

Print version | Run this demo in the Hades editor (via Java WebStart)
Usage | FAQ | About | License | Feedback | Tutorial (PDF) | Referenzkarte (PDF, in German)
Impressum http://tams.informatik.uni-hamburg.de/applets/hades/webdemos/76-mips/20-interrupt/interrupt.html