4路组相联ICache:取指命中率>90%
CPU的取指速度远快于主存(SRAM 1周期 vs DRAM 100+周期)。ICache在CPU和主存之间提供高速指令缓冲,利用程序的空间局部性和时间局部性:
| 参数 | 本课ICache | ARM A53 ICache | BOOM ICache |
|---|---|---|---|
| 容量 | 1KB | 16-64KB | 32-64KB |
| 相联度 | 4路 | 2-4路 | 4-8路 |
| 行大小 | 16B | 32-64B | 64B |
| 替换策略 | LRU | 随机/LRU | PLRU |
| 命中延迟 | 1周期 | 2周期 | 2-3周期 |
// Lesson 36: Instruction Cache — 4-way, 16 sets, 16B line
module icache #(
parameter ADDR_W=32, INDEX_W=4, OFFSET_W=4,
parameter TAG_W = ADDR_W - INDEX_W - OFFSET_W,
parameter WAYS=4, LINE_SIZE=16,
parameter LINE_W = LINE_SIZE * 8
)(
input wire clk, rst_n,
input wire [ADDR_W-1:0] cpu_addr_i,
input wire cpu_req_i,
output reg cpu_hit_o,
output reg [31:0] cpu_rdata_o,
output reg cpu_valid_o,
// Refill interface
input wire [LINE_W-1:0] mem_rdata_i,
input wire mem_valid_i,
output reg [ADDR_W-1:0] mem_addr_o,
output reg mem_req_o
);
localparam SETS = 1 << INDEX_W;
reg valid [0:WAYS-1][0:SETS-1];
reg [TAG_W-1:0] tag [0:WAYS-1][0:SETS-1];
reg [LINE_W-1:0] data [0:WAYS-1][0:SETS-1];
reg [$clog2(WAYS)-1:0] lru [0:SETS-1];
wire [INDEX_W-1:0] idx = cpu_addr_i[INDEX_W+OFFSET_W-1:OFFSET_W];
wire [TAG_W-1:0] rtag = cpu_addr_i[ADDR_W-1:INDEX_W+OFFSET_W];
wire [OFFSET_W-1:0] off = cpu_addr_i[OFFSET_W-1:0];
// 并行Tag比较
reg is_hit; reg [$clog2(WAYS)-1:0] hit_way;
integer w;
always @(*) begin
is_hit = 0; hit_way = 0;
for (w = 0; w < WAYS; w++)
if (valid[w][idx] && tag[w][idx] == rtag)
{is_hit, hit_way} = {1'b1, w[$clog2(WAYS)-1:0]};
end
// 命中输出
always @(*) begin
cpu_hit_o = is_hit & cpu_req_i;
cpu_valid_o = is_hit & cpu_req_i;
if (is_hit)
case (off[3:2])
0: cpu_rdata_o = data[hit_way][idx][31:0];
1: cpu_rdata_o = data[hit_way][idx][63:32];
2: cpu_rdata_o = data[hit_way][idx][95:64];
3: cpu_rdata_o = data[hit_way][idx][127:96];
endcase
else cpu_rdata_o = 0;
end
// 未命中时启动Refill
reg refill_req;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
mem_req_o <= 0; refill_req <= 0;
for (int s = 0; s < SETS; s++) begin
lru[s] <= 0;
for (int ww = 0; ww < WAYS; ww++) begin
valid[ww][s] <= 0;
tag[ww][s] <= 0;
data[ww][s] <= 0;
end
end
end else begin
if (cpu_req_i && !is_hit && !refill_req) begin
mem_req_o <= 1;
mem_addr_o <= {cpu_addr_i[ADDR_W-1:OFFSET_W],
{OFFSET_W{1'b0}}};
refill_req <= 1;
end
if (refill_req && mem_valid_i) begin
valid[lru[idx]][idx] <= 1;
tag[lru[idx]][idx] <= rtag;
data[lru[idx]][idx] <= mem_rdata_i;
lru[idx] <= lru[idx] + 1;
mem_req_o <= 0; refill_req <= 0;
end
end
end
endmodule
| 优化技术 | 效果 | 适用场景 |
|---|---|---|
| 行预取(Next-line Prefetch) | 命中率+5-10% | 顺序代码 |
| 分支目标缓冲(BTB) | 减少分支未命中 | 分支密集代码 |
| 非阻塞Cache | 减少停顿 | 多线程 |
| Way Prediction | 降低功耗 | 低功耗设计 |
| 临界字优先 | 减少Refill延迟 | 长Cache行 |