The easiest solution is to ignore the problem. While that might sound like a bad solution, it is actually quite usable. Consider the above program again, and assume that r1 is initially 1, and r2 is initially 2. Then:
add r0, r1, r2 // r0 := 3
sub r2, r0, r1 // r2 := -1 (uses old value of r0)
xor r2, r0, r1 // r2 := 1 (uses old value of r0)
srl r2, r0, r1 // r2 := 6 (uses new value of r0)
ori r2, r0, 10 // r2 := 11 (uses new value of r0)
It becomes a bit harder to read the source code, because the processor seems to execute instructions out of order. But as long as this behaviour is well-defined, the programmer (or the compiler) can take it into account and make good use of it. (Note that the processor does not really execute instructions out of order.)
Try it out. Follow the execution of this program in the MIPS pipeline.
Pipeline Interlock
A second solution is to stall the pipeline. To explain what a stall is, we need a bit of extra terminology. We can divide the pipeline into two parts, instruction fetch and instruction execute:
| Instruction Fetch | Instruction Execute | |||
|---|---|---|---|---|
| IF | ID | EX | MA | WB |
When an instruction makes it from the first half of this pipeline to the second half, i.e. from the ID phase to the EX phase, it is said to be issued. On a stall, we do not issue the instruction in the ID phase. Instead, we issue a NOP ("do nothing") instruction. In the meantime, the IF and and ID phase will simply re-execute (we shall later see that it is is not quite as simple as that). The above program would be executed as follows:
| Cycle | IF | ID | EX | MA | WB | |
|---|---|---|---|---|---|---|
| 1 | add | |||||
| 2 | sub | add | ||||
| 3 | xor | sub | add | We detect a stall here, and issue a nop instead of the sub | ||
| 4 | xor | sub | nop | add | The add has not yet reached WB, so we need another stalled cycle | |
| 5 | xor | sub | nop | nop | add | The add will write its results in the first half of the cycle, so the xor will now get the correct value for r0 |
| 6 | srl | xor | sub | nop | nop |
The downside is that with this solution, we need 7 cycles instead of 5 to execute our program. That's a 40% increase in execution time!
Try it out. Run this program in the animation. For clarity, the MIPS animation will issue a "stall" instruction instead of a nop instruction upon a stall. This is only to distinguish nops issued because of stalls from nops that were actually in the instruction memory. In reality, the stall instruction does not exist.
advertisement
advertisement