codexcache-line-address-geometry.py
cache-line-address-geometry.py
"""Draw byte-address geometry and distinguish line identity from cache slots.
Tested with Python 3.14.4, Matplotlib 3.10.7, NumPy 2.3.5.
Run from _media with MPLBACKEND=Agg and MPLCONFIGDIR in /tmp.
The matching PNG basename is written to the current working directory.
"""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
def main():
address, block_bytes = 52, 16
line, offset = divmod(address, block_bytes)
assert (line, offset, line * block_bytes) == (3, 4, 48)
plt.rcParams.update({"font.family": "DejaVu Sans", "font.size": 11})
fig, ax = plt.subplots(figsize=(10.4, 5.8), dpi=120)
fig.patch.set_facecolor("white")
ax.set(xlim=(-2, 68), ylim=(-0.3, 8.7))
ax.axis("off")
fig.suptitle("A byte address selects a line and an offset", fontsize=18,
fontweight="bold", y=0.965)
ax.text(32, 8.1, "Illustrative 8-bit physical address: 52 = 0011 0100₂", ha="center", fontsize=13)
for x, width, label, color in [(12, 20, "0011\nline identity q = 3", "#dceaf8"),
(32, 20, "0100\nbyte offset d = 4", "#fde8cc")]:
ax.add_patch(Rectangle((x, 6.45), width, 1.1, facecolor=color, edgecolor="#43607b"))
ax.text(x + width / 2, 7, label, ha="center", va="center", linespacing=1.6)
ax.text(32, 6.0, "B = 16 = 2⁴ bytes: low 4 bits are the offset; no set-index bits here",
ha="center", fontsize=11)
colors = ["#e8edf3", "#e8edf3", "#e8edf3", "#dceaf8"]
for q in range(4):
start = q * block_bytes
ax.add_patch(Rectangle((start, 4.1), block_bytes, 0.9,
facecolor=colors[q], edgecolor="#65788e"))
ax.text(start + 8, 5.3, f"Line q = {q}", ha="center", weight="bold")
ax.text(start + 8, 4.55, f"bytes {start}–{start + 15}", ha="center", fontsize=10)
for boundary in (0, 16, 32, 48, 64):
ax.text(boundary, 3.8, str(boundary), ha="center", fontsize=10)
ax.add_patch(Rectangle((address, 4.1), 1, 0.9, facecolor="#d67918", edgecolor="#9a4f08"))
ax.annotate("read byte 52", xy=(52.5, 4.1), xytext=(52.5, 3.05), ha="center",
arrowprops={"arrowstyle": "->", "color": "#9a4f08"}, color="#854508")
ax.text(20, 3.15, "Backing memory shown: bytes 0–63", ha="center", fontsize=11)
for x, name, label in [(12, "Slot 0", "line q = 3; bytes 48–63"),
(38, "Slot 1", "line q = 0; bytes 0–15")]:
ax.add_patch(Rectangle((x, 0.65), 23, 1.05, facecolor="#f4f7fa", edgecolor="#43607b"))
ax.text(x + 11.5, 1.37, name, ha="center", weight="bold")
ax.text(x + 11.5, 0.95, label, ha="center", fontsize=10)
ax.annotate("copy whole line", xy=(23.5, 1.75), xytext=(46, 2.75), ha="center",
arrowprops={"arrowstyle": "->", "connectionstyle": "arc3,rad=0.15", "color": "#43607b"})
fig.text(0.5, 0.04, "Resident state after read 9 of the LRU trace. Line 3 is in slot 0; its identity stays 3.\n"
"Either line could occupy either slot in a fully associative cache.",
ha="center", fontsize=11, linespacing=1.6)
fig.subplots_adjust(left=0.035, right=0.98, top=0.91, bottom=0.14)
fig.savefig(Path(__file__).stem + ".png", facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()