Cache刷新操作与DMA缓存一致性协议实战 - 第2节
2.1 Cache 行的基本结构
Cache 行(Cache Line)是 Cache 与主存之间数据交换的最小单位。每个 Cache 行不仅存储来自主存的数据块,还包含用于查找和状态管理的辅助字段。
| 字段 | 宽度(典型) | 说明 |
|---|---|---|
| Valid Bit(有效位) | 1 bit | 标记该行是否包含有效数据。复位后为 0,加载数据后置 1。 |
| Tag(标签) | 地址高位 | 用于与 CPU 发出的地址高位比较,判断是否命中。 |
| Data Block(数据块) | 16~128 字节 | 从主存一次搬入的连续数据。常见嵌入式 Cache 为 32 字节。 |
| Dirty Bit(脏位) | 1 bit | 写回策略下,标记该行数据已被修改,尚未写回主存。 |
关键概念:Cache 行大小直接影响空间局部性利用效率。行过大浪费带宽,行过小增加 Tag 存储开销。ARM Cortex-M7 的 L1 Cache 行大小为 32 字节,x86 通常为 64 字节。
2.2 直接映射(Direct Mapped)
直接映射将主存地址按固定规则映射到唯一的 Cache 行。地址被划分为三个字段:Tag、Index、Offset。
- Index:选择 Cache 行号。若 Cache 有 2n 行,则 Index 占 n 位。
- Tag:与 Cache 行中存储的 Tag 比较,判断是否命中。
- Offset:在数据块内选择具体字节。
优点:硬件简单、查找速度快,只需一次比较。
缺点:多个地址映射到同一行时频繁冲突,导致 Cache 抖动。
缺点:多个地址映射到同一行时频繁冲突,导致 Cache 抖动。
2.3 组相联映射(Set-Associative)
组相联映射是直接映射与全相联的折中方案。Cache 被分为若干组(Set),每组包含多个行(Way)。地址中的 Index 选择组,然后在组内所有行中并行比较 Tag。
- n 路组相联:每组有 n 个 Cache 行。常见配置:2 路、4 路、8 路。
- 查找过程:Index → 定位组 → 组内 n 个 Tag 同时比较 → 任意匹配即命中。
- 替换策略:组内满时需替换,常用 LRU(最近最少使用)或伪 LRU。
实战经验:在 DMA 与 Cache 交互场景中,4 路组相联是性价比最高的选择。冲突率比直接映射降低约 60%,硬件复杂度可控。
2.4 全相联映射(Fully Associative)
全相联映射允许任意主存块映射到任意 Cache 行。地址中只有 Tag 和 Offset,没有 Index 字段。查找时,CPU 将 Tag 与所有 Cache 行的 Tag 同时比较。
注意:全相联映射的硬件成本极高——需要 N 个比较器(N = Cache 行数),且比较延迟随行数线性增长。在嵌入式系统中,全相联仅用于 TLB(转译后备缓冲器)等小型查找表,不用于数据 Cache。
| 映射方式 | 冲突概率 | 硬件复杂度 | 查找延迟 | 典型应用 |
|---|---|---|---|---|
| 直接映射 | 高 | 低 | 低 | 低端 MCU、简单 Cache |
| 组相联(4 路) | 中 | 中 | 中 | ARM Cortex-A 系列、RISC-V 应用处理器 |
| 全相联 | 极低 | 极高 | 高 | TLB、专用查找硬件 |
2.5 映射方式对比与选择指南
在 DMA 与 Cache 一致性设计中,映射方式直接影响刷新操作的粒度和复杂度。
- 直接映射:刷新操作简单,只需按 Index 遍历。但冲突导致频繁替换,DMA 数据可能被意外踢出。
- 组相联:刷新时需遍历组内所有 Way。DMA 缓冲区可分散在多个组,减少冲突。
- 全相联:刷新需遍历所有行,硬件开销大。通常只在 TLB 中使用,数据 Cache 极少采用。
工程建议:对于 DMA 缓冲区,优先将其地址对齐到 Cache 行边界(如 32 字节对齐),并利用组相联特性将缓冲区分散到不同组,可显著降低 Cache 抖动和刷新开销。