The bus has been the price of the idea from the start. Tomasulo's 1967 paper on the IBM System/360 Model 91 describes "a simple common data busing and register tagging scheme which permits simultaneous execution of independent instructions while preserving the essential precedences", for a machine that looked ahead about eight instructions. Only about fifteen Model 91s were built; the first went to NASA's Goddard Space Flight Center in October 1967. The scheme, and its single bus, outlived the machine.
Tomasulo under pressure: structural squeezes and CDB fights
After this lesson you will fill the Tomasulo table of a paper in which almost no cycle is lost to a true dependence, name the structural cause of every lost cycle, and say which piece of hardware would have bought it back.
In February 2025 the written exam handed out eight instructions and a Tomasulo machine with two load/store stations, two FP units and a single integer station. The ADDI near the end has both of its operands in the register file from the first cycle on, and the integer ALU is idle — yet it is issued only at cycle 11. Add a third load/store station to cure that wait, and the CPI does not move by a hundredth: still 22 cycles, still 2.75.
Three months later the midterm asked for a software-pipelined loop: ten instructions, every memory access a cache hit, not a single true dependence until the last two instructions. Tomasulo, the champion of out-of-order execution, needs 22 cycles for it: CPI 2.2.
Where do the cycles go? And if you could add one piece of hardware to each machine — a station, a unit or a bus — which one would you choose? Keep the question. The stepper in the middle of the lesson lets you try every candidate, and the last section gives the answer.
Two papers, one machine family
Both exercises use the machine family of every official paper: a few reservation stations per class (two, sometimes one), named functional units with a latency, a single Common Data Bus, all cache hits. The stage rules and the table conventions are the ones of lesson 12; here they are only applied. Two things change from paper to paper and decide everything: how many stations and units each class gets, and which class the instructions crowd into.
The February 2025 paper (notes, page 542) numbers its instructions I0 to I7; the notes print the registers of the older papers with a dollar sign ($F0, $R0), the June 2026 paper drops it, and so does this lesson.
I0: LD F0, A(R0)
I1: LD F2, B(R0)
I2: FADD F4, F0, F2
I3: FADD F6, F4, F4
I4: SD F4, C(R0)
I5: SD F6, D(R0)
I6: ADDI R0, R0, 4
I7: BNE R0, R1, LOOP
Machine of the February paper: 2 reservation stations (RS1, RS2) with 2 load/store units (LDU1, LDU2), latency 6; 2 reservation stations (RS3, RS4) with 2 FP units (FPU1, FPU2), latency 2; one reservation station (RS5) with 1 INT_ALU/BR unit (ALU1), latency 1. The memory latency is long, the FP latency short, and the integer class has a single station.
The midterm of 5 May 2025 (notes, page 514) numbers its loop body I1 to I10, as printed. It is the software-pipelined body that lesson 21 schedules on a VLIW; here it runs on Tomasulo, a different machine with different latencies, so do not compare the two CPIs.
I1: SD F4, 0(R1)
I2: SD F6, 0(R2)
I3: FADD F4, F0, F0
I4: FADD F6, F2, F2
I5: LD F0, 16(R1)
I6: LD F2, 16(R2)
I7: ADDUI R1, R1, 8
I8: ADDUI R2, R2, 8
I9: ADD R3, R2, R1
I10: BNE R3, R4, SP_LOOP
Machine of the midterm: 2 reservation stations (RS1, RS2) with 2 load/store units (LDU1, LDU2), latency 4; 2 reservation stations (RS3, RS4) with one FP unit (FPU1), latency 4; 2 reservation stations (RS5, RS6) with 2 INT_ALU/BR units (ALU1, ALU2), latency 2. Four memory instructions for two stations, two FP additions for one unit, and one bus for ten results.
The dependence tables, recomputed
Part 1 of the February exercise asks for every true, anti and output dependence of the fragment, "with I# for Fx". Read each instruction from its sources: a true dependence (RAW) is a source written by an earlier instruction; an anti-dependence (WAR) is a destination that an earlier instruction still reads; an output dependence (WAW) is a destination written twice. A store has no destination at all, so I4 and I5 can only be readers in such a table; and I3 reads F4 twice but owes it to I2 once.
| I# | Instruction | Analysis of dependences |
|---|---|---|
| I0 | LD F0, A(R0) | None |
| I1 | LD F2, B(R0) | None |
| I2 | FADD F4, F0, F2 | True data dependence with I0 for F0; true data dependence with I1 for F2 |
| I3 | FADD F6, F4, F4 | True data dependence with I2 for F4 (both sources, counted once) |
| I4 | SD F4, C(R0) | True data dependence with I2 for F4 (the store data) |
| I5 | SD F6, D(R0) | True data dependence with I3 for F6 |
| I6 | ADDI R0, R0, 4 | Anti-dependence with I0, I1, I4 and I5 for R0 (all four read R0 as the base register) |
| I7 | BNE R0, R1, LOOP | True data dependence with I6 for R0 |
Every destination (F0, F2, F4, F6, R0) is written exactly once, so there is no output dependence; the four anti-dependences sit on an integer register although the template says "$Fy" — write R0 anyway. The dependences that cross to the next iteration (the next I0 reads the R0 that I6 wrote) are not asked.
True dependences: six values the machine must wait for
Anti-dependences: four readers of R0 before I6 overwrites it
The midterm's body (notes, page 513) is the opposite picture. Software pipelining has moved the data chain out of the iteration: the stores read the F4 and F6 of the previous pass, the additions read the F0 and F2 loaded in the previous pass. What is left inside the body is name reuse, plus the control tail.
| I# | Instruction | Analysis of dependences |
|---|---|---|
| I1 | SD F4, 0(R1) | None |
| I2 | SD F6, 0(R2) | None |
| I3 | FADD F4, F0, F0 | Anti-dependence with I1 for F4 |
| I4 | FADD F6, F2, F2 | Anti-dependence with I2 for F6 |
| I5 | LD F0, 16(R1) | Anti-dependence with I3 for F0 |
| I6 | LD F2, 16(R2) | Anti-dependence with I4 for F2 |
| I7 | ADDUI R1, R1, 8 | Anti-dependence with I1 for R1; anti-dependence with I5 for R1 |
| I8 | ADDUI R2, R2, 8 | Anti-dependence with I2 for R2; anti-dependence with I6 for R2 |
| I9 | ADD R3, R2, R1 | True data dependence with I7 for R1; true data dependence with I8 for R2 |
| I10 | BNE R3, R4, SP_LOOP | True data dependence with I9 for R3 |
So the FP half of the midterm never waits for a value. Keep that in mind: every cycle it loses from here on is structural — a station, a unit or the bus was taken — and the exam's Hazards column must say so.
Issue in order, one per cycle, into a free station of the class (a station is busy from ISSUE through WRITE RESULT inclusive). START EXEC = ISSUE + 1, or the producer's WRITE RESULT + 1, or the cycle after the unit's previous instruction wrote its result, whichever is last. WRITE RESULT = START EXEC + latency, one result per cycle on the single CDB, oldest instruction first. A store's WRITE RESULT is its memory write. CPI = last WRITE RESULT / number of instructions. Calibrate every table on the row the paper gives you: a load with latency 4 is 1 / 2 / 6.
February: a closed door at cycle 5
Walk the February paper with the rules, a few cycles per step; the table after the steps is what they build.
Cycles 1–2.
I0issues into RS1 with its base register copied (Vk = R0) and starts on LDU1 at 2: six cycles, Write Result at 8.I1issues into RS2 at 2.Cycles 3–4.
I1starts on LDU2 (write at 9).I2issues into RS3 with neither operand ready: its fields hold the tags Qj = RS1 and Qk = RS2, the names of the stations that will produce F0 and F2 — parked, not stalled.I3issues into RS4 with Qj = Qk = RS3. Both FP stations are now full, both FP units idle: nobody has operands.Cycle 5 is the cycle of the lesson.
I4is a store and needs a load/store station; RS1 holdsI0through its Write Result at 8, RS2 holdsI1through 9. No station, no issue: structural hazard, written STRUCTURAL in the Hazards column. And because issue is in order, the door is shut for everybody:I5cannot issue,I6cannot issue although R0 and the constant 4 are ready and ALU1 is idle,I7cannot issue.Cycles 6–8. Only countdowns, until
I0broadcasts F0 with the tag RS1 at 8: RS3 captures it, and RS1 is free from the next cycle.Cycles 9–11.
I1broadcasts F2 at 9; RS3 has both operands;I4at last issues into RS1, with Qj = RS3 for its store data and Vk = R0. At 10I2starts on FPU1 (write at 12) andI5issues into RS2 with Qj = RS4. At 11I6issues into RS5 with both operands — six cycles late for a reason that has nothing to do with its own data.Cycles 12–13.
I2writes F4: RS4 and RS1 capture it;I6starts on ALU1.I7wants the only integer station, RS5, busy withI6through its write at 13: STRUCTURAL again. At 13I3starts on FPU2 (FPU1 would do as well: only the latency matters),I4starts its six-cycle store on LDU1, andI6writes the new R0 whileI4andI5, which read the old R0, have not finished — harmless, because each station holds its own copy.Cycles 14–22.
I7issues at 14 with the new R0 and starts at 15.I3writes F6 at 15 and RS2 captures it;I5starts at 16, the cycle in whichI7resolves. Then only countdowns:I4writes at 19,I5at 22.
| INSTRUCTION | ISSUE | START EXEC | WRITE RESULT | Hazards Type | RSi | UNIT |
|---|---|---|---|---|---|---|
I0: LD F0, A(R0) | 1 | 2 | 8 | None | RS1 | LDU1 |
I1: LD F2, B(R0) | 2 | 3 | 9 | None | RS2 | LDU2 |
I2: FADD F4, F0, F2 | 3 | 10 | 12 | RAW with I0 (F0), I1 (F2) | RS3 | FPU1 |
I3: FADD F6, F4, F4 | 4 | 13 | 15 | RAW with I2 (F4) | RS4 | FPU2 |
I4: SD F4, C(R0) | 9 | 13 | 19 | Structural (RS1, RS2 busy, cycles 5–8); RAW with I2 (F4) | RS1 | LDU1 |
I5: SD F6, D(R0) | 10 | 16 | 22 | RAW with I3 (F6); issue delayed behind I4 | RS2 | LDU2 |
I6: ADDI R0, R0, 4 | 11 | 12 | 13 | None (WAR with I0, I1, I4, I5 on R0: solved by renaming) | RS5 | ALU1 |
I7: BNE R0, R1, LOOP | 14 | 15 | 16 | Structural (RS5 busy, cycles 12–13); RAW with I6 (R0) | RS5 | ALU1 |
The eight Write Result cycles — 8, 9, 12, 13, 15, 16, 19, 22 — are all different, so the single bus never has to choose. That is why this paper is the clean one: its 22 cycles are made of the long memory latency and one structural hole.
What the hole did not change
Here is the first half of the puzzle. Give the February machine a third load/store station. I4 now issues at 5 (into RS3, with the FP stations renumbered RS4 and RS5), I5 at 9, I6 at 10 and I7 at 14; I6 even loses the bus at cycle 12 to the older I2 and writes at 13. The last Write Result is still 22, the CPI still 2.75. Look at the arrows of Fig. 2: I1 broadcasts at 9, I2 computes 10–11 and broadcasts at 12, I3 computes 13–14 and broadcasts at 15, I5 stores 16–21 and writes at 22. That chain is made of latencies and broadcasts only; no station count shortens it. What shortens it is a shorter latency: with FP latency 4 instead of 2 the same chain ends at 26 (CPI 3.25); with memory latency 4 instead of 6 it ends at 18 (CPI 2.25).
A missing station delays when instructions enter; a dependence chain of latencies decides when the last one leaves — and the table's last cycle belongs to the chain.
The midterm: when the bus is the bottleneck
Now the midterm, where the FP side owes nothing to anybody. Step through it; the table and the timeline below are the result.
Cycles 1–4.
I1issues into RS1 with its copy of F4 and starts the store at 2 (latency 4: write at 6), so RS1 is busy through 6.I2issues at 2, starts at 3, writes at 7.I3issues at 3 with F0 ready in both operand fields and starts on FPU1 at 4 (write at 8).I4issues at 4 with F2 ready.Cycle 5.
I4has its operands, but the only FP unit belongs toI3through its Write Result at 8 — a structural wait at Start Exec, not at issue: Start Exec 9, Write Result 13. The single unit costs it four cycles (Start Exec 9 instead of 5). AndI5, a load, finds RS1 busy until 6 and RS2 until 7: the door is shut again, this time for two cycles.Cycles 6–11.
I1writes at 6,I2at 7,I3broadcasts F4 at 8 — nobody waits for it:I1copied the old F4 at cycle 1, which is the anti-dependence being free.I5issues at 7, the cycle after RS1's release, and starts at 8;I6issues at 8, starts at 9;I7issues at 9, starts on ALU1 at 10;I8issues at 10, starts on ALU2 at 11 — each two cycles later than its ideal slot. At 11I9wants an integer station: RS5 and RS6 are both busy, so it waits, andI10waits behind it.Cycle 12 starts the fight. Two results are ready:
I5(started 8, latency 4) andI7(started 10, latency 2). One bus, one result per cycle, oldest first:I5writes F0,I7waits and keeps RS5.Cycles 13–16. At 13 four results are ready —
I4(9 + 4),I6(9 + 4),I7,I8(11 + 2). The oldest,I4, writes F6; thenI6writes F2 at 14,I7writes R1 at 15 andI8writes R2 at 16, in program order.I7's write slipped from 12 to 15, so RS5 is free only from 16.Cycle 16.
I9issues into RS5, blocked since 11: three of its five lost cycles are the bus queue, two the two-cycle latency of the ADDUIs. R1 is in the register file and R2 is broadcast in this very cycle, so the station holds both values by the end of it.Cycles 17–22.
I9starts on ALU1 at 17 and writes R3 at 19.I10issues at 17 into RS6 with Qj = RS5 (the station ofI9) and Vk = R4, captures R3 from the bus at 19, starts on ALU2 at 20 and writes at 22. Ten instructions, 22 cycles, CPI 2.2 — and the only true wait in the whole table is the two cyclesI10spends on R3; everything else was a station, a unit or the bus.
| INSTRUCTION | ISSUE | START EXEC | WRITE RESULT | Hazards Type | RSi | UNIT |
|---|---|---|---|---|---|---|
I1: SD F4, 0(R1) | 1 | 2 | 6 | None | RS1 | LDU1 |
I2: SD F6, 0(R2) | 2 | 3 | 7 | None | RS2 | LDU2 |
I3: FADD F4, F0, F0 | 3 | 4 | 8 | WAR with I1 (F4): no stall | RS3 | FPU1 |
I4: FADD F6, F2, F2 | 4 | 9 | 13 | Structural (FPU1 busy with I3 until 8); WAR with I2 (F6): no stall | RS4 | FPU1 |
I5: LD F0, 16(R1) | 7 | 8 | 12 | Structural (RS1, RS2 busy, cycles 5–6); WAR with I3 (F0): no stall | RS1 | LDU1 |
I6: LD F2, 16(R2) | 8 | 9 | 14 | Structural (CDB at 13: I4 writes first); WAR with I4 (F2): no stall | RS2 | LDU2 |
I7: ADDUI R1, R1, 8 | 9 | 10 | 15 | Structural (CDB at 12, 13, 14: I5, I4, I6 write first); WAR with I1, I5 (R1): no stall | RS5 | ALU1 |
I8: ADDUI R2, R2, 8 | 10 | 11 | 16 | Structural (CDB at 13, 14, 15); WAR with I2, I6 (R2): no stall | RS6 | ALU2 |
I9: ADD R3, R2, R1 | 16 | 17 | 19 | Structural (RS5, RS6 busy, cycles 11–15); RAW with I7 (R1), I8 (R2) | RS5 | ALU1 |
I10: BNE R3, R4, SP_LOOP | 17 | 20 | 22 | RAW with I9 (R3) | RS6 | ALU2 |
Count where the 22 cycles come from and you find three structural causes — two load/store stations too few at 5–6, one FP unit at 5–8, one bus at 12–16 — and a single true wait, the two cycles I10 spends on R3. The causes form one chain from the first cycle to the last: I1's write at 6 frees RS1 for I5 (issue 7, write 12); the bus queue pushes I7's write to 15, which frees RS5 for I9 (issue 16, write 19); I10 starts at 20 and writes at 22.
Tags, not registers
Cycle 17 shows the one idea of Tomasulo that the exam checks in the station snapshots. I10 issues although R3 does not exist yet: a station needs no values to be allocated, only a free slot. In the Qj field of RS6 it writes the tag of the producer — RS5, the station holding I9 — and from then on it listens to the bus. When I9 finishes on ALU1, the bus carries the pair <RS5, value>; RS6 compares the tag with its Qj, matches, copies the value into Vj and clears Qj. The register file does the same with its own tag field for R3. Nothing in this exchange names ALU1. A unit is not a producer: it serves one station after another (ALU1 runs I7, then I9; in the FP class RS3 and RS4 share the single FPU1), so "the result of ALU1" would not say which instruction's result it is. The tag is the station, because a station holds exactly one instruction from issue to Write Result.
One bus, one result per cycle, oldest first — and a result that waits for the bus keeps its station, so the bus can block the issue of instructions that never needed a bus at all.
Step it, then change the machine
The stepper runs both papers, and the official June 2025 paper as a contrast, with the conventions of this course. Every cycle lists its events and its refusals — a shut door, a busy unit, a lost bus — and the table and the timeline fill in as you go. The what-if controls change the machine relative to the paper: a second bus or unlimited buses, one more FP unit, one more load/store or integer station.
The what-if table
Every number below comes from the same rules as the two tables above; the stepper reproduces each line.
| Paper | Change | Last WRITE RESULT | CPI | Why |
|---|---|---|---|---|
| Midterm | as in the paper | 22 | 2.2 | bus queue 12–16 holds RS5/RS6, I9 issues at 16 |
| Midterm | a second CDB | 20 | 2.0 | I7 writes at 12, I9 issues at 13; only I8 still loses one cycle at 13 |
| Midterm | unlimited CDBs | 19 | 1.9 | no collision at all; what is left is latency |
| Midterm | a second FP unit | 21 | 2.1 | I4 writes at 9 instead of 13, but the ADDUIs still queue behind I5 and I6 |
| Midterm | a third integer station | 22 | 2.2 | I9 issues at 11 but still waits for R2 at 16; I10 waits for a station until 16 |
| Midterm | a third load/store station | 21 | 2.1 | I5 issues at 5; the whole queue moves one cycle earlier |
| February | as in the paper | 22 | 2.75 | chain I1 → I2 → I3 → I5: 9, 12, 15, 22 |
| February | a third load/store station | 22 | 2.75 | I4 issues at 5, the chain does not move |
| February | FP latency 4 instead of 2 | 26 | 3.25 | two FP operations on the chain, +2 each |
| February | memory latency 4 instead of 6 | 18 | 2.25 | two memory operations on the chain, −2 each |
Before: one bus — five results, cycles 12 to 16; I9 issues at 16, the last write is 22
After: two buses — I7 writes at 12, I9 issues at 13, the last write is 20
The official contrast: when the bus bites twice
The official paper of 10 June 2025 uses the same exercise family with two units in every class, latencies 4, 3 and 2. Its three loads fill the two load/store stations at once, so I2 issues only at 7; and twice two results are ready in the same cycle. Here is the model answer in this course's conventions (no official solution exists; the numbers are recomputed).
I0: FOR: LD F2, A(R1)
I1: LD F4, B(R1)
I2: LD F6, C(R1)
I3: FADD F4, F2, F4
I4: FADD F6, F4, F6
I5: SD F6, A(R1)
I6: ADDUI R1, R1, 8
I7: BNE R1, R2, FOR
| INSTRUCTION | ISSUE | START EXEC | WRITE RESULT | Hazards Type | RSi | UNIT |
|---|---|---|---|---|---|---|
I0: LD F2, A(R1) | 1 | 2 | 6 | None | RS1 | LDU1 |
I1: LD F4, B(R1) | 2 | 3 | 7 | None | RS2 | LDU2 |
I2: LD F6, C(R1) | 7 | 8 | 12 | Structural (RS1, RS2 busy, cycles 3–6) | RS1 | LDU1 |
I3: FADD F4, F2, F4 | 8 | 9 | 13 | RAW with I0 (F2), I1 (F4), satisfied at issue; Structural (CDB at 12: I2 first); WAW with I1 (F4): renamed | RS3 | FPU1 |
I4: FADD F6, F4, F6 | 9 | 14 | 17 | RAW with I3 (F4), I2 (F6); WAW with I2 (F6): renamed | RS4 | FPU2 |
I5: SD F6, A(R1) | 10 | 18 | 22 | RAW with I4 (F6) | RS2 | LDU2 |
I6: ADDUI R1, R1, 8 | 11 | 12 | 14 | None (WAR with I0, I1, I2, I5 on R1: renamed) | RS5 | ALU1 |
I7: BNE R1, R2, FOR | 12 | 15 | 18 | RAW with I6 (R1); Structural (CDB at 17: I4 first) | RS6 | ALU2 |
Two things to say on the sheet. First, whether a branch takes a bus slot is not stated in the papers; this course lets it (it writes at 18), and an answer that writes 17 with the remark "the branch produces no register value" is defensible — the CPI is 22 / 8 = 2.75 either way, because the store I5 ends the table. Second, write the collision explicitly: "Structural (CDB at 12: I2 writes first)" is what turns a right number into a justified one.
The puzzle, answered
February: no station, no unit and no bus would change 22. Its last cycle is the chain F2 → F4 → F6 → memory, 6 + 2 + 2 + 6 cycles of latency plus the broadcasts between them; the shut door delayed four instructions by four cycles and cost not one cycle of the total. The only hardware that helps is faster hardware. The midterm: the bus. A second CDB takes the loop from 22 to 20 cycles, unlimited buses to 19, while a second FP unit buys one cycle and a third integer station none. Two ALUs sat idle for most of the 22 cycles; what they were waiting for was a slot on the bus and a free station behind it.
Reading and writing the Hazards column
The column is where the examiner sees whether you know why a number is what it is. Write one label per cause, in the order the causes happened to the row. None: nothing delayed the row — issue at the cycle after the previous instruction, start the cycle after issue, write at start plus latency. Structural (which stations, which cycles): the row issued late because every station of its class was busy; name the stations and the cycles, as in "RS1, RS2 busy, cycles 5–8". A row behind such a row issued late too: say "issue delayed behind I4". Structural (unit): the row started late because the unit was busy — "FPU1 busy with I3 until 8". Structural (CDB at c: I# first): the row wrote late because an older result took the bus. RAW with I# (Fx): the row started the cycle after that producer's Write Result; if the operand was already there at issue, say so, as the June table does. WAR / WAW with I# (Fx): renamed: optional, and worth a line, because it shows you know they cost nothing.
"It could not start because of a WAR hazard" is never right in a Tomasulo table; "it could not issue because the unit was busy" is never right either. Issue checks stations; Start Exec checks operands and units; Write Result checks the bus. Put each cause at its stage and the cycle numbers follow.
Two of these causes are present in every exam machine, whatever the code: the single bus and the non-pipelined units. The second widget isolates them on a small fragment with a mix of dependent and independent instructions. Machine: 2 load/store stations with LDU1 and LDU2 (latency 4), 3 FP stations with one FPU1 (latency 3), 2 integer stations with one ALU1 (latency 2).
I0: LD F0, 0(R1)
I1: LD F2, 8(R1)
I2: FMUL F4, F0, F0
I3: FMUL F6, F2, F2
I4: FADD F8, F4, F6
I5: ADDUI R1, R1, 16
I6: SUBI R2, R2, 1
I7: BNE R2, R3, LOOP
Every exam table hides the same two taxes: a non-pipelined unit spreads results out, a single bus serialises the ones that still arrive together — and both are paid at Write Result, where the station is released.
Exam-style questions
Explain the main concepts and benefits of each one of the following techniques used by a Tomasulo-style processor: (1) reservation stations; (2) tags on the Common Data Bus; (3) in-order issue with out-of-order execution. For each, say what it costs, with an example from an exercise.
Show model answer
(1) A reservation station is a buffer in front of a class of functional units that holds an issued instruction together with its operand values (Vj, Vk) if they are already available, or the tags (Qj, Qk) of the stations that will produce them. Benefits: the instruction leaves the issue stage without waiting for its operands, so later independent instructions can issue; the station is also the renamed destination, which removes WAR and WAW stalls (the February 2025 ADDI overwrites R0 while two stores still hold their copies of the old R0). Cost: the number of stations bounds what can be issued; when every station of a class is busy, issue stalls (RS1 and RS2 busy at cycles 5–8 of the February paper).
(2) When a unit finishes, the result is broadcast on the Common Data Bus as the pair (tag, value), the tag being the station of the producer. Every station and register whose Qj, Qk or tag field matches captures the value in the same cycle, so a consumer can start the next cycle without a trip through the register file and without a stall on name dependences. Cost: one bus delivers one result per cycle; when two are ready the older goes first and the younger waits, keeping its station (midterm 2025, cycles 12–16: five results, I7 writes at 15 instead of 12).
(3) Instructions issue strictly in program order, one per cycle, but start executing as soon as their own operands and a unit are available, and finish out of order: long-latency instructions no longer block independent ones (I6 ADDI executes at 12 while the FP work is pending), the hardware tolerates unpredictable latencies such as cache misses, and the compiler needs no knowledge of the pipeline. Cost: in-order issue means one blocked instruction blocks everything behind it; out-of-order completion makes exceptions imprecise, and nothing can pass an unresolved branch until a reorder buffer (lesson 17) adds speculation.
Each sub-point is worth a short labelled block: concept, benefit, cost, example. A complete answer names the tag as the station, says that WAR/WAW cost nothing and why, and states the structural limits (stations, bus) next to the benefits.
Let's consider the following assembly code containing multiple types of intra-loop dependences. Complete the dependence table (true data dependence with I# for Fx; anti-dependence with I# for Fy; output dependence with I# for Fz). Then consider the code executed on a CPU with dynamic scheduling based on the 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 2 FP units (FPU1, FPU2) with latency 3; 2 reservation stations (RS5, RS6) with 2 INT_ALU/BR units (ALU1, ALU2) with latency 2. Complete the table (ISSUE, START EXEC, WRITE RESULT, Hazards Type, RSi, UNIT), rows I0 (1, 2, 6, None, RS1, LDU1) and I1 (2, 3, 7, None, RS2, LDU2) given, and calculate the CPI.
I0: FOR: LD F2, A(R1)
I1: LD F4, B(R1)
I2: LD F6, C(R1)
I3: FADD F4, F2, F4
I4: FADD F6, F4, F6
I5: SD F6, A(R1)
I6: ADDUI R1, R1, 8
I7: BNE R1, R2, FOR
Show model answer
Dependences: I0, I1, I2: none. I3: true with I0 for F2 and with I1 for F4; output with I1 for F4. I4: true with I3 for F4 and with I2 for F6; output with I2 for F6. I5: true with I4 for F6. I6: anti with I0, I1, I2 and I5 for R1. I7: true with I6 for R1.
| INSTRUCTION | ISSUE | START EXEC | WRITE RESULT | Hazards Type | RSi | UNIT |
|---|---|---|---|---|---|---|
| I0 LD F2 | 1 | 2 | 6 | None | RS1 | LDU1 |
| I1 LD F4 | 2 | 3 | 7 | None | RS2 | LDU2 |
| I2 LD F6 | 7 | 8 | 12 | Structural (RS1, RS2 busy, cycles 3–6) | RS1 | LDU1 |
| I3 FADD F4 | 8 | 9 | 13 | RAW with I0, I1 (ready at issue); Structural (CDB at 12: I2 first) | RS3 | FPU1 |
| I4 FADD F6 | 9 | 14 | 17 | RAW with I3 (F4), I2 (F6) | RS4 | FPU2 |
| I5 SD F6 | 10 | 18 | 22 | RAW with I4 (F6) | RS2 | LDU2 |
| I6 ADDUI R1 | 11 | 12 | 14 | None (WAR on R1 renamed) | RS5 | ALU1 |
| I7 BNE | 12 | 15 | 18 | RAW with I6 (R1); Structural (CDB at 17: I4 first) | RS6 | ALU2 |
CPI = 22 / 8 = 2.75.
The three moves that earn the points: I2 waits four cycles for a station and drags I3–I7 with it; the single bus pushes I3 (12 → 13) and I7 (17 → 18) by one cycle; the chain I2 → I4 → I5 fixes the end at 22. State the branch-on-CDB convention in one line; 17 with the reason "the branch produces no register value" is a defensible alternative, and the CPI is the same.
The midterm 2025 code of this lesson runs on the same machine but with two FP units (FPU1, FPU2) of latency 4, still a single Common Data Bus. Complete the table and calculate the CPI.
Show model answer
I1 1 / 2 / 6 RS1 LDU1; I2 2 / 3 / 7 RS2 LDU2; I3 3 / 4 / 8 RS3 FPU1; I4 4 / 5 / 9 RS4 FPU2 (no unit wait); I5 7 / 8 / 12 RS1 LDU1 (structural: RS1, RS2 busy at 5–6); I6 8 / 9 / 13 RS2 LDU2; I7 9 / 10 / 14 RS5 ALU1 (ready at 12: CDB taken by I5 at 12 and I6 at 13); I8 10 / 11 / 15 RS6 ALU2 (ready at 13: behind I6 and I7); I9 15 / 16 / 18 RS5 ALU1 (RS5 free after 14; R2 arrives at 15); I10 16 / 19 / 21 RS6 ALU2 (R3 at 18). CPI = 21 / 10 = 2.1.
One cycle better than with one FP unit: the second unit removes I4's wait, but the ADDUIs still queue behind the loads on the bus and hold the integer stations. Write the queue 12–15 into the Hazards column as "Structural (CDB)": it is the reason the numbers are what they are.
In the February 2025 exercise the FP latency becomes 4 instead of 2; everything else is unchanged. Give the last WRITE RESULT cycle and the CPI.
Show model answer
I2 starts 10, writes 14; I3 starts 15, writes 19; I4 starts 15 (F4 at 14), writes 21; I6 11 / 12 / 13 and I7 14 / 15 / 16 unchanged; I5 starts 20 (F6 at 19), writes 26. Write cycles 8, 9, 13, 14, 16, 19, 21, 26: no bus collision. Last WRITE RESULT = 26, CPI = 26 / 8 = 3.25.
Only the two FP operations of the chain move, by two cycles each; the structural hole at 5–8 and the integer tail are untouched.
In the February 2025 exercise the BNE cannot issue at cycle 12 because: (single answer)
Show model answer
Answer 3: STRUCTURAL on RS5, the single integer station, busy with I6 through cycle 13.
The notes argue on page 552 whether the label should name RS5 or ALU1: in the issue stage it is the station that is checked.
In the Tomasulo algorithm a reservation station is released: (single answer)
Show model answer
Answer 3. This is why a result that waits for the bus delays the issue of later instructions.
Calibrate on the given row: a load that writes at 6 lets the next load/store instruction take its station at 7.
True or false: "A single Common Data Bus can delay the issue of later instructions."
Show model answer
True. Motivation: stations are released at WRITE RESULT; a write delayed by bus arbitration keeps the station busy, and in-order issue stalls on the missing station.
The one-point motivation is the chain bus → station → issue; name the cycles of an exercise.
Check yourself
February paper: at cycle 5 the ADDI has both operands in the register file and ALU1 is idle, yet it issues only at cycle 11. Why?
Which of these changes shorten the midterm's 22 cycles? (several answers)
The picture to keep: the ALUs idle, the bus crowded, the stations held by results that cannot leave.
Midterm, cycle 13: I4, I6, I7 and I8 are all ready to write. Which one writes, and what happens to the others?
At cycle 17 of the midterm I10 issues into RS6 while R3 does not exist yet. What does RS6 hold in Qj?
A third load/store station is added to the February machine: I4 issues at 5 instead of 9, yet the last WRITE RESULT is still 22. Why?
The February ADDI writes the new R0 at cycle 13 while I4 and I5, which read the old R0, have not executed yet. Why is the result still correct?
Key take-aways
- Issue is in order and needs a free station of the class: one missing station is a stall for every instruction behind it, whatever its class and however ready its operands (February, cycles 5–8; the midterm, cycles 5–6 and 11–15).
- A station is busy from ISSUE through WRITE RESULT; a result that waits for the bus keeps its station, so the bus can delay issues.
- One CDB, one result per cycle, oldest instruction first; the midterm's queue 12–16 is the whole reason I9 issues at 16 and the loop takes 22 cycles.
- A non-pipelined unit is busy through the Write Result of its instruction; the second FADD of the midterm waits four cycles for FPU1 (Start Exec 9 instead of 5).
- Tags are station names: Qj = RS5 for the midterm's branch, Qj = RS1 and Qk = RS2 for the February FADD — never a unit, never a register.
- Anti- and output dependences cost nothing: readers keep copies, the register's tag is overwritten; the February ADDI overwrites R0 at 13 with two readers still pending.
- The last cycle of a table belongs to a chain of latencies, not to the stations: February stays at 22 with a third station and moves to 26 or 18 when a latency changes; the midterm answers to the bus (20 with two, 19 unlimited) more than to a second FP unit (21).
What to watch and read
-
Tomasulo Timing Quiz Part 2 — Georgia Tech HPCA
Udacity (Milos Prvulovic)
A ready-made drill with the shape of Exercise 1: pause, fill issue / start / write for each instruction with one CDB, then check with the solution clip (Quiz Solution). Compare its conventions with this course's before trusting a number.
-
CS252 Lecture 7: Scoreboard, Tomasulo, Register Renaming
UC Berkeley, John Kubiatowicz
The Hennessy and Patterson tables as slides, in the same mnemonics as the notes and the papers: the right second source when a notes snapshot looks wrong, as the tag cells of pages 545–546 do.
-
Dynamic Scheduling with Tomasulo Algorithm — simulator
Virtual Labs, IIIT Hyderabad
Set the latencies of the exercise, type the loop body and step: the stations, the register alias table and the CDB activity are drawn live, so you can check a table you filled by hand.
-
Lecture 15: Out-of-Order Execution
Onur Mutlu, ETH Zürich
Tomasulo as "restricted dataflow": the tag as a promise of a value, the station as a waiting room, the bus as the loudspeaker — the mental model behind every cycle of this lesson, plus why issue stays in order.
-
An Efficient Algorithm for Exploiting Multiple Arithmetic Units (1967)
R. M. Tomasulo, IBM Journal of Research and Development
Read the abstract and the "common data bus" section: the single bus and the tags are there from the first page, and you will recognise Vj, Vk, Qj, Qk in Tomasulo's sink and source fields.