A hazard is any condition that blocks the ideal one-instruction-per-cycle flow. Each class has its own cause and its own fix.
Class | Cause in a five-stage pipe | Fix | Cost when hit |
|---|---|---|---|
Structural | Two stages need one resource, such as one memory port for IF and MEM | Extra ports or separate caches | One bubble per conflict |
Data (RAW) | A consumer reads a register the producer has not written yet | Forwarding, else stalls | Up to 3 bubbles without forwarding |
Control | Fetch does not know the next PC until a branch resolves | Early resolve, prediction, flush | Resolve depth in cycles per mispredict |
Stall, bubble and flush name different things. A stall holds issue, a bubble is an empty slot moving down the pipe, and a flush discards wrong-path slots.
The classic pipe reads registers in ID and writes them in WB, strictly in order. A later instruction cannot write before an earlier one reads, so WAR and WAW cannot occur here.
WAR and WAW appear only with out-of-order write, such as scoreboarding or renaming pipelines. Those belong to the out-of-order topic, which removes false dependences with physical tags.
Each mispredicted branch wastes the instructions fetched behind it. Control CPI is mispredict frequency times the flush penalty.
Assume 15% of instructions are branches, a 10% mispredict rate and a 12-cycle penalty
mispredicts per instruction = 0.15 x 0.10 = 0.015
CPI_control = 0.015 x 12 = 0.18 cycles per instruction
MPKI = 0.015 x 1000 = 15; check: 15 x 12 / 1000 = 0.18
Structural example: assume 20% memory instructions sharing one port, 1 conflict cycle each
CPI_structural = 0.20 x 1 = 0.20 stalls per instructionDeeper pipes lengthen the penalty term. Predictor detail lives in the branch prediction topic; here only the depth-times-rate product matters.
Structural. The resource is busy, so one instruction waits regardless of operand readiness.
A RAW data hazard, the load-use case. Even full forwarding leaves one bubble, covered in the next lesson.