On 28 August 1963 IBM's chairman Thomas Watson Jr. sent a memo asking how a team of "only 34 people, including the janitor" could have built the world's most powerful computer, the CDC 6600, while IBM had not; Seymour Cray answered that Mr. Watson had answered his own question. The 6600 shipped in 1964–65 with the first scoreboard, designed by James Thornton: 16 functional units (4 floating-point, 5 for memory, 7 integer) and, by Hennessy and Patterson's account, about 1.7 times the speed on FORTRAN programs and 2.5 times on hand-coded assembly. Thornton called the hazards first-, second- and third-order conflicts; the three checks below are his.
The chalkboard that beat the pipeline: the scoreboard
After this lesson you will run a six-instruction fragment through the scoreboard's three tables cycle by cycle and, for every instruction that waits, point at the one cell that holds it.
In 1964 the fastest computer in the world, the CDC 6600, did something no machine had done before: it executed instructions out of their program order and still produced the right answers. It had no compiler that rearranged the code for it, no spare register names, no forwarding path. All it had was a small table of flags that its designer, James Thornton, called a scoreboard — small enough to draw on a chalkboard.
Here is the puzzle of the lesson. In the fragment below, I4 is a multiply. From cycle 6 on, both of its operands sit in the register file and a multiplier is free. It does not issue until cycle 13, and the store that comes after it finishes two cycles before it. Which single cell of the chalkboard holds I4 back for seven cycles — and why would Tomasulo's machine, two lessons from now, not hold it at all?
Keep the question. First the machine, then its four stages, then the tables; the answer is one cell of the last table.
The machine and its six promises
Recall the in-order pipeline of lesson 7. Its ID stage decodes the instruction and reads its operands in the same cycle, so an instruction whose operand is not ready stalls in ID — and because the pipeline is a queue, every instruction behind it stalls too, however independent. Lesson 8 called the cure dynamic scheduling: let the hardware decide at run time which instruction may go next. The scoreboard is the first way of doing it.
The whole lesson runs on one fragment, written in the mnemonics of the exam papers (older papers write $F2 for F2; the 2026 paper drops the dollar sign, and so does this notebook). The latencies are the ones this exercise gives; an exam text always states its own.
I0: LD F2, 0(R1)
I1: FMUL F4, F2, F0 ; RAW on F2 with I0
I2: FADD F6, F4, F8 ; RAW on F4 with I1
I3: LD F8, 8(R1) ; WAR on F8 with I2 (I2 reads F8)
I4: FMUL F8, F2, F0 ; WAW on F8 with I3
I5: SD F6, 16(R1) ; RAW on F6 with I2
Units and latencies: one Integer unit for loads, stores and integer operations (1 cycle, cache hits), one Add unit for FADD and FSUB (2 cycles), two multipliers Mult1 and Mult2 for FMUL (4 cycles), and a Divide unit that stays idle here. The fragment is deliberately nasty: I3 loads F8 and I4 overwrites it unread. A compiler would never write that, but exam fragments do, because it is the cleanest test of what a WAW hazard costs.
In the in-order pipeline, I2 would wait in ID for F4 until the multiply is done, and I3, a load that needs nothing from anybody, would wait behind it. The scoreboard's promise is that I3 goes past. To keep that promise safe, the model makes six assumptions (notes, page 103), each of them examinable.
Scoreboard — a centralized hardware controller, introduced in the CDC 6600, that lets instructions read their operands, execute and write their results out of program order, while it tracks every data and structural hazard itself. Its model assumes: (1) a single-issue processor — one instruction fetched and issued per cycle; (2) in-order issue — instructions enter the scoreboard strictly in program order, then execute and complete out of order; (3) no forwarding — a result becomes visible only after it is written into the register file; (4) several independent functional units, each holding one instruction at a time, with different latencies; (5) execution and memory access that may take several cycles; (6) out-of-order execution and completion with no register renaming — so WAW and WAR hazards are real and must be handled by stalling, and exceptions are imprecise.
The last point in one sentence: if a later instruction has already written the register file when an earlier one raises an exception, the state is not the one a sequential machine would have had — "imprecise interrupts" (page 104); the reorder buffer of lesson 17 is the later fix.
Page 104 of the notes sums the architecture up as three phases — issue in order, execution out of order, completion out of order — and its Figure 24, redrawn below, shows what makes them possible: a shared register file, the units, data buses between them, and the scoreboard at the bottom connected to everything by control and status lines only. The scoreboard moves no data. Operands still travel from the register file to the units and results back; the scoreboard only answers, for every instruction, three questions — may I read my operands, may I start, may I write my result.
"The units are pipelined, so the second load can issue right behind the first." No. The notes word assumption 4 as "multiple pipelined functional units" (page 103) — keep that phrase for the theory question, since the slides very likely use it — but in every table of this course a unit holds one instruction at a time and stays Busy from issue through write result: the functional-unit status table has one row per unit, and that row is all the bookkeeping there is for an instruction in flight. That is why the second load of the notes' own example cannot issue before cycle 5 (page 117, "structural hazard on the Integer unit") and why I3 waits at cycle 4 above. Hennessy and Patterson treat several units and one pipelined unit as equivalent for the control logic and model the scoreboard with several non-pipelined units; a pipelined unit that took a new instruction every cycle would need one bookkeeping entry per instruction — Tomasulo's reservation stations, lesson 11, are such entries.
The scoreboard moves no data: for every instruction it answers three questions — may I read, may I start, may I write — and it answers them from a table.
Split the decoder: four stages, four checks
The classic ID stage hides an assumption: that the operands are ready when the instruction is decoded. With a four-cycle multiply and a forty-cycle divide that is often false, so the scoreboard cuts ID in two. Issue decodes the instruction and asks about resources: is a unit of the right kind free (a structural hazard), and is nobody still due to write my destination (a WAW hazard)? If so, the instruction is handed to a unit and recorded in the tables; otherwise it waits, and because issue is in order, everything behind it waits too. Read Operands asks about values: are both of my sources written into the register file (a RAW hazard)? That question is asked separately for every instruction in flight, so a later instruction whose sources are ready reads them while an earlier one is still waiting. That is the whole trick; the picture shows it.
Before: ID decodes and reads at once
After: Issue, then Read Operands per unit
Walk the first five cycles of the fragment by hand; the stepper of the next section continues from there. Cycle 1: I0 issues on the Integer unit. Cycle 2: I0 reads R1; I1 issues on Mult1 — F2 is not written yet, so it will wait. Cycle 3: I0 accesses memory (its one execution cycle); I2 issues on the Add unit and will wait for F4. Cycle 4: I0 writes F2. I3 wants to issue and needs nothing from anybody — but it needs the Integer unit, and that unit is still Busy in the cycle in which I0 writes. I3 waits one cycle: structural hazard. Cycle 5: I3 issues; I1, which saw F2 arrive at the end of cycle 4, reads F2 and F0. Its four cycles of multiplying are 6 to 9, and the product is written at 10.
Two more stages follow. Execute runs the operation in the unit for its latency; a load spends its memory access here, cache miss included. Write Result asks the last question, about earlier readers: is an earlier instruction still waiting to read the register I am about to overwrite (a WAR hazard)? If so, the result stays inside the unit and the write is postponed; execution is finished and is not repeated. A register-file write port must also be free. The table restates pages 110–111 of the notes with the column names of the January 2026 paper.
| Stage | Order | Checks | If the check fails |
|---|---|---|---|
| Issue (I) | in order | structural — a unit of the right kind is free; WAW — no pending write to the destination | the instruction waits, and so does everything behind it |
| Read Operands (RR) | out of order | RAW — both sources already written to the register file (and read ports available) | it waits in its unit; later instructions may read before it |
| Execute (E) | out of order | none — the unit runs for its latency | — |
| Write Result (WB) | out of order | WAR — no earlier instruction still has to read the destination (and a write port is free) | the result stays in the unit, which stays Busy |
Page 106 of the notes lists what the board must track to answer these questions: whether each source operand is available, whether each unit is busy, which writes to which registers are pending, and which instructions have finished and may write back. The notes' Figure 25 (page 109) draws the four stages as a map, with the scoreboard underneath consulted at every gate; Figure 3 redraws it with the three gate conditions written out.
"A WAR hazard stalls the instruction." No — it delays only the write. I3 finishes its memory access at cycle 7 and then holds a correct value inside the Integer unit until cycle 12, because I2 has not yet read the old F8. Nothing is redone; the price is that the unit stays Busy, so the next instruction that needs it cannot issue.
Why split ID instead of just letting it stall?
A stalled ID stage is a closed door: nothing behind it is decoded, so the hardware never learns that I3 needed nothing. With the split, every instruction is parked in its unit's row at issue and waits only for its own sources. That is what lets I3 read at cycle 6 while I2, issued earlier, reads at cycle 11 — "the stage that enables out-of-order execution", as the notes put it (page 110).
Issue asks about the unit and the destination (structural, WAW); Read Operands asks about the sources (RAW); Write Result asks about earlier readers (WAR).
Three tables run the show
Everything the scoreboard knows fits in three tables (notes, page 113). The instruction status table records, for every instruction, which of the four stages it has completed — write cycle numbers into it and you have exactly the I / RR / E / WB table the exam asks for. The functional-unit status table has one row per unit and is where the decisions are made. The register result status table says, for every register, which unit will write it next, or nothing if no write is pending. Here are the fields of the unit row, with the moment each one is set and the moment it changes.
| Field | Meaning | Set at issue to | Changed when |
|---|---|---|---|
| Busy | the unit holds an instruction | Yes | No at write result |
| Op | the operation | Load, Store, Mult, Add … | — |
| Fi | destination register | D | — |
| Fj, Fk | source registers (the notes put a load's base register under Fk) | S1, S2 | — |
| Qj, Qk | the unit that will produce Fj, Fk; blank when the value is already in the register file | the register result entry of S1, of S2 | blank when that unit writes (H&P clear it at the read instead; either way it is blank by the time the operand is read) |
| Rj, Rk | source ready and not yet read | Yes if Qj (Qk) is blank, else No | Yes when the producer writes; No at the read |
| Time | execution cycles still to go (the notes' first column) | — | L at the read, then one less per cycle |
Two pairs of fields get confused. Qj says who, Rj says whether. Qj names the unit the operand will come from; Rj says whether the instruction may read the operand now. At issue they are set together: Rj is Yes exactly when Qj is blank. Take I1, FMUL F4, F2, F0, issued on Mult1 at cycle 2 — the notes' Example 6 (page 114) with our registers. Busy becomes Yes, Op = Mult, Fi = F4, Fj = F2, Fk = F0. The register result entry of F2 says "Integer" (I0 has not written it), so Qj = Integer and Rj = No; nobody is due to write F0, so Qk is blank and Rk = Yes. Finally the register result entry of F4 is set to Mult1: from now on a later reader of F4 copies "Mult1" into its own Qj, and a later writer of F4 is refused at issue.
The second confusion is the one the notes fall into. Rj and Rk do not mean "ready"; they mean ready and not yet read, and both flags go back to No when the instruction reads its operands. Why spend a flag on that? Because Write Result needs it. When I3 wants to write F8, the scoreboard looks for a row that has F8 as a source with its flag still Yes — an earlier instruction that has not yet taken the old value. At the end of cycle 8 the Add row reads Fk = F8, Rk = Yes: I2 is still waiting for F4 and has not read F8, so I3 waits. At cycle 11 I2 reads, Rk flips to No, and at cycle 12 I3 writes. Figure 4 is that before/after.
Before: end of cycle 8 — I3 may not write
After: end of cycle 12 — F8 written, unit free
Rk = Yes in the Add row; when I2 reads its operands at cycle 11 the flag turns to No, and I3 writes in the next cycle. Note that the register result table never enters this test.Qj says who will produce the operand, Rj says whether it may be read now — and Rj = No means either "not ready yet" or "already read".
The exact rules, and the four numbers of an exam row
Now the rules that connect stages and tables, as Hennessy and Patterson write them (Appendix C, Figure C.57; the notes do not print them, but every number of their 62-cycle example follows from them, and the stepper above is these four steps in a loop). Read \(FU\) as the unit assigned to the instruction, \(D\) as its destination, \(S_1, S_2\) as its sources, \(\mathrm{Result}[r]\) as the register result entry of \(r\), and \(f\) as any unit row.
Issue — wait until the unit is free and nobody is due to write the destination:
\[ \neg\,\mathrm{Busy}[FU] \;\wedge\; \mathrm{Result}[D] = \varnothing . \]Then record the instruction: \(\mathrm{Busy} \leftarrow \text{Yes}\), \(\mathrm{Op}\), \(F_i \leftarrow D\), \(F_j \leftarrow S_1\), \(F_k \leftarrow S_2\), \(Q_j \leftarrow \mathrm{Result}[S_1]\), \(Q_k \leftarrow \mathrm{Result}[S_2]\), \(R_j \leftarrow (Q_j = \varnothing)\), \(R_k \leftarrow (Q_k = \varnothing)\), and \(\mathrm{Result}[D] \leftarrow FU\). Why here: the first test is the structural hazard, the second is WAW — and because issue is in order, the instruction being issued is always the later of the two writers, so one lookup settles it.
Read Operands — wait until both sources are ready and not yet read:
\[ R_j = \text{Yes} \;\wedge\; R_k = \text{Yes} . \]Then read from the register file and set \(R_j \leftarrow \text{No}\), \(R_k \leftarrow \text{No}\), \(Q_j, Q_k \leftarrow \varnothing\), \(\mathrm{Time} \leftarrow L\). Why: with no forwarding a flag can become Yes only when the producer's write has landed in the register file, which is the RAW test; flipping it back to No records "already read" for the test of step 4.
Execute — wait until the unit is done. Time counts down from \(L\); the instruction completes in the cycle in which it reaches 0, i.e. \(E = RR + L\). No hazard is checked here.
Write Result — wait until no earlier instruction still has to read the destination, i.e. for every unit row \(f\):
\[ F_j[f] \neq F_i \;\vee\; R_j[f] = \text{No} \] \[ F_k[f] \neq F_i \;\vee\; R_k[f] = \text{No} . \]Then write, and for every row with \(Q_j[f] = FU\) set \(R_j[f] \leftarrow \text{Yes}\) (same for \(Q_k\), \(R_k\)); set \(\mathrm{Result}[F_i] \leftarrow \varnothing\) and \(\mathrm{Busy}[FU] \leftarrow \text{No}\). Why: a row with my destination as a source and its flag still Yes is an earlier reader that has not taken the old value — the WAR test. The wake-up loop is how a waiting instruction learns that its value has arrived.
Why is it safe that "No" means two different things?
Suppose unit \(X\) wants to write register \(r\) and some row \(f\) has \(F_j[f] = r\) with \(R_j[f] = \text{No}\). Either \(f\) has already read \(r\) — the write is harmless — or \(f\) is still waiting for \(r\) from some unit \(Y\); but then \(X\) and \(Y\) would both have a pending write to \(r\), which the Issue stage forbids (\(X\) could not have issued while \(\mathrm{Result}[r] = Y\)). So in the basic scheme a "No" seen by a writer means "already read" or "waiting for me" (case 4 of the hazard court below), and both are safe. The argument breaks once the WAW check is postponed to Write Result, as in the optimised scheme of the January 2026 paper: then the hardware must order the two writes explicitly — lesson 10.
On paper you never run the loop: each row of the exam table is four maxima, one per wait, plus the convention that a stage takes at least one cycle. With \(L\) the latency of the unit:
- \(U\)
- the previous instruction on the same unit — a unit is Busy through its write result (structural)
- \(W\)
- an earlier, still pending writer of the destination of \(n\) (WAW)
- \(P\)
- the latest earlier writer of each source of \(n\), taken over both sources (RAW; no forwarding)
- \(A\)
- every earlier instruction that reads the destination of \(n\) and has not read it yet (WAR)
The rules fill the whole fragment. Check two rows yourself. I2 waits for F4 from I1, which writes at 10:
I3 completes at 7, but I2 reads F8 only at 11:
The CPI of the fragment is the cycle of the last write result over the instruction count, as the formula sheet defines CPI: \(19 / 6 \approx 3.17\).
| Instruction | I | RR | E | WB | Hazards Type | Unit |
|---|---|---|---|---|---|---|
I0: LD F2, 0(R1) | 1 | 2 | 3 | 4 | none | Integer |
I1: FMUL F4, F2, F0 | 2 | 5 | 9 | 10 | RAW F2 (I0) | Mult1 |
I2: FADD F6, F4, F8 | 3 | 11 | 13 | 14 | RAW F4 (I1) | Add |
I3: LD F8, 8(R1) | 5 | 6 | 7 | 12 | Structural Integer (I0); WAR F8 (I2) | Integer |
I4: FMUL F8, F2, F0 | 13 | 14 | 18 | 19 | WAW F8 (I3) | Mult1 |
I5: SD F6, 16(R1) | 14 | 15 | 16 | 17 | none (RAW F6 costs nothing) | Integer |
I1 and I2 wait at Read Operands (RAW), I3 waits one cycle at Issue for its unit and four cycles at Write Result (WAR), I4 waits seven cycles at Issue (WAW). I5, issued last, writes before I4: out-of-order completion.On the exam, fill the table row by row with four questions in order: Is my unit free, and is my destination unpromised? (I) — When was the last of my sources written? (RR = that write + 1) — Add the latency (E) — Has every earlier reader of my destination read it? (WB). In the Hazards column write what set each number, with the register and the instruction: "RAW F4 (I1)", "WAR F8 (I2)", "Structural Integer (I0)", "WAW F8 (I3)".
Now a second fragment, with a different trap in it, for the court. Same machine, same latencies.
I0: LD F0, 0(R1)
I1: LD F2, 8(R1)
I2: FMUL F4, F0, F2
I3: FADD F2, F0, F6
I4: SD F4, 16(R1)
I5: ADDUI R1, R1, 8
Four maxima fill a row: unit free and destination unpromised, sources written, latency added, earlier readers done.
What the chalkboard cannot do
Back to the puzzle. The cell that holds I4 for seven cycles is the register result entry of F8: from cycle 5 to cycle 12 it says "Integer", because I3 has promised to write F8 and has not done so yet. I4 needs no value from I3; it needs the name F8, and the scoreboard has only one of each name. That is the cost of no register renaming: a WAW hazard is pure bookkeeping, and the basic scoreboard pays for it at Issue, where a stall also stops everything behind. Tomasulo's machine gives I4 a reservation station as a temporary name for its result, and the two writes to F8 never collide — lesson 11. The second half of the puzzle, the store finishing before the multiply, is out-of-order completion, and its price is the imprecise exception of section 1.
Hennessy and Patterson close with four factors that limit how much a scoreboard can gain; the notes do not list them, and the open question of the exam ("explain the main concepts and benefits of dynamic scheduling …") is the place to show you know them.
- The parallelism available among the instructions. If every instruction depends on the previous one, there is nothing to overlap, however clever the controller.
- The number of scoreboard entries — how far ahead of a stalled instruction the pipeline may look for independent ones: the instruction window, one entry per unit in the basic model.
- The number and types of functional units — structural hazards.
I3lost a cycle to the single Integer unit; a second load unit would have removed it, as the January 2026 paper's two load/store units show. - Antidependences and output dependences — the WAR and WAW stalls, which exist only because there is no renaming.
Add what the notes stress on pages 111–112: no forwarding, so every RAW dependence costs one more cycle between the producer's write and the consumer's read; centralized control, simpler than Tomasulo's distributed stations but a limit on speculation and aggressive scheduling; and out-of-order completion without a reorder buffer, so exceptions are imprecise. The notes' 62-cycle example — lesson 10, which also switches the exam's two optimisations on and off — shows all of these at once, and its closing praise of "clean and scalable hardware coordination" (page 139) is better read backwards: the example shows the limits, and the next algorithm removes them.
The scoreboard overlaps independent instructions without a compiler and without renaming; what limits it are the parallelism in the window, the number of entries and units, and the WAR/WAW stalls that renaming would remove.
Exam-style questions
Explain the main concepts and benefits of dynamic scheduling with the scoreboard: (i) the assumptions of the model; (ii) the four stages and the hazard checked in each; (iii) the three data structures and the role of Qj/Qk and Rj/Rk; (iv) the main limitations and how Tomasulo's algorithm overcomes them.
Show model answer
(i) Single-issue, in-order issue; out-of-order read of operands, execution and write-back; no forwarding (a result is visible only after it is written in the register file); several independent functional units ("multiple pipelined FUs" in the notes) with different latencies, each holding one instruction from issue to write result in the tables; no register renaming, so WAW and WAR hazards must be handled by stalls; exceptions are imprecise.
(ii) Issue (in order): structural hazard — the functional unit must be free — and WAW — no pending write to the destination in the register result status. Read Operands (out of order): RAW — both source operands written to the register file (and read ports available). Execute: no hazard, latency of the unit. Write Result (out of order): WAR — no earlier instruction still waiting to read the destination (and a write port free).
(iii) Instruction status: the stage reached by each instruction (the I / RR / E / WB table). Functional-unit status, one row per unit: Busy, Op, Fi (destination), Fj, Fk (sources), Qj, Qk (the units that will produce Fj, Fk; blank if the value is in the register file), Rj, Rk (source ready and not yet read; set to No when the operands are read). Register result status: for each register, the unit that will write it. Qj/Qk say who produces an operand, Rj/Rk say whether it may be read now; Rj = No after the read is what the WAR test of Write Result uses. Benefits: independent instructions overlap, long latencies are hidden, functional units are better used, no compiler support is needed.
(iv) Limits: the parallelism available in the window, the number of scoreboard entries, the number and types of functional units, WAR/WAW stalls because there is no renaming, one extra cycle per RAW dependence because there is no forwarding, centralized control, imprecise exceptions. Tomasulo adds register renaming through reservation stations (WAR and WAW disappear), the Common Data Bus (results forwarded to every waiting station, distributed hazard detection) and, with a reorder buffer, speculation and precise exceptions.
The examiner checks three things: that you put each hazard in its stage (WAW at Issue, RAW at Read Operands, WAR at Write Result — not "the scoreboard checks hazards"), that you say what Qj and Rj are each for, and that part (iv) names concrete limits and the concrete Tomasulo mechanism that removes each. Write short labelled statements, one per line, as the paper's blank lines invite.
Consider the following program on a processor with dynamic scheduling based on the SCOREBOARD BASIC SCHEME (check for WAW hazards in the ISSUE stage; no forwarding), with 1 Integer unit (loads, stores and integer operations, latency 1 cycle), 1 FP ADD unit (latency 2 cycles), 2 FP MULT units (latency 4 cycles). Fill the table with the cycles of I, RR, E and WB for each instruction, the type of hazard and the unit, and compute the CPI.
I0: LD F0, 0(R1)
I1: LD F2, 8(R1)
I2: FMUL F4, F0, F2
I3: FADD F2, F0, F6
I4: SD F4, 16(R1)
I5: ADDUI R1, R1, 8
Show model answer
| Instruction | I | RR | E | WB | Hazards Type | Unit |
|---|---|---|---|---|---|---|
I0: LD F0, 0(R1) | 1 | 2 | 3 | 4 | none | Integer |
I1: LD F2, 8(R1) | 5 | 6 | 7 | 8 | Structural Integer (I0) | Integer |
I2: FMUL F4, F0, F2 | 6 | 9 | 13 | 14 | RAW F2 (I1) | Mult1 |
I3: FADD F2, F0, F6 | 9 | 10 | 12 | 13 | WAW F2 (I1); WAR F2 with I2 costs nothing (I2 read at 9) | Add |
I4: SD F4, 16(R1) | 10 | 15 | 16 | 17 | RAW F4 (I2) | Integer |
I5: ADDUI R1, R1, 8 | 18 | 19 | 20 | 21 | Structural Integer (I4); WAR R1 with I4 costs nothing (I4 read at 15) | Integer |
I1 issues at 5 because the Integer unit is Busy until I0's write at 4. I2 reads at 9 = WB(I1) + 1. I3 cannot issue while the register result status says F2 = Integer (cycles 7–8); it issues at 9 and writes at 13, allowed because I2 has read F2 at 9. I4 issues at 10 and reads at 15 = WB(I2) + 1; it holds the Integer unit until its write at 17, so I5 issues at 18. Total 21 cycles; CPI = 21 / 6 = 3.5.
The marks hide in the Hazards column and in two conventions: a unit is free again the cycle after its WB (I1, I5), and a consumer reads the cycle after the producer's WB (I2, I4). Say explicitly that the WAR of I3 and I5 costs nothing and why; a bare "WAR" in that column reads as a stall you did not find.
In the fragment of this lesson (I0 LD F2, 0(R1), I1 FMUL F4, F2, F0, I2 FADD F6, F4, F8, I3 LD F8, 8(R1), I4 FMUL F8, F2, F0, I5 SD F6, 16(R1); Integer 1, Add 2, Mult 4; basic scheme), in which cycle does I3 write its result?
Show model answer
I3 completes execution at cycle 7 but I2 (FADD F6, F4, F8) still has to read F8; I2 reads only at cycle 11 (= WB of I1 + 1). WAR on F8: WB(I3) = max(7 + 1, 11 + 1) = 12.
The wrong answer 8 forgets the WAR test; the wrong answer 11 forgets that the write comes the cycle after the read.
In the basic scoreboard scheme a WAR hazard is resolved by: (single answer)
Show model answer
Answer 2: the later writer waits at Write Result until the earlier reader has read its operands (Rj/Rk back to No).
Each hazard has its stage; the quiz checks that you do not put WAR at Issue because "it is checked early".
In the functional-unit status table, Rj = No means: (single answer)
Show model answer
Answer 3: Rj, Rk are "ready and not yet read"; No covers both "waiting for the producer" and "already read", and a writer may proceed in both cases.
With the notes' definition ("ready") you can explain why the write of ADDD in the notes' example waits (the Divide row says Rk = Yes for F6) but not why it is released at cycle 22: a flag that only meant "ready" would stay Yes for ever.
True or false: in the scoreboard, a functional unit becomes free as soon as its instruction completes execution.
Show model answer
False: Busy is cleared at Write Result, not at the end of execution. Example: in the fragment of this lesson I0 completes execution at cycle 3 and writes at 4; I3, which needs the same Integer unit, issues at 5, not at 4.
"Motivate your answer" is worth the extra point: give a cycle from a table.
Why does the basic scoreboard check WAW hazards at the Issue stage rather than at Write Result, and what must change in the hardware if the check is postponed to the write-back phase, as in the "optimised" scheme?
Show model answer
Without renaming the two writes to the same register must land in program order. Checking at Issue is the simplest guarantee: issue is in order, so the instruction being issued is always the later writer, and one lookup in the register result status (a non-blank entry for its destination) settles it. It also keeps the Write Result test simple: because two pending writes to one register can never coexist, a source flag Rj = No can only mean "already read" or "waiting for this very writer", so the WAR test may let the writer through on a No.
If the check is postponed to write-back, the later writer issues and executes early (it no longer blocks the instructions behind it), but the Write Result stage must additionally enforce WB(second) > WB(first) for every earlier pending writer of the same register — i.e. the hardware must track, per register, more than one pending writer and order the writes explicitly.
The second paragraph is what distinguishes a full answer: name the benefit (earlier issue, no in-order stall) and the new obligation (explicit ordering of the writes). Lesson 10 computes the gain on the January 2026 paper: 25 cycles become 21.
Check yourself
The Add row of the functional-unit status table shows Fk = F8 with Rk = Yes. Which instruction is held up by that cell, and in which stage?
Which statements about the flags Rj and Rk are true?
One bit, two meanings: ready-and-not-yet-read. Everything about WAR hinges on the reset at the read.
A unit becomes available for the next instruction …
In the fragment, I3 (LD F8, 8(R1)) reads its operand at cycle 6 while I2, issued two cycles earlier, reads only at cycle 11. What makes that legal?
The register result status says F6 = Add. The next instruction to issue is FMUL F6, F2, F0, and Mult2 is free. What happens?
Which of these does the scoreboard not have (and Tomasulo's machine, or its reorder-buffer extension, adds)?
Keep the list for the open question: what the scoreboard lacks is exactly what the next two lessons add.
Key take-aways
- The scoreboard is a centralized controller beside the datapath: it issues in order, lets instructions read, execute and write out of order, and tracks every hazard itself — with no forwarding, no renaming and imprecise exceptions.
- ID is split so that waiting is per instruction: Issue checks the unit and the destination (structural, WAW), Read Operands checks the sources (RAW), Write Result checks earlier readers (WAR); Execute checks nothing.
- A functional unit is Busy from issue through write result, one instruction at a time; that is where the structural stalls come from.
- Three tables hold the state: instruction status (the exam's I / RR / E / WB), functional-unit status (Busy, Op, Fi, Fj, Fk, Qj, Qk, Rj, Rk), register result status (who will write each register, used for WAW and for filling Qj/Qk).
- Qj says who produces the operand, Rj says whether it may be read; Rj/Rk mean ready and not yet read and are reset to No at the read — the notes drop this, and the WAR test needs it.
- An exam row is four maxima: I ≥ previous issue + 1, unit's last WB + 1, pending writer's WB + 1; RR ≥ producer's WB + 1; E = RR + L; WB ≥ E + 1 and ≥ every earlier reader's RR + 1.
- The limits are the parallelism in the window, the number of entries and units, and the WAR/WAW stalls that only renaming removes; Tomasulo adds renaming and a forwarding bus.
What to watch and read
-
Scoreboarding
Wikipedia10 min
The four stages in one page, with Thornton's own vocabulary ("first-, second- and third-order conflicts") next to the textbook's. Read it to know the words before the tables.
-
CDC 6600
Wikipedia15 min
The machine of the hook: the Watson memo, the 34 people, and what a 1964 supercomputer looked like.
-
CS252 Lecture 7: Scoreboard, Tomasulo, Register Renaming
John Kubiatowicz, UC Berkeley25 pages
The same three-table layout and the same mnemonics as the notes, with the four stages and their wait conditions on slides; use it as the second opinion whenever a table in the notes looks wrong.
-
Dynamic Scheduling — Scoreboarding Example
Boston University CS 55015 min
A second worked run of a scoreboard simulator with functional-unit and register-result snapshots at two cycles: practise reading the tables on a program you have not seen.
-
HASE model of the CDC 6600
University of Edinburgh, ICSA20 min to read, longer to run
An animated model of the real machine (a desktop Java application; the page itself explains the scoreboard and the parallel units with diagrams). The best picture of one controller talking to every unit.