5.2.12 · D3 · HinglishProcessor Datapath & Pipelining

Worked examplesPrecise exceptions in pipelines

3,637 words17 min read↑ Read in English

5.2.12 · D3 · Hardware › Processor Datapath & Pipelining › Precise exceptions in pipelines

Yeh Precise exceptions in pipelines ka worked-examples child note hai. Parent ne bataya tha ki precise exception kya hota hai aur kaunse mechanisms use enforce karte hain. Yahan hum ulta karte hain: hum har tarah ka situation un mechanisms ke saamne rakhte hain aur machine ko cycle-by-cycle trace karte hain jab tak answer bilkul clear na ho jaaye.

Shuru karne se pehle, ek vaada: neeche har symbol pehli baar use hone par explain kiya gaya hai. Agar aapne pehle kabhi pipeline stage nahi dekha, pehle 5.2.1-Pipelining-basics padho — lekin pehle callout mein diye mini-glossary se bhi kaam chal sakta hai.

Precision ka poora game ek sentence hai: architectural state strictly program order mein change hona chahiye, aur kabhi nahi kisi aisi instruction ke liye jo logically run hi nahi honi chahiye thi.


The scenario matrix

Is topic ke har case ko in cells mein se kisi ek mein daala ja sakta hai. Baad ke har example ko us cell ke saath tag kiya gaya hai jo woh cover karta hai, toh end tak aap har ek ko touch kar chuke honge.

# Case class Uski awkward baat Covered by
C1 Fault behind older un-retired work Faulting instr EX mein hai jabki ek purani instr abhi write back nahi hui (out-of-order completion) Ex 1
C2 Multiple faults, same cycle Do instructions ek saath exceptions raise karti hain — kaun jeeta? Ex 2
C3 Two faults inside ONE instruction Ek instruction kai checks trip kar sakti hai (page fault aur overflow) Ex 3
C4 Speculative fault, wrong path Ek aisi instruction par fault jo mispredicted branch ne skip karna tha Ex 4
C5 Speculative fault, RIGHT path Wahi fault, lekin prediction sahi thi — ab use fire karna padega Ex 4 (twin)
C6 Out-of-order execute, in-order commit (ROB) Younger instr ek older faulting instr se pehle finish hoti hai Ex 5
C7 Degenerate: exception on the very first instruction Koi purani instruction complete nahi hoti Ex 6
C8 Degenerate: exception on the very last / no younger instr Flush karne ke liye koi younger nahi Ex 6
C9 Limiting case: back-to-back exceptions Handler khud fault karta hai, ya resume ke cycle baad doosra fault Ex 7
C10 Real-world word problem Page fault → disk → resume, cycles mein measure kiya Ex 8
C11 Exam twist: store already sent to memory Ek younger store older fault se pehle memory mein "leak" ho gayi — kya yeh abhi bhi precise hai? Ex 9

Example 1 — Fault behind older un-retired work (C1)

Forecast: Abhi guess karo — kya hum is cycle mein exception lete hain, ya wait karte hain? Aur kitne cycles ke liye?

Figure — Precise exceptions in pipelines

Step 1 — Detect aur tag karo. Cycle 5 mein, EX stage ka divide unit I3 par ek fault flag set karta hai. Yeh step kyun? Detection aur exception lena alag-alag hai. Hum sirf record karte hain ki "I3 fault karna chahta hai"; abhi lena I1 aur I2 ko mid-flight strand kar dega aur rule 1 violate karega (saari older instructions complete honi chahiye). Figure mein I3 par amber flag dekho.

Step 2 — Younger instructions ko bubbles mein convert karo. I3 (EX), I4 (ID), I5 (IF) ko NOP ("no operation" — ek instruction jo kuch nahi badlati) mein badal do. PC ko freeze karo taaki koi naya fetch na ho. Yeh step kyun? Rule 2: faulting instruction aur uske baad wale architectural state ko touch nahi karne chahiye. Unhe NOPs mein badalna guarantee karta hai ki unka WB kuch nahi likhega. Figure mein cyan crosses killed slots ko mark karte hain.

Step 3 — Older instructions ko drain karo.

  • Cycle 5: I1 WB finish karta hai. ✅ committed.
  • Cycle 6: I2 (LOAD) MEM→WB move karta hai aur R4 likhta hai. ✅ committed.

Yeh step kyun? Yeh I3 se older hain, toh precise semantics ke hisaab se yeh actually execute hue. Hume unhe complete hone dena hoga.

