Pipelining is a way to reduce cycles per instruction. It allows the next instruction to process before the current instruction has completed. Pipelines are complicated to implement. It can cause problems because instructions can be dependent on each other. These problems are called hazards.
Types of hazards
There are two types of hazards:
- Data hazard
- Control hazard
- Data hazard:
A data hazard occurs when one instruction depends on the result of another instruction already in the pipeline. When the second instruction executes before the first instruction updates the value to be fetched, it can lead to incorrect results.
Add r2 r1 r3
Sub r4 r2 r5
Here we need the updated value of r2 for the second instruction but if the second instruction is executed first then it will give the wrong result.
- Control hazard:
Code is not completely linear. It has loops and conditions. If a CPU finds a conditional branch instruction, it does not know whether to execute it or jump because it does not know which branch is going to be taken or executed next. This is known as a control hazard.
Stalling is to have the CPU detect the dependency and stall the pipeline until the value to be fetched is ready.
In forwarding, the CPU detects the dependency and forwards the result from the execution phase rather than going via register i.e. after the execution phase of the first instruction, the result is stored in a temporary register. Instead of waiting for the entire instruction to execute and write back to the register we can fetch the value stored in the temporary register and execute the dependent instruction.
The CPU detects the dependency of the instruction and adds a stall instead of fetching that instruction it would jump to the next one and execute it.
- Branch Prediction:
The processor uses a heuristic to guess whether the branch will be taken or not and feeds the predicted path into the pipeline which is called speculative execution.