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.

register file functional units results operands F0 F2 F4 F6 F8 F10 … R1 Mult1 Mult2 Divide Add Integer Scoreboard may I read? may I start? may I write?
Fig. 1. The notes' Figure 24 (page 104), redrawn. Solid lines carry data: operands from the register file to the units, results back. The dashed violet lines carry only control and status: the scoreboard is a controller sitting beside the datapath, not a stage inside it.

"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.

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 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.

IF ID EX ME WB decode + read I1 FMUL F4, F2, F0 I2 FADD F6, F4, F8 I3 LD F8, 8(R1) waits for F2 frozen frozen one stall, three victims

Before: ID decodes and reads at once

IF Issue RR EX WB decode, then read Mult1 Add Integer I1 FMUL F4, F2, F0 I2 FADD F6, F4, F8 I3 LD F8, 8(R1) executes waits F4 runs the load goes past

After: Issue, then Read Operands per unit

Fig. 2. The same three instructions. Left, a classic pipeline at the moment the multiply is stuck in ID waiting for F2: the two instructions behind it are frozen, although the load needs nothing. Right, the scoreboard at cycle 6 of the fragment: the multiply has read F2 and is executing in Mult1, the add waits in the Add row for F4, and the load — issued at cycle 5 — reads its base register and goes on. Each issued instruction waits only in the row of its own 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.

The four stages, the hazard each one checks, and what a failed check does.
StageOrderChecksIf the check fails
Issue (I)in orderstructural — a unit of the right kind is free; WAW — no pending write to the destinationthe instruction waits, and so does everything behind it
Read Operands (RR)out of orderRAW — 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 ordernone — the unit runs for its latency—
Write Result (WB)out of orderWAR — 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.

R completes when both operands are ready (no RAW) Issue completes when the unit is not Busy and the destination is not pending (no WAW) IF Issue R R R R R Integer Add Mult1 Mult2 Divide M W Scoreboard W completes when no unit is still waiting to read its destination (no WAR) every stage asks the board
Fig. 3. The notes' Figure 25 (page 109) with its three "completes when" conditions. Issue asks about the unit and the destination, each R block asks about its own two sources, W asks about earlier readers. The latencies written on the units in the notes (1, 4, 7, 7, 24) are illustrative; an exercise always gives its own.

"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.

The row of a functional unit in the functional-unit status table.
FieldMeaningSet at issue toChanged when
Busythe unit holds an instructionYesNo at write result
Opthe operationLoad, Store, Mult, Add …—
Fidestination registerD—
Fj, Fksource registers (the notes put a load's base register under Fk)S1, S2—
Qj, Qkthe unit that will produce Fj, Fk; blank when the value is already in the register filethe register result entry of S1, of S2blank 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, Rksource ready and not yet readYes if Qj (Qk) is blank, else NoYes when the producer writes; No at the read
Timeexecution 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.

Name Busy Fi Fj Fk Rj Rk Integer Yes F8 — R1 — No Add Yes F6 F4 F8 No Yes F8 will be written by: Integer I2 has not read F8 yet

Before: end of cycle 8 — I3 may not write

Name Busy Fi Fj Fk Rj Rk Integer No — — — — — Add Yes F6 F4 F8 No No F8 will be written by: — read at 11, written at 12

After: end of cycle 12 — F8 written, unit free

Fig. 4. The WAR hazard on F8, as the functional-unit status table sees it. The only cell that forbids the write at cycle 8 is 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.

The scoreboard stepper

The three tables of the fragment, one cycle per step, shown as they stand at the end of the cycle. Cells that changed in this cycle are highlighted; a cell with an orange frame is the one that refused an instruction in this cycle, and the log under the controls names the rule. Program N is the notes' example (page 115, written in the papers' mnemonics; the notes write MULTD, SUBD, DIVD, ADDD) for its first three cycles only — the other 59 are lesson 10.

  1. Before you step to cycle 2, write down the Mult1 row as it will look after I1 issues: which cells are filled, what Qj and Rj say, and what the register result entry of F4 says. Then step and compare.
    What you should see

    Busy = Yes, Op = Mult, Fi = F4, Fj = F2, Fk = F0, Qj = Integer, Rj = No (F2 is promised to the Integer unit), Qk blank, Rk = Yes; and register result F4 = Mult1. Rj and Qj are set together: Rj is No exactly because Qj is not blank.

  2. Step to cycle 4. I3 is next to issue, and nothing it needs is pending. Predict whether it issues in cycle 4; then read the refusal line of the log.
    What you should see

    It does not: the Integer row still says Busy = Yes in the cycle in which I0 writes F2. A unit is Busy from issue through write result inclusive, so I3 issues at cycle 5. This is the one wait predicate of the Issue stage that is about resources, not data.

  3. Step to cycle 8. I3 completed its execution at cycle 7. Predict the single cell that forbids its write; then look for the orange frame. Keep stepping and note the cycle in which the frame disappears.
    What you should see

    The cell is Rk = Yes in the Add row (its Fk is F8): I2 has not read F8 yet. The frame stays through cycle 10. In cycle 11 I2 reads and the flag flips to No — the log says the cell is cleared at the end of that cycle, and the frame is gone — and at cycle 12 I3 writes F8. The refusal was decided by the unit rows, not by the register result table.

  4. Step to cycle 14. The Mult1 row (now holding I4) shows Rj = No and Rk = No although F2 and F0 have been in the register file for ages. Predict why; then read the log of cycle 14.
    What you should see

    I4 read both operands in cycle 14, and the flags go back to No at the read. From now on "No" in that row means "already taken": a later writer of F2 or F0 would be allowed to write. One flag, two meanings — ready and not yet read — and that is what makes four small wait predicates, one per stage, enough.

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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:

