Exercises — Reorder buffer (ROB)
This page is a self-test ladder. Each rung asks a little more of you than the last. Cover the solution, try the problem, then reveal. Every symbol used here was built in the parent ROB note — if a term feels unfamiliar, jump back and re-read before continuing.
Quick vocabulary refresher (all from the parent note), so line one makes sense:
Everything below uses a circular buffer of entries with indices that wrap around using (remainder after dividing by ). If "mod" is fuzzy: because , and the leftover is .
The picture below is the mental model to hold for the whole page. Study it before Exercise 1.1: the six numbered circles are the fixed physical slots; the pale-yellow HEAD arrow marks the oldest live instruction (retire from here), the pink TAIL arrow marks the next free slot (issue writes here). Blue circles are Completed entries, the pink circle is a Pending entry, and empty (board-coloured) circles are free. Notice that HEAD and TAIL are just indices that walk around the ring, wrapping via — that wrap is the whole reason the buffer is drawn as a circle, not a line.

Level 1 — Recognition
Goal: can you read a ROB snapshot and state facts about it?
Exercise 1.1
An 8-entry ROB currently has and . What state is the ROB in — empty or full? Explain which rule tells you.
Recall Solution 1.1
The parent note gave two rules:
- Empty condition:
- Full condition:
Here , so the empty rule fires. The ROB is empty.
Why the two rules must differ: if we let a completely full buffer also satisfy , we could not tell "full" and "empty" apart — they'd look identical. So we deliberately keep one slot sacrificed: full is declared one step before the pointers collide. That is why the full rule is , not .
Exercise 1.2
A 4-entry ROB has this snapshot. Which single instruction is eligible to retire this cycle?
| Entry | Inst | Status |
|---|---|---|
| 0 | I1 | Completed |
| 1 (H) | I2 | Pending |
| 2 | I3 | Completed |
| 3 | I4 | Completed |
Recall Solution 1.2
Retirement is in program order from the head. The head is at entry 1 (I2). To retire, the head instruction must be Completed.
I2 is Pending, so retirement stalls — even though I3 and I4 are done. No instruction retires this cycle.
Note: I1 in entry 0 is older by index but it is behind the head — it has already retired in a previous cycle (that is why the head moved past it). It is not a candidate.
Level 2 — Application
Goal: run the pointer machinery yourself.
Exercise 2.1
An ROB starts at , (empty). You issue 5 instructions, then retire 3. Give the final and .
Recall Solution 2.1
Issuing advances the tail (one slot per issue); retiring advances the head.
Issue 5 times from : Retire 3 times from :
Final: , .
Sanity check — occupancy = number issued minus number retired = live instructions. Occupancy from pointers is . ✓ Matches.
Exercise 2.2
Same 6-entry ROB. It is currently full. How many valid (occupied) entries does it hold — is it or ?
Recall Solution 2.2
Because "full" is declared when , one slot is always kept empty as the tie-breaker between full and empty. So a "full" 6-entry ROB holds ==5 valid instructions==, not 6.
(Real designs often add a separate 1-bit "full" flag so they can use all slots and drop the sacrificed slot. But with the pointers-only scheme the parent described, usable depth is .)
Level 3 — Analysis
Goal: reason about correctness, not just mechanics.
Exercise 3.1 — Newest-writer operand lookup (with wrap-around)
A 6-entry ROB whose live region has wrapped past the top of the ring: the tail index sits below the head index. The live entries, in program order (oldest first), occupy slots . The head is at slot 4; the tail (next free) is at slot 2:
| Entry | Dest | Status | Value | Program order |
|---|---|---|---|---|
| 4 (H) | R1 | Completed | 25 | oldest |
| 5 | R4 | Completed | 15 | 2nd |
| 0 | R1 | Pending | ? | 3rd |
| 1 | R7 | Completed | 40 | newest |
| 2 (T) | — | free | — | — |
| 3 | — | free | — | — |
A new instruction (issued into the tail region) needs source register R1. Which entry does it read/wait for, and how do you scan the ring backwards across the boundary?
Recall Solution 3.1
The lookup scans from the tail backwards toward the head for the newest entry whose dest = R1. Because the region wrapped, "backwards from the tail" means: start just before the tail and decrement with , so the scan order of live slots is
Notice the step : that is the wrap — decrementing index gives , exactly crossing the top-of-ring boundary. This is the only subtle part; the logic is otherwise identical to the non-wrapped case.
Scanning : the first (newest) match for R1 is slot 0 (entry 1 writes R7, not R1). Slot 0 is Pending, so the new instruction does not grab the older R1=25 from slot 4. It tags itself to ROB slot 0 and waits for that broadcast.
Why newest wins even across the wrap: R1 was defined at slot 4, then redefined at slot 0; slot 0 is later in program order (3rd vs oldest), so a subsequent read must see slot 0's (future) value, not the stale 25. The physical index being numerically smaller is irrelevant — program order, tracked by the pointer walk, is what counts. This "newest matching writer" search is exactly register renaming in action.
The figure below draws exactly this wrapped snapshot so you can watch the backward scan cross the boundary.

