4.1.22 · D5Computer Architecture (Deep)

Question bank — Out-of-order execution — Tomasulo algorithm (conceptual)

1,884 words9 min readBack to topic

The vocabulary below is all from the parent note. A quick reminder of the shorthand so no symbol is unearned:

Recall The words you need before you start
  • RS = reservation station: a waiting-room slot in front of a functional unit that holds an instruction plus its operands (or a promise of them).
  • tag = the name of an RS (e.g. Add1, Mult1). After issue, an operand-that-is-not-ready-yet is remembered by the tag of whoever will produce it.
  • Qj, Qk = the two operand tag slots inside an RS. Qj == 0 means "operand present as a value."
  • Vj, Vk = the two operand value slots. Filled once the value arrives.
  • Qi[r] = register status: which RS tag currently "owns" (will next write) architectural register r.
  • CDB = Common Data Bus: the single loudspeaker that broadcasts (tag, value) to everyone at once.
  • RAW = Read-After-Write (true dependency). WAR = Write-After-Read. WAW = Write-After-Write.

True or false — justify

TF1. "Tomasulo executes instructions in a completely random order."
False — Issue is strictly in program order; only Execute and Write may reorder, and even then RAW dependencies are honored, so the order is constrained, not random.
TF2. "Because Issue is in order, Tomasulo cannot hide the latency of a slow load."
False — Issue being in order just assigns names/tags quickly; the Execute stage runs whatever has its operands ready, so independent instructions behind a slow load still fire and hide its latency.
TF3. "Register renaming needs extra architectural registers that the programmer can see."
False — the renaming in Tomasulo is implicit: results are named by RS tags, which are internal hardware names invisible to the program. See Register Renaming.
TF4. "The CDB can carry two completed results in the same cycle if two units finish together."
False — the CDB is a single shared bus, one (tag, value) per cycle; simultaneous finishers must arbitrate and one waits, a genuine structural bottleneck.
TF5. "After issue, a reservation station remembers which architectural register its operand came from."
False — it remembers either the operand's value (Vj/Vk) or the producing RS's tag (Qj/Qk); the architectural register number is discarded, and that discarding is the renaming.
TF6. "Classic Tomasulo by itself gives precise interrupts."
False — plain Tomasulo writes results out of order and has no in-order commit point; precise exceptions require adding a Reorder Buffer (ROB).
TF7. "An instruction may begin executing before both of its operands are available."
False — Execute waits until Qj == 0 && Qk == 0; you literally cannot start until both real values have arrived, which is exactly how RAW is enforced.
TF8. "If five instructions all wait on the same producer, that producer must broadcast its result five times."
False — one CDB broadcast; all five RS entries snoop it simultaneously. Broadcast is one-to-many for free.
TF9. "WAR and WAW are real data dependencies that Tomasulo carefully sequences."
False — they are false dependencies caused only by name reuse; renaming dissolves them, and only RAW (the true dependency) survives.
TF10. "Out-of-order execution means the visible program result can differ from an in-order run."
False — RAW is respected and in-order Issue enforces "last writer wins," so the architectural outcome is identical to sequential execution.

Spot the error

SE1. "Issue: source F2 isn't ready, so we stall this instruction until F2 arrives, then issue it."
Error — we do not stall Issue for a data-not-ready operand; we issue it and record the producer's tag in Qj. Only a lack of free RS (structural) stalls Issue.
SE2. "When Add1 finishes, it writes its result back to the register file, and Mult1 later reads F2 from the register file."
Error — Add1 broadcasts on the CDB and Mult1 snoops the value directly into Vj. The value flows tag-to-RS without a round trip through the register file (register-to-register forwarding).
SE3. "I4 overwrites Qi[F6] with Mult1, so when the earlier writer Add1 finishes it corrupts F6."
Error — Add1's broadcast is ignored for the register because Qi[F6] != Add1 anymore; the stale write silently drops. This is how WAW is solved automatically.
SE4. "I2 grabbed F8's tag at issue, so a later writer of F8 can clobber the value I2 needs."
Error — I2 grabbed F8's value (Vk) at issue because it was ready; a later write of F8 lands in a different RS tag and cannot touch I2's captured copy. That is WAR being neutralized.
SE5. "A reservation station holds Qj and Vj populated at the same time for one operand."
Error — per operand it is one or the other: a valid tag (Qj != 0, not yet ready) or a valid value (Qj == 0, ready). The tag is cleared the instant the value is captured.
SE6. "If no reservation station is free, Tomasulo picks a different, later instruction to issue instead."
Error — Issue is in order; no free RS is a structural stall that blocks Issue entirely. Reordering happens at Execute, not Issue.
SE7. "The Register Status table Qi stores the current numeric value of each register."
Error — Qi stores the tag of the RS that will next write that register (or "ready" if a real value sits in the register file). The value lives in the register file, not in Qi.
SE8. "Two loads to the same address can always execute in any order safely."
Error — memory ordering is not automatically free; loads/stores use load/store buffers and must respect memory dependencies through their address field A. See Cache Misses & Memory Latency.

