Exercises — Cache lines, tags, index, offset
This page is a self-testing ladder. Each rung is harder than the last: from just recognizing the three fields, up to synthesizing a whole cache design and reasoning about corner cases. Every problem has a full worked solution hidden inside a collapsible callout — try first, then peek.
Everything here builds on the parent note. If a term feels unfamiliar, that note defines it.
The one rule we lean on constantly:
Before we start, one picture of the address so every word below has a home:

The address is one long row of bits. The lowest bits (rightmost, starting at bit 0) are the offset, the next chunk is the index, everything left over on top is the tag. We always peel from the right — this is exactly the peel direction the coral arrow shows.
Level 1 — Recognition
Goal: can you name the field and count its bits without any tricky bit-peeling?
Exercise 1.1
A cache uses -byte lines. How many offset bits does each address have?
Recall Solution 1.1
The offset must be able to name every byte inside one line. A line has bytes, numbered to . To count that many distinct positions you need bits. Answer: 6 offset bits. Notice this used only the line size — nothing about how big the whole cache is.
Exercise 1.2
A cache has sets. How many index bits?
Recall Solution 1.2
The index picks one row (set) out of . To address distinct rows you need Answer: 7 index bits.
Exercise 1.3
Which field answers "Is the block sitting in this slot actually the one I asked for?"
Recall Solution 1.3
The tag. The index already chose the row and the offset picks a byte; only the tag is stored next to the data and compared to verify identity. Answer: the tag.
Level 2 — Application
Goal: plug numbers into the split and get all three field widths.
Exercise 2.1
-bit addresses, bytes, and sets. Give tag / index / offset.
Recall Solution 2.1
Peel from the right:
- Offset bits.
- Index bits.
- Tag bits.
Answer: tag 17 / index 9 / offset 6. Check they sum: . ✓
Exercise 2.2
A direct-mapped cache holds lines, bytes, -bit addresses. Give the three field widths.
Recall Solution 2.2
Direct-mapped means 1 line per set, so .
- Offset bits.
- Index bits.
- Tag bits.
Answer: tag 17 / index 10 / offset 5. Sum . ✓
Exercise 2.3
-bit addresses (a small embedded chip), bytes, sets. Field widths?
Recall Solution 2.3
- Offset bits.
- Index bits.
- Tag bits.
Answer: tag 6 / index 6 / offset 4. Sum . ✓
Level 3 — Analysis
Goal: peel real bits out of a real address, respecting the non-nibble-aligned boundary.
Exercise 3.1
-bit addresses, bytes, sets. For address 0xCAFEF00D, find the
offset value, index (set number), and how many tag bits.
Recall Solution 3.1
Widths: offset , index , tag .
Write the address in binary (0xCAFEF00D):
We need the low bits (bits = index offset). The low 14 bits are
01 1111 0000 1101 — read them off the last three-and-a-bit hex digits F00D:
the byte 0x0D = 0000 1101 and the nibble above it (from F00D) contributes the higher index
bits.
Let's be exact by masking:
- Offset = low bits = . Since
0x0D= and bit 6 above it comes from0x00, the low 6 bits are001101. So byte inside the line. - Index = next bits (bits ). Shift the address right by and keep bits:
. Working it out gives
11000000, i.e. set 192 (0xC0). - Tag = top bits (compared, not "computed as a nice number" here).
Answer: offset , index set , tag bits. The picture below shows the peel line landing inside the last hex nibble, not on its edge — the mint INDEX box straddles a coral nibble tick, which is exactly why the naive "grab a hex byte" shortcut fails here.

