62 cycles, one at a time: the scoreboard example and the exam table

After this lesson you will recompute the notes' 62-cycle example from the four rules of the scoreboard, point at the table cell that holds each waiting instruction, and fill the January 2026 scoreboard table in both of its schemes — with the CPI and the speedup.

In the notes' example the last instruction, FADD F6, F8, F2, finishes computing at cycle 16. Its sum is correct and sits inside the Add unit. The scoreboard lets it write F6 only at cycle 22: five full cycles with the answer in hand. Nothing is wrong with the adder and nothing is wrong with the sum. Why the ban, what would break if the write went through at 17, and which single cell of the three tables enforces it?

A second puzzle, from the paper of 8 January 2026 (reproduced in the notes from page 479): seven instructions, row I0 given as 1 / 2 / 5 / 6. On the basic scoreboard they take 25 cycles. Switch on forwarding and postpone the WAW check to write-back and they take 21. Which of the two switches is worth more — and why do their savings not add up?

Both answers are one table cell each. First the run, cycle by cycle.

Six instructions, five units, four rules

The example is the one the notes walk on pages 115–139, one page per cycle, with the cells that changed highlighted in yellow. Here it is in the mnemonics of the exam papers; the notes write it in Hennessy and Patterson's spelling (LD, MULTD, SUBD, DIVD, ADDD), which means the same thing.

I0: LD   F6, 34(R2)
I1: LD   F2, 45(R3)
I2: FMUL F0, F2, F4   ; RAW F2
I3: FSUB F8, F6, F2   ; RAW F6, F2
I4: FDIV F10, F0, F6  ; RAW F0, F6
I5: FADD F6, F8, F2   ; RAW F8, F2
                      ; WAW F6, WAR F6

The machine: one Integer unit for the loads (latency 1 — every access is a cache hit), one Add unit for FADD and FSUB (2 cycles), two multipliers Mult1 and Mult2 (10 cycles), one Divide unit (40 cycles). The scheme is the basic one of lesson 9: WAW checked at Issue, no forwarding. The notes' Figure 25 (page 109) carries other latencies, 1, 4, 7, 7 and 24; they are illustrative. Latencies always come from the exercise text.

Before touching a table, list the dependences, as the exam's dependency-analysis question does. Seven true dependences: F6 feeds I3 and I4; F2 feeds I2, I3 and I5; F0 feeds I4; F8 feeds I5. One output dependence: I0 and I5 both write F6. Two anti-dependences: I3 and I4 read F6 before I5 overwrites it. Figure 1 draws them, and marks the chain that will decide the whole count.

I0 LD F6, 34(R2) I1 LD F2, 45(R3) I2 FMUL F0, F2, F4 I3 FSUB F8, F6, F2 I4 FDIV F10, F0, F6 I5 FADD F6, F8, F2 F2 F2 F0 F8 F6 F6 F2 WAR F6 WAR F6 WAW F6 critical chain
Fig. 1. The dependences of the example. Solid orange arrows are true dependences (RAW), labelled with the register; the dashed arrows are the two anti-dependences and the dotted one the output dependence, all on F6. The highlighted chain I1 → I2 → I4 — a load, a 10-cycle multiply and a 40-cycle divide — is what the 62 cycles are made of.

Every number of the run comes from the four rules of lesson 9, which the stepper there ran on a smaller fragment. Restated in one line each, in the form you will use them:

"LD F6, 34(R2) is issued and begins execution." Not in cycle 1: it only issues. It reads R2 in cycle 2 and accesses memory in cycle 3 — the table on the same page is right (Issue = 1, nothing else). Every row of the exam table starts this way: one cycle to issue, one to read, then the latency.

Four questions fill a row: is my unit free and my destination unpromised; when was the last of my sources written; add the latency; has every earlier reader of my destination read it.

Cycles 1 to 12: a busy unit and the RAW jungle

Cycle 1. I0 issues on the Integer unit; the register result entry of F6 becomes "Integer". Cycle 2. I0 reads R2. I1 wants to issue. It depends on nobody — but the only Integer unit is Busy: a structural hazard, and because issue is in order nothing behind I1 moves either. Cycle 3. I0 accesses memory, its one execution cycle. Cycle 4. I0 writes F6. The unit is still Busy in its write cycle, so I1 waits once more. Three cycles lost on the one unit that both loads need; keep the number, it comes back at the end.

Cycle 5. I1 issues; F2 is promised to the Integer unit. Cycle 6. I1 reads R3. I2 (FMUL) issues on Mult1 — the unit is free and nobody is due to write F0 — and copies "Integer" into its Qj: Rj = No, it waits for F2. Cycle 7. I1 completes (a hit). I3 (FSUB) issues on the Add unit: F6 is in the register file (Rj = Yes), F2 is not (Qk = Integer, Rk = No). Cycle 8. I1 writes F2, and the write wakes two rows at once: Rj of Mult1 and Rk of Add flip to Yes. I4 (FDIV) issues on the Divide unit and waits for F0 from Mult1. A cascade is forming: FDIV waits for FMUL, which waited for the load.

