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

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • Architecture Metrics Reference
  • Workload Taxonomy for Architects
  • Architecture Glossary
  • Computer Architecture Cheatsheet
  • Pipeline Fundamentals14
  • Memory Hierarchy15
    • Caches
      • Address Decode and the Access Path
      • Associativity and the Three Cs
      • AMAT, MPKI and Memory-Level Parallelism
      • Replacement and Thrashing
      • Write Policies and Coherence Hooks
      • Sizing a Level and Triaging Misses
    • Memory Bandwidth and Latency
    • Virtual Memory and the TLB
  • NoC and Interconnect Architecture6
  • Coherency and Memory Ordering9
  • Performance Analysis9
  • Accelerator Architectures6
  • SoC Architecture Tradeoffs9
  • Architecture Interview Prep14
Loading lesson

‹Caches
  1. Topics
  2. Computer Architecture
  3. Memory Hierarchy
  4. Caches
  5. Associativity and the Three Cs
On this page

    Computer ArchitectureAll levels

    Associativity and the Three Cs

    Direct-mapped, set-associative and fully associative caches, and the three kinds of misses.

    From one way to many

    Associativity is the number of lines per set. More ways hold more aliasing addresses at once, but every way adds a tag compare and widens the select mux.

    The hit path slows as ways grow. That delay is paid on every access, while the miss saving only applies to conflict misses.

    Ways

    Tag compares per access

    What improves

    What worsens

    1 (direct-mapped)

    1

    Nothing to choose, fastest hit

    Any alias pair thrashes

    4 to 8

    4 to 8

    Most conflict misses gone

    Hit delay and tag energy up

    16 and above

    16 and above

    Little extra miss saving

    Delay, power and timing closure pain

    The three Cs and one more

    Compulsory misses touch data for the first time. Capacity misses happen even in a fully associative cache of the same size. Conflict misses are the rest, and only associativity or mapping fixes remove them.

    Multicore designs add a fourth class. Coherence misses come from invalidations by other cores, and they belong to the coherency topic, not to sizing.

    Class

    Removed by

    Diagnosed with

    Compulsory

    Larger lines or prefetch, never by ways

    First-touch share of misses

    Capacity

    Larger cache at fixed associativity

    Fully associative shadow model

    Conflict

    More ways, better mapping, victim buffer

    Set-pressure heatmap

    Coherence

    Less sharing or better layout

    Invalidation counters per core

    Conflict misses, measured

    The two models below share geometry: 4 sets and 1-byte lines, so index and tag decode match. Only the way count differs.

    The trace writes two aliasing addresses, then reads them alternately twelve times. The direct-mapped cache misses every read, while the 2-way cache holds both lines.

    Every miss fetches the line, for loads and stores alike. The two fill misses are compulsory, and the twelve alternating-read misses vanish in a fully associative cache of the same size, so they are conflict misses.

    cache_dm.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
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    module cache_dm (
      input  logic       clk,
      input  logic       rst,
      input  logic       req,
      input  logic       wr,
      input  logic [7:0] addr,      // tag[7:2] index[1:0], 1-byte lines
      output logic       hit,
      output logic [31:0] hits,
      output logic [31:0] misses
    );
      logic [5:0] tag_arr [4];
      logic       valid_arr [4];
      logic [1:0] idx;
      logic [5:0] tag;
      logic       match_line;
      integer i;
      assign idx = addr[1:0];
      assign tag = addr[7:2];
      assign match_line = valid_arr[idx] && (tag_arr[idx] == tag);
      assign hit = req && match_line;
      always_ff @(posedge clk) begin
        if (rst) begin
          hits <= 0; misses <= 0;
          for (i = 0; i < 4; i = i + 1) begin valid_arr[i] <= 0; tag_arr[i] <= 0; end
        end else if (req) begin
          if (match_line) hits <= hits + 1;
          else begin
            misses <= misses + 1;
            // every miss fetches the line: stores allocate, loads fill from memory
            if (wr) begin tag_arr[idx] <= tag; valid_arr[idx] <= 1; end
            else begin tag_arr[idx] <= tag; valid_arr[idx] <= 1; end
          end
        end
      end
    endmodule
    
    module cache_tw (
      input  logic       clk,
      input  logic       rst,
      input  logic       req,
      input  logic       wr,
      input  logic [7:0] addr,      // tag[7:2] index[1:0], 1-byte lines
      output logic       hit,
      output logic [31:0] hits,
      output logic [31:0] misses
    );
      logic [5:0] tag_arr [4][2];
      logic       valid_arr [4][2];
      logic       lru_arr [4];
      logic [1:0] idx;
      logic [5:0] tag;
      logic       m0;
      logic       m1;
      logic       vw;
      integer i;
      integer w;
      assign idx = addr[1:0];
      assign tag = addr[7:2];
      assign m0 = valid_arr[idx][0] && (tag_arr[idx][0] == tag);
      assign m1 = valid_arr[idx][1] && (tag_arr[idx][1] == tag);
      assign vw = !valid_arr[idx][0] ? 1'b0 : (!valid_arr[idx][1] ? 1'b1 : lru_arr[idx]);
      assign hit = req && (m0 || m1);
      always_ff @(posedge clk) begin
        if (rst) begin
          hits <= 0; misses <= 0;
          for (i = 0; i < 4; i = i + 1) begin
            lru_arr[i] <= 0;
            for (w = 0; w < 2; w = w + 1) begin valid_arr[i][w] <= 0; tag_arr[i][w] <= 0; end
          end
        end else if (req) begin
          if (m0 || m1) begin
            hits <= hits + 1;
            lru_arr[idx] <= m0 ? 1'b1 : 1'b0;
          end else begin
            misses <= misses + 1;
            // every miss fetches the line: stores allocate, loads fill from memory
            if (wr) begin
              tag_arr[idx][vw] <= tag;
              valid_arr[idx][vw] <= 1;
              lru_arr[idx] <= vw ? 1'b0 : 1'b1;
            end else begin
              tag_arr[idx][vw] <= tag;
              valid_arr[idx][vw] <= 1;
              lru_arr[idx] <= vw ? 1'b0 : 1'b1;
            end
          end
        end
      end
    endmodule
    

    Cache

    Hits

    Misses

    Reading

    Direct-mapped

    0

    14

    Every read evicts the other line

    2-way

    12

    2

    Both aliasing lines stay resident

    Two bounded fixes avoid paying full associativity. A victim buffer catches freshly evicted lines, and way prediction probes the likely way first.

    Common mistakes

    Recommending direct-mapped L1 caches as current practice is dated. Modern L1 caches are usually 4-way to 8-way set-associative, and direct-mapped survives only in tiny or deeply timing-bound spots.

    Likely probes: which miss class grows with associativity fixed and size fixed, and what a victim buffer changes.

    • Fix size and ways to isolate capacity, then vary the mapping to isolate conflict.

    • A victim buffer converts some conflict misses into buffer hits without widening the main array.

    • Way prediction trims hit energy and delay, with a mispredict penalty on the wrong guess.

    Check yourself Misses persist in a fully associative model of the same size. Which classes remain?

    Compulsory and capacity only. Conflict misses cannot exist with no set restriction, so the survivors define the floor for this size.

    Check yourself Adding ways cut misses but IPC fell. What is the first suspect?

    Hit latency. AMAT in the next lesson prices the slower hit against the miss saving.

    Related topics

    • Memory bandwidth and latency

    • CPU design course

    Previous

    20 / 86

    Next: AMAT, MPKI and Memory-Level Parallelism

    Up next

    Up nextAMAT, MPKI and Memory-Level Parallelism

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Replacement and Thrashing
    • Write Policies and Coherence Hooks
    • Sizing a Level and Triaging Misses