Doing more per cycle: superscalar, static vs dynamic scheduling, the limits of ILP

After this lesson you will turn any issue width into an ideal CPI, place a processor on the four-step ladder from scalar to superscalar, write the exam's "main concepts and benefits" answer in five lines per technique, and say why real cores stopped at four to six instructions per cycle.

In 1967 Robert Tomasulo described the IBM System/360 Model 91's floating-point unit as hardware that speeds execution by "looking ahead" about eight instructions for work it can run early. Intel's Golden Cove core (2021) keeps 512 instructions in flight in its reorder buffer and decodes six per cycle: the window grew 64 times, the width 6 times.

Yet on ordinary programs such a core completes about two to three instructions per cycle. Lighterra's guide to modern microprocessors quotes Andy Glew's confession: "the dirty little secret of OOO is that we are often not very much OOO at all". Where did the other slots go?

That gap is this lesson: the trick that makes a CPI below 1 possible, the ladder of designs that reach it, the five walls that stop it — and the exam question that asks for all of it in five lines per technique.

One instruction per cycle is a ceiling, not a law

Every pipeline so far — the five-stage datapath of lesson 1, the multi-cycle pipelines of lesson 7 — obeys one silent rule: at most one instruction enters per clock and at most one leaves. Ideal CPI = 1; hazards push it above 1. Even a program of independent instructions is processed by the scalar pipeline "sequentially, one at a time" (p. 89).

Dynamic scheduling (lesson 7) attacks the stalls, not the rule. The notes' three instructions of p. 87, numbered from I0 as the papers do and in the papers' mnemonics (older papers write $F0; the 2026 paper and this notebook drop the dollar sign):

I0: FDIV F0, F2, F4       ; long: the divider takes many cycles
I1: FADD F10, F0, F8      ; RAW on F0: must wait for I0
I2: FSUB F12, F8, F14     ; independent of both

In order, I2 waits behind I1 and I1 waits for the divider. With dynamic scheduling the three are still issued in program order, but into reservation stations: I1 waits there for F0 while I2 executes, and each result reaches its consumers over the common data bus (lessons 11–13; the scoreboard, lessons 9–10). What does not change: one instruction is still issued per cycle, so the CPI can approach 1 but never go below it.

Multiple-issue processor — a processor that fetches, decodes, issues and executes more than one instruction per clock cycle (Definition 1, p. 89), the parallel instructions chosen by the hardware at run time (superscalar) or by the compiler at compile time (VLIW).

The simplest case is the dual-issue pipeline: up to two instructions fetched, decoded and issued per clock (Definition 2, p. 90). Fig. 1 redraws the notes' Figure 22 as a before / after pair: same stages, same clock, instructions travelling in pairs.

C1 C2 C3 C4 C5 I1 I2 I3 I4 I5 IF ID EX ME WB IF ID EX ME IF ID EX IF ID IF 5 in flight one finishes per cycle

Before: scalar, one instruction per clock

C1 C2 C3 C4 C5 I1 I2 I3 I4 I5 I6 I7 I8 I9 I10 IF ID EX ME WB IF ID EX ME WB IF ID EX ME IF ID EX ME IF ID EX IF ID EX IF ID IF ID IF IF 10 in flight two finish per cycle

After: dual issue, two instructions per clock

Fig. 1. The notes' Figure 22 redrawn. Same stages, same clock: the dual-issue pipeline holds twice as many instructions in the highlighted clock C5 and finishes two per cycle. Multiple issue multiplies the work in flight by the width, not by the depth.

The notes' figure runs its clock at 2 ns: two instructions every 2 ns is one per nanosecond, 1000 MIPS from a 500 MHz clock — twice the scalar pipeline. Ideal IPC = 2, ideal CPI = 1/2 = 0.5. The general rule (p. 95), on which every "ideal CPI" quiz of the exam rests, is one line:

\[ \mathrm{CPI}_{ideal} = \frac{1}{\text{issue width}} = \frac{1}{w} \] \[ \text{instructions in flight} = w \times \text{depth} \] \[ \mathrm{CPI} = \mathrm{CPI}_{ideal} + \text{stalls/instr} \]
\(w\)
issue width: instructions fetched, decoded, issued and started per clock, at most
depth
pipeline stages (Fig. 1: 2 × 5 = 10)
stalls/instr
what hazards, misses and mispredictions add, as the example formula sheet writes it

What a second issue slot costs

Figure 23 of the notes (p. 91) is Patterson and Hennessy's two-issue datapath, its additions drawn in orange but not explained; Fig. 2 names them. One packet per cycle — one ALU-or-branch instruction plus one load-or-store, p. 91 — needs five additions:

  1. a wider fetch: two instructions, 64 bits, per cycle;
  2. two decoders;
  3. a register file with 4 read ports and 2 write ports — an ALU operation reads two registers and a store reads two more (base and data); an ALU operation and a load both write in the same cycle;
  4. a second adder for the load's address;
  5. hazard detection across the pair (p. 93): independent, compatible types.

Even this ideal 2-wide machine rarely reaches its width. Patterson and Hennessy's own five-instruction loop runs on it at IPC 1.25, not 2: the pairing rule and the load-use delay leave three of the eight slots empty, and only unrolling the loop four times lifts it to 1.75. That gap is what the notes mean by "it cannot be always reached" (p. 95) and what the exam measures as code efficiency (section 4).