Cycle 9. FMUL and FSUB read their operands in the same cycle — the notes assume a register file with enough read ports ("e.g., 4 read ports", page 124) — and the Time counters start at 10 and 2. I5 (FADD) cannot issue: not because of F6, whose register result entry has been blank since cycle 4, but because the Add unit is Busy with FSUB. The second structural stall. Cycle 11. FSUB completes: Time = 0, E = 11. Cycle 12. FSUB writes F8. Its WAR test passes trivially — no row lists F8 as an unread source; FADD is not even in the machine — and the Add unit is free from cycle 13.

Sixty-two cycles on one slider

The notes' example on the basic scoreboard: the instruction status table as it stands at the end of the chosen cycle (cells that changed in that cycle are highlighted), the timeline below it, and the log of what happened. The switches change the machine: forwarding, the postponed WAW check, a second load unit, a second adder, a shorter divide. The total and the CPI follow.

  1. Before you move anything: in which cycle does I1, the second load, issue, and which cell of the tables holds it until then? Then press Next cycle up to cycle 5 and read the log of each cycle on the way.
    What you should see

    Cycle 5. The Integer row says Busy = Yes from cycle 1 through cycle 4 — the cycle in which I0 writes — so the structural check at Issue fails three times. No data is involved: I1 depends on nobody.

  2. Go to cycle 9. Predict which two instructions read their operands in this cycle, and why I5 cannot issue although the register result entry of F6 is blank.
    What you should see

    FMUL and FSUB both read: both were waiting for the same write of F2 at cycle 8. I5 is refused by the Add row's Busy = Yes — FSUB holds the unit through its write at 12 — not by a WAW, which ended when I0 wrote F6 at cycle 4.

  3. Step from 16 to 22 and watch the bar of I5. Predict what the dashed segment after its execution means and in which cycle it ends.
    What you should see

    Execution is over at 16; the dashed bar is the WAR wait at Write Result, cycles 17 to 21: FDIV has not read F6. It ends at 22, the cycle after FDIV reads (21). The hazard delays only the write.

  4. Now the switches, one at a time, with a prediction before each: forwarding only; a second load unit only; both; a second adder only.
    What you should see

    60, 59, 57 and 62. Forwarding takes one cycle out of each of the two RAW links of the chain (F2 → FMUL, F0 → FDIV); the second load unit removes the three-cycle structural stall of I1; the second adder changes nothing, because FSUB and FADD are not on the chain — FADD issues at 9 instead of 13 and still writes at 22, behind FDIV's read.

Three of the 62 cycles are lost at the very start: the second load, the head of the critical chain, waits for the only Integer unit, which is Busy through the first load's write result.

Cycles 13 to 22: an out-of-order read, and a write that must wait

Cycle 13. I5 (FADD) issues on the Add unit: no structural hazard any more, and the register result entry of F6 is blank — the WAW with I0 was over at cycle 4. Its sources: F8, written at 12, so Rj = Yes; F2, written at 8, so Rk = Yes. Nothing holds it. Cycle 14. FADD reads F8 and F2 — before FDIV, issued at 8, has read anything. This is the out-of-order read that the split of ID was built for: each issued instruction waits only for its own two flags. Cycles 15–16. FADD executes; E = 16.

Cycle 17. FADD asks to write F6. The Write Result test scans the unit rows for a row that has F6 as a source with its flag still Yes — and finds one: the Divide row, Fk = F6, Rk = Yes. FDIV, an earlier instruction, has not read the old F6; it is still waiting for F0. Refused. The sum stays inside the Add unit, the unit stays Busy, and nothing else is touched: issue is long over, and no other instruction wants the adder. The notes' page 132 says it exactly: "WAR hazards delay write-back, not execution."

What would break. FDIV computes F0 / F6 and, because it comes before FADD in program order, must see the F6 that I0 loaded. If FADD wrote at 17, FDIV at 21 would read F8 + F2 — a value from an instruction that comes after it. (In this particular program F8 + F2 = (F6 − F2) + F2 happens to be the loaded F6 again in exact arithmetic; floating-point rounding would expose the difference, and the hardware neither knows nor cares: it protects the order of the names, not the values.)

Cycles 17–19. Mult1's Time, 3 at the end of cycle 16, goes 2, 1, 0: FMUL completes at 19, not 18. Cycle 20. FMUL writes F0. Its own WAR test looks at the Divide row: Fj = F0, but Rj = No — FDIV is waiting for exactly this write — so the write is allowed; it flips Rj to Yes and clears the register result entry of F0. Cycle 21. FDIV reads F0 and F6; both flags go to No; Time = 40. Cycle 22. FADD's test now passes (Rk = No in the Divide row) and it writes F6. FDIV executes from 22 to 61 and writes F10 at 62. Figure 2 is the before and after of the one cell that decided.

Name Busy Fi Fj Fk Rj Rk Time Add Yes F6 F8 F2 No No 0 Divide Yes F10 F0 F6 No Yes — F6 will be written by: Add I4 has not read F6 yet

Before: end of cycle 16 — I5 may not write

Name Busy Fi Fj Fk Rj Rk Time Add No — — — — — — Divide Yes F10 F0 F6 No No 39 F6 will be written by: — read at 21, written at 22

After: end of cycle 22 — F6 written, unit free

