Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Architecture Metrics Reference
  • Workload Taxonomy for Architects
  • Architecture Glossary
  • Computer Architecture Cheatsheet
  • Pipeline Fundamentals14
    • Pipeline Throughput
    • Branch Prediction and Fetch
      • Predictor Structures
      • MPKI and Recovery Math
      • Fetch and Recovery Pipeline
      • Tuning, Cost and Interviews
    • Out-of-Order Superscalar Execution
  • Memory Hierarchy15
  • NoC and Interconnect Architecture6
  • Coherency and Memory Ordering9
  • Performance Analysis9
  • Accelerator Architectures6
  • SoC Architecture Tradeoffs9
  • Architecture Interview Prep14
Loading lesson

‹Branch Prediction and Fetch
  1. Topics
  2. Computer Architecture
  3. Pipeline Fundamentals
  4. Branch Prediction and Fetch
  5. Predictor Structures

Computer Architecture · All levels

Predictor Structures

Direction tables, BTB targets and the return stack, with a runnable predictor model.

On this page

    What predicts what

    Direction prediction answers taken or not taken for conditional branches. Target prediction answers where fetch goes next when the branch is taken.

    The two answers fail independently. A correct direction with a wrong target still redirects fetch late.

    Structure

    Predicts

    Indexed by

    Bimodal table

    Direction

    Low PC bits

    Gshare table

    Direction

    PC mixed with global history

    BTB

    Target address

    Branch PC with tag check

    Return stack

    Return target

    Call and return pairing

    Direction tables

    A bimodal table holds one 2-bit saturating counter per entry, indexed by low PC bits. Counters 0 and 1 predict not taken, counters 2 and 3 predict taken.

    Gshare mixes global branch history with the PC before indexing. Correlated branches then use different entries, which cuts aliasing from unrelated PCs sharing one counter.

    Aliasing never disappears entirely. Two active branches can still share an entry and untrain each other, which workload phase changes expose quickly.

    Predictor

    State per entry

    Strength

    Weakness

    Bimodal, 4K entries

    2-bit counter

    Fast lookup, tiny state

    Aliasing on correlated branches

    Gshare, 4K entries, 12-bit history

    2-bit counter

    Learns correlated patterns

    History must warm up after phase change

    TAGE sketch, tagged tables

    Tagged counters plus base bimodal

    Long histories without explosion

    More complex update and allocation

    Target structures

    A BTB caches recent branch targets indexed by branch PC with a tag check. A hit redirects fetch to the stored target, while a miss falls back to sequential fetch until resolution.

    The return stack pushes call targets and pops them at returns. Deep or unbalanced call depth overflows or underflows it, so returns mispredict until it refills.

    Indirect branches change target per execution, so a plain BTB underperforms on them. Tagged indirect predictors and compiler layout help; security mitigations add lookup cost, and predictor depth lives in the cpu-design course.

    Structure

    Hit behavior

    Miss behavior

    Direct-mapped BTB

    Redirect fetch to stored target

    Sequential fetch until resolution

    Return stack

    Pop returns the call site target

    Fall back to BTB or sequential on underflow

    Indirect predictor

    Tagged history picks per-context target

    Wrong target treated like a BTB miss

    Testbench

    The model below is a plain-SystemVerilog sketch of the mechanism. A bimodal table, a gshare table and a tagged BTB mock train on one 24-branch trace.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    class bimodal_c;
      int unsigned tab[];
      function new(int unsigned n);
        tab = new[n];
        for (int i = 0; i < n; i++) tab[i] = 1;
      endfunction
      function bit predict(int unsigned pc);
        return tab[pc % tab.size()] >= 2;
      endfunction
      function void train(int unsigned pc, bit taken);
        int unsigned idx = pc % tab.size();
        if (taken) begin
          if (tab[idx] < 3) tab[idx] = tab[idx] + 1;
        end else begin
          if (tab[idx] > 0) tab[idx] = tab[idx] - 1;
        end
      endfunction
    endclass
    
    class gshare_c;
      int unsigned tab[];
      int unsigned hist;
      int unsigned hbits;
      function new(int unsigned n, int unsigned hb);
        tab = new[n];
        for (int i = 0; i < n; i++) tab[i] = 1;
        hist = 0;
        hbits = hb;
      endfunction
      function int unsigned index(int unsigned pc);
        int unsigned mask = (1 << hbits) - 1;
        return (pc ^ (hist & mask)) % tab.size();
      endfunction
      function bit predict(int unsigned pc);
        return tab[index(pc)] >= 2;
      endfunction
      function void train(int unsigned pc, bit taken);
        int unsigned idx = index(pc);
        if (taken) begin
          if (tab[idx] < 3) tab[idx] = tab[idx] + 1;
        end else begin
          if (tab[idx] > 0) tab[idx] = tab[idx] - 1;
        end
        hist = ((hist << 1) | (taken ? 1 : 0)) & 15;
      endfunction
    endclass
    
    class btb_c;
      int unsigned valid[];
      int unsigned tag[];
      int unsigned tgt[];
      function new(int unsigned n);
        valid = new[n];
        tag = new[n];
        tgt = new[n];
        for (int i = 0; i < n; i++) valid[i] = 0;
      endfunction
      function bit hit(int unsigned pc);
        int unsigned idx = pc % valid.size();
        return (valid[idx] != 0) && (tag[idx] == pc);
      endfunction
      function void install(int unsigned pc, int unsigned t);
        int unsigned idx = pc % valid.size();
        valid[idx] = 1;
        tag[idx] = pc;
        tgt[idx] = t;
      endfunction
    endclass
    

    Common pitfall

    Two branch PCs that share one bimodal entry untrain each other. The model above shows it: both trace PCs index entry 0, so the alternating tail disturbs the loop entry.

    Interview

    Likely probes: bimodal versus gshare indexing, and what aliasing costs.

    • Bimodal indexes by PC alone, so unrelated branches collide.

    • Gshare mixes in global history, so correlated branches separate at the price of warm-up.

    • The BTB needs tags: an index hit with a wrong tag is still a miss.

    Check yourself The trace loop is taken 9 times then not taken once. Why does the bimodal counter sit at strongly taken after the loop?

    Nine trains upward saturate the counter at 3, and one not-taken train only steps it to 2. The exit is mispredicted, then the counter relearns.

    Check yourself Both trace PCs map to BTB index 0. Why does the second PC still miss once?

    The index matches but the tag does not, so the first touch of each PC installs its own tag. Every later repeat hits.

    Related topics

    • Pipeline throughput

    • CPU Design course (predictor depth)

    Previous

    10 / 86

    Next: MPKI and Recovery Math

    Up next

    Up nextMPKI and Recovery Math

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Fetch and Recovery Pipeline
    • Tuning, Cost and Interviews