\[ \begin{aligned} I_n = \max\big(&I_{n-1} + 1, \\ &WB_U + 1,\ WB_W + 1\big) \end{aligned} \] \[ RR_n = \max\big(I_n + 1,\ WB_P + 1\big) \] \[ E_n = RR_n + L \] \[ WB_n = \max\big(E_n + 1,\; RR_A + 1\big) \]
\(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:

\[ RR_2 = \max(3 + 1,\ 10 + 1) = 11 . \]

I3 completes at 7, but I2 reads F8 only at 11:

\[ WB_3 = \max(7 + 1,\ 11 + 1) = 12 . \]

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\).

The fragment on the scoreboard — basic scheme (WAW at Issue, no forwarding); Integer 1, Add 2, Mult 4.
InstructionIRREWBHazards TypeUnit
I0: LD F2, 0(R1)1234noneInteger
I1: FMUL F4, F2, F025910RAW F2 (I0)Mult1
I2: FADD F6, F4, F83111314RAW F4 (I1)Add
I3: LD F8, 8(R1)56712Structural Integer (I0); WAR F8 (I2)Integer
I4: FMUL F8, F2, F013141819WAW F8 (I3)Mult1
I5: SD F6, 16(R1)14151617none (RAW F6 costs nothing)Integer
12345678910111213141516171819 I0 LD I1 FMUL I2 FADD I3 LD I4 FMUL I5 SD I R I RAW F2 R I RAW F4 R STR I R WAR F8 WAW F8 I R I R I5 finishes before I4 execution waiting (the hazard) write result I = issue, R = read
Fig. 5. The same table as a timeline. Each dashed bar is one wait predicate failing: 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

The hazard court

Eight cycles of the second fragment, chosen where something is decided. For each case the tables show the state at the start of the cycle. Tick every move you think the scoreboard allows in that cycle, then press Check: the court applies the four conditions and explains every refusal, framing the cell that decided it.

  1. Case 1 (cycle 2). Tick what happens, then check. Which stage refused I1, and which single cell did that stage read?
    What you should see

    I0 reads R1; I1 is refused at Issue because the Integer row says Busy = Yes. Nothing about data: I1 depends on nobody. The unit is Busy until I0's write result at cycle 4, so I1 issues at 5.

  2. Case 3 (cycle 7). I3, FADD F2, F0, F6, has a free Add unit and both its sources already in the register file. Predict whether it issues; then check and name the table that said no.
    What you should see

    Refused: the register result status says F2 = Integer — I1 has not written F2 yet, so a second write to F2 may not even enter the machine. WAW is checked at Issue, from the register result table, and it stalls I3 until cycle 9 although I3 needs no data at all.

  3. Case 4 (cycle 8). I1 wants to write F2, and the Mult1 row shows Fk = F2. Predict allowed or refused; then check which flag decided.
    What you should see

    Allowed: the Mult1 row has Rk = No. I2 has not read F2 — it is waiting for exactly this write — and "No" lets the write through. The write then flips Rk to Yes, and I2 reads in cycle 9.

  4. Case 6 (cycle 13). I3 wants to write F2 and the Mult1 row still shows Fk = F2. Predict; then check — and compare with case 4.
    What you should see

    Allowed again, for the other reason: Rk = No because I2 read F2 at cycle 9. The same flag value means "already read" here and "not ready yet" in case 4, and both are safe for a writer. Three checks, three stages: WAW at Issue (case 3), RAW at Read Operands (I2 in cases 3 and 4, I4 in case 6), WAR at Write Result (the test that passed here).

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.

  1. The parallelism available among the instructions. If every instruction depends on the previous one, there is nothing to overlap, however clever the controller.
  2. 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.
  3. The number and types of functional units — structural hazards. I3 lost 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.
  4. 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