Fig. 2. The WAR hazard on F6 as the functional-unit status table sees it. Left, the end of cycle 16: FADD is done (Time 0), but the Divide row still lists F6 as an unread source, Rk = Yes, and that one cell refuses the write. Right, the end of cycle 22: FDIV read its operands at 21, the flag turned to No, FADD wrote at 22 and the Add unit is free. The register result table played no part in the decision.

The write that must wait

Cycles 16 to 22 of the run, one per step, as the two rows that matter stand at the end of each cycle, with the Write Result test for FADD spelled out underneath. The second switch breaks the rule and lets FADD write as soon as it is done, so you can see what FDIV would read.

  1. Before stepping: name the single cell that forbids FADD's write at the end of cycle 16 — table, row, column, value. Then look for the orange frame.
    What you should see

    Functional-unit status, row Divide, column Rk, value Yes: FDIV lists F6 as its second source and has not read it. The register result status (F6 = Add) is not consulted; it only knows who will write F6.

  2. Predict the cycle at the end of which the frame disappears, and what happens in that cycle. Then step until it does.
    What you should see

    End of cycle 21: FDIV reads F0 and F6, and both flags go to No. The flag could not flip earlier, because FDIV could not read before FMUL had written F0 at 20. FADD writes in the next cycle, 22.

  3. Switch on "break the rule" and step to cycle 21. What does FDIV read as F6, and what does that mean for the program?
    What you should see

    The value FADD wrote at 17 — the result of an instruction that comes after FDIV in program order. The sequential meaning of the program is broken; the hardware has no way to know that in this program the two values happen to coincide. That is what a WAR hazard is, and why the writer waits.

  4. With the rule broken or kept, does the E column of FADD change?
    What you should see

    No: E = 16 either way. The hazard moves one number only, the WB of the writer; execution is never delayed by a WAR. The notes' page 128 says the opposite for cycle 13 — see the red pen below.

A WAR hazard moves one number of the table, the writer's WB. The cell that decides is the earlier reader's flag — Rk = Yes in the Divide row — and it flips at that reader's RR.

Where the 62 cycles went: the chain, the CPI and four what-ifs