Instr. memory 2 per cycle Decoder 1 pair check Decoder 2 Registers 4 read ports 2 write ports ALU or branch ALU write 1 address adder load or store Data mem write 2 shaded = added for dual issue
Fig. 2. The notes' Figure 23, simplified. The single-issue datapath gets a second decoder, a check that the pair is independent and compatible, two extra read ports and one extra write port, and a second adder for the load/store address so that both instructions execute in the same cycle.

Each costs area and power, and not alike: ports and decoders grow with w, the bypass network — each result compared with every source operand of the next packet — with w². The widget shows that growth, and the ideal CPI falling as 1/w while the achieved one goes flat.

The issue-width dial

The upper picture is one clock of a w-wide, d-deep pipeline — the highlighted column of Fig. 1 for any width and depth — with bars for the hardware that grows with w. The plot compares the ideal IPC (= w) with a stylised model of the achieved IPC: switch the three walls on to see what each one costs. The model is a caricature, not a measurement; the shape is what matters.

  1. Before touching anything: how many instructions are in flight with w = 4 and 5 stages, and with w = 2 and 10 stages? Then set both and compare the bypass readout.
    What you should see

    Both hold 20 instructions in flight: w × depth = 4 × 5 = 2 × 10. But the 4-wide machine needs 32 bypass paths and 12 register ports against 8 and 6 — the same in-flight count, four times the forwarding hardware. Depth is cheap; width is not.

  2. Switch on only wall 1 (finite ILP). Predict: when w goes from 4 to 8, by how much does the achieved IPC rise?
    What you should see

    From about 2.53 to 3.46 — less than one extra instruction per cycle for twice the width, while the ideal doubles from 4 to 8. The window finds about four independent instructions per cycle on average; slots beyond that stay empty. This is the notes' "diminishing returns" (p. 97) made visible.

  3. Switch on all three walls with depth 7 and read the IPC at w = 1, 2, 4 and 8. Which step buys the most?
    What you should see

    About 0.71, 1.10, 1.50 and 1.79. Going from 1 to 2 gains 0.39; going from 4 to 8 gains 0.29 for four extra slots. The ideal CPI falls as 1/w, but the achieved curve flattens after three or four — the insight this widget exists for.

  4. Leave only wall 2 (branch mispredictions) on, set w = 8 and move the depth from 5 to 10. Why does the depth matter here and nowhere else?
    What you should see

    The IPC falls from about 5.7 to 4.4. A misprediction throws away everything fetched since the branch, and that is depth cycles of fetch — depth × w instructions. The deeper and wider the machine, the more a wrong guess costs; this is why branch prediction (lessons 4–6) matters more on a superscalar than on a scalar pipeline.

Multiple issue multiplies the work in flight by the width: ideal CPI = 1/w, in flight = w × depth — a ceiling, because the slots still have to be filled with independent instructions.

Four steps from scalar to superscalar

The notes (pp. 92–94) describe the road from the scalar pipeline to the modern core as four steps, summed up in Table 10. Read it column by column first.

Table 10 of the notes (p. 94): the evolution towards superscalar execution.
StepIssueExecutionCommitExample
1In-orderIn-orderIn-orderScalar pipeline
2In-orderOut-of-orderIn-orderDynamic single-issue
3In-orderIn-orderIn-orderDual-issue pipeline
4In-orderOut-of-orderIn-orderSuperscalar processor

Issue is in order in every row; commit is in order in every row; only Execution changes, and the width. A processor becomes superscalar by widening issue and freeing execution — never by reordering issue or commit. Issue stays in order so that each instruction meets its predecessors on the way in; commit stays in order so that an exception finds the state a sequential execution would have left — precise, as in lesson 7; the reorder buffer of lesson 17 enforces it, and the notes assume it for step 2 ("a commit stage ensures in-order architectural updates", p. 92).

One fragment, four rows. The machine: one unit of each kind, all pipelined; FDIV 8 cycles, FADD and FMUL 3, LD 2, ADDUI 1; a result is written the cycle after execution ends and committed the cycle after that; different units may write in the same cycle; at most w commits per cycle. "In-order execution" means that the starts are in program order — a short operation may still finish before a longer one that started earlier, as in the multi-cycle pipeline of lesson 7; the in-order commit puts the results back in order.

I0: FDIV  F0, F2, F4        ; 8 cycles
I1: FADD  F6, F0, F8        ; RAW on F0 (I0)
I2: LD    F10, 0(R1)        ; 2 cycles, independent
I3: FMUL  F12, F10, F14     ; RAW on F10 (I2)
I4: ADDUI R1, R1, 8         ; writes the R1 that I2 reads (WAR)
I5: FADD  F16, F8, F14      ; independent

Step 1 — single issue, in-order execution. I0 issues in cycle 1, starts in 2, writes F0 in 10. I1 needs F0 and cannot issue before 10 — nor can anything behind it: I2, dependent on nobody, waits until 11. Last commit: cycle 21. "Hazards (data, structural, control) cause pipeline stalls that affect all subsequent instructions" (p. 92).

Step 2 — single issue, out-of-order execution. I1 issues in cycle 2 into a reservation station and waits; I2 issues in 3, starts in 4, writes in 6; I3 to I5 follow. Every result exists by cycle 14, but commit is in order, one per cycle: I1 at 15, I2 to I5 at 16 to 19. "Throughput is still constrained by the single-issue limit" (p. 92).

Step 3 — dual issue, in-order execution. Two independent instructions on different units issue together: I1 and I2 in cycle 10, I3 and I4 in 13, I5 in 14 — 19 again, because an in-order packet stalls as a unit: I2 waited with I1. "Dependent instructions must wait, even if others could proceed" (p. 93).