Step 4 — Cycle 6 mein exception lo. I2 ke WB ke baad, I3 ka PC EPC mein save karo (Exception Program Counter — woh register jo handler read karta hai yeh jaanne ke liye ki fault kahan tha) aur handler ko vector karo. Yeh step kyun? Yeh pehla cycle hai jis par "sab purane done hain, kisi younger ne state nahi badla" simultaneously true hai — precision ki definition.

Verify: Architectural registers change hue: R-dest(I1) aur R4 (I2 se). Registers NOT changed: R6 (I3), plus jo bhi I4/I5 target karte the. EPC = address(I3). Instructions committed = 2, instructions squashed = 3. Total pipeline drain = 2 cycles (5→6). "Drain depth = number of older un-retired instructions" ke saath consistent, jo yahan 2 hai. ✔


Example 2 — Two faults, same cycle (C2)

Forecast: Illegal opcode pipe mein pehle pakda gaya (ID, EX se pehle hai). Kya "hardware mein pehle pakda" jeetat hai, ya kuch aur?

Step 1 — Program-order sequence numbers attach karo. I3, I4 se purani hai (I3 pehle fetch hui thi). Yeh step kyun? Precision ek sequential machine ke against define hoti hai. Ek sequential machine I4 se pehle I3 tak pahunchi hogi, toh I3 par fault hoga aur woh I4 ko kabhi fetch bhi nahi karega.

Step 2 — Oldest fault select karo. I3 ka divide-by-zero (Exception B) chuno. I4 ka exception bilkul discard karo. Yeh step kyun? I4 report karna OS ko falsely batayega ki I3 tak ke saare instructions succeed hue — ek jhooth, kyunki I3 divide by zero karta hai.

Step 3 — Younger flush karo, older drain karo. I3, I4, I5 squash karo. I1, I2 complete hone do. B lo.

Verify: Reported exception = divide-by-zero at PC(I3). I4 ka illegal-opcode gayab ho jaata hai (I4 sequential model mein kabhi run nahi karta). Yeh parent ke rule se match karta hai: "program order mein sab se pehle wala report karo." ✔ Trap: hardware ne A time mein pehle detect kiya lekin B program order mein pehle — program order jeetta hai.


Example 3 — Two faults inside ONE instruction (C3)

Forecast: Ek hi instruction, toh program order tie nahi tod sakta. Tie-breaker kya hai?

Step 1 — Faults ko pipeline stage of detection ke hisaab se order karo instruction ke andar. Fetch/address faults data actual return se pehle detect hote hain; alignment/memory-access faults access ke part ke roop mein check hote hain. Yeh step kyun? Ek instruction ke andar, sabse pehla logical sub-step jo fail hota hai, yeh define karta hai ki "kya hona chahiye tha." Ek per-instruction fixed priority list ise encode karti hai (parent dekho): fetch faults > illegal/privilege > arithmetic. Alignment (ek address-computation fault) yahan page-fault-triggered data fetch se zyada rank karta hai sirf tab agar address translate hone ki koshish se pehle illegal compute ho jaaye; zyaatar ISAs par page/TLB translation pehle check hota hai.

Step 2 — Fixed priority lagao. Parent ki priority follow karte hue (fetch/translation sabse high), page fault report karo. Alignment report ko abhi ke liye suppress karo. Yeh step kyun? Agar hum pehle alignment report karte hain aur OS "fix" karta hai, toh retry par immediately page fault hit hoga — bekar churn. Pehle higher-priority translation fault report karna OS ko page load karne deta hai; alignment check retry par tabhi dobara fire hoga agar abhi bhi relevant ho.

Verify: Exactly ek exception har instruction har attempt par deliver hota hai. EPC = PC(LOAD) (unchanged, toh retry yahan land karti hai). 7.2.5-Virtual-memory-exceptions dekho kyun page faults restartable hote hain (state kabhi modify nahi hui thi — precise). ✔


Example 4 — Speculative fault: wrong path AUR right path (C4, C5)

Forecast: Ek case mein divide-by-zero OS tak pahuncha hai; doosre mein silently gayab ho jaata hai. Kaunsa kaunsa hai?

Figure — Precise exceptions in pipelines

Step 1 — Mark karo, fire mat karo. Jab I2 fault kare, I2 par ROB mein ek speculation bit set karo (Reorder Buffer — in-order waiting list jahan results commit se pehle park karte hain; 6.3.4-Reorder-buffer-in-superscalar dekho). Fault ko ROB entry ke andar record karo, handler ko jump mat karo. Yeh step kyun? Hame abhi nahi pata ki I2 hona bhi chahiye tha ya nahi. Abhi fire karna ek phantom instruction par fault report kar sakta hai.

