vortex/hw/rtl/cache/VX_cache_repl.sv
2024-10-24 01:44:55 -07:00

202 lines
6.4 KiB
Systemverilog

// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
`include "VX_cache_define.vh"
// Fast PLRU encoder and decoder utility
// Adapted from BaseJump STL: http://bjump.org/data_out.html
module plru_decoder #(
parameter NUM_WAYS = 1,
parameter WAY_IDX_BITS = $clog2(NUM_WAYS),
parameter WAY_IDX_WIDTH = `UP(WAY_IDX_BITS)
) (
input wire [WAY_IDX_WIDTH-1:0] way_idx,
output wire [`UP(NUM_WAYS-1)-1:0] lru_data,
output wire [`UP(NUM_WAYS-1)-1:0] lru_mask
);
if (NUM_WAYS > 1) begin : g_dec
wire [`UP(NUM_WAYS-1)-1:0] data;
`IGNORE_UNOPTFLAT_BEGIN
wire [`UP(NUM_WAYS-1)-1:0] mask;
`IGNORE_UNOPTFLAT_END
for (genvar i = 0; i < NUM_WAYS-1; ++i) begin : g_i
if (i == 0) begin : g_i_0
assign mask[i] = 1'b1;
end else if (i % 2 == 1) begin : g_i_odd
assign mask[i] = mask[(i-1)/2] & ~way_idx[WAY_IDX_BITS-$clog2(i+2)+1];
end else begin : g_i_even
assign mask[i] = mask[(i-2)/2] & way_idx[WAY_IDX_BITS-$clog2(i+2)+1];
end
assign data[i] = ~way_idx[WAY_IDX_BITS-$clog2(i+2)];
end
assign lru_data = data;
assign lru_mask = mask;
end else begin : g_no_dec
`UNUSED_VAR (way_idx)
assign lru_data = '0;
assign lru_mask = '0;
end
endmodule
module plru_encoder #(
parameter NUM_WAYS = 1,
parameter WAY_IDX_BITS = $clog2(NUM_WAYS),
parameter WAY_IDX_WIDTH = `UP(WAY_IDX_BITS)
) (
input wire [`UP(NUM_WAYS-1)-1:0] lru_in,
output wire [WAY_IDX_WIDTH-1:0] way_idx
);
if (NUM_WAYS > 1) begin : g_enc
wire [WAY_IDX_BITS-1:0] tmp;
for (genvar i = 0; i < WAY_IDX_BITS; ++i) begin : g_i
if (i == 0) begin : g_i_0
assign tmp[WAY_IDX_WIDTH-1] = lru_in[0];
end else begin : g_i_n
VX_mux #(
.N (2**i)
) mux (
.data_in (lru_in[((2**i)-1)+:(2**i)]),
.sel_in (tmp[WAY_IDX_BITS-1-:i]),
.data_out (tmp[WAY_IDX_BITS-1-i])
);
end
end
assign way_idx = tmp;
end else begin : g_no_enc
`UNUSED_VAR (lru_in)
assign way_idx = '0;
end
endmodule
module VX_cache_repl #(
parameter CACHE_SIZE = 1024,
// Size of line inside a bank in bytes
parameter LINE_SIZE = 64,
// Number of banks
parameter NUM_BANKS = 1,
// Number of associative ways
parameter NUM_WAYS = 1,
// replacement policy
parameter REPL_POLICY = `CS_REPL_CYCLIC
) (
input wire clk,
input wire reset,
input wire stall,
input wire hit_valid,
input wire [`CS_LINE_SEL_BITS-1:0] hit_line,
input wire [`CS_WAY_SEL_WIDTH-1:0] hit_way,
input wire repl_valid,
input wire [`CS_LINE_SEL_BITS-1:0] repl_line,
output wire [`CS_WAY_SEL_WIDTH-1:0] repl_way
);
localparam WAY_SEL_WIDTH = `CS_WAY_SEL_WIDTH;
`UNUSED_VAR (stall)
if (NUM_WAYS > 1) begin : g_enable
if (REPL_POLICY == `CS_REPL_PLRU) begin : g_plru
// Pseudo Least Recently Used replacement policy
localparam LRU_WIDTH = `UP(NUM_WAYS-1);
wire [LRU_WIDTH-1:0] plru_rdata;
wire [LRU_WIDTH-1:0] plru_wdata;
wire [LRU_WIDTH-1:0] plru_wmask;
VX_dp_ram #(
.DATAW (LRU_WIDTH),
.SIZE (`CS_LINES_PER_BANK),
.WRENW (LRU_WIDTH),
.RDW_MODE ("R")
) plru_store (
.clk (clk),
.reset (reset),
.read (repl_valid),
.write (hit_valid),
.wren (plru_wmask),
.waddr (hit_line),
.raddr (repl_line),
.wdata (plru_wdata),
.rdata (plru_rdata)
);
plru_decoder #(
.NUM_WAYS (NUM_WAYS)
) plru_dec (
.way_idx (hit_way),
.lru_data (plru_wdata),
.lru_mask (plru_wmask)
);
plru_encoder #(
.NUM_WAYS (NUM_WAYS)
) plru_enc (
.lru_in (plru_rdata),
.way_idx (repl_way)
);
end else if (REPL_POLICY == `CS_REPL_CYCLIC) begin : g_cyclic
// Cyclic replacement policy
`UNUSED_VAR (hit_valid)
`UNUSED_VAR (hit_line)
`UNUSED_VAR (hit_way)
wire [WAY_SEL_WIDTH-1:0] ctr_rdata;
wire [WAY_SEL_WIDTH-1:0] ctr_wdata = ctr_rdata + 1;
VX_sp_ram #(
.DATAW (WAY_SEL_WIDTH),
.SIZE (`CS_LINES_PER_BANK),
.RDW_MODE ("R")
) ctr_store (
.clk (clk),
.reset (reset),
.read (repl_valid),
.write (repl_valid),
.wren (1'b1),
.addr (repl_line),
.wdata (ctr_wdata),
.rdata (ctr_rdata)
);
assign repl_way = ctr_rdata;
end else begin : g_random
// Random replacement policy
`UNUSED_VAR (hit_valid)
`UNUSED_VAR (hit_line)
`UNUSED_VAR (hit_way)
`UNUSED_VAR (repl_valid)
`UNUSED_VAR (repl_line)
reg [WAY_SEL_WIDTH-1:0] victim_idx;
always @(posedge clk) begin
if (reset) begin
victim_idx <= 0;
end else if (~stall) begin
victim_idx <= victim_idx + 1;
end
end
assign repl_way = victim_idx;
end
end else begin : g_disable
`UNUSED_VAR (clk)
`UNUSED_VAR (reset)
`UNUSED_VAR (hit_valid)
`UNUSED_VAR (hit_line)
`UNUSED_VAR (hit_way)
`UNUSED_VAR (repl_valid)
`UNUSED_VAR (repl_line)
assign repl_way = 1'b0;
end
endmodule