Step 4 — dual issue, out-of-order execution. I0 and I1 issue in cycle 1, I2 and I3 in 2, I4 and I5 in 3; the independent work is written by cycle 9, the chain at 14, and two commits per cycle end at 17. In the layout of the exam's Tomasulo tables, with a commit column:

Step 4 on the fragment: dual issue, out-of-order execution, in-order commit (two per cycle).
INSTRUCTIONISSUESTART EXECWRITE RESULTCOMMITHazards Type
I0: FDIV F0, F2, F4121011None
I1: FADD F6, F0, F81111415RAW with I0 for F0
I2: LD F10, 0(R1)23515None
I3: FMUL F12, F10, F1426916RAW with I2 for F10
I4: ADDUI R1, R1, 834516WAR with I2 for R1, solved (operand copied at issue)
I5: FADD F16, F8, F1434717None

Against step 1: step 2 saves two cycles, step 3 two, step 4 four. Each middle step removes one restriction — the order of execution or the width of issue — and the superscalar removes both. And no machine on the ladder, however wide, finishes before cycle 15: issue, start, eight cycles of divide, three of add and one commit for the chain FDIV → FADD. A true dependence is what no width can touch; section 5 names that fact.

The evolution stepper: one fragment, four machines

The timeline runs the six instructions above through the four rows of Table 10. Every row shows when the instruction issues, how long it waits for an operand, when it executes, when it writes and when it commits. Step through and watch what each row of the table changes — and what it never changes.

  1. Before stepping: which will take fewer cycles — step 2 (single issue, out of order) or step 3 (dual issue, in order)? Then step through and check.
    What you should see

    Both take 19 cycles, two fewer than step 1. Each removes one restriction and gains the same here, but differently: in step 2 everything is computed by cycle 14 and the single commit slot stretches the end; in step 3 the pairs issue two at a time but the first pair waits as a unit behind the divide until cycle 10. Step 4 removes both restrictions and takes 17.

  2. In step 4, I1 is issued in cycle 1 together with I0 but starts only in cycle 11. Where does it spend the nine cycles, and why does it not block I2?
    What you should see

    In a reservation station, with the tag of I0 in place of F0 (the orange dashed bar). Issue continues because the station, not the pipeline, holds the waiting instruction; I2 and I3 issue in cycle 2 and execute while I1 waits. In steps 1 and 3 the same wait blocks the issue of everything behind it.

  3. Look only at the commit marks (the dashed boxes) in each of the four steps. In which step do they ever come out of program order?
    What you should see

    In none. Even in step 2, where I2 has its result at cycle 6, it commits at 16, after I1. Execution and write-result reorder; issue and commit never do — Table 10's two unchanging columns.

  4. Could a 4-wide or 8-wide machine finish this fragment before cycle 15?
    What you should see

    No. The chain FDIV → FADD needs 1 (issue) + 1 (start) + 8 + 3 cycles before its write at 14 and its commit at 15, whatever runs beside it. Width multiplies the independent work; it does nothing for the dependent chain — Amdahl's serial part in miniature.

Intel's Pentium (1993) is step 3: two in-order pipes, U and V, taking a pair of instructions per cycle when the pair fits the rules. The Pentium Pro of 1995 is step 4 — a February 1995 Microprocessor Report describes x86 instructions decoded into micro-operations, a reservation station, a reorder buffer and out-of-order execution, with a 133 MHz target. The big x86 and ARM cores in your laptop and phone are step-4 machines of this kind, four to eight wide.

"Out of order means out-of-order issue." No: in all four rows the instructions are issued in program order, one packet per cycle; execution and write-result reorder, and commit restores the order. The exam's Tomasulo tables rest on this — the ISSUE column grows by one per row.

Issue and commit are in order in every design; only execution is freed, and only the width grows. Step 2 and step 3 each remove one restriction of the scalar pipeline; the superscalar removes both.

The superscalar recipe and its six parts

Superscalar processor — "a dynamically scheduled, multiple-issue architecture capable of issuing and executing several instructions per clock cycle, using complex hardware mechanisms to detect and exploit instruction-level parallelism at runtime" (Definition 3, p. 95).

The notes reserve the word for step 4 — multiple issue plus dynamic scheduling; some textbooks also call step 3 an in-order superscalar, but on the exam follow the notes. Four key characteristics (pp. 95–96): an issue width, "the maximum number of instructions a processor can fetch, decode, issue, and begin executing in a single clock cycle", which "cannot be always reached (hazards, etc.)"; dynamic scheduling, the hardware analysing dependences in real time; out-of-order execution, as soon as operands and resources are ready; in-order commit, so that the architectural state follows program order and exceptions stay precise. A superscalar is not several pipelines side by side: one front end issues up to w instructions per cycle into one shared pool of units, and they still form one program.

The architecture "must include" six components (p. 96). Fig. 3 places each in the path of an instruction; the list says what each buys, because the exam asks for benefits.

issue: w per cycle, in order CDB tag + value wakes the consumers commit, in order Fetch, decode Rename table Reservation stations = the window Load/store FP ALU Int ALU ROB Register file architectural state in order in and out
Fig. 3. The six components of the notes' recipe (p. 96) in the path of an instruction. The violet boxes are bookkeeping about the stream; the units compute; the common data bus carries each result, with its tag, to the stations that wait for it and to the reorder buffer, which commits in program order.