Step 2 — Branch resolve hone ka wait karo. I1 apni condition compute karta hai.

Step 2a — Case (a), branch actually TAKEN (wrong-path, C4). I2 discarded path par thi. I2 (aur branch ke baad wrong path par sab kuch) ko ROB se flush karo. Fault use saath hi throw away ho jaata hai. Kyun? Ek sequential machine jisne branch liya woh I2 kabhi execute nahi karti, toh uska fault exist hi nahi hona chahiye. Figure mein amber "discarded" arrow dekho.

Step 2b — Case (b), branch actually NOT taken (right-path, C5). I2 genuine hai. Woh ROB head ban jaati hai, recorded fault ab fire hota hai: EPC = PC(I2), vector to handler. Kyun? Ab sequential machine actually I2 tak pahunchi hogi aur divide by zero karti, toh precision demand karti hai exception.

Verify: Same physical fault, do outcomes sirf is baat se decide hue ki kaunsa path commit hua. C4 → 0 exceptions delivered; C5 → 1 exception delivered at PC(I2). Isi liye speculation aur precise exceptions coexist karte hain (5.2.11-Branch-prediction). ✔


Example 5 — Out-of-order execute, in-order commit (C6)

Forecast: I4 done hai — kya R8 already update ho gaya? Agar haan, toh kya precision break nahi ho gayi?

Figure — Precise exceptions in pipelines

Step 1 — Out of order execute karo, results ROB mein likho, registers mein nahi. Execution ke baad:

ROB entry Instr Status Result parked in ROB
1 I1 COMPLETE R1 value
2 I2 COMPLETE R4 value
3 I3 FAULTED (div-by-zero)
4 I4 COMPLETE R8 value

Yeh step kyun? "COMPLETE" matlab computed hai, not committed. R8 ki value ROB entry 4 mein baithi hai — architectural R8 untouched hai. Yahi decoupling saara trick hai.

Step 2 — Strict head-to-tail order mein commit karo.

  • Head=1 → I1 commit → architectural R1 update. ✅
  • Head=2 → I2 commit → architectural R4 update. ✅
  • Head=3 → I3 FAULTED hai → yahan exception lo.

Yeh step kyun? Commit woh akela jagah hai jahan architectural state change hoti hai, aur woh program order mein hoti hai. Toh bhale hi I4 pehle finish hui, uska result ROB mein stuck hai.

Step 3 — Faulting head se aage flush karo. ROB entries 3 aur 4 discard karo. Entry 4 mein parked R8 value kabhi register file mein copy nahi hogi. Kyun? I4 fault se younger hai → state affect nahi karni chahiye.

Verify: Committed: R1, R4. Kabhi committed nahi: R6, R8. Note R8 compute hua tha phir bhi architectural R8 unchanged hai — precision holds kyunki "computed ≠ committed." ROB ki yahi superpower hai. ✔


Example 6 — Degenerate ends: first-instruction aur last-instruction faults (C7, C8)

Forecast: Kya "drain older" aur "flush younger" steps tab break ho jaate hain jab ek side empty ho?

Step 1 — Case (a): khali "older" set. "Saari older instructions complete karo" vacuously satisfied hai — koi hain hi nahi. Turant EPC = PC(I1) save karo aur handler ko vector karo. Yeh step kyun? Rule "sab older complete" ek empty set par ∀ (for-all) hai → automatically true. Koi special case nahi chahiye; wohi logic bas kuch nahi karta.

Step 2 — Case (b): khali "younger" set. "Saare younger flush karo" vacuously satisfied hai. Older waalon ko drain karo (Ex 1 ki logic) aur fault lo. Yeh step kyun? Wohi reasoning: flush loop zero times run karta hai.

Verify: (a) mein: committed = 0, EPC = PC(I1), toh retry I1 ko re-fetch karta hai OS ke page map karne ke baad. (b) mein: committed = I1 se older sab, squashed = 1 (sirf faulting instr). Dono koi extra hardware ke bina precise hain — general mechanism already degenerate boundaries cover kar leta hai. ✔ (Isi liye hum kehte hain mechanism total hai: koi scenario unhandled nahi rehta.)


Example 7 — Limiting case: back-to-back / nested faults (C9)

Forecast: Agar doosra fault pehle fault ka saved PC overwrite kar de, toh kya hum user program par kabhi wapas ja sakte hain?

