A prefetcher bets future addresses and spends bandwidth on each bet. Two ratios judge the bet: accuracy, the fraction of prefetches ever used, and coverage, the fraction of demand misses avoided.
Both ratios share one numerator, used prefetches. Accuracy divides by prefetches issued, coverage by demand misses that would occur without prefetching.
Metric | Numerator | Denominator |
|---|---|---|
Accuracy | Prefetches later demanded | Prefetches issued |
Coverage | Demand misses avoided | Demand misses without prefetching |
Pollution | Demand misses caused by prefetch evictions | Total demand misses |
A prefetch that evicts a live line before reuse causes a miss it was meant to prevent. That is pollution, and it shows up as demand misses on lines the cache once held.
A prefetch that arrives after the demand is merely late. It wastes bandwidth without helping latency, so distance and trigger matter as much as direction.
Demand | Result | Prefetch action |
|---|---|---|
100 | Miss | Fetch 100, prefetch 101 |
101 | Hit (prefetched) | Prefetch 102 |
0 | Miss | Fetch 0, prefetch 1 (evicts 100) |
1 | Hit (prefetched) | Prefetch 2 (evicts 101) |
2 | Hit (prefetched) | Prefetch 3 (evicts unused 102) |
3 | Hit (prefetched) | Prefetch 4 (evicts 0) |
100 | Miss (pollution) | Line 100 was evicted by prefetch 1 |
Walk totals for the 4-line cache above (7 demands):
hits: 4 (101, 1, 2, 3)
misses: 3 (100, 0, and 100 again)
issued: 6 prefetches (101, 102, 1, 2, 3, 4)
used: 4 (101, 1, 2, 3)
accuracy: 4 / 6 = 0.6667 ~ 67%
coverage: 4 avoided of 7 demands = 4 / 7 = 0.5714 ~ 57%
pollution: 1 of 3 misses caused by a prefetch evictionThe model below replays the walk on a 4-line FIFO cache with next-line prefetch and checks the counts above.
module pf_model (
output logic [31:0] hits,
output logic [31:0] misses,
output logic [31:0] pf_issued,
output logic [31:0] pf_used,
output logic [31:0] pollution
);
function automatic int get_dem(int i);
case (i)
0: return 100;
1: return 101;
2: return 0;
3: return 1;
4: return 2;
5: return 3;
default: return 100;
endcase
endfunction
always_comb begin
int cline[4];
bit cispf[4];
bit cdem[4];
int evlog[8];
int fill;
int evn;
int d;
int p;
int idx;
int k;
bit pfound;
hits = 0; misses = 0; pf_issued = 0; pf_used = 0; pollution = 0;
fill = 0; evn = 0;
for (int i = 0; i < 7; i++) begin
d = get_dem(i);
idx = -1;
for (k = 0; k < fill; k++) begin
if (cline[k] == d) idx = k;
end
if (idx == -1) begin
misses++;
for (k = 0; k < evn; k++) begin
if (evlog[k] == d) pollution++;
end
if (fill < 4) begin
cline[fill] = d; cispf[fill] = 1'b0; cdem[fill] = 1'b1; fill++;
end else begin
for (k = 0; k < 3; k++) begin
cline[k] = cline[k+1]; cispf[k] = cispf[k+1]; cdem[k] = cdem[k+1];
end
cline[3] = d; cispf[3] = 1'b0; cdem[3] = 1'b1;
end
end else begin
hits++;
if (cispf[idx]) begin
pf_used++;
cispf[idx] = 1'b0;
end
cdem[idx] = 1'b1;
end
if (i < 6) begin
p = d + 1;
pfound = 1'b0;
for (k = 0; k < fill; k++) begin
if (cline[k] == p) pfound = 1'b1;
end
if (!pfound) begin
pf_issued++;
if (fill < 4) begin
cline[fill] = p; cispf[fill] = 1'b1; cdem[fill] = 1'b0; fill++;
end else begin
if (cdem[0]) begin
evlog[evn] = cline[0]; evn++;
end
for (k = 0; k < 3; k++) begin
cline[k] = cline[k+1]; cispf[k] = cispf[k+1]; cdem[k] = cdem[k+1];
end
cline[3] = p; cispf[3] = 1'b1; cdem[3] = 1'b0;
end
end
end
end
end
endmodule
module tb_pf;
logic [31:0] hits, misses, pf_issued, pf_used, pollution;
int errors = 0;
pf_model dut (.*);
initial begin
#1;
if (hits !== 32'd4 || misses !== 32'd3) errors++;
if (pf_issued !== 32'd6 || pf_used !== 32'd4) errors++;
if (pollution !== 32'd1) errors++;
if (errors == 0) $display("PASS: next-line run gives 4 hits 3 misses 6 issued 4 used 1 pollution miss");
else $display("FAIL: %0d prefetch checks wrong", errors);
$finish;
end
endmoduleAccuracy is 4/6, about 67 percent. Coverage is 4/7, about 57 percent.
The first 100 installed on demand, a prefetch evicted it before reuse, and 100 appears in the eviction log at the second miss.