Raising Interrupts

It is common that device models need to raise an interrupt. For this purpose there are two interfaces to consider. The IrqCtrlIface which is used to raise and / or lower interrupts. The IrqCtrlIface is implemented by processor models and interrupt controllers.

There is also IrqClientIface which is implemented by interrupt controllers so they support lazy interrupt evaluation. A device model will normally only need to bother about the IrqCtrlIface.

// Header for interface
#include "temu-c/Models/IrqController.h"

// Raise IRQ 1
Obj->IrqCtrl.Iface->raiseInterrupt(Obj->IrqCtrl.Obj, 1);

// Lower IRQ 1
Obj->IrqCtrl.Iface->lowerInterrupt(Obj->IrqCtrl.Obj, 1);

In most cases, a device model should be connected to an interrupt controller and not directly to the CPU.

When a multi-core system is emulated, an interrupt controller may need to distribute interrupts to different processors. There are the following alternatives for this:

  • An interrupt is sent to the same CPU who initiated the interrupt (e.g. by MMIO or event execution).

  • An interrupt is sent to another CPU than the one initiating the interrupt (e.g. an Inter-Processor Interrupt (IPI)).

  • An interrupt is sent to several CPUs (multi- or broadcast interrupt).

In the case an IRQ is raised on the initiator CPU (or from a synchronized event) then the IRQ will be taken in natural order.

In the case the interrupt is raised on another CPU, the IRQ raising time will be at the start of the current quanta or at the start of the next quanta. That is, the IRQ may be raised earlier in apparent time for the other CPU than for the current CPU.