Set-associative and fully associative caches
Overview
We saw that direct-mapped caches suffer from conflict misses when multiple addresses map to the same cache line. Set-associative caches solve this by allowing each memory block to go into multiple possible locations, while fully associative caches take this to the extreme by allowing a block to go anywhere. This is the fundamental tradeoff: flexibility vs. hardware complexity.
Why Do We Need Associativity?
Set-associative caches give you a small choice of spots. Fully associative caches let you park anywhere. More choice = fewer conflicts, but finding your car takes longer (more comparison hardware).
Set-Associative Caches
- N = 1: direct-mapped
- N = 2, 4, 8: common set-associative configurations
- N = total cache lines: fully associative
Address Decomposition
For a set-associative cache, the address splits into:
Why this formula?
- Total cache lines =
- Each set holds lines
- So number of sets =
The set index bits select which set to search. The tag bits distinguish between different blocks mapped to the same set. The block offset selects the byte within the block (same as direct-mapped).
Step 1: Calculate number of sets
Why 65536? bytes.
Step 2: Calculate bit fields
- Block offset: bits
- Set index: bits
- Tag: bits
Why 8 bits for index? We need to distinguish between 256 sets, and .
Step 3: Example address lookup
Address: 0x001A4C0 (a 32-bit address, shown as 7 hex digits = 28 bits; the top 4 hex digits are 0).
Full 32-bit binary:
0000 0000 0001 1010 0100 1100 0000
(That is .)
Partition into Tag(18) | Index(8) | Offset(6), from MSB to LSB:
Tag (18 bits): 00 0000 0000 0001 1010 = 0x01A
Index (8 bits): 0100 1100 = 0x4C = 76
Offset (6 bits): 00 0000 = 0
Check: bits ✓, and the 8-bit index .
The block maps to set 76. The cache controller checks all 4 tag fields in set 76 in parallel to find a match.
How Set-Associative Lookup Works
- Extract set index from address → select the set
- Compare tag against all N tags in the set simultaneously (parallel comparators)
- If any tag matches and valid bit = 1 → HIT, use that line's data
- If no match → MISS, fetch from memory, place in any line of that set (replacement policy decides which)
Fully Associative Caches
Address Decomposition
No index field! The tag must be large enough to identify the block uniquely.
Why no index? Since a block can go anywhere, we don't partition the cache into sets. We search everything.
Lines: lines
Bit fields:
- Offset: bits
- Tag: bits
- Index: 0 bits
On every access, the hardware compares the 26-bit tag against all 256 tags in parallel. This requires 256 comparators—expensive but eliminates conflict misses entirely.
Comparison: Direct-Mapped vs. Set-Associative vs. Fully Associative
| Property | Direct-Mapped | N-Way Set-Assoc | Fully Associative | |----------|---------------|-----------------| | Ways per set | 1 | N | C/B (all lines) | | Number of sets | C/B | C/(B×N) | 1 | | Comparators | 1 | N | C/B | | Hit time | Fastest | Medium | Slowest | | Miss rate | Highest (conflicts) | Medium | Lowest | | Hardware cost | Cheapest | Medium | Most expensive | | Use case | L1 caches (speed critical) | L2, L3 caches | TLBs, small caches |
Most real caches use 2-way, 4-way, or 8-way set-associative as a sweet spot.
Replacement Policies
When a miss occurs in a set-associative or fully associative cache, we must choose which line to evict. Direct-mapped caches have no choice (only one possible location), but associative caches need a replacement policy.
LRU performs best in practice but requires tracking access order (e.g., with counter bits or an "age matrix"). For 2-way, LRU needs 1 bit per set. For 4-way, it needs more complex logic.
A miss occurs. We evict Way 1 (least recently used). After filling Way 1 with new data, it becomes the most recently used: [Way 1, Way 2, Way 0, Way 3]
Why track order? LRU exploits temporal locality: if a block was used recently, it's likely to be used again soon. Evicting the "coldest" block minimizes future misses.
Derivation: Cache Configuration Math
Let's derive the relationship between cache parameters.
Given:
- Total cache size: bytes
- Block size: bytes
- Associativity: ways
Total cache lines:
Why? Each line stores one block of bytes. If we have total bytes, we can fit blocks.
Number of sets:
Why? We have total lines, distributed evenly into -way sets. Each set gets lines, so we need sets.
Set index bits:
Why? We need enough bits to uniquely identify one of sets. bits can represent values.
Tag bits:
where is address width, is block offset bits.
Why? The address is partitioned into tag, index, and offset. What's not used for index and offset must be tag.
Common Mistakes
Why it feels right: "4-way" sounds like "4 times."
The fix: Associativity describes how many places a block can go, not total capacity. A 64 KB direct-mapped cache and a 64 KB 4-way set-associative cache have the same total storage. The 4-way version just has fewer sets (each with 4 lines), while direct-mapped has more sets (each with 1 line).
Why it feels right: "Any block can go anywhere" sounds unlimited.
The fix: Fully associative still has total lines. It just means no index bits—the block can occupy any of those lines. You still evict when full.
Why it feels right: Sequential thinking from software.
The fix: Hardware uses parallel comparators. All N tag comparisons happen simultaneously. Hit time grows slightly due to multiplexer delay, but it's not linear in N.
Worked Problem: Designing a 2-Way Set-Associative Cache
Problem: Design a 2-way set-associative cache with 32 KB capacity, 128-byte blocks, for a system with 32-bit addresses. Calculate:
- Number of sets
- Bit field sizes
- Total tag storage bits
Solution:
Step 1: Number of sets
Why divide by 2? We have 2 ways, so lines are split into 2 groups per set.
Step 2: Bit fields
- Block offset: bits
- Set index: bits
- Tag: bits
Step 3: Total tag storage
- Each line needs: 18-bit tag + 1 valid bit + 1 dirty bit (if write-back) = 20 bits overhead
- Total lines: lines
- Total overhead: bits = 640 bytes
Additional: Each set has 2 lines, so we need 1 LRU bit per set (to track which way is least recent). Total: 128 sets × 1 bit = 128 bits = 16 bytes.
Active Recall
Recall Explain to a 12-year-old
Imagine you have a small notebook where you write down answers to homework problems so you don't have to look them up in big textbook every time.
In a direct-mapped notebook, each problem must go on a specific page number (like problem 10 always goes on page 10). If you have two problem 10s from different chapters, they fight for the same page—every time you write one, you erase the other. Super annoying!
In a set-associative notebook, you divide your notebook into sections. Problem 10 still maps to a specific section, but within that section, you have 2 or 4 empty slots. So two different problem 10s can both fit without erasing each other. Much better!
In a fully associative notebook, problem 10 can go on any page you want. No fights! But now finding where you wrote problem 10 takes longer—you have to scan every page. That's the tradeoff: more flexibility but slower to search.
Mnemonic
Connections
- Direct-mapped caches — the N=1 special case
- Cache replacement policies — LRU, FIFO, Random for choosing eviction victim
- Cache coherence — more complexity when multiple cores have associative caches
- Translation Lookaside Buffer (TLB) — often fully associative, small, fast
- Conflict misses vs capacity misses — associativity reduces conflict misses
- Cache performance metrics — hit time increases, miss rate decreases with associativity
- Write policies — write-back and write-through work the same across associativity types
#flashcards/hardware
What does "4-way set-associative" mean? :: A cache where each set contains 4 lines (ways), and a memory block maps to a specific set but can occupy any of the 4 lines within that set.
How many sets in a cache with C bytes, B-byte blocks, N-way associativity?
In a fully associative cache, how many set index bits are there?
What is the main advantage of higher associativity?
What is the main disadvantage of higher associativity?
Why do we use parallel comparators in set-associative caches?
What replacement policy tracks which line was accessed least recently?
In a 2-way set-associative cache, how many bits are needed for LRU per set?
If a 64 KB cache has 64-byte blocks and is 8-way set-associative, how many sets?
Why does fully associative have the lowest miss rate?
What are the three address fields in a set-associative cache?
Why are TLBs often fully associative?
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho, direct-mapped cache mein ek problem thi—har memory block ka ek fixed spot hota tha, jaise parking lot mein tumhari car sirf ek hi numbered spot mein park ho sakti thi. Agar do blocks ka wahi spot ban gaya, toh ek dusre ko baar baar evict karte rehte, chahe puri cache khaali ho. Isko conflict miss kehte hain. Set-associative cache is problem ko solve karti hai by giving tumhein thodi choice—ab block ek particular set mein toh jayega, lekin us set ke andar N locations (ways) mein se kisi bhi mein baith sakta hai. Aur fully associative cache toh full freedom deti hai—block kahin bhi jaa sakta hai. Simple funda: zyada choice = kam conflict misses.
Ab core intuition samjho address decomposition ka. Har address teen parts mein toot ta hai—Tag, Set Index, aur Block Offset. Number of sets nikalne ka formula hai S = C / (B × N), jahan C cache size, B block size, aur N associativity hai. Logic seedha hai: total lines = C/B, aur har set mein N lines hoti hain, toh sets = (C/B)/N. Set index bits batate hain kaunse set mein jaana hai, tag bits distinguish karte hain same set ke different blocks ko. Jab lookup karte hain, toh us set ke saare N tags ko parallel mein compare karte hain—sequentially nahi, warna 4-way cache 4 guna slow ho jaati. Isiliye hardware mein N parallel comparators lagte hain, yahi associativity ka real cost hai.
Yeh baat matter kyun karti hai? Kyunki real-world programs mein memory access patterns aise hote hain ki bahut saare addresses same set pe hash ho jaate hain, aur direct-mapped cache tab bekaar performance deti hai. Set-associativity ek beautiful tradeoff hai—thoda extra hardware (comparators, replacement logic) daalke tum conflict misses drastically kam kar sakte ho, jisse programs faster chalte hain. Isiliye modern CPUs mein 4-way, 8-way associativity common hai. Yeh concept samajhna zaroori hai kyunki flexibility vs hardware complexity ka yeh tradeoff pure computer architecture ka ek fundamental theme hai—jise tum aage cache design, memory systems, aur performance tuning har jagah dekhoge.