Exercise 3.2
Same cache (, , -bit). For 0xDEADBEEF, find the set number.
Recall Solution 3.2
Binary of 0xDEADBEEF:
Low bits (bits ) = 11 1110 1110 1111.
- Offset = low (bits ) =
101111(0x2F). - Index = next (bits ) =
11111011(0xFB).
Answer: set , offset byte . Note the index is 11111011, not the nibble-looking
10111011 — the -bit offset shifts the boundary off the hex grid.
Level 4 — Synthesis
Goal: design or re-shape a cache and predict how bits move between fields.
Exercise 4.1
Take a direct-mapped cache: lines, bytes, -bit. Now make it 8-way set-associative with the same total size (same , same ). By how much does the tag grow, and give the new tag / index / offset.
Recall Solution 4.1
Before (direct-mapped): .
- Offset , index , tag .
After (8-way): .
- Offset (unchanged, still ).
- Index .
- Tag .
Tag grew by bits . ✓ Answer: tag grows by bits; new split = tag 20 / index 6 / offset 6.
Exercise 4.2
Design a cache: -bit addresses, you want exactly tag bits and -byte lines. How many sets must the cache have, and how many total lines if it is -way?
Recall Solution 4.2
Offset . From the tag formula: Solve: , so sets. If -way: lines.
Answer: sets; lines if -way.
Exercise 4.3
A fully associative cache with bytes and -bit addresses. Give tag / index / offset.
Recall Solution 4.3
Fully associative means one giant set: , so index bits.
- Offset bits.
- Index bits.
- Tag bits.
Answer: tag 33 / index 0 / offset 7. Every non-offset bit is tag, because any line can live in any slot — you must compare the tag of every slot.
Level 5 — Mastery
Goal: full accounting — silicon cost, corner cases, and cross-topic reasoning.
Exercise 5.1
A -way cache: lines, bytes, -bit addresses. Each line stores its data plus a valid bit and its tag. Compute (a) tag bits, (b) total SRAM bits including overhead.
Recall Solution 5.1
(a) Tag: , so index , offset , tag bits.
(b) Bits per line data tag valid: Total over all lines: Answer: tag 19 bits; total bits of SRAM. The overhead bits per line are real silicon you pay for on every line — this is why tiny lines are expensive per byte of useful data.
Exercise 5.2
Two designs, both -bit, both sets, both direct-mapped, but line size differs: Design A has B, Design B has B. Compare their tag widths and explain the direction of the change in words.
Recall Solution 5.2
Index is for both.
- A: offset , tag .
- B: offset , tag .
Answer: A tag , B tag . Bigger lines consume more offset bits (more bytes to name inside a line). With index fixed, those extra offset bits come out of the tag, so the tag shrinks as line size grows. Bigger lines also lean harder on spatial locality.
Exercise 5.3
Corner case. A cache has set, byte, -bit addresses. Give tag / index / offset, and describe in one sentence what this "cache" actually behaves like.
Recall Solution 5.3
- Offset bits (a "line" is a single byte — nothing to index inside it).
- Index bits (one set — no row to choose).
- Tag bits (the entire address is the tag).
Answer: tag 16 / index 0 / offset 0. With a single one-byte slot and a full-address tag, it is a degenerate fully-associative cache of exactly one byte — it can hold one byte at a time and must compare all address bits to decide a hit. Both degenerate logs () collapse two whole fields to zero width — a good reminder that is not a bug (and that are still powers of two, so the split stays integer).
Exercise 5.4
Cross-topic. A cache is VIPT (virtually indexed, physically tagged) with B and a page ( page-offset bits). What is the maximum number of sets the cache may have so that the index bits stay inside the page offset (the usual VIPT non-aliasing condition)?
Recall Solution 5.4
The page offset is the low bits (unchanged by translation). VIPT wants index offset page-offset bits so the index is taken from bits that virtual and physical addresses share. Offset . So: Answer: at most sets. Beyond that the index would reach into translated bits and risk aliasing — see Virtual vs physical addressing (VIPT/PIPT) and TLB and page tables.
Quick self-check
Cover the answers and rebuild these from scratch.
Offset bits for ?
Index bits for ?
Tag for -bit, , ?
Going direct-mapped -way (same size), tag changes by?
Set number of 0xDEADBEEF with offset index bits?
0xFB .Set number of 0xCAFEF00D with offset index bits?
0xC0 .