|
<< Click to Display Table of Contents >> Navigation: ASA-EMulatR Reference Guide > Introduction > Architecture Overview > Chapter 13 – AlphaPipeline Implementation > 13.6 Stage Implementations |
Consumes the FetchResult from m_pendingFetch (supplied by IBox via supplyFetchResult()). Transfers the decoded instruction (DecodedInstruction + grain pointer) into the IF-stage slot. Assigns monotonic sequence number (m_nextSequence++). Sets slot.valid = true, slot.cycle = m_cycleCount. No execution occurs here.
Mostly a pass-through — the grain was pre-decoded in IBox during fetch. Future: could detect early hazards here.
Mostly a pass-through — hazard checks are now performed in boxes during EX. Future: could handle dual-issue logic here.
All instruction semantics occur here. The implementation:
Early exits: if (!slot.valid || slot.stalled || slot.faultPending) return.
Illegal instruction check: if (!slot.grain) → set faultPending, trapCode = ILLEGAL_INSTRUCTION, return.
Grain execution: slot.grain→execute(slot) — the grain calls EBox, FBox, MBox, CBox, or PalBox as needed, performs arithmetic/logical work, executes memory accesses, detects exceptions, sets stall or serialization flags, and produces result payload in slot.payLoad.
Branch/jump misprediction detection: after execution, if isBranchOrJump and branchTaken, compare actualTarget vs predictedTarget. If mispredicted, set slot.flushPipeline = true.
Multi-cycle operations block EX until complete.
Despite the name, no memory access occurs here (memory was accessed in EX via MBox). stage_MEM() has two responsibilities:
Register writeback: commitPending(slot) writes deferred register results from the PendingCommit structure. For integer results: slot.writeIntReg(destReg, value), then m_eBox→clearDirty(reg). For FP results: slot.writeFpReg(destReg, value), then m_fBox→clearDirty(reg).
Stall check: if needsMemoryBarrier and !memoryBarrierCompleted → stall. If needsWriteBufferDrain and !writeBufferDrained → stall. This is where barrier instructions block the pipeline until CBox confirms completion.
WB is the architectural commit point. Execution order within stage_WB:
1. Fault check — if slot.faultPending: discard m_pending (younger instruction squashed), set PipelineAction::FAULT with trapCode/faultVA/faultPC, return immediately. The fault propagates to AlphaCPU via BoxResult::faultDispatched().
2. CALL_PAL check — if isCallPal(slot.di): discard m_pending (pipeline serializes), compute PAL entry vector via computeCallPalEntry(), set PipelineAction::PAL_CALL, return.
3. Store commit — if slot has store semantics (S_Store): m_guestMemory→write64(slot.pa, slot.payLoad), then m_reservationManager→breakReservationsOnCacheLine(slot.pa).
4. Branch predictor update — if branchTaken: m_cBox→updatePrediction(pc, taken, target).
5. Retirement — commitInstruction(slot): increment m_instructionsRetired, update m_totalCycles, emit EXECTRACE_WB_RETIRE.
6. Cleanup — slot.valid = false, slot.clear().
Note: registers were already written in stage_MEM — WB only commits stores and retires.
See Also: cpuCoreLib/AlphaPipeline.h (stage implementations lines 860–1430).