4.1.19 · D4Computer Architecture (Deep)

Exercises — Pipeline hazards — structural, data (RAW - WAR - WAW), control

2,060 words9 min readBack to topic

Throughout, we reuse the parent's 5-stage pipeline: IF (fetch), ID (decode + read registers), EX (execute in the ALU), MEM (memory access), WB (write result back to a register). We also reuse the parent's symbols:


Level 1 — Recognition

Goal: name the hazard family and the mechanism, no maths.

L1.1

I1: LW  R1, 0(R2)     # load: R1 <- memory[R2]
I2: ADD R3, R1, R4    # uses R1

Which hazard family is this, and can plain forwarding remove it completely?

Recall Solution

RAW data hazard (I2 reads R1 which I1 must write first). It is the special load-use case. Plain forwarding cannot fully remove it: a load's value is only ready at the end of MEM (cycle 4), but the dependent ADD wants it in EX (also cycle 4). There is no earlier stage to forward from, so you need one bubble, then forward. See Forwarding and bypassing.

L1.2

Two independent instructions both need the single unified memory in the same cycle — one for IF, one for MEM. Name the family and the by-design cure.

Recall Solution

Structural hazard (resource conflict, not a value conflict). By-design cure: split the memory into a separate I-cache and D-cache (Harvard style) so IF and MEM never fight.

L1.3

Match each label to its dependence type: RAW, WAR, WAW.

Recall Solution
  • RAW = Read After Write = true dependence (real data flow).
  • WAR = Write After Read = anti-dependence (a name hazard).
  • WAW = Write After Write = output dependence (a name hazard). Only RAW is a true dependence; WAR/WAW come from reusing register names and vanish with Register renaming.

Level 2 — Application

Goal: use the parent's formulas on concrete numbers.

L2.1

A program has branches, misprediction rate , branch penalty cycles. Ideal CPI is 1. Find the actual CPI.

Recall Solution

Use . Why this form? Only branches () can stall; only mispredicted ones () actually do; each costs .

L2.2

A 5-stage pipeline has an average stall of cycles per instruction. What is the speedup over a single-cycle machine?

Recall Solution

Use . Why: single-cycle spends stage-times per instruction; the pipeline spends cycles.

L2.3

Same , , but you install a good predictor that drops from to . New CPI?

Recall Solution

The branch stall term fell from to — see Branch prediction (static vs dynamic) for why dynamic prediction earns this.


Level 3 — Analysis

Goal: reason about cycle grids and count bubbles.

L3.1

Draw the cycle grid and count stalls (forwarding enabled) for:

I1: ADD R1, R2, R3
I2: SUB R4, R1, R5
Recall Solution

Figure — Pipeline hazards — structural, data (RAW - WAR - WAW), control
I1 finishes computing R1 at the end of EX (c3). I2 needs R1 as an EX input at c4. Forwarding routes the EX/MEM register value straight into I2's EX — no bubble. Stalls = 0.

L3.2

Now the producer is a load:

I1: LW  R1, 0(R2)
I2: SUB R4, R1, R5

With forwarding, how many bubbles?

Recall Solution

Figure — Pipeline hazards — structural, data (RAW - WAR - WAW), control
The load's R1 is only ready at the end of MEM (c4), but I2 wants it in EX at c4 too — same cycle, impossible to forward backward in time. Insert 1 bubble: I2's EX slides to c5, then forward from I1's MEM/WB register. Stalls = 1.

L3.3

A branch resolves in EX (the 3rd stage). With a predict-not-taken scheme, how many instructions are flushed on a taken branch, and what is ?

Recall Solution

With no prediction help, IF keeps fetching the fall-through instructions in c2 and c3 while the branch is in ID and EX. When the branch resolves taken in EX (c3), the 2 instructions fetched behind it (in IF at c2, c3) are wrong and get flushed. So cycles. Correctly predicted (not-taken and it is not-taken): . The penalty only bites on the outcome the predictor missed.


Level 4 — Synthesis

Goal: combine multiple hazard sources into one CPI.

L4.1

A workload runs on the 5-stage pipeline with all three stall sources:

  • Data stalls: 30% of instructions are loads; half of those ( of all) are immediately load-used → 1 bubble each.
  • Control stalls: , , .
  • Structural stalls: none (split caches).

Compute the total CPI.

Recall Solution

Add each stall contribution to the ideal CPI of 1.

  • Data: .
  • Control: .
  • Structural: .

L4.2

For the L4.1 machine, what speedup does it get over a single-cycle machine ()? Then: which single fix helps more — eliminating the load-use stalls, or halving ?

Recall Solution

, so .

Eliminate load-use (e.g. compiler scheduling): remove → CPI . Halve to : control term → CPI . The load-use fix drops CPI to 1.06 vs 1.18 — removing load-use stalls helps far more here, because . Attack the biggest stall term first (this is Amdahl's Law thinking).


Level 5 — Mastery

Goal: reason where the simple in-order model breaks and why renaming/OoO is needed.

L5.1

I1: MUL R1, R2, R3    # multi-cycle EX, writes R1 LATE
I2: ADD R1, R4, R5    # single-cycle EX, writes R1 EARLY

In a machine where MUL's WB can arrive after ADD's WB, name the hazard, explain why our textbook in-order pipeline is immune but this machine is not, and give the fix.

Recall Solution

WAW (Write After Write / output dependence). The architectural R1 must end up holding I2's (later, in program order) value, but if MUL's WB lands after ADD's, R1 is left with the stale MUL result. Why the simple pipeline is immune: all instructions write in the same stage (WB) and flow in order, so writes retire in program order automatically. WAW only becomes real when write timing can be reordered (variable-latency EX or out-of-order retire). See Out-of-order execution and Tomasulo. Fix: Register renaming — give each write a fresh physical register, so I1 and I2 no longer share the name R1. WAW and WAR are name dependences; renaming dissolves them. Only RAW (true data flow) survives.

L5.2

Explain why WAR hazards cannot occur in the plain in-order 5-stage pipeline, using the exact stage where reads and writes happen.

Recall Solution

A WAR hazard needs a later instruction to write a register before an earlier instruction reads it. In our pipeline, reads happen in ID (early) and writes happen in WB (late), and instructions enter in program order. So (earlier) reaches its ID before (later) reaches its WB. The read always precedes the write — WAR is structurally impossible here. It only appears once writes can happen early or instructions issue out of order.

L5.3 (capstone)

A design team proposes deepening the pipeline from to stages. This doubles clock frequency but the branch penalty grows from to (branch resolves later). Given , : does the deeper pipeline actually run the program faster? Assume performance and ignore other stalls.

Recall Solution

Compute CPI for each (control stalls only):

  • 5-stage: .
  • 10-stage: .

Performance . Let 5-stage frequency , so 10-stage . Yes, ~1.86× faster — the doubled frequency wins even though CPI rose slightly. But note the deeper pipeline only delivered , not the naive : the bigger branch penalty ate part of the frequency gain. That gap is exactly why deep pipelines demand excellent branch prediction. (See the CPI and performance equation.)


Recall Quick self-check clozes

RAW is the only true dependence; WAR and WAW are name dependences. The one RAW forwarding cannot fully remove ::: the load-use hazard (needs 1 bubble first). Formula linking branches to CPI ::: . Why WAR/WAW never happen in the plain in-order pipeline ::: reads are in ID (early), writes in WB (late), and instructions flow in program order. Fix that dissolves WAR and WAW ::: register renaming.

Return to the parent: 4.1.19 topic note.