18.6 Pipeline Fault Detection and Delivery Flow

<< Click to Display Table of Contents >>

Navigation:  ASA-EMulatR Reference Guide > Introduction > Architecture Overview > Chapter 18 – Fault Dispatcher & Precise Exceptions >

18.6 Pipeline Fault Detection and Delivery Flow

18.6.1 Detect-Early / Deliver-Late Model

 

EMulatR implements the Alpha precise exception model through a detect-early/deliver-late pattern. Faults are detected in the Execute (EX) stage but not delivered until the faulting instruction reaches the Writeback (WB) stage. This ensures that all prior instructions have committed and no younger instruction has modified architectural state.

 

Detection (EX stage):

 grain->execute(slot)

 │

 ├── MBox detects: DTB miss, alignment, ACV, FOE/FOW/FOR

 ├── EBox detects: integer overflow, divide by zero

 ├── FBox detects: FP overflow/underflow/inexact/invalid/DBZ

 └── Pipeline: illegal instruction, privilege violation

 │

 ▼

 slot.faultPending = true

 slot.trapCode = ExceptionClass_EV6::...

 slot.faultVA = faulting_address

 

Transit (MEM stage):

 Faulting instruction flows through MEM

 Pending commit preserved but may be discarded

 No side effects committed for faulting instruction

 

Delivery (WB stage):

 stage_WB() checks slot.faultPending BEFORE any commit

 │

 ├── Discard pending commit (PendingCommit{})

 ├── Set PipelineAction::FAULT with trapCode/faultVA/faultPC

 ├── Invalidate slot

 ├── flushYoungerSlots() — clear all younger instructions

 └── BoxResult::faultDispatched() → enterPalMode()

 

The key guarantee: the fault check in WB fires before any store commit or register writeback for the faulting instruction. Older instructions have already committed in prior WB cycles. Younger instructions are flushed and never commit.

 


 

18.6.2 Interrupt Delivery Flow

 

Interrupts follow a different path than synchronous faults. They are sampled during the pre-cycle phase of the CPU run loop, before pipeline advancement:

 

AlphaCPU::runOneInstruction()

 │

 ├── 1. Check FaultDispatcher::eventPending()

 │ (delivers queued faults/traps from prior cycle)

 │

 ├── 2. Poll IRQPendingState (if !inPalMode)

 │ hasDeliverable(currentIPL) → true?

 │ claimNext() → ClaimedInterrupt{source, IPL, vector}

 │ break reservation

 │ PalService::deliverInterrupt(claimed)

 │ flush pipeline

 │ return (skip instruction execution this cycle)

 │

 ├── 3. Poll for IPIs (if !inPalMode)

 │ TLB shootdown, barrier synchronization

 │

 └── 4. Execute pipeline stages (IF → DE → IS → EX → MEM → WB)

 

Interrupts are never taken mid-instruction. The interrupt check occurs at instruction boundaries, after the previous instruction has fully retired. PAL mode blocks non-critical interrupt delivery — only machine checks override PAL mode.

 

See Also: 13.10 Exception Precision; 7.8 Precise Exception Model; cpuCoreLib/AlphaCPU.h – runOneInstruction(), checkInterrupts().