2. Cache 基础回顾:Cache 的工作原理与关键结构
在深入分析 DMA 与 Cache 的失效交互之前,必须牢固掌握 Cache 的核心工作原理。Cache 是处理器与主存之间的高速缓冲存储器,其设计目标是通过空间局部性和时间局部性来减少平均访存延迟。本节将系统回顾 Cache 的三种基本映射方式,并详细拆解 Cache 行的核心字段:Tag、Index 与 Offset。
2.1 Cache 映射方式
Cache 的映射方式决定了主存块如何放置到 Cache 行中。不同的映射方式在硬件复杂度、命中率和灵活性上存在显著差异。以下是三种经典映射方式的对比:
| 映射方式 | 主存块可放置位置 | 硬件复杂度 | 命中率 | 典型应用场景 |
|---|---|---|---|---|
| 直接映射 | 唯一固定的 Cache 行 | 低 | 较低(冲突失效多) | 简单嵌入式 MCU、低功耗设计 |
| 组相联 | 固定组内的若干行(如 4 路) | 中 | 高(平衡冲突与成本) | 主流 CPU L1/L2 Cache |
| 全相联 | 任意 Cache 行 | 高 | 最高(无冲突失效) | TLB、小容量专用缓存 |
2.1.1 直接映射 (Direct-Mapped Cache)
直接映射是最简单的映射方式。每个主存块只能映射到 Cache 中唯一的一个行位置。映射关系由主存地址的 Index 字段决定。
下图展示了直接映射 Cache 的结构:
2.1.2 组相联 (Set-Associative Cache)
组相联是直接映射和全相联的折中方案。Cache 被分成若干组,每组包含多个行(称为路)。主存块首先通过 Index 映射到固定组,然后在组内通过全相联方式查找。
下图展示了 4 路组相联 Cache 的结构:
2.1.3 全相联 (Fully-Associative Cache)
全相联 Cache 允许任何主存块放置在任何 Cache 行中。这种方式消除了冲突失效,但需要全相联比较器,硬件成本最高,通常仅用于小容量缓存(如 TLB)。
2.2 Cache 行核心字段详解
每个 Cache 行由三个核心字段组成:Tag、Index 和 Offset。理解这三个字段的划分和用途,是定位 Cache 失效问题的前提。
| 字段 | 位宽(示例) | 作用 | 在 DMA 故障排查中的意义 |
|---|---|---|---|
| Tag | 20-bit | 标识主存块的高位地址,用于与 Cache 行中存储的 Tag 比较 | 判断 DMA 访问的地址是否与 Cache 中缓存的地址匹配 |
| Index | 8-bit | 选择 Cache 行或组的位置 | 确定 DMA 数据在 Cache 中的映射位置,用于分析冲突失效 |
| Offset | 4-bit | 在 Cache 行内选择具体字节 | 确认 DMA 传输的字节对齐和部分行更新问题 |
2.2.1 Tag 字段
Tag 是主存地址的高位部分,用于唯一标识一个主存块。当 CPU 访问内存时,Cache 控制器使用 Index 找到对应的 Cache 行,然后比较该行存储的 Tag 与请求地址的 Tag 是否一致。如果一致,则 Cache 命中;否则发生 Cache 失效。
2.2.2 Index 字段
Index 用于选择 Cache 行或组。在直接映射 Cache 中,Index 直接对应唯一的 Cache 行号;在组相联 Cache 中,Index 对应组号,然后在组内通过 Tag 比较选择具体路。
Index 的位宽决定了 Cache 的行数或组数:
// 示例:计算 Cache 行数
// 假设 Cache 大小为 32KB,每行 32 字节
// 直接映射:行数 = 32KB / 32B = 1024 行
// Index 位宽 = log2(1024) = 10-bit
// 4 路组相联:组数 = 1024 / 4 = 256 组
// Index 位宽 = log2(256) = 8-bit
2.2.3 Offset 字段
Offset 用于在 Cache 行内选择具体的字节。Cache 行的大小通常为 16、32 或 64 字节。Offset 的位宽由 Cache 行大小决定:
// Offset 位宽计算
// Cache 行大小 = 32 字节
// Offset 位宽 = log2(32) = 5-bit
// 地址分解示例(32-bit 地址,Cache 行 32 字节)
// 地址: 0x12345678
// Offset: 0x78 & 0x1F = 0x18 (24 字节偏移)
// Index: (0x12345678 >> 5) & 0x3FF = 0x2B3
// Tag: 0x12345678 >> 15 = 0x2468A
2.3 Cache 行状态与失效类型
Cache 行除了存储数据外,还包含状态位,用于管理 Cache 一致性。常见的状态包括:
- Valid (V):指示该 Cache 行是否包含有效数据。
- Dirty (D):指示该 Cache 行中的数据是否已被修改(写回策略)。
- LRU (Least Recently Used):用于组相联 Cache 的替换策略。
Cache 失效主要分为三种类型:
| 失效类型 | 触发原因 | 在 DMA 场景中的典型表现 |
|---|---|---|
| 强制失效 | 首次访问某个主存块 | DMA 传输完成后,CPU 首次读取新数据时必然发生 |
| 容量失效 | Cache 容量不足以容纳工作集 | DMA 传输大量数据,导致 Cache 被频繁替换 |
| 冲突失效 | 多个主存块映射到同一 Cache 行 | DMA 地址与 CPU 频繁访问的地址共享同一 Index |
2.4 本节小结
Cache 的映射方式决定了主存块在 Cache 中的放置策略,直接映射简单但冲突多,组相联平衡了成本和性能,全相联灵活但硬件开销大。Tag、Index 和 Offset 三个字段共同构成了 Cache 行的寻址和比较机制。理解这些基础概念,是后续分析 DMA 与 Cache 交互故障的基石。