降低冲突失效:LRU替换策略
组相联是直接映射和全相联的折中:每个内存地址可以映射到一组中的任意一路:
| 相联度 | 每组路数 | 冲突概率 | 硬件成本 |
|---|---|---|---|
| 1路(直接映射) | 1 | 高 | 最低 |
| 2路 | 2 | 中 | ×1.5 |
| 4路 | 4 | 低 | ×2 |
| 8路 | 8 | 很低 | ×3 |
| 全相联 | 全部 | 无 | 最高 |
// Lesson 12: Set-Associative Cache (16 sets × 4 ways, LRU)
module cache_set_assoc(
input wire clk, rst_n,
input wire cpu_req, cpu_we,
input wire [31:0] cpu_addr, cpu_wdata,
output reg [31:0] cpu_rdata,
output reg cpu_hit
);
parameter NUM_SETS=16, NUM_WAYS=4;
reg [25:0] tags [0:NUM_SETS-1][0:NUM_WAYS-1];
reg [31:0] data [0:NUM_SETS-1][0:NUM_WAYS-1];
reg valid [0:NUM_SETS-1][0:NUM_WAYS-1], dirty [0:NUM_SETS-1][0:NUM_WAYS-1];
reg [2:0] lru [0:NUM_SETS-1];
wire [3:0] idx=cpu_addr[5:2]; wire [25:0] tag=cpu_addr[31:6];
reg [1:0] hit_way; reg hit_found; integer w,s;
always @(*) begin
hit_found=0; hit_way=0;
for(w=0;w<NUM_WAYS;w=w+1)
if(valid[idx][w]&&tags[idx][w]===tag) begin hit_found=1; hit_way=w[1:0]; end
end
reg [1:0] replace_way;
always @(*) begin
replace_way=0;
for(w=0;w<NUM_WAYS;w=w+1) if(!valid[idx][w]) replace_way=w[1:0];
if(valid[idx][0]&&valid[idx][1]&&valid[idx][2]&&valid[idx][3])
case(lru[idx]) 0:replace_way=0; 1:replace_way=1; 2:replace_way=2; 3:replace_way=3; endcase
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
for(s=0;s<NUM_SETS;s=s+1) begin for(w=0;w<NUM_WAYS;w=w+1) begin valid[s][w]<=0; dirty[s][w]<=0; end; lru[s]<=0; end
cpu_hit<=0;
end else if(cpu_req) begin
if(hit_found) begin
cpu_hit<=1; cpu_rdata<=data[idx][hit_way];
if(cpu_we) begin data[idx][hit_way]<=cpu_wdata; dirty[idx][hit_way]<=1; end
lru[idx]<=lru[idx]+1;
end else begin
cpu_hit<=0; tags[idx][replace_way]<=tag; valid[idx][replace_way]<=1;
dirty[idx][replace_way]<=cpu_we;
if(cpu_we) data[idx][replace_way]<=cpu_wdata;
lru[idx]<=lru[idx]+1;
end
end else cpu_hit<=0;
end
endmodule
组相联Cache在现代处理器中的实际配置:
| 处理器 | L1 I-Cache | L1 D-Cache | L2 Cache | L3 Cache |
|---|---|---|---|---|
| Rocket (RV64) | 16KB/4路 | 16KB/4路 | — | — |
| BOOM v3 | 32KB/4路 | 32KB/4路 | 256KB/8路 | — |
| ARM A76 | 64KB/4路 | 64KB/4路 | 256KB/8路 | 共享 |
| Apple M1 | 192KB/8路 | 128KB/8路 | 12MB | 系统级 |
| AMD Zen4 | 32KB/8路 | 32KB/8路 | 512KB/8路 | 32MB |
MESI保证了多核系统中Cache的一致性。RISC-V的原子扩展(A扩展)LR/SC指令也依赖Cache一致性协议来实现。
| 资料 | 内容 | 链接 |
|---|---|---|
| RISC-V特权规范 | CSR、Trap、中断完整定义 | riscv.org/specifications |
| RISC-V手册 | 中文版免费教材 | crva.ict.ac.cn |
| OpenSBI源码 | M-mode固件参考实现 | github.com/riscv/opensbi |
| Linux RISC-V | 内核移植与驱动 | kernel.org |
| BOOM处理器 | UC Berkeley开源OoO核心 | github.com/riscv-boom/riscv-boom |
| 香山处理器 | 中科院开源高性能核心 | github.com/OpenXiangShan |
| 课程范围 | 课程号 | 主题 |
|---|---|---|
| 特权架构 | 01-06 | 特权级→CSR→ecall→mret→trap→中断 |
| 内存系统 | 07-12 | PLIC→CLINT→SV39→TLB→直接映射→组相联 |
| 算术单元 | 13-14 | Booth乘法器→恢复余数除法 |
| 乱序执行 | 15-19 | OoO→ROB→寄存器重命名→记分牌→Tomasulo |
| 分支预测 | 20-21 | 2位预测器→BTB |
| RISC-V扩展 | 22-26 | RVC→RVM→RVA→RVF→RVD |
| 系统集成 | 27-30 | PMP→解码器→SoC→启动流程 |
建议使用以下环境进行实验:
组相联Cache的性能取决于多种优化技术的组合:
| 优化 | 命中率提升 | 硬件开销 | 应用场景 |
|---|---|---|---|
| 增加相联度 | +5-15% | 每路+比较器 | 通用 |
| 增大Cache | +10-30% | 面积翻倍 | 通用 |
| 增加行大小 | +2-8% | 带宽增加 | 顺序访问 |
| Victim Cache | +5-10% | 小全相联Cache | 冲突密集 |
| 预取 | +10-50% | 预取引擎 | 流式访问 |
| 非阻塞Cache | +10-30% | MSHR | 乱序处理器 |
Victim Cache是一个小的全相联Cache(通常4-8项),存储被主Cache驱逐的行。当主Cache miss但Victim Cache命中时,只需交换两个Cache行,避免访问内存。Intel Pentium首次使用Victim Cache,现代处理器中仍常见于L1和L2之间。
乱序处理器需要非阻塞Cache,允许Cache缺失时不阻塞后续访问:
MSHR数量决定了Cache可以同时处理多少个缺失。太少的MSHR会导致处理器在多个缺失时仍然阻塞。太多则增加面积和功耗。