Why questions

WHY1. "Why does Tomasulo store a tag instead of just waiting to read the register later?"
Because by the time the value is ready the register may have been renamed by a newer writer; the tag names the exact producer, so the right value is captured regardless of later reuse.
WHY2. "Why is Issue kept in program order if the whole point is to run out of order?"
In-order Issue is what lets renaming preserve "last writer wins" for each register (Qi always reflects the latest issuer), keeping the architectural result correct despite out-of-order execution.
WHY3. "Why does the single CDB matter enough to name it a bottleneck?"
Every result-producing unit competes for one broadcast slot per cycle; in a wide Superscalar Execution machine many results finish together and serialize on the CDB, motivating multiple CDBs.
WHY4. "Why does renaming automatically kill WAR without any extra logic?"
Readers capture their producer's tag (or value) at Issue time; a later writer gets a brand-new tag, so it physically cannot overwrite something an earlier reader already recorded.
WHY5. "Why does a broadcast reach both reservation stations and registers?"
Because a produced value may be needed by waiting RS entries (to fire the next instruction) and must update the architectural register state — one broadcast serves both consumers at once.
WHY6. "Why is Tomasulo said to do renaming 'implicitly' compared to explicit schemes?"
There is no separate physical register file being allocated by name; the RS tags themselves act as the fresh names, so renaming falls out of the buffering mechanism rather than a dedicated rename table. Contrast with explicit Register Renaming.
WHY7. "Why does Tomasulo handle RAW but Scoreboarding stalls on WAR/WAW?"
Scoreboarding tracks register names without renaming, so it must stall on anti/output hazards; Tomasulo's tag-based renaming removes the name conflict, leaving only the genuine RAW to enforce.
WHY8. "Why doesn't out-of-order execution need branch instructions to resolve first?"
With Branch Prediction & Speculation the machine issues down the predicted path; classic Tomasulo executes those, but recovering cleanly on a mispredict again needs a Reorder Buffer (ROB) to squash wrong-path results.

Edge cases

EC1. "Both operands are already ready at Issue time."
Then Qj == 0 and Qk == 0 immediately; the instruction can move to Execute as soon as the functional unit is free — no waiting, no tags needed.
EC2. "An instruction has only one source operand (e.g. a load or a negate)."
The unused operand slot is simply marked ready (Qk == 0 with a don't-care value), so the fire condition Qj == 0 && Qk == 0 isn't blocked by a nonexistent operand.
EC3. "A producer broadcasts a tag that no one is currently waiting on."
The CDB broadcast still updates the register file if Qi[dest] still equals that tag; if not even the register wants it (renamed away), the value is simply written to no one — harmless. The RS is freed either way.
EC4. "Two instructions in a row write the same register, and the first is much slower."
Qi[dest] ends pointing at the second (later) writer; the slow first writer's eventual broadcast is ignored for the register — WAW resolved, and the register ends with the correct last value.
EC5. "An instruction depends on a value that will be produced this same cycle it becomes ready to fire."
The RS captures the CDB value in the write cycle and can begin Execute the next cycle; it cannot both snoop and start in the same cycle because the value arrives at cycle's end.
EC6. "All reservation stations of a unit are busy and a new op wants that unit."
Structural stall at Issue — the pipeline front end freezes for that op (and everything behind it, since Issue is in order) until a matching RS frees up.
EC7. "A result is broadcast but the destination register was never read again."
The register file still updates (state must stay correct in case a later instruction reads it), but no RS snoops it; the update is invisible to execution until someone reads that register.
EC8. "The slow load finally completes after many independent instructions have already executed and written results."
Correctness holds because those independents had no RAW on the load; the load's result flows to whoever tagged it, and in-order Issue guarantees the final register state matches sequential order. This is exactly the latency-hiding win over strict Pipelining and Hazards.