mirror of
https://github.com/vortexgpgpu/vortex.git
synced 2025-04-24 13:57:17 -04:00
202 lines
6.4 KiB
Systemverilog
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
|