Why pipeline?
The assembly-line idea
Doing laundry takes four steps: wash, dry, fold, put away. If each takes 30 minutes and you finish one load completely before starting the next, four loads take 8 hours. If you start the second wash as soon as the first load moves to the dryer, all four steps stay busy and the same four loads finish in 3.5 hours.
No single load finished faster; each still took 2 hours. What improved is throughput: once the pipeline is full, a load finishes every 30 minutes. A processor pipeline works the same way. Instruction execution is split into stages, and a new instruction enters the first stage every clock cycle while older instructions move along behind it.
| Load | 6:00 | 6:30 | 7:00 | 7:30 | 8:00 | 8:30 | 9:00 |
|---|---|---|---|---|---|---|---|
| Load A | Wash | Dry | Fold | Store | |||
| Load B | Wash | Dry | Fold | Store | |||
| Load C | Wash | Dry | Fold | Store | |||
| Load D | Wash | Dry | Fold | Store |
The five-stage pipeline
The classic RISC pipeline, used in MIPS, early Arm cores and most textbook RISC-V designs, has five stages. Pipeline registers between stages (IF/ID, ID/EX, EX/MEM, MEM/WB) hold each instruction's values and control signals as it advances, so every stage can work on a different instruction in the same cycle. Every instruction passes through all five stages, even ones it does not need, which keeps the timing uniform.
| Stage | Work done | lw | add | sw | beq |
|---|---|---|---|---|---|
| IF Fetch | Read the instruction at PC; PC + 4 | ✓ | ✓ | ✓ | ✓ |
| ID Decode | Decode; read source registers; sign-extend the immediate | ✓ | ✓ | ✓ | ✓ |
| EX Execute | ALU operation or address calculation; compare for branches | Address | Sum | Address | Compare, target |
| MEM Memory | Read or write data memory | Read | – | Write | – |
| WB Write back | Write the result to the register file | ✓ | ✓ | – | – |
Timing and speedup
The first instruction needs k cycles to fill the pipeline; after that, one instruction finishes per cycle. For long instruction streams the ideal speedup approaches k. Three things keep real pipelines below that:
- Unbalanced stages. The clock must fit the slowest stage, so faster stages sit idle for part of every cycle.
- Register overhead. Each pipeline register adds setup time and clock skew to every cycle.
- Hazards. Stalls add cycles in which no instruction finishes (Part B).
Take stage delays of 200 ps for fetch, 100 ps for register read, 200 ps for the ALU, 200 ps for data memory and 100 ps for write-back. An unpipelined design that runs one load per 800 ps cycle becomes a pipeline with a 200 ps clock, so the speedup is 800 / 200 = 4, not 5, because the two 100 ps stages waste half their cycle.
Pipeline timing calculator
Each bar is one clock cycle. Teal: time the stage spends working. Copper: register overhead. Pale: time it sits idle waiting for the clock. Try splitting the 200 ps stages in two, or adding 20 ps of overhead.
Hazards
Three kinds of hazard
A hazard is any situation that prevents the next instruction from entering the pipeline in its planned cycle. The pipeline must stall, inserting a bubble (an empty slot that does no work), until the hazard clears.
| Hazard | Cause | Effect if untreated |
|---|---|---|
| Structural | Two instructions need the same hardware in the same cycle | One must wait |
| Data | An instruction needs a value an earlier instruction has not yet written | It would read a stale value, so it must wait |
| Control | The address of the next instruction depends on a branch not yet resolved | Wrong-path instructions must be discarded, or fetch must wait |
Structural hazards
If instructions and data share one memory port, a load in MEM and a fetch in IF collide every time. Pipelined processors avoid this with separate instruction and data caches. The register file is read in ID and written in WB in the same cycle, so it is designed to write in the first half of the cycle and read in the second, or given separate read and write ports. Long operations such as floating-point division are often not fully pipelined, so two divides in a row still contend for one unit; designers accept this when the operation is rare enough.
Data hazards
In this sequence, sub reads x1 in ID (cycle 3), but add does not write it until WB (cycle 5):
| Instruction | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 |
|---|---|---|---|---|---|---|---|---|
| add x1, x2, x3 | IF | ID | EX | MEM | WB | |||
| sub x4, x1, x5 | IF | ID | stall | stall | EX | MEM | WB |
With a register file that writes before it reads within a cycle, sub can read the correct value in cycle 5, so it repeats ID for two extra cycles. Hardware that detects this and holds the instruction is called an interlock.
Control hazards
A conditional branch in the five-stage pipeline is not resolved until EX. By then, two more instructions have already been fetched from the path that may be wrong. The simplest fix stalls fetch until the outcome is known, which costs 2 cycles on every branch. Since roughly 15 to 20% of instructions in typical integer code are branches, that alone adds 0.3 to 0.4 cycles to every instruction's average. Control hazards grow with pipeline depth, because the branch resolves further from the front.
What stalls cost
The second formula assumes perfectly balanced stages. Suppose a five-stage pipeline with no special hazard hardware runs code in which 30% of instructions use the result of the instruction just before (2 stalls each), 10% use a result from two instructions back (1 stall each), and 15% are branches (2 stalls each):
Stalls per instruction = 0.30 × 2 + 0.10 × 1 + 0.15 × 2 = 1.0, so CPI = 2.0 and the speedup is 5 / 2 = 2.5 instead of 5. Hazards erased half the benefit of pipelining, which is why so much processor design effort goes into removing them.
Data dependences
Types of dependence
A dependence is a property of the program: two instructions must keep their order to produce the right result. A hazard is a property of the pipeline: whether that dependence, at that distance, would be violated by overlapping the instructions. The same dependence can cause a hazard on one pipeline and none on another.
| Dependence | Also called | Example | Matters when |
|---|---|---|---|
| True (data) | RAW, read after write | add x1, x2, x3 sub x4, x1, x5 | Always: a value flows from one instruction to the next |
| Anti | WAR, write after read | sub x4, x1, x5 addi x1, x6, 1 | Only if a later write can complete before an earlier read, as in out-of-order execution |
| Output | WAW, write after write | add x1, x2, x3 addi x1, x6, 1 | Only if writes can complete out of order, as with mixed-latency units |
| Control | beq x1, x0, skip add x2, x2, x3 | Always: whether add runs depends on the branch |
Anti and output dependences are name dependences: no value passes between the instructions, they just reuse a register name. In the simple in-order five-stage pipeline, reads always happen in ID and writes in WB, in program order, so only true dependences cause stalls.
Dependence distance
The number of instructions between a producer and its consumer decides the stall. Without any hazard-removal hardware, in the five-stage pipeline:
| Distance | Example | Stall cycles |
|---|---|---|
| 1 | Consumer immediately follows the producer | 2 |
| 2 | One independent instruction in between | 1 |
| 3 or more | Two or more independent instructions in between | 0 |
This is why the order of instructions matters so much: placing independent work between a producer and its consumer hides the latency for free.
Dependence analyzer
Enter RISC-V code or pick an example. The analyzer lists every dependence and shows the resulting pipeline timing with interlocks only (no forwarding). Supported: add sub and or xor sll srl sra slt sltu mul div rem, the matching -i forms, and loads and stores.
Assumes separate instruction and data memories, straight-line code, and a register file that writes in the first half of a cycle and reads in the second.
Chains and parallelism
A program's dependences form a graph. The longest path through it, the critical path, sets a lower bound on execution time no matter how the instructions are scheduled. Compare the "Dependent chain" and "Two chains interleaved" examples: the second does twice as much work in only a few more cycles, because instructions from one chain fill the gaps left by the other.
How much independent work real programs contain was measured in limit studies. Wall found that typical programs expose only a handful of independent instructions at a time; Austin and Sohi traced dynamic dependence graphs to see where the parallelism lies; and Lam and Wilson showed that control dependences, more than data dependences, limit how much can be found. These results shaped everything from compiler scheduling to how wide processors are built.
Resources
Interactive tools and references
Peer-reviewed reading
- Ramamoorthy, C. V., & Li, H. F. (1977). Pipeline architecture. ACM Computing Surveys, 9(1), 61–102.A comprehensive early survey of pipelining principles and hazards.doi.org/10.1145/356683.356687
- Patterson, D. A., & Ditzel, D. R. (1980). The case for the reduced instruction set computer. ACM SIGARCH Computer Architecture News, 8(6), 25–33.Why simple instructions suit pipelining.doi.org/10.1145/641914.641917
- Radin, G. (1982). The 801 minicomputer. Proc. ASPLOS I, 39–47.An early design built around a one-instruction-per-cycle pipeline.doi.org/10.1145/800050.801824
- Hennessy, J., et al. (1982). MIPS: A microprocessor architecture. Proc. MICRO-15, 17–22.The pipeline behind the classic five-stage model, with hazards handled by software.doi.org/10.1145/1014194.800930
- Kunkel, S. R., & Smith, J. E. (1986). Optimal pipelining in supercomputers. Proc. ISCA, 404–411.How register overhead and hazards limit useful pipeline depth.doi.org/10.1145/17356.17403
- McFarling, S., & Hennessy, J. (1986). Reducing the cost of branches. Proc. ISCA, 396–403.Quantifies control hazards and early ways to reduce them.doi.org/10.1145/17356.17402
- Lee, J. K. F., & Smith, A. J. (1984). Branch prediction strategies and branch target buffer design. IEEE Computer, 17(1), 6–22.How often branches occur and what they cost a pipeline.doi.org/10.1109/MC.1984.1658927
- Smith, J. E., & Pleszkun, A. R. (1988). Implementing precise interrupts in pipelined processors. IEEE Transactions on Computers, 37(5), 562–573.Keeping a pipeline's state consistent when an instruction faults.doi.org/10.1109/12.4607
- Wall, D. W. (1991). Limits of instruction-level parallelism. Proc. ASPLOS IV, 176–188.How much independent work real programs contain.doi.org/10.1145/106972.106991
- Austin, T. M., & Sohi, G. S. (1992). Dynamic dependency analysis of ordinary programs. Proc. ISCA, 342–351.Dependence graphs of running programs and where parallelism hides.doi.org/10.1145/139669.140395
- Lam, M. S., & Wilson, R. P. (1992). Limits of control flow on parallelism. Proc. ISCA, 46–57.Why control dependences limit overlap more than data dependences.doi.org/10.1145/139669.139702