The whole run in the format of the exam, recomputed cell by cell with the rules above (and by the engine of the widget, which agrees with the notes' final table on page 139):

The notes' example on the basic scoreboard — Integer 1, Add 2, Mult 10, Divide 40; WAW at Issue, no forwarding.
InstructionIRREWBHazards TypeUnit
I0: LD F6, 34(R2)1234noneInteger
I1: LD F2, 45(R3)5678Structural Integer (I0)Integer
I2: FMUL F0, F2, F4691920RAW F2 (I1)Mult1
I3: FSUB F8, F6, F2791112RAW F2 (I1)Add
I4: FDIV F10, F0, F68216162RAW F0 (I2)Divide
I5: FADD F6, F8, F213141622Structural Add (I3); WAR F6 (I4)Add

The CPI is the cycle of the last write result over the instruction count, as the formula sheet defines it: \(62 / 6 \approx 10.3\). Ten cycles per instruction on a machine that can overlap — because one chain of true dependences runs from the second load to the end, and nothing is left to overlap with its last link, the 40-cycle divide. Follow the chain:

  1. I1 issues at 5, not 2: the single Integer unit is Busy through I0's write at 4. It reads at 6, completes at 7, writes F2 at 8:

    \[ WB_1 = 8 \quad (\text{3 cycles structural}) . \]
  2. I2 may read F2 only after it is in the register file (no forwarding), then multiplies for 10 cycles and writes the cycle after:

    \[ \begin{aligned} RR_2 &= 8 + 1 = 9, \\ E_2 &= 9 + 10 = 19, \quad WB_2 = 20 . \end{aligned} \]
  3. I4 needs F0 and waits at Read Operands from 9 to 20; it reads at 21, divides for 40 cycles, writes the cycle after:

    \[ \begin{aligned} RR_4 &= 20 + 1 = 21, \\ E_4 &= 21 + 40 = 61, \quad WB_4 = 62 . \end{aligned} \]
  4. Add it up: the two loads back to back on the one Integer unit (4 + 4 = 8), then a read, the multiply, a write, a read, the divide and a write.

    \[ 62 = 8 + 1 + 10 + 1 + 1 + 40 + 1 . \]

    I3 and I5 finish inside the shadow of this chain; so does the five-cycle WAR wait of I5, which ends at 22, when the divide has only just started.

1 5 10 15 20 25 30 35 40 45 50 55 60 I0 LD I1 LD I2 FMUL I3 FSUB I4 FDIV I5 FADD issue read executing waiting write
Fig. 3. The 62 cycles as a timeline. Dashed bars are waits: I1 at Issue (structural), I2, I3 and I4 at Read Operands (RAW), I5 first at Issue (structural) and then at Write Result (WAR). The chain I1 → I2 → I4 executes at 7, 10–19 and 22–61, with only a write and a read cycle between its links; the three cycles I1 spends waiting for the Integer unit are the only wait on it.

Because only the chain matters, each change to the machine can be judged by one question: which rule on the chain does it attack? The widget's switches give the numbers; here is why each is what it is.

What-ifs on the notes' example (recomputed with the same rules).
ChangeRule attackedTotalWhy
forwarding only\(RR \ge WB_P + 1\) becomes \(RR \ge WB_P\)60one cycle on each of the two RAW links of the chain: FMUL reads at 8, FDIV at 19
a second load unit onlythe structural check at Issue59I1 issues at 2 and writes F2 at 5: the three lost cycles come back
bothboth57the savings add up here because they hit different links
a second adder onlythe structural check at Issue — for I562I5 issues at 9 instead of 13 and still writes at 22, after FDIV's read; nothing on the chain moved
divide latency 20 instead of 40\(E = RR + L\) on the last link42the chain is shorter by exactly 20

Read the notes' closing paragraph (page 139) with this table in mind. It calls the example "a demonstration of: efficient hazard management, robust scheduling logic, clean and scalable hardware coordination"; the same run, read with Hennessy and Patterson, shows rather what limits the scoreboard, the list of lesson 9: a structural stall on the first instruction that could have overlapped, a five-cycle WAR wait that only renaming removes, one extra cycle on every RAW link because there is no forwarding, and a CPI above 10. The next algorithm, Tomasulo's (lesson 11), attacks all three: several reservation stations per unit, so the second load can issue while the first is still in flight; results renamed to those stations, so no WAR wait; and a common data bus that hands each result to its consumers as it is written.

62 = 8 + 1 + 10 + 1 + 1 + 40 + 1: the critical chain LD F2 → FMUL → FDIV; everything else finishes in its shadow, and a change that does not touch the chain changes nothing.

The January 2026 paper: 25 cycles, then 21

Exercise 1 of the paper of 8 January 2026 (reproduced in the notes from page 479) is the only scoreboard exercise among the papers of this course, and it is the model you just ran with the units and the latencies as parameters. Part A: "SCOREBOARD BASIC SCHEME … Check for WAW hazards in the ISSUE stage; No Forwarding; 2 LOAD/STORE Units (LDU1, LDU2) with latency 3 cycles; 1 FP Unit (FPU1) with latency 3 cycles; 1 ALU/BR Unit (ALU1) with latency 1 cycle." Then: "Calculate the CPI of the program and draw the timing diagram showing the status of each instruction at each clock cycle."

I0: LD    F2, VB(R6)  ; given: 1-2-5-6, LDU1
I1: FADD  F4, F2, F6
I2: SD    F4, VA(R7)
I3: LD    F4, VC(R6)
I4: SD    F4, VC(R7)
I5: ADDUI R6, R6, 4
I6: ADDUI R7, R7, 4

(The notes print the registers of this paper as $F2, $R6, the way the 2024 and 2025 papers do; the June 2026 paper and this notebook drop the dollar sign.) The given row is a gift: it fixes the conventions. E is the cycle in which execution completes, \(E = RR + 3\); the write comes the cycle after; a store has an E and a WB like everything else (its WB is the cycle its memory write completes) but no destination register, so no WAW is ever checked against it; and, as in the example, a unit is free again the cycle after its WB. The dependences, before anything else: true dependences on F2 (I0 → I1) and on F4 (I1 → I2, I3 → I4); an output dependence on F4 (I1, I3); anti-dependences on F4 (I2 reads it, I3 overwrites it), on R6 (I5 after I0, I3) and on R7 (I6 after I2, I4); and two load/store units for four memory instructions, one FP unit, one ALU.

Part A — the basic scheme: WAW at Issue, no forwarding. Last WB 25: CPI = 25 / 7 ≈ 3.57.
InstructionIRREWBHazards TypeUnit
I0: LD F2, VB(R6)1256none (given)LDU1
I1: FADD F4, F2, F6271011RAW F2 (I0)FPU1
I2: SD F4, VA(R7)3121516RAW F4 (I1)LDU2
I3: LD F4, VC(R6)12131617Structural LDU1/LDU2 (I0, I2), then WAW F4 (I1); WAR F4 (I2) costs nothingLDU1
I4: SD F4, VC(R7)17182122Structural LDU1/LDU2 (I3, I2); RAW F4 (I3) costs nothingLDU2
I5: ADDUI R6, R6, 418192021none; WAR R6 (I0, I3) costs nothingALU1
I6: ADDUI R7, R7, 422232425Structural ALU1 (I5); WAR R7 (I2, I4) costs nothingALU1

Where the cycles go. I1 waits four cycles for F2 and I2 eight for F4: a load, an add and a store in a straight RAW chain, one register-file round trip each. I3 is the expensive row: at cycle 4 both load/store units are Busy; when LDU1 frees at 7 the register result entry of F4 still says FPU1, so the WAW with I1 holds it at Issue until I1's write at 11 — and, issue being in order, holds I4, I5 and I6 behind it although none of them waits for I1. Its WB at 17 passes the WAR test because I2 read F4 at 12. I4 then finds both units Busy again and takes LDU2, the first to free (I2's WB at 16). I6 waits for the single ALU. Last WB 25: \(\mathrm{CPI} = 25/7 \approx 3.57\).

