A bubble in the pipeline (sometimes represented by a NOP) is the result of stalling for 1 cycle.
A bubble is something you see and talk about when looking at a pipeline diagram of how instructions go through the pipeline, and what stage they're in at any given cycle. A bubble propagates through the pipeline, so it appears in each stage once. (For a structural hazard like instruction fetch competing with data load/store, the bubble will start in IF, like your first example.)
A stall is something that a single stage decides to do, creating one or more bubbles depending on how long it stalls for.
A row of bubbles vs. a bubble within the row for an instruction
Notice that they've added a vertical row for the one bubble going through all 5 stages of the pipeline. As if you'd written a NOP in your program to fill the load delay slot (necessary on MIPS I R2000 / R3000 if you can't schedule other instructions to fill it; on later MIPS the ISA guarantees that hardware will stall for you). Except a true nop
in the machine code still gets fetched and decoded. MIPS doesn't have a special opcode for nop
, you write one as add $zero, $zero, $zero
or equivalent with no inputs to stall for and an output of $zero
which ignores writes, always reads as zero.
Vertical rows are for instructions, not time. Stalls mean that later instructions (or stages of them) start farther to the right, not in the cycle after the current one reaches that stage.
The diagram could indicate the same timing by skipping a clock cycle (column) for the IF stage of the instruction after the load. You could maybe draw one bubble to the left of that IF, in the spot where IF would normally fetch it in the cycle after fetching the lw
.
The diagram is not how a real CPU would execute the example 1 code. You didn't include the captions in your question, which would probably have explained why they drew it that way. Perhaps showing that leaving a gap before even starting the instruction would solve the problem.
A CPU running that code won't know whether or not the instruction after an lw
depends on the result until it has fetched and decoded it. That's where it checks for hazards. The cycle after add $8, $7, $2
reaches ID is when IF would either be idle or re-fetch the instruction after the add
.
Your example 2 is the more normal way to draw things, showing a load delay (on MIPS II or later), where the load result isn't available for forwarding until after stalling for a cycle, so ID does that and sets up the forwarding. The instruction not moving forward in the pipeline leaves a bubble that you can see in the next few instructions: note that EX didn't appear in cycle 4. And that MEM didn't appear in cycle 5. etc. That's the bubble moving through the pipeline over time.
The same instruction staying around in reg reg
(decode) is the back pressure created by the stall to open up that bubble.
A row of 5 bubbles due to a structural hazard on instruction fetch
In my copy of Patterson & Hennesy (2nd edition), Figure 3.7 has a row of 5 bubbles, but for a different reason than your example 1. It's talking about a machine without split L1i / L1d caches, or with no cache and single-ported memory, hence IM/DM (instruction memory / data memory stages). You omitted the caption, which is
Figure 3.7 The structural hazard causes pipeline bubbles to be inserted. The effect is that no instruction will finish during clock cycle 8, when instruction 3 would normally have finished. (Instruction 1 is assumed to not be a load or store; otherwise, instruction 3 cannot start execution).
The "code" and pipeline diagram is figure 3.9: A pipeline stalled for a structural hazard - a load with one memory port.
load IF ID EX MEM WB
instruction 1 IF ID EX MEM WB
instruction 2 IF ID EX MEM WB
instruction 3 (stall) IF ID EX MEM WB ; (would be in IF at the same time the load is in MEM, structural hazard)
instruction 4 IF ID EX MEM WB
Figure 3.6 shows the conflict if you don't have a stall/bubble. In the 2nd edition of the book, they actually label both the first and fourth pipeline stages as MEM, instead of IF/MEM or IM/DM.
I don't know if my copy of the textbook has a diagram like yours at some later point when they're talking about data hazards. I didn't flip through it further. Perhaps they're showing how an idle cycle there would make the dependency work, and will go on to show what really happens, that the CPU has to fetch and decode to discover the hazard.
Another answer claims that a stall would let the control signals go down the pipeline unchanged instead of inserting a NOP, but that doesn't sound right or seem practical.
Letting add $8, $7, $2
go through the pipeline with a wrong value for the $7
input doesn't seem not directly harmful; a scalar in-order pipeline doesn't have WAW or WAR hazards so letting it reach the WB stage and write a wrong value into the register file isn't going to hurt correctness of other instructions; the right value will get written in the next cycle, when the instruction goes through the pipeline again with the right value this time... Unless an interrupt is taken in that cycle while the register file holds the wrong value!! Then there's an architecturally-visible wrong value.
It would also be a problem for memory operations to let them run in the MEM stage with potentially a bad pointer as part of the addressing mode. You could get a spurious TLB miss or page fault, or a store to the wrong place.
So very likely a stage that detects a stall would mux some of the control bits to send a NOP down the pipe, or there'd be a dedicated control line for NOP/bubble to deactivate stages.