Skip to content

Cache Organization

The cache is divided into fixed-size blocks called cache lines (typically 64 bytes on x86). Each line stores:

  • Data — the 64-byte block from memory
  • Tag — the high-order address bits identifying which memory block is stored
  • Valid bit — whether the line contains valid data
  • Dirty bit — whether the data has been modified (for write-back caches)

Given a memory address, the cache hardware splits it into three parts:

Tagt bits    Indexs bits    Offsetb bits\underbrace{\text{Tag}}_{t \text{ bits}} \;\; \underbrace{\text{Index}}_{s \text{ bits}} \;\; \underbrace{\text{Offset}}_{b \text{ bits}}
  • Offset (bb bits): selects the byte within the cache line. For 64-byte lines, b=6b = 6.
  • Index (ss bits): selects which set in the cache to check. With SS sets, s=log2Ss = \log_2 S.
  • Tag (tt bits): the remaining bits, used to verify if the correct block is stored.

The associativity determines how many lines can map to the same set:

Each memory block maps to exactly one cache line. Simple and fast, but vulnerable to conflict misses when two frequently used addresses map to the same index.

Address → Index → Check tag → Hit or miss

Set-Associative (W=2,4,8,W = 2, 4, 8, \ldots)

Section titled “Set-Associative (W=2,4,8,…W = 2, 4, 8, \ldotsW=2,4,8,…)”

Each set contains WW ways. A memory block can go in any of the WW lines in its set. This reduces conflict misses at the cost of comparing WW tags in parallel.

For a cache with CC bytes, LL-byte lines, and WW-way associativity:

S=CL×W(number of sets)S = \frac{C}{L \times W} \quad \text{(number of sets)}

A block can go anywhere in the cache. No conflict misses, but requires comparing against every tag — expensive and typically only used for small caches (e.g., TLBs).

S=32,76864×8=64 setsS = \frac{32{,}768}{64 \times 8} = 64 \text{ sets}
  • Offset: b=log264=6b = \log_2 64 = 6 bits
  • Index: s=log264=6s = \log_2 64 = 6 bits
  • Tag: remaining address bits (e.g., 4866=3648 - 6 - 6 = 36 bits for 48-bit addresses)