As discussed previously, one of the methods to handle data hazards in pipelined datapaths is stalling, forwarding, or even a combination of both.
Consider this sequence:
sub $2, $1,$3 # Register $2 written by sub
and $12,$2,$5 # 1st operand($2) depends on sub
or $13,$6,$2 # 2nd operand($2) depends on sub
add $14,$2,$2 # 1st($2) & 2nd($2) depend on sub
sw $15,100($2) # Base ($2) depends on sub
In simplified datapaths, detecting dependencies and the need for forwarding can be easily identified. These dependencies are marked in blue, while the forwarding paths are marked in red.
Now, the question is how do we implement it in our pipeline datapath? The forwarding control will be in the EX stage, because the ALU forwarding multiplexors are found in that stage.
Figure 11.1 Pipeline datapath with forwarding.
But as we learned, forwarding is not always possible, like when an instruction tries to read a register following a load instruction that writes the same register.
It involves inserting a no-operation or nop instruction into the pipeline to delay the processing of subsequent instructions until the dependency can be resolved.
In our pipeline datapath, we combine the forwarding unit with the introduction to the hazard detection unit:
If the load-use hazard test is true, the hazard detection unit stalls and deasserts the control fields.