Forwarding, stalls and branch prediction
How hazards are reduced: forwarding paths and their control conditions, the load-use stall, compiler scheduling, the branch penalty and the ways to cut it (stall, predict not taken, resolve early, delayed branch), and static and dynamic branch prediction with one-bit and two-bit counters, with the effect on CPI.
Why it exists
A pipeline that stalls on every dependence or every branch wastes most of its gain. Two ideas recover almost all of it. Forwarding (bypassing) hands a result straight from where it is produced to where it is needed, instead of waiting for it to be written to the register file. Branch prediction guesses the outcome of a branch so that fetching can continue down the likely path. What is left is a small number of unavoidable stalls, chiefly the load-use stall and the cost of mispredicted branches. GATE asks for the stalls that remain after forwarding, the penalty with different branch policies, and how predictors behave on loops.
Prerequisites
You need the three hazard classes and the stall counts without forwarding from pipeline hazards.
Precise definitions
Forwarding (bypassing). Extra data paths and multiplexers let the ALU inputs take their operands not only from the ID/EX register but also from the EX/MEM register (the ALU result of the previous instruction) or the MEM/WB register (the result of the instruction before that, which may be a loaded value). The ALU result of an instruction is therefore usable by the next instruction without any stall.
For the first ALU input, with the usual signals:
- EX hazard:
EX/MEM.RegWriteandEX/MEM.RdandEX/MEM.RdID/EX.Rs: forward from EX/MEM. - MEM hazard:
MEM/WB.RegWriteandMEM/WB.RdandMEM/WB.RdID/EX.Rsand not an EX hazard: forward from MEM/WB.
The second input uses Rt in the same way. The condition on register matters in machines where is wired to zero and must never be forwarded. The "not an EX hazard" clause matters when two earlier instructions write the same register: the newer value (EX/MEM) must win.
Load-use hazard. A load produces its value at the end of MEM, one stage later than an ALU result, so an instruction that uses the loaded register in the very next cycle cannot be given the value by forwarding: it must be delayed one cycle. The hazard detection unit in ID detects it: ID/EX.MemRead and (ID/EX.Rt IF/ID.Rs or IF/ID.Rt). It then freezes the PC and IF/ID for a cycle and inserts a bubble. Load followed by use after one unrelated instruction needs no stall.
Compiler scheduling. The compiler reorders independent instructions to fill the gap after a load (the load delay slot), so the stall never happens. The program means the same; only the order changes.
Branch penalty. The cycles lost when the instruction fetched after a branch is not the correct one. With the branch resolved in stage (IF is stage 1), the penalty is cycles for a mispredicted branch. Policies:
- Stall (freeze). Fetch nothing until the branch is resolved. Costs the full penalty on every branch.
- Predict not taken. Keep fetching the next instructions in sequence. If the branch is not taken nothing is lost; if it is taken the wrong-path instructions are squashed (flushed) and the penalty is paid.
- Predict taken. Start fetching at the branch target as soon as it is known; needs the target address early (a branch target buffer). Right when the branch is taken.
- Resolve earlier. Extra hardware (a comparator and adder in ID) resolves the branch in ID, cutting the penalty from 2 to 1, at the price of forwarding paths into ID (a branch that uses a result produced just before it may stall).
- Delayed branch. The instruction(s) immediately after the branch, in the branch delay slot, are always executed whether or not the branch is taken. The compiler puts a useful instruction there; if it cannot, it puts a no-operation. No flush is needed.
Branch prediction.
- Static prediction does not use history: always not taken, always taken, or by direction (backward branches, as in loops, are predicted taken; forward ones not taken). The compiler can also put a hint in the instruction.
- Dynamic prediction uses the past behaviour of each branch, kept in a branch history table (indexed by the low bits of the branch address). A branch target buffer additionally stores the target address so that fetching can follow a predicted-taken branch at once.
- One-bit predictor: remembers the last outcome and predicts the same again. A loop branch that is taken times and then not taken mispredicts twice per execution of the loop (at the exit, and at the first iteration of the next execution).
- Two-bit saturating counter: four states, strongly and weakly not taken, weakly and strongly taken. The counter moves one step toward the actual outcome and stays at the ends. It must be wrong twice in a row to change its prediction, so a loop branch mispredicts only once per execution (at the exit).
CPI with branches.
How it works
With forwarding the same five instructions as on the previous page need 10 cycles, not 15: the only stall left is the load-use pair.
The same instructions with forwarding: start
Pipeline simulated, not typed| cycle | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| lw r1,0(r2) | ||||||||||
| add r3,r1,r4 | ||||||||||
| sub r5,r3,r6 | ||||||||||
| sw r5,0(r7) | ||||||||||
| or r8,r9,r10 |
Step 0
The same five instructions. With forwarding the ALU result is passed straight from the EX/MEM or MEM/WB register to the next instruction's EX input, so only the load-use pair (lw then add) still has to wait: the loaded value exists only after MEM.
Load-use stalls disappear if the compiler moves another independent instruction into the gap. These are the same four instructions in two orders, with full forwarding: the first order stalls twice, the second order not at all.
Load-use stalls even with forwarding: start
Pipeline simulated, not typed| cycle | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| lw r1,0(r10) | ||||||||||
| add r2,r1,r4 | ||||||||||
| lw r5,4(r10) | ||||||||||
| add r6,r5,r4 |
Step 0
Two loads, each followed at once by an instruction that uses the loaded register. Forwarding cannot help: the loaded value is not available until the end of MEM, one cycle later than the dependent instruction wants it in EX. Each pair costs one stall cycle.
The same work, reordered by the compiler: start
Pipeline simulated, not typed| cycle | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| lw r1,0(r10) | ||||||||
| lw r5,4(r10) | ||||||||
| add r2,r1,r4 | ||||||||
| add r6,r5,r4 |
Step 0
The same four instructions with the second load moved up between the first load and its use. Each add now comes at least two instructions after its load, so no stall is needed. Same results, 2 cycles saved.
A taken branch with a "predict not taken" machine: the branch is resolved in EX, two wrong-path instructions have been fetched, and they are squashed (red). Compare with resolving in ID, where only one is lost, and with the stall policy, which pays the penalty even when the branch is not taken.
A taken branch resolved in EX, fetch continuing down the fall-through path: start
Pipeline simulated, not typed| cycle | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| add r1,r8,r9 | ||||||||||
| beq r2,r3,L | ||||||||||
| (squashed) or r3,r4,r5 | ||||||||||
| (squashed) and r6,r4,r5 | ||||||||||
| lw r7,0(r10) | ||||||||||
| sw r8,4(r10) |
Step 0
The machine guesses that the branch is not taken and keeps fetching the next instructions. The branch is resolved only when it reaches EX (cycle 4). It IS taken, so the two instructions fetched after it are wrong and are squashed (red), and the correct target is fetched in cycle 5. Two cycles were wasted: the branch penalty is 2.
The same branch resolved earlier, in ID: start
Pipeline simulated, not typed| cycle | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| add r1,r8,r9 | |||||||||
| beq r2,r3,L | |||||||||
| (squashed) or r3,r4,r5 | |||||||||
| lw r7,0(r10) | |||||||||
| sw r8,4(r10) |
Step 0
Extra comparison hardware lets the branch be resolved in ID (cycle 3). Only one wrong instruction has been fetched by then, so the penalty is 1. (This needs the branch operands to be available in ID; a branch that depends on the instruction just before it would have to wait.)
No prediction: stop fetching until the branch is resolved: start
Pipeline simulated, not typed| cycle | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| add r1,r8,r9 | ||||||||||
| beq r2,r3,L | ||||||||||
| or r4,r5,r6 | ||||||||||
| and r7,r5,r6 |
Step 0
The simplest policy: after a branch, fetch nothing until the branch is resolved (cycle 4). This costs 2 cycles EVERY time, even when the branch is not taken (as here), because the machine does not know in advance. Compare with the next policy: guess not taken and be right.
The last animation is the two-bit predictor on a loop branch (taken four times, then not taken, repeated). The state is the counter; the machine's output is its prediction. After 15 branches it mispredicted 4 times, a one-bit predictor 5 times. Steady state is the important comparison: once warm, each execution of the loop costs the two-bit counter one misprediction and the one-bit predictor two.
Two-bit branch predictor on a loop branch (TTTTN repeated): start
Simulated, not typedMoore machine: the output is written inside the state (state/output); edges are labelled with the input.
Run so far
Step 1
A two-bit saturating counter predicts a branch. States SN (strongly not taken) and WN (weakly not taken) predict NOT TAKEN; WT and ST predict TAKEN. A taken branch moves one step toward ST, a not-taken branch one step toward SN, and the counter stops at the ends. The input is the actual outcome (T or N). The machine starts in WN. The branch here is a loop branch: taken four times, then not taken, repeated.
Worked examples
EX 1The forwarding select, checked
EasyDoes the control logic always pick the newest value for an ALU input? A program tries every combination of the source register (0 to 3), two producers' write enables and destination registers.
#include <stdio.h>
/* forwarding select for one ALU input: 0 = register file, 2 = EX/MEM result, 1 = MEM/WB result */
static int select_fwd(int rs, int exmem_we, int exmem_rd, int memwb_we, int memwb_rd) {
if (exmem_we && exmem_rd != 0 && exmem_rd == rs) return 2;
if (memwb_we && memwb_rd != 0 && memwb_rd == rs && !(exmem_we && exmem_rd != 0 && exmem_rd == rs)) return 1;
return 0;
}
int main(void) {
int cases = 0, wrong = 0;
for (int rs = 0; rs < 4; rs++)
for (int e_we = 0; e_we < 2; e_we++) for (int e_rd = 0; e_rd < 4; e_rd++)
for (int m_we = 0; m_we < 2; m_we++) for (int m_rd = 0; m_rd < 4; m_rd++) {
/* sequential meaning: the newest write to rs, if any, else the register file; r0 is always 0 */
int expected = 100 + rs;
if (rs == 0) expected = 0;
else if (e_we && e_rd == rs) expected = 200;
else if (m_we && m_rd == rs) expected = 300;
int sel = select_fwd(rs, e_we, e_rd, m_we, m_rd);
int got = rs == 0 ? 0 : sel == 2 ? 200 : sel == 1 ? 300 : 100 + rs;
cases++;
wrong += got != expected;
}
printf("%d combinations, %d wrong\n", cases, wrong);
return 0;
}256 combinations, 0 wrongReading it. The reference is "what a program running one instruction at a time would read": the newest earlier write, or the register file if nobody wrote it, and always 0 for register 0. The two conditions (EX hazard first, MEM hazard only if there is no EX hazard) reproduce it in all 256 cases. Without the "not an EX hazard" clause, add r1,r1,r2 followed by add r1,r1,r3 followed by add r1,r1,r4 would read the older value from MEM/WB.
EX 2Branch policies and CPI
Medium20% of the instructions are branches, 60% of them are taken, and the pipeline has five stages.
#include <stdio.h>
int main(void) {
/* 20% of instructions are branches and 60% of branches are taken. The pipeline has 5 stages. */
double branch = 0.20, taken = 0.60;
printf("stop fetching until the branch is resolved in EX (penalty 2): CPI = %.2f\n", 1 + branch * 2);
printf("predict not taken, resolved in EX (penalty 2 when taken): CPI = %.2f\n", 1 + branch * taken * 2);
printf("predict not taken, resolved in ID (penalty 1 when taken): CPI = %.2f\n", 1 + branch * taken * 1);
printf("predictor right 90%% of the time, mistakes cost 2: CPI = %.2f\n", 1 + branch * 0.10 * 2);
return 0;
}stop fetching until the branch is resolved in EX (penalty 2): CPI = 1.40
predict not taken, resolved in EX (penalty 2 when taken): CPI = 1.24
predict not taken, resolved in ID (penalty 1 when taken): CPI = 1.12
predictor right 90% of the time, mistakes cost 2: CPI = 1.04Reading it. The penalty is paid by all branches (stall), by the taken ones (predict not taken), or only by the mispredicted ones (a predictor). The stall policy costs 0.4 cycles per instruction; a good predictor, 0.04. Resolving in ID halves the penalty of the same policy.
EX 3One-bit against two-bit on a loop
MediumA loop whose branch is taken times and not taken once, executed 20 times in a row.
#include <stdio.h>
/* mispredictions of a 1-bit and a 2-bit predictor on a loop branch: L-1 times taken, then once not taken, repeated */
static int one_bit(int len, int reps, int *steady) {
int last = 1, miss = 0, miss_before_last = 0;
for (int r = 0; r < reps; r++) {
if (r == reps - 1) miss_before_last = miss;
for (int i = 0; i < len; i++) {
int taken = i < len - 1;
miss += last != taken;
last = taken;
}
}
*steady = miss - miss_before_last;
return miss;
}
static int two_bit(int len, int reps, int *steady) {
int c = 1, miss = 0, miss_before_last = 0; /* 0 and 1 predict not taken, 2 and 3 predict taken */
for (int r = 0; r < reps; r++) {
if (r == reps - 1) miss_before_last = miss;
for (int i = 0; i < len; i++) {
int taken = i < len - 1;
miss += (c >= 2) != taken;
if (taken) { if (c < 3) c++; } else if (c > 0) c--;
}
}
*steady = miss - miss_before_last;
return miss;
}
int main(void) {
int lens[3] = {5, 10, 100};
for (int k = 0; k < 3; k++) {
int s1, s2;
int m1 = one_bit(lens[k], 20, &s1), m2 = two_bit(lens[k], 20, &s2);
printf("loop of %3d: 20 executions -> 1-bit %2d mispredictions (%d per execution when warm), 2-bit %2d (%d per execution when warm)\n", lens[k], m1, s1, m2, s2);
}
return 0;
}loop of 5: 20 executions -> 1-bit 39 mispredictions (2 per execution when warm), 2-bit 21 (1 per execution when warm)
loop of 10: 20 executions -> 1-bit 39 mispredictions (2 per execution when warm), 2-bit 21 (1 per execution when warm)
loop of 100: 20 executions -> 1-bit 39 mispredictions (2 per execution when warm), 2-bit 21 (1 per execution when warm)Reading it. The one-bit predictor is wrong at the loop exit (it expected taken) and wrong again at the next execution's first branch (it now expects not taken). The two-bit counter, sitting at "strongly taken" through the loop, drops only to "weakly taken" at the exit and still predicts taken for the first branch of the next execution: one mistake per execution, independent of the loop length. Start-up adds a few more (39 against ; 21 against ). For a loop of 5, the accuracy of the one-bit scheme is and of the two-bit scheme in the steady state.
EX 4A loop with a load-use stall and a taken branch
GATE levelLoop body: lw r1,0(r2); add r3,r1,r4; sw r3,0(r2); addi r2,r2,4; bne r2,r5,loop. Five-stage pipeline, full forwarding, branches resolved in EX, "predict not taken". Per iteration: the add uses the loaded r1 in the next instruction, 1 stall; the bne is taken and the prediction is wrong, 2 penalty cycles; everything else is forwarded. Cycles per iteration , so CPI in steady state. For 4 iterations (the last branch not taken) the total is cycles, which the simulation of this exact sequence confirms. A compiler that moves addi between the lw and the add (and adjusts the store's offset to match) removes the load-use stall and gives cycles per iteration.
EX 5Delayed branch
GATE levelWith a one-instruction branch delay slot the instruction after the branch always executes. In add r1,r2,r3; beq r4,r5,L; sub r6,r7,r8, if the branch only depends on r4 and r5, the compiler can move the add into the slot: beq r4,r5,L; add r1,r2,r3. The add runs either way, as before, and no instruction is flushed: the branch costs no lost cycle. If no independent instruction exists, a no-operation fills the slot and the cycle is lost anyway. The slot makes the pipeline's timing visible in the instruction set, which is why later machines preferred hardware prediction.
Cheat box
Cheat box
- Forwarding: EX/MEM to ALU (previous instruction), MEM/WB to ALU (two back). Newer value wins; never forward register 0.
- ALU result to the next ALU use: no stall. Load then immediate use: 1 stall. Load and use one instruction apart: no stall.
- Branch penalty resolving stage : ID 1, EX 2, MEM 3.
- Stall policy: every branch pays. Predict not taken: taken branches pay. Predictor: mispredicted branches pay.
- CPI branch frequency (fraction paying) penalty.
- Delayed branch: the slot instruction always executes.
- Loop branch, steady state: 1-bit predictor 2 mispredictions per execution, 2-bit counter 1.
- Two-bit counter changes its prediction only after two wrong outcomes in a row.
Traps and GATE patterns
Connections
Builds on
Across subjects
These are the remedies for the hazards of the previous page, and the stall terms they leave are the ones added in the CPI arithmetic. The branch history table is a small direct-mapped memory indexed by address bits, like the lookup of a cache, and the two-bit predictor is a saturating counter. A regular instruction set (ISA design) is what lets the forwarding and detection hardware be this simple.
PYQs
15 previous year questions from your book. I re-solved each one myself (11 by running or simulating, 4 by reasoning only); the book's key is shown next to my answer. All PYQs
Consider a 5-stage pipelined processor with Instruction Fetch (IF), Instruction Decode (ID), Execute (EX), Memory Access (MEM), and Register Writeback (WB) stages. Which of the following statements about forwarding is/are CORRECT?
- (a)In a pipelined execution, forwarding means the result from a source stage of an earlier instruction is passed on to the destination stage of a later instruction.
- (b)In forwarding, data from the output of the MEM stage can be passed on to the input of the EX-stage of the next instruction.
- (c)Forwarding cannot prevent all pipeline stalls.
- (d)Forwarding does not require any extra hardware to retrieve the data from the pipeline stages.
A processor X1 operating at 2 GHz has a standard 5- stage RISC instruction pipeline having a base CPI (cycles per instruction) of one without any pipeline hazards. For a given program P that has 30% branch instructions, control hazards incur 2 cycles stall for every branch. A new version of the processor X2 operating at the same clock frequency has an additional branch predictor unit (BPU) that completely eliminates stalls for correctly predicted branches. There is neither any savings nor any additional stalls for wrong predictions. There are no structural hazards and data hazards for X1 and X2. If the BPU has a prediction accuracy of 80%, the speed up (rounded off to two decimal places) obtained by X2 over X1 in executing P is . Computer Organization and Architecture
Consider a pipelined processor with 5 stages, Instruction Fetch (IF), Instruction Decode (ID), Execute (EX), Memory Access (MEM), and Write Back (WB). Each stage of the pipeline, except the EX-stage, takes one cycle. Assume that the ID stage merely decodes the instruction and the register read is performed in the EX-stage. The EX-stage takes one cycle for ADD instruction and two cycles for MUL instruction. Ignore pipeline register latencies. Consider the following sequence of 8 instructions: ADD, MUL, ADD, MUL, ADD, MUL, ADD, MUL Assume that every MUL instruction is data- dependent on the ADD instruction just before it and every ADD instruction (except the first ADD) is data-dependent on the MUL instruction just before it. The speedup is defined as follows: Speedup = Execution time without operand forwarding Execution time with operand forwarding The Speedup achieved in executing the given instruction sequence on the pipelined processor (rounded to 2 decimal places) is . and 50% of the branch instructions cause stalls of 2 cycles each. Assume that there are no stalls associated with the execution of ALU instructions. For this program, the speedup achieved by the pipelined processor over the non-pipelined processor (round off to 2 decimal places) is .
Consider the sequence of machine instructions given below In the above sequence, R0 to R8 are general purpose registers. In the instructions shown, the first register stores the result of the operation performed on the second and the third registers. This sequence of instructions is to be executed in a pipelined instruction processor with the following 4 stages: (1) Instruction Fetch and Decode (IF) (2) Operand Fetch (OF) (3) Perform Operation (PO) and (4) Write back the result (WB). The IF, OF and WB stages take 1 clock cycle each for any instruction. The PO stage takes 1 clock cycle for ADD or SUB instruction, 3 clock cycles for MUL instruction and 5 clock cycles for DIV instruction. The pipelined processor uses operand forwarding from the PO stage to the OF stage. The number of clock cycles taken for the execution of the above sequence of instructions is .
An instruction pipeline has five stages, namely, instruction fetch (IF), instruction decode and register fetch (ID/RF), instruction execution (EX), memory access (MEM), and register writeback (WB) with stage latencies 1 ns, 2.2 ns, 2 ns, 1 ns, and 0.75 ns, respectively (ns stands for nanoseconds). To gain in terms of performance, the designers have decided to split the ID/RF stage into three stages (ID, RF1, RF2) each of latency 2.2/3 ns. Also, the EX stage is split into two stages (EX1, EX2) each of latency 1 ns. The new design has a total of eight pipeline stages. A program has 20% branch instructions which execute in the EX stage and produce the next instruction pointer at the end of the EX stage in the old design and at the end of the EX2 stage in the new design. The IF stage stalls after fetching a branch until the next instruction pointer is computed. All instructions other than the branch instruction have an average CPI of one in both the designs. The execution times of this program on the old and the new design are P and Q nanoseconds, respectively. The value of P/Q is .
Consider an instruction pipeline with five stages without any branch prediction: Fetch Instruction (FI), Decode Instruction (DI), Fetch Operand (FO), Execute Instruction (EI) and Write Operand (WO). The stage delays for FI, DI, FO, EI and WO are 5 ns, 7 ns, 10 ns, 8 ns and 6 ns, respectively. There are Computer Organization and Architecture intermediate storage buffers after each stage and the delay of each buffer is 1 ns. A program consisting of 12 instructions I1, I2, I3, .... I12 is executed in this pipelined processor. Instruction I4 is the only branch instruction and its branch target is I9. If the branch is taken during the execution of this program, the time (in ns) needed to complete the program is
- (a)132
- (b)165
- (c)176
- (d)328
A 5-stage pipelined processor has Instruction Fetch (IF), Instruction Decode (ID), Operand Fetch (OF), Perform Operation (PO) and Write Operand (WO) stages. The IF, ID, OF and WO stage take 1 clock cycle each for any instruction. The PO stage takes 1 clock cycle for ADD and SUB instructions ,3 clock cycles for MUL instruction, and 6 clock cycles for DIV instruction respectively. Operand forwarding is used in the pipeline. What is the number of clock cycles needed to execute the following sequence of instructions?
- (a)13
- (b)15
- (c)17
- (d)19
Delayed branching can help in the handling of control hazards The following code is to run on a pipelined processor with one branch delay slot: I1: ADD R2 ← R7 + R8 I2: SUB R4 ← R5 - R6 I3: ADD R1 ← R2 + R3 I4: STORE Memory [R4] ← R1 BRANCH to Label if R1 == 0 Which of the instructions I1, I2, I3 or I4 can legitimately occupy the delay slot without any other program modification?
- (a)I1
- (b)I2
- (c)I3
- (d)I4
Which of the following are NOT true in a pipelined processor? 1. Bypassing can handle all RAW hazards. 2. Register renaming can eliminate all register carried WAR hazards. 3. Control hazard penalties can be eliminated by dynamic branch prediction.
- (a)1 and 2 only
- (b)1 and 3 only
- (c)2 and 3 only
- (d)1, 2 and 3
Delayed branching can help in the handling of control hazards For all delayed conditional branch instructions, irrespective of whether the condition evaluates to true or false.
- (a)The instruction following the conditional branch instruction in memory is executed
- (b). The first instruction in the fall through path is executed
- (c). The first instruction in the taken path is executed
- (d). The branch takes longer to execute than any other instruction
Consider a pipelined processor with the following four stages: IF: Instruction Fetch ID: Instruction Decode and Operand Fetch EX: Execute WB: Write Back The IF, ID, and WB stages take one clock cycle each to complete the operation. The number of clock cycles for the EX stage depends on the instruction. The ADD and SUB instructions need 1 clock cycle, and the MUL instruction needs 3 clock cycles in the EX stage. Operand forwarding is used in the pipelined processor. What is the number of clock cycles taken to complete the following sequence of instructions?
- (a)7
- (b)8
- (c)10
- (d)14 Computer Organization and Architecture
A CPU has a five-stage pipeline and runs at a 1 GHz frequency. Instruction fetch happens in the first stage of the pipeline. A conditional branch instruction computes the target address and evaluates the condition in the third stage of the pipeline. The processor stops fetching new instructions following a conditional branch until the branch outcome is known. A program executes 109 instructions out of which 20% are conditional branches. If each instruction takes one cycle to complete on average, then the total execution time of the program is:
- (a)1.0 second
- (b)1.2 Seconds
- (c)1.4 Seconds
- (d)1.6 Seconds
A pipelined processor uses a 4-stage instruction pipeline with the following stages: Instruction fetch (IF), Instruction decode (ID), Execute (EX) and Writeback (WB). The arithmetic operations as well as the load and store operations are carried out in the EX stage. The sequence of instructions corresponding to the statement X=(S-R*(P+Q))/T is given below. The values of variables P,Q,R,S and T are available in the registers R0,R1,R2,R3 and R4 respectively, before the execution of the instruction sequence. ADD R5,R0,R1 ;R5←R0 + R1 MUL R6,R2,R5 ;R6←R2 * R5 SUB R5,R3,R6 ;R5←R3 -R6 DIV R6,R5,R4 ;R6←R5/R4 STORE R6,X ;X←R6 The IF, ID and WB stages take 1 clock cycle each. The EX stage takes 1 clock cycle each for the ADD, SUB and STORE operations, and 3 clock cycles each for MUL and DIV operations. Operand forwarding from the EX stage to the ID stage is used. The number of clock cycles required to complete the sequence of instructions i
- (a)10
- (b)12
- (c)14
- (d)16 Computer Organization and Architecture
A 5 stage pipelined CPU has the following sequence of stages: IF – Instruction fetch from instruction memory RD – Instruction decode and register read EX – Execute: ALU operation for data and address computation MA – Data memory access - for write access, the register read at RD state is used. WB – Register write back Consider the following sequence of instructions: I1: L R0, Loc1; R0 ← M[Loc1] I2: A R0, R0; R0 ← R0 + R0 I3: A R2, R0; R2 ← R2 - R0 Let each stage takes one clock cycle. What is the number of clock cycles taken to complete the above sequence of instructions starting from the fetch of I1?
- (a)8
- (b)10
- (c)12
- (d)15
Data forwarding techniques can be used to speed up the operation in the presence of data dependencies. Consider the following replacements of LHS with RHS: (i) R1 → Loc, Loc → R2 ≡ R1 → R2,R1→Loc (ii) R1 → Loc, Loc → R2 ≡ R1 → R2 (iii) R1 → Loc, R2 → Loc ≡ R1 → Loc (iv) R1 → Loc, R2 → Loc ≡ R2 → Loc In which of the following options will the result of executing the RHS be the same as executing the LHS irrespective of the instruction that follow ? Computer Organization and Architecture
- (a)(i) and (iii)
- (b)(i) and (iv)
- (c)(ii) and (iii)
- (d)(ii) and (iv)
Self-check
Question 1
With full forwarding, how many stalls does lw r1,0(r2) followed by add r3,r1,r4 cause, and how many if an independent instruction is placed between them?
Show answerHide
One with the add right after; none with an independent instruction in between.
Question 2
15% of instructions are branches, a third of them taken. Predict-not-taken, resolved in EX (penalty 2). CPI?
Show answerHide
.
Question 3
A two-bit counter is in "strongly taken" and the branch is not taken once, then taken. How many mispredictions?
Show answerHide
One (the not-taken outcome). After it the counter is "weakly taken" and still predicts taken for the next branch.
Question 4
Why must the MEM-hazard forwarding condition exclude the case in which an EX hazard exists?
Show answerHide
If both stages hold a result for the same register, the one in EX/MEM is from the newer instruction. The older value must not override it.
Revision card
One-screen revision
- Forward from EX/MEM then MEM/WB (newest first, never register 0). ALU to ALU: 0 stalls. Load-use: 1 stall.
- Compiler can fill the load slot by reordering.
- Branch penalty resolving stage . Stall: all branches pay. Not taken: taken ones pay. Predictor: mispredicted pay.
- Delayed branch: the slot always executes.
- Loop branch: 1-bit 2 mispredictions, 2-bit 1 per execution.
- CPI frequency rate penalty.
References
- ·Hennessy and Patterson, Computer Organization and Design, Chapter 4 The Processor (forwarding, load-use hazard, branch hazards, dynamic branch prediction)
- ·Hamacher, Vranesic, Zaky, Computer Organization, 5th ed., the Pipelining chapter (operand forwarding, branch prediction, delayed branch)
- ·Stallings, Computer Organization and Architecture, Instruction pipelining chapter (dealing with branches, branch prediction)
Verification
The CPI figures, the predictor mispredictions on loops and the forwarding-select check (all 256 combinations of source register, two producers and register 0) are produced by the C programs on this page (npm run verify:c). The diagrams come from scripts/gen-coa-hazard-traces.py and are compared in scripts/enum-checks/coa_hazard.py with an independent cycle-driven machine on 6000 random programs; the loop example (34 cycles for 4 iterations) and the stall counts by distance are asserted there; tests/coa-hazard-traces.test.ts rechecks every diagram and the two-bit predictor run against an independent counter. The model is the textbook five-stage pipeline with the stated conventions; real predictors (history tables, correlating and tournament predictors) are only mentioned. Which instructions are in the branch delay slot, and whether a branch target is available at ID, vary between machines and are stated as assumptions. Textbook chapter titles are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand (long C programs were not re-read line by line: they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose). No defect found. Status raised to self-checked; verified needs a textbook or human check.
last verified: never
My notes (saved in this browser)