Part B keeps everything and adds two "Optimizations: Check for WAW postponed to the WRITE BACK phase; Forwarding", asking for the table, the stalls, the CPI "and the speedup with respect to the previous case". Each one changes exactly one rule. Forwarding: a consumer reads in the cycle in which the producer writes, \(RR \ge WB_P\) instead of \(WB_P + 1\) — the result leaves the unit at the end of the producer's last execution cycle and is bypassed around the register file. That is how the notes' solution reads the paper's one word "Forwarding" (I0 writes at 6, I1 reads at 6); that solution is the note author's, not an official one, so write the convention you use next to your table. WAW postponed: Issue no longer looks at the register result table, so a second writer issues as soon as a unit is free; Write Result gains a second test, \(WB \ge WB_W + 1\) for every earlier writer \(W\) of the same register, next to the WAR test it already had — the explicit ordering of the two writes that lesson 9 said the hardware needs once the WAW check leaves Issue.

Part B — forwarding and the WAW check at write-back. Last WB 21: CPI = 21 / 7 = 3.0; speedup 25 / 21 ≈ 1.19.
InstructionIRREWBHazards TypeUnit
I0: LD F2, VB(R6)1256none (given)LDU1
I1: FADD F4, F2, F626910RAW F2 (I0), forwardedFPU1
I2: SD F4, VA(R7)3101314RAW F4 (I1), forwardedLDU2
I3: LD F4, VC(R6)781112Structural LDU1/LDU2 (I0, I2); WAW F4 (I1) checked at WB, no stall (I1 wrote at 10); WAR F4 (I2) no stall (I2 read at 10)LDU1
I4: SD F4, VC(R7)13141718Structural LDU1/LDU2 (I3, I2); RAW F4 (I3) costs nothingLDU1
I5: ADDUI R6, R6, 414151617noneALU1
I6: ADDUI R7, R7, 418192021Structural ALU1 (I5)ALU1

Now the second puzzle. Switch the two on one at a time and recompute (the trainer below checks you): forwarding alone gives 23 cycles, the postponed WAW check alone 22, both 21. The postponed check is worth more because it attacks the stall that blocks the queue: I3 issues at 7 instead of 12, and I4, I5, I6 move with it. Forwarding trims one cycle from each RAW link on the way to the end, and there are only two: I0 → I1 and I1 → I2, whose write frees LDU2 for I4. And the savings do not add up — 2 + 3 would be 5, both together save 4 — because both shorten the same wait, the issue of I4. In the basic scheme I4 waits for LDU2, freed at the end of the chain I0 → I1 → I2, and forwarding shortens that chain by two cycles. Once I3 issues at 7, I4 waits for LDU1 instead, freed by I3's write, and forwarding has only one cycle left to take: in the postponed-only variant I3 completes at 11 but I2 reads F4 only at 12, a genuine WAR stall that puts I3's write at 13; with forwarding I2 reads at 10 and I3 writes at 12.

1 5 10 15 20 25 I0 I1 I2 I3 I4 I5 I6 8 cycles stuck at Issue

Before: Part A, 25 cycles

1 5 10 15 20 25 I0 I1 I2 I3 I4 I5 I6 4 cycles saved

After: Part B, 21 cycles

Fig. 4. The "timing diagram" the paper asks for, for both parts: issue and read cells, execution bars, dashed waits, write ticks. Left, the eight-cycle issue stall of I3 (cycles 4–11) and the queue behind it. Right, forwarding moves the read of I1 one cycle left and that of I2 two, the postponed WAW check lets I3 issue at 7, and I4 to I6 follow four cycles earlier; the dashed line is where Part A ended.

Exam table trainer: January 2026, Exercise 1A and 1B