InstructionIRREWBHazards TypeUnit
I0: LD F0, 0(R1)1234noneInteger
I1: LD F2, 8(R1)5678Structural Integer (I0)Integer
I2: FMUL F4, F0, F2691314RAW F2 (I1)Mult1
I3: FADD F2, F0, F69101213WAW F2 (I1); WAR F2 with I2 costs nothing (I2 read at 9)Add
I4: SD F4, 16(R1)10151617RAW F4 (I2)Integer
I5: ADDUI R1, R1, 818192021Structural 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)

  • stalling the reader in the Read Operands stage That is what the scoreboard does for a RAW hazard; a WAR hazard is about a writer that is too early.
  • stalling the writer in the Write Result stage until every earlier reader has read the register The write is postponed while a unit row has the register as a source with Rj or Rk still Yes.
  • renaming the destination register The scoreboard has no renaming; that is Tomasulo's answer.
  • stalling the writer in the Issue stage Issue stalls on structural and WAW hazards, not on WAR.
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)

  • the operand Fj is not ready yet That is one of the two cases, not the only one.
  • the operand Fj has already been read That is the other case, not the only one.
  • either "not ready yet" or "already read" — and both are safe for a later writer, because the basic scheme blocks WAW at Issue The flag means "ready and not yet read"; after the read it is reset to No, and the Write Result test only has to look for a Yes.
  • the unit is idle An idle unit has Busy = No; the flags of an idle row are blank.
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.

  • True The result may still be waiting to be written (a WAR hazard, or a busy write port), and the unit holds it meanwhile.
  • False The unit is Busy from issue through write result; the next instruction for it can issue the cycle after the write.
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?

  • The instruction in the Add unit, in the Read Operands stage Rk = Yes says its operand is ready: that instruction is not held by this cell at all — it is held, if anything, by its other flag.
  • A later instruction that wants to write F8, in the Write Result stage Yes: an earlier reader of F8 has not read it, so a writer of F8 would create a WAR hazard and is kept from writing.
  • A later instruction that reads F8, in the Issue stage A later reader of F8 is not in danger: it simply copies the register result entry of F8 into its own Qj or Qk.

Which statements about the flags Rj and Rk are true?

  • They are set to No in the cycle in which the instruction reads its operands That is the half the notes forget; the Write Result test needs it.
  • At issue, Rj is Yes exactly when Qj is blank Nobody is due to write the source, so its value is in the register file.
  • Rj = Yes means the instruction has finished executing Execution progress is in the Time column (and in the instruction status table); the flags are about the sources.
  • Rj = No can mean "already read" After the read, No means exactly that — and a later writer of Fj may then proceed.

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 cycle after its instruction completes execution The result may still be waiting for a WAR hazard or a write port; the unit holds it meanwhile.
  • in the cycle after its instruction writes its result Busy is cleared at Write Result; the structural check at Issue sees it free from the next cycle.
  • in the cycle after its instruction reads its operands The unit is executing then — it is at its busiest.

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?

  • Loads have priority over floating-point instructions There is no priority; each row waits only for its own sources.
  • Read Operands is out of order: each issued instruction waits only for its own two flags I3's only source, R1, is ready; I2's F4 is not. Nothing links the two decisions.
  • The scoreboard renamed F8 so that I3 does not conflict with I2 No renaming exists; the conflict on F8 is real and is paid later, at I3's write.

The register result status says F6 = Add. The next instruction to issue is FMUL F6, F2, F0, and Mult2 is free. What happens?

  • It issues on Mult2 and waits at Read Operands Its sources F2 and F0 may well be ready; the problem is its destination.
  • It stalls at Issue until the Add unit has written F6 — and every later instruction stalls behind it WAW is checked at Issue from the register result table; in-order issue means the queue behind it stops too.
  • It issues and the scoreboard delays only its write until after the Add unit's write That is the postponed-WAW variant of the exam's optimised scheme, not the basic scheme.

Which of these does the scoreboard not have (and Tomasulo's machine, or its reorder-buffer extension, adds)?

  • A bus that forwards a result to the waiting instructions No forwarding: the consumer reads from the register file the cycle after the write. Tomasulo's Common Data Bus is that bus.
  • Register renaming Hence WAR and WAW stalls; reservation stations give each result a temporary name.
  • Out-of-order execution It has it — that is the whole point of the scoreboard.
  • Precise exceptions Out-of-order completion with no reorder buffer makes exceptions imprecise.

Keep the list for the open question: what the scoreboard lacks is exactly what the next two lessons add.

Key take-aways

What to watch and read