Exercise 3.2 — Precise exception boundary
A 4-entry ROB, head at entry 1:
| Entry | Inst | Status |
|---|---|---|
| 1 (H) | I2 | Completed |
| 2 | I3 | Exception (DIV/0) |
| 3 | I4 | Completed |
| 0 | I5 | Completed |
I4 and I5 are already computed. Which results reach the architectural register file, and which are discarded?
Recall Solution 3.2
Retire from the head in order:
- Retire I2 (Completed) → commits. ✓
- Head reaches I3 → it carries an Exception. Retirement stops here. We do not commit I3's (garbage) result; instead we take the exception.
- Flush everything younger than I3: entries 3 (I4) and 0 (I5) are thrown away — even though they finished executing.
Committed: only I2 (plus anything older that retired earlier). Discarded: I3, I4, I5.
This is the definition of a precise exception: state reflects all instructions before the fault and none at-or-after it. The in-order retirement discipline gives it for free — the fault can only take effect once it becomes the oldest instruction.
Level 4 — Synthesis
Goal: combine pointer math, timing, and performance reasoning.
Exercise 4.1 — Branch misprediction flush count (no wrap and wrap cases)
A 16-entry ROB. A mispredicted branch sits at entry , and the tail (next free) is at entry .
(a) How many entries are flushed? (b) Now suppose instead the branch is at and the tail is at entry — so the younger, speculative entries wrap across the boundary. How many entries are flushed, and does the same formula still work?
Recall Solution 4.1
The flush count is always "number of live entries strictly younger than the branch," which is the ring-distance from the slot after the branch up to (but not including) the tail:
(a) No wrap. Younger entries are (entry 12 is the free tail). 6 entries flushed. The branch at slot 5 is kept — it is a real, correct instruction; only its prediction was wrong.
(b) Wrap. Younger entries are — the range crosses the top-of-ring boundary . Plugging in , : 4 entries flushed — and indeed listing them () gives 4. The same formula handles the wrap automatically: the negative intermediate is folded back into range by , which is precisely why the circular-buffer arithmetic is written with everywhere. No special "did we wrap?" branch is needed in hardware.
Exercise 4.2 — ROB-limited IPC
The parent gave the performance model: A program has independent instructions per cycle. The longest dependency chain has average latency cycles. Compute the sustained IPC for (a) and (b) . Which resource limits each case?
Recall Solution 4.2
(a) : . Then . The ROB is the bottleneck — the window is too small to expose all 4-wide parallelism given the 5-cycle occupancy.
(b) : . Then . Now the program's ILP (4) is the bottleneck — enlarging the ROB further buys nothing.
Interpretation: is "how many instructions we can keep in flight given each stays cycles." Growing helps only until it exceeds . Beyond the min is pinned by ILP. So the smallest ROB that reaches full IPC here is .
The plot below draws both terms and the between them, so you can see the "knee" where the limit switches from ROB to ILP. Look at the yellow curve: it rises along the blue dashed line until the knee at , then flattens onto the pink ILP ceiling; the two marked dots are exactly the and answers above.

Level 5 — Mastery
Goal: design-level reasoning where several structures interact.
Exercise 5.1 — Sizing a balanced machine
You are designing a superscalar core (see Superscalar-processors) that issues and retires up to 4 instructions per cycle. Loads have latency cycles and dominate the dependency chains. You want the ROB large enough that it never becomes the retirement bottleneck for this workload.
(a) What is the minimum ROB size ? (b) You also have separate Reservation-stations. If an instruction occupies a reservation station for only 1 cycle after operands arrive but sits in the ROB for up to cycles, roughly what ratio of ROB entries to reservation stations keeps them balanced?
Recall Solution 5.1
(a) The machine wants sustained . From , we need Minimum entries. (Real cores round up generously — e.g. 32, 64, 224 — to tolerate cache misses that stretch far beyond 5.)
(b) Little's-law intuition: occupancy arrival-rate residence-time. Both structures see the same arrival rate (4/cycle). A reservation station is held ~1 cycle; a ROB entry ~ cycles. So Roughly 5× as many ROB entries as reservation stations. This matches the parent's remark that an instruction can leave its reservation station after ~1 cycle yet linger in the ROB for many cycles — so the commit-side buffer must be the deeper one.
Recall One-line self-checks (cloze)
A completed instruction cannot retire while an older instruction is still ::: pending (in-order retirement). The full condition for an -entry ROB is ::: . On operand lookup we search for the ::: newest (closest-to-tail) matching writer. A mispredicted branch flushes all entries ::: younger than the branch, keeping the branch itself. ROB-limited IPC caps at ::: .
Related deep-dive threads: Register-renaming, Tomasulo-algorithm, Precise-exceptions, Speculative-execution, Branch-prediction, Instruction-retirement, Memory-ordering, Register-file-management.