Step 1 — EPC save hona chahiye pehle ki handler re-interrupt ho sake, aur handler ko EPC promptly memory mein save karna chahiye. Yeh step kyun? Single EPC register original faulting PC hold karta hai. Agar handler ne EPC ko apne stack mein copy karne se pehle nested exception aaye, toh EPC clobber ho jaata hai aur user program lost ho jaata hai.

Step 2 — Entry par further exceptions mask karo (ya ek separate handler stack + banked EPC use karo). Zyaatar ISAs trap entry par auto-disable interrupts aur ek "in-exception" mode bit set karte hain. Yeh step kyun? Yeh handler ko EPC aur status spill karne ka ek safe window deta hai pehle ki kuch aur interrupt kar sake. 3.4.7-Exception-handling-in-ISA dekho.

Step 3 — Resume par: EPC ko PC mein restore karo. Kyunki LOAD ne kabhi state modify nahi ki (precise!), use re-execute karna safe aur idempotent hai.

Verify: Requirement = EPC nested execution mein preserved ⇒ handler ko EPC(=PC of original LOAD) save karna chahiye nested traps enable karne se pehle. LOAD ko re-runnable hone ki zaroorat kitni baar hai = ≥1. Precision guarantee karta hai koi partial side effect nahi, toh re-run correct hai. ✔


Example 8 — Real-world word problem: page-fault cost (C10)

Forecast: Kya "ise precise banana" ek 10-million-cycle disk read ke saamne dikhega bhi?

Step 1 — Fixed CPU overheads sum karo. Yeh step kyun? Yeh cycles processor mein fault handle karne se hain, disk se independent.

Step 2 — Disk wait add karo.

Step 3 — Pipeline precision ki wajah se fraction (drain + vector = 10 cycles).

Yeh step kyun? "Precision tax" sirf drain+vector cost hai; baaki avoidable OS + disk work hai.

Verify: , yaani approximately one part per million — bilkul negligible. Disk dominate karta hai (). Lesson: precise exceptions essentially free hain rare, expensive faults par, jo exactly wohi workload hai jise yeh target karte hain. ✔


Example 9 — Exam twist: kya younger store memory mein leak ho gayi? (C11)

Forecast: Memory writes permanent hote hain. Agar STORE ho gaya, toh kya hum kabhi precise ho sakte hain?

Step 1 — Danger identify karo. Agar I2 memory likhta hai I1 ka fault resolve hone se pehle, toh ek younger instruction ke liye architectural memory change ho gayi → precision violate ho gayi. Yeh step kyun? Rule 2 kisi bhi younger instruction ko architectural state (registers ya memory) modify karne se forbid karta hai.

Step 2 — Fix: ek store buffer jo in order commit karta hai. Stores MEM mein memory nahi likhte; woh ek store buffer mein park karte hain aur sirf memory mein commit par drain karte hain, program order mein — exactly ROB register writes ki tarah. Yeh step kyun? Yeh memory ko registers jaisa "in-order commit" rule follow karta hai. Jab I1 commit par fault kare, I2 abhi bhi store buffer mein baitha hai aur flush ho jaata hai, memory tak kabhi nahi pahuncha.

Step 3 — I1 ka exception lo; buffered store discard karo.

Verify: I2 ne memory change ki? Nahi — uske bytes store buffer se kabhi baahar nahi aaye. Committed state = I1 se older jo bhi hai (yahan kuch nahi). EPC = PC(I1). Precise ✔. Isi liye loads/stores precise exceptions ke saath interact karte hain forwarding AND commit-ordered store buffer ke zariye, kabhi bare MEM write ke zariye nahi.


Recall Self-test — answers cover karo

Jab ek hi cycle mein do faults fire hon toh kaunsa jeetta hai? ::: Jo program order mein sabse purana hota hai (Ex 2). ROB mein architectural state actually kab change hoti hai? ::: Sirf commit par, program order mein — kabhi execute/complete par nahi (Ex 5). Ek speculatively-executed instruction fault karti hai. Pehle kya karte ho? ::: Mark karo, fire mat karo; branch resolve hone ka wait karo (Ex 4). "Pehli instruction ever par exception" case special kyun nahi hai? ::: "Saare older drain karo" empty set par vacuously true hai (Ex 6). Younger store ke liye memory precise kaise rehti hai? ::: Ek store buffer jo memory mein sirf in-order commit par drain karta hai (Ex 9). Ek page-fault ki cost mein precision overhead ka fraction kya hai? ::: Lagbhag one part per million — negligible (Ex 8).