Computer Architecture Cheatsheet
Pipelining
Use this Computer Architecture reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
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.