234 lines
8.2 KiB
Systemverilog
234 lines
8.2 KiB
Systemverilog
`include "VX_cache_define.vh"
|
|
|
|
module VX_miss_resrv #(
|
|
parameter CACHE_ID = 0,
|
|
parameter BANK_ID = 0,
|
|
|
|
// Number of Word requests per cycle
|
|
parameter NUM_REQS = 1,
|
|
|
|
// Size of line inside a bank in bytes
|
|
parameter CACHE_LINE_SIZE = 1,
|
|
// Number of banks
|
|
parameter NUM_BANKS = 1,
|
|
// Number of ports per banks
|
|
parameter NUM_PORTS = 1,
|
|
// Size of a word in bytes
|
|
parameter WORD_SIZE = 1,
|
|
// Miss Reserv Queue Knob
|
|
parameter MSHR_SIZE = 1,
|
|
// core request tag size
|
|
parameter CORE_TAG_WIDTH = 1,
|
|
|
|
parameter MSHR_ADDR_WIDTH = $clog2(MSHR_SIZE)
|
|
) (
|
|
input wire clk,
|
|
input wire reset,
|
|
|
|
`IGNORE_UNUSED_BEGIN
|
|
input wire[`DBG_CACHE_REQ_IDW-1:0] deq_req_id,
|
|
input wire[`DBG_CACHE_REQ_IDW-1:0] lkp_req_id,
|
|
input wire[`DBG_CACHE_REQ_IDW-1:0] rel_req_id,
|
|
`IGNORE_UNUSED_END
|
|
|
|
// allocate
|
|
input wire allocate_valid,
|
|
input wire [`LINE_ADDR_WIDTH-1:0] allocate_addr,
|
|
input wire [`MSHR_DATA_WIDTH-1:0] allocate_data,
|
|
output wire [MSHR_ADDR_WIDTH-1:0] allocate_id,
|
|
output wire allocate_ready,
|
|
|
|
// fill
|
|
input wire fill_valid,
|
|
input wire [MSHR_ADDR_WIDTH-1:0] fill_id,
|
|
output wire [`LINE_ADDR_WIDTH-1:0] fill_addr,
|
|
|
|
// lookup
|
|
input wire lookup_valid,
|
|
input wire lookup_replay,
|
|
input wire [MSHR_ADDR_WIDTH-1:0] lookup_id,
|
|
input wire [`LINE_ADDR_WIDTH-1:0] lookup_addr,
|
|
output wire lookup_match,
|
|
|
|
// dequeue
|
|
output wire dequeue_valid,
|
|
output wire [MSHR_ADDR_WIDTH-1:0] dequeue_id,
|
|
output wire [`LINE_ADDR_WIDTH-1:0] dequeue_addr,
|
|
output wire [`MSHR_DATA_WIDTH-1:0] dequeue_data,
|
|
input wire dequeue_ready,
|
|
|
|
// release
|
|
input wire release_valid,
|
|
input wire [MSHR_ADDR_WIDTH-1:0] release_id
|
|
);
|
|
`UNUSED_PARAM (CACHE_ID)
|
|
`UNUSED_PARAM (BANK_ID)
|
|
|
|
reg [MSHR_SIZE-1:0][`LINE_ADDR_WIDTH-1:0] addr_table, addr_table_n;
|
|
reg [MSHR_SIZE-1:0] valid_table, valid_table_n;
|
|
reg [MSHR_SIZE-1:0] ready_table, ready_table_n;
|
|
|
|
reg allocate_rdy_r, allocate_rdy_n;
|
|
reg [MSHR_ADDR_WIDTH-1:0] allocate_id_r, allocate_id_n;
|
|
|
|
reg dequeue_val_r, dequeue_val_n, dequeue_val_x;
|
|
reg [MSHR_ADDR_WIDTH-1:0] dequeue_id_r, dequeue_id_n, dequeue_id_x;
|
|
|
|
reg [MSHR_SIZE-1:0] valid_table_x;
|
|
reg [MSHR_SIZE-1:0] ready_table_x;
|
|
|
|
wire [MSHR_SIZE-1:0] addr_matches;
|
|
|
|
wire allocate_fire = allocate_valid && allocate_ready;
|
|
|
|
wire dequeue_fire = dequeue_valid && dequeue_ready;
|
|
|
|
for (genvar i = 0; i < MSHR_SIZE; ++i) begin
|
|
assign addr_matches[i] = (addr_table[i] == lookup_addr);
|
|
end
|
|
|
|
always @(*) begin
|
|
valid_table_x = valid_table;
|
|
ready_table_x = ready_table;
|
|
if (dequeue_fire) begin
|
|
valid_table_x[dequeue_id] = 0;
|
|
end
|
|
if (lookup_replay) begin
|
|
ready_table_x |= addr_matches;
|
|
end
|
|
end
|
|
|
|
VX_lzc #(
|
|
.N (MSHR_SIZE)
|
|
) dequeue_sel (
|
|
.in_i (valid_table_x & ready_table_x),
|
|
.cnt_o (dequeue_id_x),
|
|
.valid_o (dequeue_val_x)
|
|
);
|
|
|
|
VX_lzc #(
|
|
.N (MSHR_SIZE)
|
|
) allocate_sel (
|
|
.in_i (~valid_table_n),
|
|
.cnt_o (allocate_id_n),
|
|
.valid_o (allocate_rdy_n)
|
|
);
|
|
|
|
always @(*) begin
|
|
valid_table_n = valid_table_x;
|
|
ready_table_n = ready_table_x;
|
|
addr_table_n = addr_table;
|
|
dequeue_val_n = dequeue_val_r;
|
|
dequeue_id_n = dequeue_id_r;
|
|
|
|
if (dequeue_fire) begin
|
|
dequeue_val_n = dequeue_val_x;
|
|
dequeue_id_n = dequeue_id_x;
|
|
end
|
|
|
|
if (allocate_fire) begin
|
|
valid_table_n[allocate_id] = 1;
|
|
ready_table_n[allocate_id] = 0;
|
|
addr_table_n[allocate_id] = allocate_addr;
|
|
end
|
|
|
|
if (fill_valid) begin
|
|
dequeue_val_n = 1;
|
|
dequeue_id_n = fill_id;
|
|
end
|
|
|
|
if (release_valid) begin
|
|
valid_table_n[release_id] = 0;
|
|
end
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
valid_table <= 0;
|
|
allocate_rdy_r <= 0;
|
|
dequeue_val_r <= 0;
|
|
end else begin
|
|
valid_table <= valid_table_n;
|
|
allocate_rdy_r <= allocate_rdy_n;
|
|
dequeue_val_r <= dequeue_val_n;
|
|
end
|
|
ready_table <= ready_table_n;
|
|
addr_table <= addr_table_n;
|
|
dequeue_id_r <= dequeue_id_n;
|
|
allocate_id_r <= allocate_id_n;
|
|
|
|
`ASSERT(!allocate_fire || !valid_table[allocate_id_r], ("runtime error"));
|
|
`ASSERT(!release_valid || valid_table[release_id], ("runtime error"));
|
|
end
|
|
|
|
`RUNTIME_ASSERT((!allocate_fire || ~valid_table[allocate_id]), ("%t: *** cache%0d:%0d in-use allocation: addr=%0h, id=%0d", $time, CACHE_ID, BANK_ID,
|
|
`LINE_TO_BYTE_ADDR(allocate_addr, BANK_ID), allocate_id))
|
|
|
|
`RUNTIME_ASSERT((!fill_valid || valid_table[fill_id]), ("%t: *** cache%0d:%0d invalid fill: addr=%0h, id=%0d", $time, CACHE_ID, BANK_ID,
|
|
`LINE_TO_BYTE_ADDR(addr_table[fill_id], BANK_ID), fill_id))
|
|
|
|
VX_dp_ram #(
|
|
.DATAW (`MSHR_DATA_WIDTH),
|
|
.SIZE (MSHR_SIZE),
|
|
.LUTRAM (1)
|
|
) entries (
|
|
.clk (clk),
|
|
.waddr (allocate_id_r),
|
|
.raddr (dequeue_id_r),
|
|
.wren (allocate_valid),
|
|
.wdata (allocate_data),
|
|
.rdata (dequeue_data)
|
|
);
|
|
|
|
assign fill_addr = addr_table[fill_id];
|
|
|
|
assign allocate_ready = allocate_rdy_r;
|
|
assign allocate_id = allocate_id_r;
|
|
|
|
assign dequeue_valid = dequeue_val_r;
|
|
assign dequeue_id = dequeue_id_r;
|
|
assign dequeue_addr = addr_table[dequeue_id_r];
|
|
|
|
wire [MSHR_SIZE-1:0] lookup_entries;
|
|
for (genvar i = 0; i < MSHR_SIZE; ++i) begin
|
|
assign lookup_entries[i] = (i != lookup_id);
|
|
end
|
|
assign lookup_match = |(lookup_entries & valid_table & addr_matches);
|
|
|
|
`UNUSED_VAR (lookup_valid)
|
|
|
|
`ifdef DBG_TRACE_CACHE_MSHR
|
|
always @(posedge clk) begin
|
|
if (allocate_fire || fill_valid || dequeue_fire || lookup_replay || lookup_valid || release_valid) begin
|
|
if (allocate_fire)
|
|
dpi_trace("%d: cache%0d:%0d mshr-allocate: addr=%0h, id=%0d (#%0d)\n", $time, CACHE_ID, BANK_ID,
|
|
`LINE_TO_BYTE_ADDR(allocate_addr, BANK_ID), allocate_id, deq_req_id);
|
|
if (fill_valid)
|
|
dpi_trace("%d: cache%0d:%0d mshr-fill: addr=%0h, id=%0d, addr=%0h\n", $time, CACHE_ID, BANK_ID,
|
|
`LINE_TO_BYTE_ADDR(addr_table[fill_id], BANK_ID), fill_id, `LINE_TO_BYTE_ADDR(fill_addr, BANK_ID));
|
|
if (dequeue_fire)
|
|
dpi_trace("%d: cache%0d:%0d mshr-dequeue: addr=%0h, id=%0d (#%0d)\n", $time, CACHE_ID, BANK_ID,
|
|
`LINE_TO_BYTE_ADDR(dequeue_addr, BANK_ID), dequeue_id_r, deq_req_id);
|
|
if (lookup_replay)
|
|
dpi_trace("%d: cache%0d:%0d mshr-replay: addr=%0h, id=%0d (#%0d)\n", $time, CACHE_ID, BANK_ID,
|
|
`LINE_TO_BYTE_ADDR(lookup_addr, BANK_ID), lookup_id, lkp_req_id);
|
|
if (lookup_valid)
|
|
dpi_trace("%d: cache%0d:%0d mshr-lookup: addr=%0h, id=%0d, match=%b (#%0d)\n", $time, CACHE_ID, BANK_ID,
|
|
`LINE_TO_BYTE_ADDR(lookup_addr, BANK_ID), lookup_id, lookup_match, lkp_req_id);
|
|
if (release_valid)
|
|
dpi_trace("%d: cache%0d:%0d mshr-release id=%0d (#%0d)\n", $time, CACHE_ID, BANK_ID, release_id, rel_req_id);
|
|
dpi_trace("%d: cache%0d:%0d mshr-table", $time, CACHE_ID, BANK_ID);
|
|
for (integer i = 0; i < MSHR_SIZE; ++i) begin
|
|
if (valid_table[i]) begin
|
|
dpi_trace(" ");
|
|
if (ready_table[i])
|
|
dpi_trace("*");
|
|
dpi_trace("%0d=%0h", i, `LINE_TO_BYTE_ADDR(addr_table[i], BANK_ID));
|
|
end
|
|
end
|
|
dpi_trace("\n");
|
|
end
|
|
end
|
|
`endif
|
|
|
|
endmodule |