Tomasulo meets a loop: eighteen cycles of renaming in action
After this lesson you will run two iterations of the notes' loop through Tomasulo's four tables cycle by cycle, explain why a register ignores the very value it was waiting for, say where the eighteen cycles go, and fill the exam's one-iteration table for the same loop.
Five instructions, the same five every time round the loop: load an element into F0, multiply it by F2 into F4, store F4 back, step R1 down by 8, branch back. The first load misses in the cache and spends eight cycles in memory. At cycle 10 it finally puts its value, M[80], on the common data bus — and F0, the very register the load names as its destination, ignores it.
At cycles 15 and 16 the two multiplies broadcast their products, and F4 ignores both. Yet at cycles 17 and 18 both products land in memory, at addresses 80 and 72, exactly where they belong. Who took the values, if not the registers? And why is ignoring them the right thing to do?
The notes spend pages 194–221 on these eighteen cycles. The answer is a single word, and it comes at the end of section 5.
The loop, the machine and the four tables
The loop is the one lesson 15 unrolled by hand: it multiplies every element of an array by the scalar in F2, walking down from the address in R1. This time nobody touches the code. In the papers' mnemonics:
I0 LOOP: LD F0, 0(R1) ; F0 ← M[R1]
I1 FMUL F4, F0, F2 ; F4 ← F0 × F2
I2 SD F4, 0(R1) ; M[R1] ← F4
I3 SUBI R1, R1, 8 ; next element, 8 bytes down
I4 BNE R1, R2, LOOP ; predicted taken
The assumptions are on page 194: the first LD misses in the cache and takes 8 clock cycles, the second hits and takes 1 (so does the third, in the tables), FMUL takes 4, and the branch is predicted taken, so issue carries on with the next iteration. SUBI and BNE run on the integer side and are not tabulated. R1 starts at 80, so the iterations touch the addresses 80, 72 and 64. The question behind the example: memory is slow and floating point moderately slow — can the machine keep working while the first load is stuck in memory?
The notes never draw the machine; you read it off their tables. Three load buffers, Load1 to Load3; three store buffers, Store1 to Store3; two multiply stations, Mult1 and Mult2 (the add stations stay empty). One common data bus, the CDB. One memory unit that serves one load at a time, so a hit cannot overtake a miss. And a multiplier that works on two FMULs at once: in cycles 12 to 14 both stations count down together. Fields and stages are those of lesson 11 and lesson 12.
| Table | Columns | What a cell holds |
|---|---|---|
| Instruction status | Issue Exec Comp Write Res | pencil bookkeeping, not hardware: the cycle of issue, the last cycle of execution, the cycle of the broadcast (for a store: of the memory write) |
| Load and store buffers | Busy Addr FU | Addr: the effective address, computed at issue from the R1 of that moment; FU, for a store: the tag of the producer of its data, replaced by the value when it arrives |
| Reservation stations | Time Name Busy Op Vj Vk Qj Qk | Vj, Vk: operand values already in the station; Qj, Qk: tags of the producers of the missing ones (empty = present); Time: execution cycles still to run after this one |
| Register result status | R1 F0 F2 F4 … | for each FP register the tag of the youngest instruction that will write it, empty when the register holds its value; R1 is shown as a value, because the integer side is not tabulated |
Two kinds of field do the renaming. Addr, Vj and Vk are copies: what exists at issue is copied into the entry, so a later write to R1 or F2 cannot disturb it — a WAR hazard dies there. Qj, Qk and a store's FU hold a tag, the name of the buffer or station that will produce the missing value: a reader is tied to its producer, not to a register name. And the register status names only the youngest writer of each register, so an older result can never land on top of a younger one — a WAW hazard dies there.
The timing rules are lesson 12's stages turned into arithmetic, as in lesson 13. Issue goes in program order, one instruction per cycle, into a free entry of the right class; a missing operand never delays issue — it becomes a tag. Execution starts the cycle after the last operand arrives. The CDB carries one result per cycle, oldest first: every entry holding the tag copies it, the register file only if the register's status still names that tag. An entry stays busy until its result has been broadcast; a store executes the cycle after its data arrives and writes memory in the next.
- \(I\)
- issue cycle
- \(S\)
- first execution cycle — the START EXEC column of the exam's table
- \(W_{\text{prod}}\)
- write cycle of the producer of the last operand to arrive; the value is usable from the next cycle
- \(U\)
- first cycle in which the unit is free (for a load: the memory unit)
- \(L\)
- latency: 8 for the missing load, 1 for a hit, 4 for FMUL
- \(W\)
- write-result cycle: the notes' Write Res, the exam's WRITE RESULT — one cycle later for every older result that takes the CDB first
"WAW hazards mainly on R1" (page 194). Inside an iteration the hazard on R1 is a WAR — LD and SD read R1, SUBI writes it after them — written "anti-dependence with I0 and I2 for R1" in the row of I3 of the exam's table. It dies when Load1 and Store1 copy the address 80 at issue. Across iterations R1 carries a true dependence; the WAW from one SUBI to the next never binds. Full inventory: lesson 15's dependence tables.
Issue copies what exists — a value, an address — and writes a tag for what does not; after that, no entry cares what its registers are called.
Cycles 1–8: issue runs ahead of the data
Fig. 1 is the end of cycle 3: LD₁ entered Load1 at cycle 1, FMUL₁ entered Mult1 at cycle 2 — copying the value of F2 (Vk = R(F2)) and recording the tag of F0 (Qj = Load1) — and SD₁ entered Store1 at cycle 3 with FU = Mult1. Nothing has been computed, yet the iteration's data-flow graph already exists in hardware, written in tags.
Cycles 4 and 5 belong to the integer side: SUBI₁ and BNE₁ issue, R1 reads 72 from cycle 5, the branch is predicted taken. Cycles 6 to 8 are the reason the example exists: iteration 2 issues while iteration 1 still waits for memory — LD₂ into Load2 with Addr = 72, FMUL₂ into Mult2 with Qj = Load2, SD₂ into Store2 with FU = Mult2. The register status is simply overwritten, F0 from Load1 to Load2 and F4 from Mult1 to Mult2, while Mult1 keeps Qj = Load1 and Store1 keeps FU = Mult1.
At the end of cycle 8, six instructions from two iterations are in flight, all spelled with F0 and F4, and nothing conflicts: every waiting field holds a tag, and the tags all differ. The notes call it the dynamic loop unrolling effect (page 193): two copies of the body side by side, although nobody copied the code.
One thing looks odd: LD₂, a hit issued at cycle 6, executes only at cycle 10. The notes' reason (page 202) is wrong.
In order in, out of order through: issue goes 1, 2, 3, 6, 7, 8, while LD₂ finishes executing at cycle 10 — before FMUL₁ has even started.
Cycle 10: one broadcast, two answers
At cycle 9 Load1 completes its eighth memory cycle and SUBI₂ issues. Cycle 10 is the moment of the puzzle. Load1 puts ⟨Load1, M[80]⟩ on the CDB, and every entry compares the tag with its fields. Mult1 holds Qj = Load1: it copies the value into Vj, and its Time field starts at 4, for the execution cycles 11 to 14. The register file compares the tag with F0's status, which since cycle 6 says Load2: no match, F0 does not change. Load1 is freed, and Load2 finally gets the memory unit.
If F0 still named Load1
Cycle 10 as it happens
Ignoring the value loses nothing: the only instruction that needed M[80] was FMUL₁, and it took it from the bus. F0 must end up holding what the youngest load put in it, so it listens for that load's tag only; taking M[80] would overwrite a claim that belongs to a younger instruction. This is WAW protection, and it costs no stall at all.
Dynamic register renaming — at issue, the reservation station or buffer that will produce a result becomes the name of that result, its tag. Readers record the tag instead of the register, and the register file accepts a broadcast only from the youngest writer of each register. WAR and WAW hazards disappear; RAW dependences stay.
What did the tags buy? Draw both iterations as a dependence graph, as lesson 15 did: a chain of true dependences inside each iteration, LD → FMUL → SD, and four name dependences between them — two WAW, because F0 and F4 are written twice, and two WAR, because FMUL₁ reads F0 before LD₂ writes it and SD₁ reads F4 before FMUL₂ writes it. A machine that tracks registers by name must respect all of them; one that renames keeps only the true ones.
A value goes to whoever holds its tag; the register file is one more listener, and it listens only for its youngest writer.
Cycles 11–18: countdowns, a full house and two stores
Cycle 11 repeats cycle 10 for the second iteration: Load2 broadcasts M[72] and Mult2 takes it. In the same cycle LD₃ is issued into Load3 (Addr = 64) and F0's status becomes Load3. Issued, not started — the notes say otherwise.
From cycle 11 the two multiplies count down side by side, Mult1 from 3 to 0 and Mult2 from 4 to 1. At cycle 12 the machine hits its first wall. FMUL₃ is next in program order and its operand will be ready at cycle 13, but both multiply stations are busy — and a station stays busy until its result has been broadcast, at 15 and 16. No free station, no issue: a structural hazard on the reservation stations, not a data hazard. Because issue is in order, SD₃ waits behind it although Store3 is free. At cycle 13 Load3 broadcasts M[64]; no younger load has claimed F0, so the register file takes it — the only loaded value F0 keeps in the whole run.
At cycle 15 Mult1 broadcasts M[80]×F2: Store1, which has held FU = Mult1 since cycle 3, takes it, and F4, whose status names Mult2, ignores it. Mult1 is freed and, in the notes, refilled in the same cycle with FMUL₃, which reads F0 = M[64] from the register file. At cycle 16 Mult2's product goes to Store2, and F4 ignores this one too: its status now names Mult1. Cycles 17 and 18 belong to the stores, and the notes narrate them with two slips.
The result of the exercise is the notes' last instruction-status table (page 221), here in the paper's headings plus the notes' Exec Comp:
| Iter | INSTRUCTION | ISSUE | START EXEC | EXEC COMP | WRITE RESULT | Hazards Type | RSi |
|---|---|---|---|---|---|---|---|
| 1 | LD F0, 0(R1) | 1 | 2 | 9 | 10 | None (a cache miss: 8 cycles) | Load1 |
| 1 | FMUL F4, F0, F2 | 2 | 11 | 14 | 15 | RAW with LD₁ for F0 | Mult1 |
| 1 | SD F4, 0(R1) | 3 | 16 | 16 | 17 | RAW with FMUL₁ for F4 | Store1 |
| 2 | LD F0, 0(R1) | 6 | 10 | 10 | 11 | Structural: memory unit busy until 9; WAW with LD₁, WAR with FMUL₁ for F0 (solved by renaming) | Load2 |
| 2 | FMUL F4, F0, F2 | 7 | 12 | 15 | 16 | RAW with LD₂ for F0; WAW with FMUL₁, WAR with SD₁ for F4 (solved by renaming) | Mult2 |
| 2 | SD F4, 0(R1) | 8 | 17 | 17 | 18 | RAW with FMUL₂ for F4 | Store2 |
Four causes account for every cycle of the chart. The miss: nothing floating-point executes from cycle 2 to 9, yet issue goes on, and by cycle 8 six instructions wait in buffers and stations. Stations held until write result: Mult1 is occupied from cycle 2 to 15 — fourteen cycles for four of multiplying — and that keeps FMUL₃ out for three cycles. In-order issue: SD₃ queues behind FMUL₃. The memory unit: one access at a time, so LD₂ waits behind the miss. What costs nothing: the CDB (results at 10, 11, 13, 15 and 16, never two in a cycle; on the papers' machine they collide, lesson 14) and the register names.
Change one assumption at a time and the chain moves (same rules as the notes' run):
| Machine | LD₂ | FMUL₂ | FMUL₃ | SD₃ writes | What it shows |
|---|---|---|---|---|---|
| the notes' machine | 6/10/11 | 7/12/16 | 15/16/20 | 22 | the run of Fig. 3 |
| a third multiply station | 6/10/11 | 7/12/16 | 12/14/18 | 20 | FMUL₃ issues right behind LD₃; SD₃ follows at 13 |
| a non-blocking cache | 6/7/8 | 7/9/13 | 13/15/19 | 21 | a hit may pass the miss: the second product is written at 13, before the first at 15 |
| the first load hits too | 6/7/9 | 7/10/14 | 12/14/18 | 20 | one iteration every 5 cycles; LD₂ slips one cycle on the CDB |
| the papers' release rule | 6/10/11 | 7/12/16 | 16/17/21 | 23 | a station is free only the cycle after its write: one cycle later from FMUL₃ on |
Two rows deserve a sentence. With a non-blocking cache, LD₂ writes F0 at cycle 8 and LD₁'s older value arrives at 10 — the classic WAW hazard, a stale write after a fresh one — and the register file ignores it, because F0's status no longer names Load1. With every load a hit, the loop settles into one iteration every 5 cycles, CPI = 1, the single-issue limit: each FMUL holds its station 7 or 8 cycles while a new one arrives every 5, so on average 1.5 stations are busy (a count not in the notes). The miss alone stretched Mult1's stay to fourteen cycles.
The time goes to the miss, to stations held until write result, to in-order issue and to the single memory unit — never to the register names.
The paper's version: one iteration, one table
The exam never asks for the four tables: Exercise 1 of every paper from 2024 to 2026 gives one iteration on a fixed machine, a dependence table and then one timing table, filled with the eight conventions of lesson 12. The formats differ in more than layout:
Two iterations and a bit, on a machine read off the tables: the first load misses (8 cycles), later loads hit (1), FMUL takes 4. Issue / Exec Comp / Write Res; SUBI and BNE not tabulated. A station freed by its broadcast is refilled in the same cycle; Time counts down.
One iteration, all hits; LDU 4, FPU 3, ALU 2; stations RS1 to RS6. ISSUE / START EXEC / WRITE RESULT / Hazards Type / RSi / UNIT for every instruction, the branch included. In the model answers a station is free only the cycle after its WRITE RESULT, and a store writes memory at START EXEC + 4 without using the CDB. CPI = last WRITE RESULT / instructions.
Here is the loop on the machine of July 2024 and June 2026: a single CDB; RS1 and RS2 with load/store units LDU1 and LDU2, latency 4; RS3 and RS4 with FPU1, latency 3; RS5 and RS6 with ALU1, latency 2. The first row is the one every paper pre-fills.
| INSTRUCTION | ISSUE | START EXEC | WRITE RESULT | Hazards Type | RSi | UNIT |
|---|---|---|---|---|---|---|
I0 LOOP: LD F0, 0(R1) | 1 | 2 | 6 | None | RS1 | LDU1 |
I1 FMUL F4, F0, F2 | 2 | 7 | 10 | RAW with I0 for F0 | RS3 | FPU1 |
I2 SD F4, 0(R1) | 3 | 11 | 15 | RAW with I1 for F4 | RS2 | LDU2 |
I3 SUBI R1, R1, 8 | 4 | 5 | 7 | WAR with I0, I2 for R1 (solved by renaming) | RS5 | ALU1 |
I4 BNE R1, R2, LOOP | 5 | 8 | 11 | RAW with I3 for R1; Structural: CDB taken at 10 by I1 | RS6 | ALU1 |
I0, given. Issue 1 into RS1; R1 is valid, so it starts at 2, occupies LDU1 for 4 cycles (2 to 5) and writes F0 on the CDB at 6. From cycle 1, F0's tag is RS1.
I1 FMUL. Issue 2 into RS3: F2 is copied, F0 is recorded as the tag RS1 — a RAW with I0. The value arrives on the CDB at 6, so START EXEC = 6 + 1 = 7 and WRITE RESULT = 7 + 3 = 10.
I2 SD. Issue 3 into RS2, since RS1 is busy until 6. The address uses R1, valid now; the data is the tag RS3, a RAW with I1 for F4. START EXEC = 10 + 1 = 11; WRITE RESULT = 11 + 4 = 15, the end of the memory write — a store takes no CDB slot.
I3 SUBI. Issue 4 into RS5; R1 is valid, so it starts at 5 and writes at 5 + 2 = 7, the bus being free. It overwrites R1 while I2 still has to use its address (from cycle 11): a WAR with I0 and I2 for R1, harmless because both copied R1 at issue.
I4 BNE. Issue 5 into RS6. R1 comes from I3 at 7 and ALU1 is free after I3's write, so START EXEC = 8 and the result would be ready for 8 + 2 = 10. At 10 the bus belongs to I1, the older instruction: BNE writes at 11 — Structural on the CDB. The papers never say whether a branch uses the CDB; if you assume it does not, write 10 and say so — the CPI does not change.
CPI. The last WRITE RESULT of the iteration is the store's: CPI = 15 / 5 = 3.0.
Two cells deserve a second look. FMUL waits in RS3 from cycle 3 to 6 while FPU1 is idle — a RAW wait inside a station, not a stall at issue. SUBI writes R1 at 7 while SD still needs its address at 11 to 15: harmless, because the address was copied at issue ("solved by renaming"). A second FP unit or ALU, as on the June 2025 machine, changes nothing here: every wait is a RAW or the bus.
The theory part asks for the same mechanism in words; the first exam-style question below answers four items of the June 2026 question on this loop.
One assumption the walkthrough never questions: the branch. BNE₁ and BNE₂ are predicted taken, and the next iteration issues before either is resolved. The rule of lesson 4 forbids updating registers or memory before the branch outcome is known, and plain Tomasulo cannot take a write back: a broadcast goes straight into the register file, a store straight into memory. So, as lesson 15 said when it struck out the notes' word "speculatively" (page 193), it may issue past a predicted branch, but nothing behind the branch may execute until the branch is resolved. Here that costs nothing: a BNE needs only R1, which the integer side has ready, so BNE₂ (issued at 10) is resolved by cycle 11, before LD₃ executes at 12. Make the branch wait for a slow result, a load that misses, and everything behind it sits in its station: the overlap is gone. Executing past the branch and undoing a wrong guess is the reorder buffer's job.
Back to the puzzle. F0 and F4 ignored those values because each register listens only for the tag of its youngest writer; the values went where their tags pointed — M[80] to Mult1, the two products to Store1 and Store2 and on to memory at 80 and 72. The one word is tag: in Tomasulo's machine a value is addressed to the instructions that wait for it, not to a register.
On the paper: one iteration, START EXEC = the producer's WRITE RESULT + 1, a station free the cycle after its write, CPI = 15 / 5 = 3.0 for this loop.
Exam-style questions
Explain the main concepts and benefits of each one of the following techniques used by modern superscalar processors (Tomasulo-style), in about five lines each: (1) dynamic instruction scheduling; (4) reservation stations; (5) dynamic register renaming; (6) out-of-order execution. Use as example the loop LD F0, 0(R1); FMUL F4, F0, F2; SD F4, 0(R1); SUBI R1, R1, 8; BNE R1, R2, LOOP, not unrolled, whose first LD misses in the cache.
Show model answer
Dynamic instruction scheduling. The hardware decides at run time when each instruction executes, preserving the data flow: instructions issue in program order and wait in reservation stations until their operands are available, instead of stalling the pipeline behind the first one that must wait. Benefit: it adapts to latencies known only at run time, such as a cache miss. In the loop the second iteration's LD, FMUL and SD issue at cycles 6, 7 and 8 while the first LD is still missing; the same code runs well on different implementations. Cost: stations, tag-compare logic and a common data bus.
Reservation stations. Buffers in front of the functional units (Load1–3, Mult1–2, Store1–3 in the example) holding the operation, the operand values (Vj, Vk) or the tags of the stations that will produce them (Qj, Qk). An instruction enters a free station even when its operands are missing (the first FMUL at cycle 2 with Qj = Load1) and fires when they arrive on the CDB. Benefits: distributed hazard detection, operands read once, and the station names serve as tags for renaming. Limit: a station is held from issue to write result, so their number bounds the overlap; with two multiply stations the third FMUL cannot issue until cycle 15.
Dynamic register renaming. At issue, the station or buffer that will produce a result becomes the name of that result; the register result status maps each register to its youngest producer (F0: Load1, then Load2 from cycle 6; F4: Mult1, then Mult2). Readers record the tag, not the register, and the register file accepts a broadcast only from the youngest producer: at cycle 10 M[80] goes to Mult1 but not to F0. Benefit: WAR and WAW hazards disappear without stalls, so two iterations using the same F0 and F4 are in flight together (dynamic loop unrolling); only RAW dependences remain.
Out-of-order execution. Instructions execute and complete when their operands are ready, not in program order; issue stays in order. The second LD completes at cycle 10, before the first FMUL starts at 11. Benefit: long latencies (misses, FP operations) are overlapped with independent work, functional units stay busy and CPI drops. Requirements and limits: renaming against WAR and WAW; without a reorder buffer results reach the registers out of order, so exceptions are imprecise and nothing may execute past an unresolved branch.
Four of the eight sub-points of the June 2026 open question, one point each. Give a mechanism and a benefit in every item, with its cost or limit; the numbers of the loop are the evidence. Do not write "Tomasulo is speculative": speculation (item 2) and the reorder buffer (item 7) are the answers of lesson 17.
Let's consider the following assembly code containing multiple types of intra-loop dependences. Complete the following table by inserting all types of true-data-dependences, anti-dependences and output dependences for each instruction (I0: None).
I0 LOOP: LD F0, 0(R1)
I1 FMUL F0, F0, F2
I2 SD F0, 0(R1)
I3 SUBI R1, R1, 8
I4 BNE R1, R2, LOOP
Let's consider the previous assembly code to be executed on a CPU with dynamic scheduling based on TOMASULO algorithm with all cache HITS, a single Common Data Bus and: 2 RESERVATION STATIONS (RS1, RS2) with 2 LOAD/STORE units (LDU1, LDU2) with latency 4; 2 RESERVATION STATIONS (RS3, RS4) with 1 FP unit (FPU1) with latency 3; 2 RESERVATION STATIONS (RS5, RS6) with 1 INT_ALU/BR unit (ALU1) with latency 2. Please complete the table INSTRUCTION / ISSUE / START EXEC / WRITE RESULT / Hazards Type / RSi / UNIT (row I0 given: 1, 2, 6, None, RS1, LDU1). Calculate the CPI.
Show model answer
Dependences: I0 — None. I1 — true data dependence with I0 for F0; output dependence with I0 for F0. I2 — true data dependence with I1 for F0. I3 — anti-dependence with I0 and I2 for R1. I4 — true data dependence with I3 for R1.
| INSTRUCTION | ISSUE | START EXEC | WRITE RESULT | Hazards Type | RSi | UNIT |
|---|---|---|---|---|---|---|
I0 LD F0, 0(R1) | 1 | 2 | 6 | None | RS1 | LDU1 |
I1 FMUL F0, F0, F2 | 2 | 7 | 10 | RAW with I0 for F0; WAW with I0 for F0 (solved by renaming) | RS3 | FPU1 |
I2 SD F0, 0(R1) | 3 | 11 | 15 | RAW with I1 for F0 | RS2 | LDU2 |
I3 SUBI R1, R1, 8 | 4 | 5 | 7 | WAR with I0, I2 for R1 (solved by renaming) | RS5 | ALU1 |
I4 BNE R1, R2, LOOP | 5 | 8 | 11 | RAW with I3 for R1; Structural: CDB taken at 10 by I1 | RS6 | ALU1 |
CPI = 15 / 5 = 3.0.
The timing is cell for cell the table of section 5: reusing F0 as the destination of FMUL costs nothing, because the SD records the tag RS3, not the name F0. Check the dependence table first — the output dependence of I1 with I0 for F0 is the easiest line to forget — and then the CDB conflict at cycle 10. If you assume that a branch does not use the CDB, write 10 for I4 and say so; the CPI does not change.
The notes' loop example (first LD misses: 8 cycles; later LDs hit: 1 cycle; FMUL: 4 cycles; 3 load buffers, 3 store buffers, 2 multiply reservation stations; one memory unit serving one access at a time; a store executes in the cycle after its data arrives and writes memory in the next cycle) is redone with the convention of the exam papers: a reservation station becomes free only in the cycle after its WRITE RESULT. In which clock cycle does the store of the third iteration write to memory?
Show model answer
Iterations 1 and 2 do not change: no station is reused before cycle 15. Mult1 writes at 15 and is free at 16, so the third FMUL issues at 16 with both operands ready (F0 = M[64] since cycle 13), executes from 17 to 20 and writes at 21. The third SD issues at 17 into Store3, receives the product at 21, executes at 22 and writes memory at 23.
One convention moves two numbers: the notes refill Mult1 in the cycle it broadcasts (third FMUL at 15, third SD writing at 22). On the paper, use the papers' rule and state it in one line.
In the loop example (the first LD misses in the cache, 8 cycles), at cycle 10 the LD of the first iteration writes M[80] on the Common Data Bus. At that moment the register result status of F0 holds Load2. Which units store the value? (single answer)
Show model answer
Answer 2. Only Mult1, whose Qj = Load1, captures M[80]; the register file writes F0 only if F0's status equals the broadcast tag, and since cycle 6 it equals Load2.
The distractors test the two halves of the rule: stations match on Q fields, the register file on its own status field.
In the same example, why can the FMUL of the third iteration not be issued at cycle 12? (single answer; motivate your answer)
Show model answer
Answer 2: a structural hazard on the reservation stations. A station stays busy from issue to write result; Mult1 holds the first FMUL from cycle 2 to 15 because its load missed, Mult2 holds the second until 16. The third FMUL issues at 15, when Mult1 is freed, and in-order issue keeps the third SD behind it until 16.
The motivation point is for naming the station's lifetime — from ISSUE to WRITE RESULT, not to the end of execution — and the knock-on effect on the SD behind it.
True or false: in the loop example, the LD of the second iteration — a cache hit issued at cycle 6 — starts executing only at cycle 10 because two loads to the same address must be executed in program order.
Show model answer
False. The addresses differ and loads do not conflict with loads; the delay is structural — one memory unit, occupied by the miss from cycle 2 to 9. Memory disambiguation concerns a load and an earlier store to the same address.
The notes give the wrong reason on pages 202 and 208; the statement is built from it.
Check yourself
At cycle 8, F4's register status says Mult2. Store1, issued at cycle 3, has to store the first product. Where will it get it?
At cycle 10 Load2's buffer still shows Addr = 72, although R1 already reads 64. Why is that right?
Which changes would let FMUL₃ issue at cycle 12, right behind LD₃? Select all that apply.
The obstacle at cycle 12 is a full house of stations: anything that frees a station earlier, or adds one, helps; anything else does not.
At cycle 13 Load3 broadcasts M[64] and F0 takes it. Who reads that value from the register file?
At cycle 12 Mult2's Time field reads 3. What does it tell you?
BNE₂ issues at cycle 10, predicted taken, and LD₃ issues at 11. On plain Tomasulo, without a reorder buffer, which statement is true?
Key take-aways
- Tomasulo's machine overlaps the iterations of an unchanged loop: every instance of LD, FMUL and SD gets its own buffer or station, and the name of that entry is the tag of its result.
- At issue, values that exist are copied (Addr, Vj, Vk) and missing ones are recorded as tags (Qj, Qk, FU); the register status is overwritten with the youngest writer's tag. WAR and WAW disappear, RAW chains stay.
- A broadcast ⟨tag, value⟩ is taken by every entry holding the tag and by a register only if its status still names that tag — so F0 ignores M[80] at cycle 10, and that is correct.
- Issue is in order (1, 2, 3, 6, 7, 8, 11, 15, 16); execution and completion are not (LD₂ finishes at 10, before FMUL₁ starts).
- The cycles go to the miss, to stations held until write result (FMUL₃ cannot issue from 12 to 14), to in-order issue (SD₃ behind it) and to the single memory unit — never to the register names.
- On the paper the same loop is one iteration, all hits, START EXEC = producer's WRITE RESULT + 1, a station free the cycle after its write: CPI = 15 / 5 = 3.0. Plain Tomasulo issues past a predicted branch but executes nothing behind it until it is resolved, because it cannot undo a write; undoing is the reorder buffer's job.
What to watch and read
-
Dynamic Scheduling with Tomasulo Algorithm — simulator
Virtual Labs, IIIT Hyderabad15 min
Type in this loop's body twice and watch two writes to the same register get two different station tags — the WAW demonstration its guided procedure asks for. The register alias table it shows is the register result status of the notes.
-
Lecture 15: Out-of-Order Execution
Onur Mutlu, ETH Zürichfull lecture
Tomasulo taught as restricted dataflow: a tag is a promise of a value, a station a waiting room, the bus a loudspeaker. The cycle-by-cycle walk with the register alias table is this lesson's mechanism on another example.
-
L12 — Complex Pipelining: Out-of-Order Execution & Register Renaming
MIT 6.823 (Arvind, Asanović, Emer)28 slides
Renaming from the designers' side: why tags, what a rename table costs. Its notation is its own (tags t1 … tn, not Vj, Vk, Qj, Qk), so translate before you copy anything onto your sheet.
-
Lecture 8: Explicit Renaming, Precise Interrupts
UC Berkeley CS252, John Kubiatowicz15 pages
The step after this lesson: renaming with a physical register file, and the precise-interrupt problem that plain Tomasulo cannot solve — the bridge to the reorder buffer.