Computer Architecture Cheatsheet
Pipelining
Use this Computer Architecture reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
What Pipelining Is
Pipelining overlaps the execution of multiple instructions by dividing the datapath into stages, each completing in one clock cycle. Like an assembly line: a new instruction enters the pipeline every cycle (ideally).
Throughput gain: an n-stage pipeline can process up to n instructions simultaneously, approaching n× speedup (ignoring hazards and fill/drain time).
Classic 5-Stage RISC Pipeline
| Stage | Name | Work done |
|---|---|---|
| IF | Instruction Fetch | Read instruction from I-cache at PC; PC ← PC + 4 |
| ID | Instruction Decode / Register Read | Decode opcode; read rs1, rs2 from register file |
| EX | Execute | ALU computes result or branch target |
| MEM | Memory Access | Load/store to D-cache (or pass-through) |
| WB | Write Back | Write result to destination register |
Pipeline Diagram (no hazards)
Cycle: 1 2 3 4 5 6 7 8 9 I1: IF ID EX MEM WB I2: IF ID EX MEM WB I3: IF ID EX MEM WB I4: IF ID EX MEM WB I5: IF ID EX MEM WB
At cycle 5 all five stages are busy simultaneously.
Pipeline Hazards
Structural Hazard
Two instructions need the same hardware resource at the same time.
- Classic example: single memory for instructions and data (unified cache) — IF and MEM conflict.
- Solution: separate I-cache and D-cache (Harvard-style split at L1).
Data Hazard (RAW — Read After Write)
An instruction reads a register that a previous instruction has not yet written.
ADD r1, r2, r3 # writes r1 in WB (cycle 5) SUB r4, r1, r5 # reads r1 in ID (cycle 3) — stale!
Solutions:
| Technique | Mechanism | Cost |
|---|---|---|
| Stall (bubble) | Insert NOPs until value available | Up to 2 cycles wasted |
| Forwarding (bypassing) | Route EX/MEM result directly to EX input | Extra mux paths; no cycles lost (usually) |
| Code reordering | Compiler moves independent instructions into the gap | Software; no hardware cost |
Forwarding paths that cover most RAW hazards:
- EX/MEM → EX input (1-cycle lag)
- MEM/WB → EX input (2-cycle lag)
- MEM/WB → MEM input (load-use with intermediate instruction)
Load-Use hazard — unavoidable 1-cycle stall even with forwarding:
LW r1, 0(r2) # r1 not ready until end of MEM ADD r3, r1, r4 # needs r1 at start of EX → 1 stall
Cycle: 1 2 3 4 5 6 7 LW: IF ID EX MEM WB ADD: IF ID stall EX MEM WB
Control Hazard (Branch)
The pipeline doesn't know the next PC until the branch resolves.
Without prediction (stall until branch resolves at EX): - 1–3 wasted cycles per branch depending on when branch is resolved
Branch resolution stage and penalty:
| Resolved at stage | Penalty (cycles flushed) |
|---|---|
| ID | 1 |
| EX | 2 |
| MEM | 3 |
Solutions:
| Method | Description | Downside |
|---|---|---|
| Predict not taken | Fetch sequentially; flush on taken | Branch-penalty on taken |
| Predict taken | Pre-fetch branch target | Penalty on not-taken |
| Delayed branch | Always execute n instructions after branch | Compiler burden; MIPS uses 1 delay slot |
| Dynamic prediction | Hardware predictor updates at run time | Complex hardware |
| Branch target buffer (BTB) | Caches (PC → target) pairs | Misprediction still costs |
Branch Prediction Detail
1-Bit Predictor (last outcome, per branch)
| State | Prediction |
|---|---|
| 0 | Not Taken |
| 1 | Taken |
On taken: state ← 1. On not-taken: state ← 0.
Bimodal Predictor (2-bit saturating counter)
States: Strongly Not Taken (00) ↔ Weakly Not Taken (01) ↔ Weakly Taken (10) ↔ Strongly Taken (11) Predict Taken if state ≥ 2.
| Current state | Outcome | Next state |
|---|---|---|
| 00 | Taken | 01 |
| 00 | Not Taken | 00 |
| 01 | Taken | 10 |
| 01 | Not Taken | 00 |
| 10 | Taken | 11 |
| 10 | Not Taken | 01 |
| 11 | Taken | 11 |
| 11 | Not Taken | 10 |
A single mispredict no longer flips the prediction — tolerates one anomalous outcome.
Two-Level / Correlating Predictor
Uses a global history register (GHR) of the last k branch outcomes, indexing a table of 2-bit counters. Correlation: if (aa) if (bb) — knowing aa's outcome predicts bb's.
TAGE (Tagged Geometric History Lengths)
Modern CPUs (Intel, AMD). Multiple tables with geometrically increasing history lengths; tags distinguish conflicting entries. Achieves ~96–99% accuracy.
Pipeline CPI Formula
CPI = Ideal CPI + Stall cycles per instruction
Stall sources:
| Source | Contribution |
|---|---|
| Load-use stalls | freq_load_use × 1 |
| Branch mispredictions | freq_branch × miss_rate × penalty |
| Structural stalls | rare in modern CPUs (multiple ports) |
| Cache misses | freq_miss × miss_penalty |
Example: - Ideal CPI = 1, branch freq = 15%, miss rate = 10%, penalty = 15 cycles - Stalls = 0.15 × 0.10 × 15 = 0.225 cycles/instr - Effective CPI = 1 + 0.225 = 1.225
Deeper Pipelines
Modern high-performance CPUs use 14–22+ stages to allow higher clock frequencies. Each stage does less work → shorter critical path → higher fmax. Trade-off: branch misprediction penalty grows proportionally.
| CPU | Pipeline depth | Peak frequency |
|---|---|---|
| MIPS R3000 (1988) | 5 | 33 MHz |
| Intel Pentium 4 Prescott (2004) | 31 | 3.8 GHz |
| Intel Core (2006+) | ~14–16 | 3–5+ GHz |
| Modern AMD Zen 4 | ~16 | 5.7 GHz |
Superscalar Pipelines
Issue multiple instructions per cycle (issue width = n):
- In-order superscalar: issue 2–4 instructions/cycle, all must be hazard-free
- Out-of-order (OOO): dynamic scheduling; instructions execute as operands are ready, not in program order; results committed in order via Reorder Buffer (ROB)
| Approach | IPC potential | Complexity |
|---|---|---|
| In-order scalar | ≤1 | Low |
| In-order superscalar | ≤n | Medium |
| Out-of-order superscalar | Approaches n (with enough ILP) | High |
VLIW (Very Long Instruction Word)
Compiler statically schedules multiple operations into one wide instruction word. Used in DSPs, Intel Itanium (IA-64). Relies entirely on compiler to find ILP; no OOO hardware needed but binary compatibility suffers when execution units change.