G27
Self-checkedTier 1 15 min readcoa.pipeline-forwarding-branch

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.RegWrite and EX/MEM.Rd ≠0\neq 0 and EX/MEM.Rd == ID/EX.Rs: forward from EX/MEM.
  • MEM hazard: MEM/WB.RegWrite and MEM/WB.Rd ≠0\neq 0 and MEM/WB.Rd == ID/EX.Rs and not an EX hazard: forward from MEM/WB.

The second input uses Rt in the same way. The condition on register 00 matters in machines where r0r0 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 rr (IF is stage 1), the penalty is r−1r - 1 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 L−1L - 1 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.

CPI=1+branch frequency×(fraction of branches that cost the penalty)×penalty.\text{CPI} = 1 + \text{branch frequency} \times \text{(fraction of branches that cost the penalty)} \times \text{penalty}.

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
cycle12345678910
lw r1,0(r2)
add r3,r1,r4
sub r5,r3,r6
sw r5,0(r7)
or r8,r9,r10
IF
-
ID
-
EX
-
MEM
-
WB
-
cycles so far
0
completed
0
cycles per completed instruction
-

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.

0 / 10
computed by script: cycle-by-cycle simulation of an in-order pipeline with hazard rules. python3 scripts/gen-coa-hazard-traces.py

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
cycle12345678910
lw r1,0(r10)
add r2,r1,r4
lw r5,4(r10)
add r6,r5,r4
IF
-
ID
-
EX
-
MEM
-
WB
-
cycles so far
0
completed
0
cycles per completed instruction
-

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.

0 / 10
computed by script: cycle-by-cycle simulation of an in-order pipeline with hazard rules. python3 scripts/gen-coa-hazard-traces.py

The same work, reordered by the compiler: start

Pipeline simulated, not typed
cycle12345678
lw r1,0(r10)
lw r5,4(r10)
add r2,r1,r4
add r6,r5,r4
IF
-
ID
-
EX
-
MEM
-
WB
-
cycles so far
0
completed
0
cycles per completed instruction
-

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.

0 / 8
computed by script: cycle-by-cycle simulation of an in-order pipeline with hazard rules. python3 scripts/gen-coa-hazard-traces.py

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
cycle12345678910
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)
IF
-
ID
-
EX
-
MEM
-
WB
-
cycles so far
0
completed
0
cycles per completed instruction
-

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.

0 / 10
computed by script: cycle-by-cycle simulation of an in-order pipeline with hazard rules. python3 scripts/gen-coa-hazard-traces.py

The same branch resolved earlier, in ID: start

Pipeline simulated, not typed
cycle123456789
add r1,r8,r9
beq r2,r3,L
(squashed) or r3,r4,r5
lw r7,0(r10)
sw r8,4(r10)
IF
-
ID
-
EX
-
MEM
-
WB
-
cycles so far
0
completed
0
cycles per completed instruction
-

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.)

0 / 9
computed by script: cycle-by-cycle simulation of an in-order pipeline with hazard rules. python3 scripts/gen-coa-hazard-traces.py

No prediction: stop fetching until the branch is resolved: start

Pipeline simulated, not typed
cycle12345678910
add r1,r8,r9
beq r2,r3,L
or r4,r5,r6
and r7,r5,r6
IF
-
ID
-
EX
-
MEM
-
WB
-
cycles so far
0
completed
0
cycles per completed instruction
-

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.

0 / 10
computed by script: cycle-by-cycle simulation of an in-order pipeline with hazard rules. python3 scripts/gen-coa-hazard-traces.py

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 typed
TNTNTNTNSN/NWN/NWT/TST/T

Moore machine: the output is written inside the state (state/output); edges are labelled with the input.

Run so far

input (none)
output (none)

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.

1 / 16
computed by script: the counter is run on the outcome sequence. python3 scripts/gen-coa-hazard-traces.py

Worked examples

EX 1The forwarding select, checked

Easy

Does 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 wrong

Reading 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

Medium

20% 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.04

Reading 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

Medium

A loop whose branch is taken L−1L - 1 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 2×20−12 \times 20 - 1; 21 against 20+120 + 1). For a loop of 5, the accuracy of the one-bit scheme is 1−2/5=60%1 - 2/5 = 60\% and of the two-bit scheme 80%80\% in the steady state.

EX 4A loop with a load-use stall and a taken branch

GATE level

Loop 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 =5+1+2=8= 5 + 1 + 2 = 8, so CPI =8/5=1.6= 8/5 = 1.6 in steady state. For 4 iterations (the last branch not taken) the total is 5+20−1+4×1+3×2=345 + 20 - 1 + 4 \times 1 + 3 \times 2 = 34 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 5+2=75 + 2 = 7 cycles per iteration.

EX 5Delayed branch

GATE level

With 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 −1- 1: ID 1, EX 2, MEM 3.
  • Stall policy: every branch pays. Predict not taken: taken branches pay. Predictor: mispredicted branches pay.
  • CPI =1+= 1 + branch frequency ×\times (fraction paying) ×\times 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

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

GATE 2024 · MSQQ6 · page 455 of the book
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.
GATE 2022 · NATQ10 · page 455 of the book
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
GATE 2021 · NATQ11 · page 456 of the book
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
.
GATE 2015 · NATQ20 · page 457 of the book
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
.
GATE 2014 · NATQ24 · page 458 of the book
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
.
GATE 2013 · MCQ · 2 marksQ27 · page 458 of the book
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
GATE 2010 · MCQ · 2 marksQ30 · page 459 of the book
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
GATE 2008 · MCQ · 2 marksQ32 · page 460 of the book
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
GATE 2008 · MCQ · 2 marksQ33 · page 460 of the book
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
GATE 2008 · MCQ · 2 marksQ34 · page 460 of the book
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
GATE 2007 · MCQ · 2 marksQ36 · page 460 of the book
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
GATE 2006 · MCQ · 1 markQ38 · page 461 of the book
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
GATE 2006 · MCQ · 2 marksQ40 · page 461 of the book
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
GATE 2005 · MCQQ41 · page 462 of the book
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
GATE 2007 · MCQ · 2 marksQ29 · page 480 of the book
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 answer

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 answer

1+0.15×(1/3)×2=1.101 + 0.15 \times (1/3) \times 2 = 1.10.

Question 3

A two-bit counter is in "strongly taken" and the branch is not taken once, then taken. How many mispredictions?

Show answer

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 answer

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 −1- 1. 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 =1+∑= 1 + \sum frequency ×\times rate ×\times 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