Benefits (p. 96): high ILP; dynamic parallelism — "no need for compiler to expose ILP, hardware finds it at runtime"; latency hiding of misses and FP divides; generality, "even without manual tuning". Challenges (pp. 96–97): complex hardware; issue-logic scalability — "the complexity of deciding which N instructions to issue out of M in-flight grows quickly", every broadcast tag being compared with every waiting operand every cycle; branch and memory dependences; diminishing returns — "after 3-4 issue width, real programs rarely expose enough parallelism to fully utilize the issue bandwidth" (p. 97; p. 102 says 4–6 for the hardware's own limit).

The exam question this section answers

Question 1 of the 22 June 2026 paper (8 points): "Explain the main concepts and benefits of each one of the following techniques used by modern superscalar processors (Tomasulo-style)" — eight techniques, five lines each. The discipline is concept, benefit, cost: the table is the compressed form, the exam section writes it out. Reservation stations, the reorder buffer and SMT have their own lessons (11, 17, 29).

The eight techniques of the June 2026 question in one line each: what it is, what it buys, what it costs.
TechniqueMain conceptBenefitCost
Dynamic instruction schedulinghardware decides at run time when each instruction executes: in-order issue, out-of-order executiona stalled instruction no longer blocks independent ones; handles latencies unknown at compile time; one binary fits many pipelinesstations, tags, a broadcast bus
Branch prediction and speculationpredict outcome and target at fetch; execute the predicted path before the branch resolves, results held backremoves most control stalls; keeps a wide front end fedflush on a misprediction, costing depth × width slots
Multiple-issue pipelinefetch, decode, issue up to w per cycle into several unitsIPC above 1, ideal CPI = 1/wwider fetch, more ports, cross-packet checks
Reservation stationsbuffers at each unit holding the operands or the tags of their producersdistributed hazard detection; operands fetched once; issue continues past a waitone station per in-flight instruction
Register renaminga new name (tag, physical register) for every destination; readers redirectedWAR and WAW disappear; only RAW remains; loops overlapa larger register set or tag space, a rename table
Out-of-order executionexecute in the order operands become ready, not program orderfills the stall cycles of long operations; more ILP from the windowneeds renaming and in-order commit
Reorder buffera FIFO in program order holding results until commitprecise exceptions; speculation undone by discarding entriesbuffer space, commit latency
Simultaneous multithreadingseveral threads issue in the same cycle into one out-of-order coreempty issue slots filled with another thread's work; per-thread ideal CPI = threads/wper-thread state; threads contend for caches and units

Three true sentences from the 2025 midterm

The midterm of 5 May 2025, as the notes transcribe it (pp. 540–541), ends with three true-or-false statements to motivate: doubling the number of issues reduces the CPI; out-of-order execution can be generated by data cache misses; dynamic branch predictors improve the CPI. All three are true, and the motivation earns the points — the first only for the ideal CPI, the second because the scheduler, not the miss, is the mechanism. They are the fourth exam question below, with the motivations; the third one rests on the notes' formula (p. 541):

\[ \mathrm{CPI} = \mathrm{CPI}_{ideal} + f_b \times m \times P \]
\(f_b\)
branch frequency
\(m\)
misprediction rate
\(P\)
misprediction penalty in cycles; it grows with the depth, and the work thrown away with depth × width

Superscalar = multiple issue + dynamic scheduling + out-of-order execution + in-order commit, built from units, renaming, stations, a reorder buffer, a common data bus and a window — and the exam wants the benefit of each.

Compiler or hardware: static vs dynamic scheduling

Who finds the parallelism? Table 11 (p. 98) answers in two rows, and everything else follows from them.

Performed by the compiler, at compile time: the schedule is fixed before the program runs.

Performed by the hardware, at run time: decided every cycle from what is ready.

A VLIW (Very Long Instruction Word) processor is "a statically scheduled, multiple issue processor architecture in which the compiler selects and packs multiple independent operations into a single, wide instruction word that is executed in parallel by the processor" (p. 98) — a memory, a floating-point and an integer operation per word, the three columns of the exam's VLIW table. The compiler detects the ILP, schedules around the hazards (it knows every latency) and fills the empty slots "with NOPs when no instruction fits" (p. 98); the hardware checks nothing.

Mem FP Int C1 op1 op2 op3 C2 op4 NOP op5 C3 NOP NOP op6 C4 op7 op8 NOP C5 NOP NOP op9 C6 NOP NOP NOP C7 NOP op10 NOP 10 of 21 slots used

Static: the compiler packs the words, NOPs included

code I0 I1 I2 I3 I4 I5 I6 I7 window I3 ready I4 waits I5 ready Mem FP Int picked each cycle

Dynamic: the hardware fills the units from the window

Fig. 4. The same work two ways. Left: ten operations packed by the compiler into seven 3-slot words — eleven slots are NOPs, so the code efficiency is 10/21 = 47.6 %. Right: ordinary sequential code, and a window from which the hardware picks the ready instructions every cycle.

The formula sheet measures the left panel in one number:

\[ \text{code efficiency} = \frac{\mathrm{IC}}{\#\text{cycles} \times \#\text{issues}} \]
\(\mathrm{IC}\)
instructions (operations) actually scheduled
\(\#\text{cycles} \times \#\text{issues}\)
all the slots of the schedule: cycles times issue width; the difference is NOPs

In Fig. 4, 10/21 = 47.6 % of the slots do work; lesson 20 computes it for the exam's schedules, where every VLIW exercise asks it. The right panel is the superscalar's answer: "the compiler generates sequential code (as usual, no additional effort)" (p. 99); the hardware chooses every cycle from whatever is ready.

The balance sheet (pp. 98–99) follows from who decides. The VLIW gains simple hardware — "no need for out-of-order logic, dependency checks at runtime, or renaming hardware" — predictable timing, and energy efficiency, the decision being made once at compile time instead of every cycle in silicon. It loses three ways: performance depends on the compiler and on the visible ILP; binary compatibility — the schedule encodes one machine's units and latencies, so the next machine needs a recompilation, and it "cannot adapt to unpredictable latencies at runtime"; and wasted slots — NOPs that still cost fetch bandwidth and code size. The superscalar reverses every line — adapts, stays portable, finds hidden ILP — and pays in area, power, scheduling logic that "becomes a bottleneck at wider issue widths" and timing that is hard to verify (Table 12).

Table 12 of the notes (p. 99): static vs dynamic scheduling.
FeatureStatic (VLIW)Dynamic (superscalar)
Scheduling responsibilityCompilerHardware
Instruction issueFixed and pre-plannedDetermined at runtime
Flexibility at runtimeLowHigh
Hardware complexityLowHigh
Compiler complexityHighModerate
Portability of compiled codeLow (machine-dependent)High
Latency tolerancePoor (fixed schedule)Good (adaptive execution)
ILP exploitationOnly what compiler exposesAlso includes dynamic/hidden parallelism

"Moderate" on the dynamic side is a real middle: a scheduling compiler still helps a superscalar (fewer stalls inside the window), but nothing breaks without it, whereas on a VLIW the compiler's schedule is the only thing that keeps the results right.

Why can a VLIW binary not run on the next chip?

The compiler placed a load's consumer two words later because the memory latency was 3; on a chip where it is 5 the consumer fires before the value exists. The schedule is the hazard check, and it is wrong for the new machine: add interlocks and lose the simplicity, or recompile. A superscalar reads the same binary and waits in the station for the tag.

Hence the domains (p. 100): VLIW "for predictable workloads, embedded systems, or domain specific processors, where simplicity and determinism matter"; superscalar for general-purpose computing, where run-time variability makes "hardware-managed scheduling more effective". Lessons 19–21 open the static side: bundles, list scheduling, software pipelining.

Static: the compiler packs independent operations into wide words and pays in NOPs and portability. Dynamic: the hardware picks from a window every cycle and pays in silicon and power.

Why ILP hit a wall — and the way out

Pipelining, multiple issue, dynamic scheduling and renaming "have pushed ILP to impressive levels" (p. 101) — and then it stops. Five limits, each already met in a widget:

  1. Limited parallelism in programs. Much code is sequential in logic, and the hardware exploits only what it sees: the instruction window, "the set of instructions that the processor can see and analyze" at a given time — a few dozen to a few hundred, bounded by area, power and timing, "a practical limit". Behind it stands a theoretical one, Amdahl's law.
  2. Dependency constraints. True dependences "cannot be bypassed or parallelized because the value doesn't exist yet": a chain executes one link at a time — the FDIV → FADD chain of the stepper.
  3. Control dependences and branches. Even with prediction and speculation, "mispeculation causes flushes and wasted cycles", growing with depth × width — the dial's second wall.
  4. Memory latency and aliasing. Misses are long and unpredictable, and dependences through memory are hard to resolve at run time, addresses being known only after execution — the third wall.
  5. Hardware complexity and power. The logic for dependence checking, wakeup-select, renaming and window scaling "grows rapidly"; "superscalar processors beyond 4-6 issue width become infeasible to scale" (p. 102) — the quadratic bar.

Amdahl's law, derived and corrected

The notes put limit 1 in numbers: "if 10% of our program is serial (f = 0.1), then the best speedup we can ever get is 1/0.1 = 10", even with "unlimited issue width, perfect branch prediction, and ideal memory". Lesson 3 met the law for one enhancement; here the enhancement is everything the machine can overlap and the serial part is the dependent chain.

  1. Call the original execution time 1. A fraction \(f\) of it is serial and cannot be sped up; the rest, \(1 - f\), can be run \(p\) times faster (more issue slots, more units — any overlap).

  2. The serial part still takes \(f\). The parallel part now takes \((1-f)/p\):

    \[ T_{new} = f + \frac{1-f}{p} . \]
  3. Speedup is old time over new time:

    \[ \mathrm{Speedup}(p) = \frac{1}{\,f + \dfrac{1-f}{p}\,} . \]
  4. Let \(p\) grow without bound; the parallel term vanishes and the serial one stays:

    \[ \mathrm{Speedup}_{max} = \frac{1}{f} \quad (p \to \infty) . \]

The example formula sheet writes the same law with the enhanced fraction \(F\) and its speedup \(S\):

\[ \mathrm{Speedup} = \frac{1}{(1-F) + \dfrac{F}{S}} \] \[ \mathrm{Speedup}_{max} = \frac{1}{1-F} \]
\(F\)
fraction of the time that is enhanced (parallelisable): \(F = 1 - f\)
\(S\)
speedup of the enhanced part: \(S = p\)

Same formula, \(F = 1 - f\) and \(S = p\). The exam trap is the reading: check whether the fraction you are given is the serial or the enhanced one before substituting. With \(f = 0.1\): \(p = 2\) gives 1.82, \(p = 4\) gives 3.08, \(p = 8\) gives 4.71, and no \(p\) reaches 10.

Amdahl's ceiling

The curve is the speedup of a program whose serial fraction is f when the rest runs p times faster; the dashed line is the ceiling 1/f. The toggle relabels the readouts in the formula sheet's F and S.

  1. Keep f = 0.1. Predict the speedup at p = 8 before you move the slider there, and say how far below the ceiling it is.
    What you should see

    About 4.71 — less than half of the ceiling 10, although the parallel part already runs eight times faster. The 10 % serial part, unchanged, is now almost half of the new time: 0.1 out of 0.1 + 0.9/8 = 0.2125.

  2. Push p to 64. Does the curve reach 10?
    What you should see

    No: 8.77. The ceiling is a limit for p → ∞, and every extra doubling of p buys less. An infinite issue width with perfect prediction and ideal memory is p → ∞; a real 8-wide core is a small p.

  3. Set f = 0.5 (half the program is a dependent chain). What is the most any hardware can do?
    What you should see

    Speed it up by less than 2: at p = 64 the readout shows 1.97, and the ceiling is 2. This is why "10 % serial gives 90 % of the ideal speedup" is wrong: the serial fraction sets the ceiling as 1/f, not as a percentage of anything.

  4. Switch to the formula sheet's reading with f = 0.1 and p = 8. Which numbers does it show, and does the speedup change?
    What you should see

    F = 0.9, S = 8, and the same 4.71: one law, two spellings. On the exam, decide first whether the "fraction" you are given is the serial f or the enhanced F.

Where the slots went

Now the opening puzzle. A 512-entry window sees sixty-four times more than Tomasulo's eight instructions, but it sees the same programs: dependence chains executed one link at a time (limit 2, Amdahl's serial part); a branch every few instructions, each misprediction discarding depth × width slots (limit 3); loads that miss, stores whose addresses arrive late (limit 4). Two or three of the six slots fill on an average cycle, and widening window or issue adds comparators to a wakeup-select network that grows with window × width (limit 5). The slots went into the structure of the programs. The notes' "alternative forms of parallelism" (p. 102) are the rest of this course:

Five walls — window, true dependences, branches, memory, wakeup-select hardware — cap the sustained IPC at two or three; Amdahl says 1/f is the most any width can give; the way past is threads, data parallelism and accelerators.

Exam-style questions

Explain the main concepts and benefits of each one of the following techniques used by modern superscalar processors (Tomasulo-style): 1. Dynamic instruction scheduling; 2. Dynamic branch prediction and speculative execution; 3. Multiple-issue pipeline; 4. Reservation stations; 5. Dynamic register renaming; 6. Out-of-order execution; 7. Reorder buffer; 8. Simultaneous multithreading. (Five lines each.)

Show model answer

1. Dynamic instruction scheduling. The hardware, not the compiler, decides at run time when each instruction executes: instructions are issued in program order to reservation stations and start as soon as their operands and a functional unit are available, so execution and completion are out of order while issue and commit stay in order. Benefits: an instruction stalled on a long-latency producer (FP divide, cache miss) no longer blocks the independent instructions behind it; higher ILP and unit utilisation; latency hiding; dependences unknown at compile time (memory, misses) are handled; the same binary runs efficiently on different pipelines; it is the base for hardware speculation.

2. Dynamic branch prediction and speculative execution. A branch history table (with a branch target buffer) predicts the outcome and the target at fetch time from the past behaviour of the branch; the processor fetches, issues and executes the predicted path before the branch is resolved, keeping the results in the reorder buffer, and squashes them if the prediction was wrong. Benefits: removes most control stalls, keeps the issue slots of a wide machine full and exposes ILP across branches; the cost is the flush on a misprediction, which grows with pipeline depth and issue width.

3. Multiple-issue pipeline. The front end fetches, decodes and issues up to w instructions per cycle (the issue width) into several functional units, so IPC can exceed 1 and the ideal CPI is 1/w. It needs wider fetch and decode, a multi-ported register file, more functional units and hazard checks across the instructions issued together. Benefit: throughput multiplied by the width when enough independent instructions are available; the ideal is a maximum, rarely sustained because of dependences, branches and misses.

4. Reservation stations. Buffers in front of each functional unit that hold the operation, the operand values already available (Vj, Vk) or the tags of the instructions that will produce them (Qj, Qk); an instruction waits in its station and fires when the last operand arrives on the common data bus. Benefits: hazard detection is distributed (no central bottleneck), operands are fetched once at issue, so WAR hazards vanish, the station's tag renames the destination, so WAW hazards vanish, and issue continues past a waiting instruction.

5. Dynamic register renaming. At issue, every destination register is mapped to a new name — a reservation-station tag, a ROB entry or a physical register — and later readers are redirected to that name, so two instructions that reuse the same architectural register no longer conflict. Benefits: WAR and WAW hazards, which are name dependences, are eliminated; only true RAW dependences remain; more instructions can be in flight and loop iterations overlap without unrolling.

6. Out-of-order execution. Instructions execute in the order in which their operands become ready rather than in program order; issue and commit remain in order and results are broadcast on the common data bus to the waiting consumers. Benefits: independent instructions fill the cycles that dependent ones would waste, long latencies (loads, FP operations) are overlapped and more ILP is extracted from the instruction window; the cost is renaming, reservation stations and a reorder buffer to keep exceptions precise.

7. Reorder buffer. A FIFO in program order that holds each result from write-result to commit; the entry at the head commits to the register file (or to memory, for a store) only when it is complete and no longer speculative. Benefits: precise exceptions and an architectural state updated in program order; speculation can be undone by discarding the entries after a mispredicted branch; the register file is written only at commit.

8. Simultaneous multithreading. Several hardware threads issue in the same cycle into the functional units of one out-of-order core, each with its own PC and rename table, sharing the units and the caches. Benefits: thread-level parallelism fills the issue slots that the ILP of one thread leaves empty (both horizontal and vertical waste), so throughput rises at a small hardware cost; the ideal CPI of the core stays 1/w and the ideal per-thread CPI is threads/w; threads contend for caches and units, so single-thread performance can drop.

Five lines per item is the paper's own allowance: name the mechanism in one sentence, then the benefit, then one cost or condition. The examiner looks for the key words of each row (in-order issue, out-of-order execution, tags, broadcast, in-order commit, precise exceptions, threads/w) and for the distinction between items 1 and 6 — dynamic scheduling is the policy, out-of-order execution is what it produces.

Compare static (VLIW) and dynamic (superscalar) scheduling: who schedules the instructions and when, the main advantages and drawbacks of each approach, and their typical application domains.

Show model answer

Static (VLIW). The compiler, at compile time, packs independent operations into long instruction words, scheduling around the known latencies and inserting NOPs where no operation fits. Advantages: simple hardware (no dependence checks, no renaming, no out-of-order logic), predictable timing, low energy per instruction. Drawbacks: performance depends entirely on the compiler and on the visible ILP; the binary is tied to one machine configuration (units, latencies), so it must be recompiled for a new one; the schedule cannot adapt to run-time events such as cache misses or mispredictions; unused slots become NOPs, lowering the code efficiency IC/(cycles × issues). Domains: embedded, real-time, DSP and domain-specific processors.

Dynamic (superscalar). The hardware, at run time, detects the parallelism with reservation stations, register renaming and a reorder buffer, and issues whatever is ready. Advantages: adapts to unpredictable latencies, keeps binary portability (no recompilation), exploits the hidden parallelism of general-purpose code. Drawbacks: complexity, area and power; the scheduling logic becomes the bottleneck at wide issue widths; timing is hard to verify. Domains: general-purpose x86 and ARM cores. Both aim at IPC above 1; the trade-off between hardware complexity and compiler sophistication decides where each wins.

The two columns of Table 12 in sentences. Say explicitly who and when in the first line of each half; the binary-compatibility point and the NOP/code-efficiency point are the drawbacks the examiner expects to see named.

Let's consider a dual-issue SMT processor that can manage up to 4 hardware threads. What are the values of the ideal CPI and the ideal per-thread CPI? (Single answer.)

  • Ideal CPI = 1 & ideal per-thread CPI = 0.25 A dual-issue core has ideal CPI 1/2, not 1; and a thread with a quarter of the slots cannot have a CPI below the core's.
  • Ideal CPI = 0.25 & ideal per-thread CPI = 0.25 0.25 would be a quad-issue core; the per-thread CPI is always larger than the core's when several threads share it.
  • Ideal CPI = 0.5 & ideal per-thread CPI = 2 Core: 1/w = 1/2 = 0.5. The four threads share the two slots, so each ideally completes half an instruction per cycle: per-thread CPI = threads/w = 4/2 = 2.
  • Ideal CPI = 0.5 & ideal per-thread CPI = 1 The core is right; 1 per thread would need 2 threads on 2 slots (or 4 threads on 4 slots).
  • Ideal CPI = 0.25 & ideal per-thread CPI = 4 Both numbers belong to other machines: 0.25 is quad-issue, 4 would be 8 threads on 2 slots.
Show model answer

Answer 3: ideal CPI = 1/issue width = 1/2 = 0.5; ideal per-thread CPI = threads/issue width = 4/2 = 2.

The same question is in all three papers, always with five options built from the same numbers permuted: dual-issue with 4 threads in July 2024 and June 2026 (0.5 and 2), quad-issue with 8 threads in June 2025 (0.25 and 2). In 2026 a second point asks for a practical example of SMT scheduling with up to 4 threads on the dual-issue core. The two formulas are all you need here; the reasoning behind them and the scheduling example are lesson 29.

Considering superscalar processors, which of the following statements are TRUE? (Multiple answers; motivate each.)

  • Doubling the number of issues reduces the CPI metric. True for the ideal CPI = 1/issue width (0.5 becomes 0.25); the achieved CPI improves only as far as the ILP, the dependences and the memory system allow.
  • Out-of-order execution can be generated by data cache misses. True: a missing load stalls its own chain while the dynamic scheduler keeps executing the independent instructions in the window, so later instructions finish earlier — the miss triggers it, the scheduler does it.
  • The introduction of dynamic branch predictors improves the CPI metric. True: fewer mispredictions mean fewer flushes; CPI = CPI_ideal + branch frequency × misprediction rate × penalty.
  • Doubling the issue width halves the execution time of any program. False: only the ideal CPI halves. The serial part of the program (Amdahl), the branches and the misses are untouched, and beyond 3–4 issue slots real programs rarely offer enough independent instructions.
Show model answer

Statements 1, 2 and 3 are true (1 only for the ideal CPI, 1/issue width); statement 4 is false, because dependences, branches and memory stalls do not shrink with the width and Amdahl's law bounds the gain at 1/f.

The first three statements are the True/False quiz of the 5 May 2025 midterm (notes pp. 540–541); the fourth is the standard distractor. The motivation earns the extra point: write "ideal", name the scheduler as the mechanism behind the miss, and write the CPI formula with its branch term.

A program spends 20 % of its execution time in a part that must run sequentially. The rest is accelerated 4 times by a wider, out-of-order core. What is the overall speedup?

Show model answer

Serial fraction \(f = 0.2\), \(p = 4\):

\[ \mathrm{Speedup} = \frac{1}{0.2 + \dfrac{0.8}{4}} = \frac{1}{0.4} = 2.5 \]

In the formula sheet's form, \(F = 0.8\) and \(S = 4\): \(1/(0.2 + 0.8/4) = 2.5\). The ceiling for this program is \(1/0.2 = 5\).

Read the fraction first: "20 % sequential" is the serial \(f\), so \(F = 0.8\). The typical slip is to put 0.2 into the sheet's \(F\) and get \(1/(0.8 + 0.05) = 1.18\).

A compiler schedules the 10 operations of one loop iteration on a 3-issue VLIW processor in 7 cycles (delay slot included). How much is the code efficiency for a single iteration, in percent?

Show model answer
\[ \text{code efficiency} = \frac{\mathrm{IC}}{\#\text{cycles} \times \#\text{issues}} \] \[ = \frac{10}{7 \times 3} = \frac{10}{21} = 47.6\,\% \]

The formula is on the example formula sheet; the exam's VLIW exercises ask it after the schedule, together with the critical path, the CPI and the FP operations per cycle (lesson 20). Eleven of the 21 slots are NOPs.

Check yourself

In Table 10, going from step 1 (scalar pipeline) to step 2 (dynamic single-issue) changes exactly one column. Which?

  • Issue Issue is in order in all four rows: the instructions still enter one per cycle, in program order.
  • Execution Right: execution becomes out of order; a waiting instruction sits in a reservation station while independent ones proceed.
  • Commit Commit is in order in all four rows, which is what keeps the exceptions precise.
  • Issue and execution Only execution changes between steps 1 and 2; the issue width changes between steps 2 and 3.

In the dual-issue in-order pipeline (step 3), I1 waits eight cycles for a divide. I2, right behind it, depends on nothing. What happens to I2?

  • It issues in the free second slot and executes while I1 waits That is step 4. In an in-order pipeline the packet stalls as a unit; there is no station in which I1 could wait while I2 passes.
  • It waits with I1 and issues together with it when the divide result arrives Yes: "dependent instructions must wait, even if others could proceed" (p. 93). Width helps only when the head of the line is free.
  • It is executed speculatively and squashed if I1 faults Speculation concerns branches, not operand waits, and this pipeline has no reorder buffer to squash anything.

Which of these does a dual-issue in-order datapath need, compared with the single-issue one? Select all that apply.

  • A register file with 4 read ports and 2 write ports An ALU operation reads two registers and a store reads two; both results of the packet are written in the same cycle.
  • A second adder for the load/store address So that the address is computed while the ALU operation executes.
  • Hazard detection across the two instructions of the packet The pair must be independent and of compatible types.
  • A reorder buffer In the datapath of Fig. 2 every instruction spends one cycle in EX, so execution and write-back stay in program order and there is nothing to put back in order; the ROB is step 4's bookkeeping.
  • Register renaming Renaming removes WAR and WAW hazards. In the in-order dual-issue pipeline every read (ID) and every write (WB) still happens in program order, so there is nothing to rename; renaming is step 4's bookkeeping.

Step 3 widens the datapath; step 4 adds the bookkeeping. Keep the two kinds of hardware apart in the open question.

A VLIW binary was compiled for a machine whose loads take 3 cycles. It is run, unchanged, on a successor whose loads take 5 cycles. What happens?

  • It runs correctly and faster, because the new chip is newer The schedule encodes the old latency: the consumer of a load is placed three words after it, whatever the new chip needs.
  • It runs correctly but slower, because the hardware stalls the dependent operation Only if the new chip added interlocks — which a plain VLIW does not have; the notes' point is precisely that the hardware checks nothing.
  • It may compute wrong results unless it is recompiled or the hardware interlocks Right: the consumer fires before the value exists. This is the binary-compatibility drawback of static scheduling (p. 99).

A quarter of a program's time is an inherently serial dependence chain. With unlimited issue width, perfect prediction and ideal memory, the best possible speedup is…

  • Unlimited, since the other three quarters can be overlapped without bound The serial quarter still takes its time: the new time is at least 0.25 of the old.
  • 1.33 1.33 = 1/0.75 is what you get by mistaking the parallel fraction for the serial one.
  • 4 Speedup_max = 1/f = 1/0.25 = 4: however fast the parallel part runs, the serial quarter remains.
  • 75 % of the ideal speedup Amdahl's ceiling is 1/f, an absolute number, not a percentage of some ideal.

A core's instruction window is doubled; the program and its longest dependence chain are unchanged. Which statement is right?

  • The IPC doubles, because the window sees twice as many instructions Seeing more instructions helps only if they are independent; the chain is still executed one link at a time.
  • The IPC may rise if more independent work becomes visible, but the chain still bounds it, and the wakeup-select logic grows with the window Right on both counts: limit 1 (window) is relieved, limits 2 and 5 are not — more tag comparisons every cycle.
  • Nothing changes, since the window only matters for branch prediction The window is the set of instructions the scheduler can choose from; it has nothing to do with prediction.

What is true of the issue width of a superscalar processor? Select all that apply.

  • It is a maximum that hazards keep the processor from reaching every cycle "It is the maximum and it cannot be always reached (hazards, etc.)" (p. 95).
  • The ideal CPI is its reciprocal CPI_ideal = 1/issue width — the formula of every ideal-CPI quiz.
  • It equals the number of functional units A 4-wide core may have ten units of different types; width counts what can be issued per cycle, not what can execute.
  • It equals the number of instructions in flight In flight is width × depth; the width is the number entering per cycle.

Key take-aways

What to watch and read