The paper's table with row I0 given. Fill I, RR, E and WB, pick the hazard label and the unit for each row, then press Check: every cell is marked, and the wrong ones are explained with the rule that sets them. The scheme menu switches between the basic scheme, each optimisation alone, and both. The CPI and the speedup follow from your WB column.

  1. Basic scheme. Before writing anything, predict the issue cycle of I3 and the two reasons it is late; then fill rows I1 to I3 and check.
    What you should see

    12. Both load/store units are Busy at cycle 4 (I0 through 6, I2 through 16); when LDU1 frees, the WAW on F4 with I1 keeps I3 at Issue until I1's WB at 11. Write both in the Hazards column.

  2. Still basic: predict the unit of I4 and its issue cycle; then fill rows I4 to I6 and check. Which WB is the last, and what is the CPI?
    What you should see

    LDU2 at 17: both units are Busy again when I4 wants to issue, and LDU2 frees first (I2's WB at 16). I6 writes at 25; CPI = 25 / 7 ≈ 3.57.

  3. Switch to "forwarding only" and then to "WAW check at write-back only". Before each: which rows change, by how much, and what is the total? Fill, check, compare.
    What you should see

    Forwarding: I1 reads one cycle earlier and I2 two (the savings pile up along the chain), I3 issues at 11, everything behind it moves one or two cycles — 23 cycles, CPI ≈ 3.29. WAW at write-back: I3 issues at 7 — but writes only at 13, after I2's read of F4 at 12 (a real WAR stall) — and I4 to I6 move three cycles each — 22 cycles, CPI ≈ 3.14. The postponed check is worth more.

  4. Both optimisations (Part B). Predict the total and the speedup; fill and check. Why does I4 now sit on LDU1?
    What you should see

    21 cycles, CPI = 3.0, speedup 25 / 21 ≈ 1.19. I4 issues at 13 on LDU1, freed by I3's WB at 12, while LDU2 is held by I2 through 14 — the notes' solution says LDU2 (page 486), its own final table says LDU1.

"So, I2 is stalled until cycle 9 (inclusive), when I1 completes its Write Back stage" (page 481; I1 writes back at 11 and I2 reads at 12, as the table of cycle 12 on page 482 shows — \(RR_2\) is the larger of \(I_2 + 1 = 4\) and \(WB_1 + 1 = 12\), and 9 fits no rule). "I4 completes its execution in cycle 20" (page 484; its row says E = 21 = RR 18 + 3). "STR $F4 I3" as the hazard of I4 (pages 482–484) mixes two things: the stall is structural, on the load/store units held by I3 and I2; the RAW on F4 from I3 is real but costs nothing. Every cycle number in the notes' tables is right, and so is every CPI (25 → 3.57, 21 → 3.0, speedup 1.19); the sentences around them, and two hazard labels, are off in several places. When a sentence and a table disagree, recompute the cell with the rule.

Fill the Hazards Type column with what set the number, with the register and the instruction: "RAW F2 (I0)", "STR LDU1/LDU2 (I0, I2) + WAW F4 (I1)", "STR ALU1 (I5)". A hazard that exists but costs nothing ("WAR R6 (I0, I3), no stall") is worth a word too. For the "timing diagram" draw one row per instruction and write the stage letter under each cycle — I, RR, E, E, E, WB — with the waits shown; Figure 4 is that diagram. Give the speedup as a ratio of cycle counts, 25 / 21 ≈ 1.19; the notes' 3.57 / 3 is the same number with a rounded numerator.

Forwarding shortens every RAW wait by one cycle; postponing the WAW check lets the second writer issue early and only orders its write after the first — and because it unblocks the in-order issue queue, it is the switch that saves more.

Exam-style questions

Consider the following program on a CPU with dynamic scheduling based on the SCOREBOARD BASIC SCHEME (check for WAW hazards in the ISSUE stage; no forwarding), with 1 Integer unit for the loads (latency 1, all cache hits), 2 FP MULT units (latency 10), 1 FP ADD unit (latency 2) and 1 FP DIV unit (latency 40). (a) Fill the table with I, RR, E and WB for each instruction, the hazard type and the unit, and compute the CPI. (b) Which hazard delays the write of I5, and until which cycle? (c) Would a second FP ADD unit reduce the total number of cycles? Justify.

I0: LD   F6, 34(R2)
I1: LD   F2, 45(R3)
I2: FMUL F0, F2, F4
I3: FSUB F8, F6, F2
I4: FDIV F10, F0, F6
I5: FADD F6, F8, F2
Show model answer
InstructionIRREWBHazards TypeUnit
I0: LD F6, 34(R2)1234noneInteger
I1: LD F2, 45(R3)5678Structural Integer (I0)Integer
I2: FMUL F0, F2, F4691920RAW F2 (I1)Mult1
I3: FSUB F8, F6, F2791112RAW F2 (I1)Add
I4: FDIV F10, F0, F68216162RAW F0 (I2)Divide
I5: FADD F6, F8, F213141622Structural Add (I3); WAR F6 (I4)Add

(a) 62 cycles; CPI = 62 / 6 ≈ 10.3. I1 issues at 5 because the Integer unit is Busy through I0's WB at 4; I2 and I3 read at 9 = WB(I1) + 1; I4 reads at 21 = WB(I2) + 1; I5 issues at 13, the cycle after I3's WB.

(b) A WAR hazard on F6 with I4: I4 reads F6 only at 21, because it waits for F0 (written at 20); I5 completes at 16 and writes at RR(I4) + 1 = 22.

(c) No. With a second adder I5 issues at 9 and completes at 15, but it still cannot write before I4 has read F6, so WB(I5) = 22; the total is fixed by the chain LD F2 → FMUL → FDIV, which ends at 62 whatever happens to the adds.

Three conventions decide the numbers: the unit is Busy through its WB (I1 at 5, I5 at 13), the consumer reads at WB + 1 (I2, I3, I4), and the WAR delays only the write. Part (c) asks, in effect, whether you know what a critical path is: name the chain and say the add is not on it.

Consider the program of the January 2026 paper (I0 LD F2, VB(R6); I1 FADD F4, F2, F6; I2 SD F4, VA(R7); I3 LD F4, VC(R6); I4 SD F4, VC(R7); I5 ADDUI R6, R6, 4; I6 ADDUI R7, R7, 4) on the same resources (2 LOAD/STORE units LDU1, LDU2 with latency 3; 1 FP unit FPU1 with latency 3; 1 ALU/BR unit ALU1 with latency 1), with FORWARDING but with the check for WAW hazards still in the ISSUE stage. Row I0 is given: 1, 2, 5, 6, LDU1. Fill the table, compute the CPI and the speedup with respect to the basic scheme (25 cycles).

Show model answer
InstructionIRREWBHazards TypeUnit
I0: LD F2, VB(R6)1256none (given)LDU1
I1: FADD F4, F2, F626910RAW F2 (I0), forwarded: RR = WB(I0)FPU1
I2: SD F4, VA(R7)3101314RAW F4 (I1), forwardedLDU2
I3: LD F4, VC(R6)11121516Structural LDU1/LDU2 (I0, I2), then WAW F4 (I1) at Issue until WB(I1) = 10LDU1
I4: SD F4, VC(R7)15161920Structural LDU1/LDU2 (I3 through 16, I2 through 14): LDU2 at 15; RAW F4 (I3) forwarded, RR = 16LDU2
I5: ADDUI R6, R6, 416171819noneALU1
I6: ADDUI R7, R7, 420212223Structural ALU1 (I5)ALU1

23 cycles; CPI = 23 / 7 ≈ 3.29; speedup = 25 / 23 ≈ 1.09. Forwarding takes one cycle out of each RAW wait (I1, I2, I4); the WAW on F4 still holds I3 at Issue, so the queue behind it moves only with I1's earlier write.

What this variant tests is that forwarding changes the RR rule only (read in the producer's write cycle) and nothing else: I3 still waits at Issue for I1's WB, and the structural rules are untouched. A table that lets I3 issue at 7 has confused this variant with Part B.

Same program and resources as the January 2026 paper, with the check for WAW hazards postponed to the WRITE BACK phase but NO forwarding. How many clock cycles does the program take (the cycle of the last write-back)?

Show model answer

I1 2–7–10–11 and I2 3–12–15–16 as in the basic scheme (no forwarding). I3 issues at 7 (LDU1 free, no WAW check at Issue), reads at 8, completes at 11 — but may write only after I2 has read F4, at 12 (WAR), and after I1's write at 11 (WAW at write-back): WB = 13. I4 issues at 14 on LDU1, reads F4 at 15 = WB(I3) + 1, E 18, WB 19. I5 15–16–17–18. I6 issues at 19 (ALU1 free after 18), 20, 21, WB = 22. CPI = 22 / 7 ≈ 3.14.

The one row that decides is I3's WB: 12 forgets the WAR with I2, which still reads F4 at 12 because there is no forwarding. Postponing the WAW check never removes the WAR test.

In a scoreboard with forwarding (columns I, RR, E, WB as in the papers), a consumer of a value produced by instruction P may read its operands at the earliest in cycle: (single answer)

  • E of P In its last execution cycle the producer is still computing; the value exists only at the end of that cycle.
  • WB of P, i.e. E of P + 1 The result leaves the unit at the end of P's last execution cycle and is bypassed around the register file: the consumer reads in the cycle P writes (the notes' solution of January 2026: I0 writes at 6, I1 reads at 6).
  • WB of P + 1 That is the rule without forwarding: the value must be in the register file first.
  • I of P + latency Issue is not where execution starts; the read cycle and any waits come between.
Show model answer

Answer 2: RR = WB of the producer (one cycle earlier than without forwarding).

Do not mix this with Tomasulo's convention of the same papers, where the dependent instruction starts executing the cycle after the producer's WRITE RESULT. Same idea, different column.

On the program of the January 2026 paper, which single optimisation saves more cycles with respect to the basic scheme (25 cycles)? (single answer)

  • Forwarding (23 cycles) Forwarding saves one cycle per RAW wait — two chained waits here — but leaves I3 stuck at Issue behind the WAW on F4.
  • The WAW check postponed to write-back (22 cycles) I3 issues at 7 instead of 12, and I4, I5, I6 — stuck behind it in the in-order issue queue — move with it.
  • They save the same number of cycles 23 and 22 differ; and with both switched on the total is 21, not 25 − 2 − 3.
  • Neither: the structural hazards fix the total Each one alone saves cycles (23 and 22 instead of 25); the structural waits remain, but they are not the whole story.
Show model answer

Answer 2: postponing the WAW check (22) beats forwarding (23); together they give 21.

"Motivate your answer" is the extra point: say that the WAW stall blocks the in-order issue queue, so removing it moves four instructions at once.

True or false: in the basic scoreboard scheme a WAR hazard can delay the execution of the later instruction.

  • True The later instruction reads and executes as soon as its own sources are ready; only its write is held.
  • False WAR is checked at Write Result: the writer completes on time and keeps its result in the unit until every earlier reader has read.
Show model answer

False. In the notes' example FADD F6 reads at 14 and completes at 16 although FDIV, an earlier reader of F6, reads only at 21; the WAR delays FADD's write to 22, not its execution.

Give the cycle numbers: they are the motivation the quiz asks for.

Explain the main concepts and benefits of each one of the following techniques of a scoreboard-based CPU, saying for each which hazard it addresses and what it cannot fix: 1. splitting the decode stage into Issue and Read Operands; 2. checking WAW hazards at write-back instead of at issue; 3. forwarding; 4. in-order issue with out-of-order completion.

Show model answer

1. Issue decodes and checks the resources (a free unit, no pending write to the destination: structural and WAW hazards), in order; Read Operands waits for the sources to be in the register file (RAW), separately for every issued instruction. Benefit: an instruction waits in the row of its own unit while independent later instructions issue behind it and may read before it (in the notes' example FADD, issued at 13, reads at 14 while FDIV, issued at 8, reads at 21). Cannot fix: a stall at Issue still blocks every later instruction.

2. The register result table is not consulted at Issue, so a later writer of a busy register issues as soon as a unit is free; Write Result then enforces the order of the two writes (WB of the second after WB of the first) in addition to the WAR test. Benefit: the in-order issue queue is not blocked by an output dependence (January 2026: I3 issues at 7 instead of 12 and the three instructions behind it issue 3 cycles earlier: 25 → 22). Cannot fix: the dependence itself — the two writes are still serialised, and the WAR test can still delay the second write; only renaming removes it.

3. A result is bypassed from the unit to a waiting consumer in the cycle it is written instead of after the register-file write: each RAW wait is one cycle shorter (RR = WB of the producer). Benefit: one cycle per link of every true-dependence chain (January 2026: 25 → 23). Cannot fix: the latency itself, and nothing about structural, WAW or WAR waits.

4. Instructions enter in program order, which keeps the hardware simple (the instruction being issued is always the later writer, so one lookup settles a WAW), and leave as soon as they are done, which lets independent instructions overlap long latencies (in the notes' example the subtract and the add complete inside the load–multiply–divide chain, which alone sets the 62 cycles). Cannot fix: WAR and WAW stalls (no renaming), imprecise exceptions (no reorder buffer), and the stalls of the issue queue behind a blocked instruction.

Four short lines per technique are enough: what it is, which hazard it addresses, what it buys (with a number from an exercise if you have one) and what it does not fix. The last line is what separates a full answer from a definition.

Check yourself

In the notes' example the second load, I1, depends on nobody and still issues only at cycle 5. What holds it?

  • The WAW on F6: the first load has not written yet I1 writes F2, not F6; no output dependence exists between the two loads.
  • The single Integer unit, Busy through I0's write at cycle 4 A unit holds its instruction from issue through write result; the structural check at Issue fails in cycles 2, 3 and 4.
  • The RAW on R3: the base register is not ready R3 is never written in the program; its value is in the register file from the start.

Which statements about the WAR stall of I5 (FADD F6) in the notes' example are true?

  • It delays only the write: execution completes at 16 whatever happens Write Result is the stage that checks WAR; the earlier stages never see it.
  • The cell that enforces it is Rk = Yes in the Divide row FDIV lists F6 as its second source and has not read it; the register result table is not consulted.
  • It ends the cycle after FDIV reads its operands, at 22 FDIV reads at 21 (one cycle after FMUL writes F0); the flag flips to No and FADD writes at 22.
  • A second adder would remove it A second adder lets FADD issue at 9, but the write still waits for FDIV's read at 21; only renaming removes a WAR.

One cell, one number: the earlier reader's flag decides the later writer's WB, and nothing else moves.

Which chain fixes the 62 cycles, so that a change elsewhere changes nothing?

  • LD F6 → FSUB → FADD FSUB finishes at 12 and FADD at 22, forty cycles before the end: they sit in the shadow of the real chain.
  • LD F2 → FMUL → FDIV 8 cycles to get F2 (three of them structural), 10 of multiply, 40 of divide, plus a read and a write per link: 62.
  • LD F6 → FDIV → FADD FDIV reads F6 at 21, but it is waiting for F0 then, not for F6; and FADD needs no value from FDIV — only a WAR links them, and it ends at 22, forty cycles before the end.

January 2026, Part B (WAW check at write-back): why does I3 issue at 7 and not at 4, when nothing forbids a second writer of F4 any more?

  • Because I1 has not written F4 yet That is the WAW test — which Part B has moved to write-back; it no longer holds anything at Issue.
  • Because both load/store units are Busy at cycle 4, and the first to free is LDU1, after I0's write at 6 LDU1 holds I0 through 6 and LDU2 holds I2 through 14: the structural check fails in cycles 4, 5 and 6, and I3 takes LDU1 at 7.
  • Because I2 must read F4 before I3 may issue That is the WAR, checked at Write Result; it does not delay an issue.

What changes in the rules of the table under the January 2026 optimisations?

  • A consumer reads in the producer's write cycle: RR ≥ WB of the producer Forwarding bypasses the register file by one cycle.
  • Issue no longer looks at the register result table The WAW check is postponed: a second writer issues as soon as a unit is free.
  • Write Result must also come after every earlier writer of the same register The postponed WAW check lives here: WB of the second writer after WB of the first.
  • The WAR test at Write Result is dropped It stays — in the postponed-only variant it costs I3 one cycle (WB 13).
  • A unit becomes free at the end of execution Unchanged: Busy lasts through the write-back in every scheme.

Two switches, two rules: one on RR, one moved from Issue to Write Result. Everything else is as in the basic scheme.

In Part B I4 ends on LDU1 and in Part A on LDU2. What decides the unit?

  • Loads go to LDU1 and stores to LDU2 Both units take loads and stores; I2 (a store) is on LDU2 only because LDU1 was Busy at cycle 3.
  • The first unit of the class that is free when the instruction may issue In Part A LDU2 frees first (I2's WB at 16); in Part B LDU1 does (I3's WB at 12 against I2's WB at 14).
  • The least recently used unit, as the notes say The notes' sentence on page 486 contradicts their own final table; a unit is chosen because it is free.

Key take-aways

What to watch and read