Files
kernels/hw/rtl/cache/VX_cache_dram_req_arb.v
2020-05-04 20:12:05 -04:00

136 lines
4.9 KiB
Verilog

`include "VX_cache_config.vh"
module VX_cache_dram_req_arb #(
// Size of cache in bytes
parameter CACHE_SIZE = 1024,
// Size of line inside a bank in bytes
parameter BANK_LINE_SIZE = 16,
// Number of banks {1, 2, 4, 8,...}
parameter NUM_BANKS = 8,
// Size of a word in bytes
parameter WORD_SIZE = 4,
// Number of Word requests per cycle {1, 2, 4, 8, ...}
parameter NUM_REQUESTS = 2,
// Number of cycles to complete stage 1 (read from memory)
parameter STAGE_1_CYCLES = 2,
// Queues feeding into banks Knobs {1, 2, 4, 8, ...}
// Core Request Queue Size
parameter REQQ_SIZE = 8,
// Miss Reserv Queue Knob
parameter MRVQ_SIZE = 8,
// Dram Fill Rsp Queue Size
parameter DFPQ_SIZE = 2,
// Snoop Req Queue
parameter SNRQ_SIZE = 8,
// Queues for writebacks Knobs {1, 2, 4, 8, ...}
// Core Writeback Queue Size
parameter CWBQ_SIZE = 8,
// Dram Writeback Queue Size
parameter DWBQ_SIZE = 4,
// Dram Fill Req Queue Size
parameter DFQQ_SIZE = 8,
// Lower Level Cache Hit Queue Size
parameter LLVQ_SIZE = 16,
// Fill Invalidator Size {Fill invalidator must be active}
parameter FILL_INVALIDAOR_SIZE = 16,
// Prefetcher
parameter PRFQ_SIZE = 64,
parameter PRFQ_STRIDE = 2
) (
input wire clk,
input wire reset,
// Fill Request
input wire [NUM_BANKS-1:0] per_bank_dram_fill_req_valid,
input wire [NUM_BANKS-1:0][`DRAM_ADDR_WIDTH-1:0] per_bank_dram_fill_req_addr,
output wire dfqq_full,
// Writeback Request
input wire [NUM_BANKS-1:0] per_bank_dram_wb_req_valid,
input wire [NUM_BANKS-1:0][`DRAM_ADDR_WIDTH-1:0] per_bank_dram_wb_req_addr,
input wire [NUM_BANKS-1:0][`BANK_LINE_WORDS-1:0][`WORD_WIDTH-1:0] per_bank_dram_wb_req_data,
output wire [NUM_BANKS-1:0] per_bank_dram_wb_queue_pop,
// Merged Request
output wire dram_req_read,
output wire dram_req_write,
output wire [`DRAM_ADDR_WIDTH-1:0] dram_req_addr,
output wire [`BANK_LINE_WIDTH-1:0] dram_req_data,
input wire dram_req_ready
);
wire pref_pop;
wire pref_valid;
wire[`DRAM_ADDR_WIDTH-1:0] pref_addr;
wire dwb_valid;
wire dfqq_req;
assign pref_pop = !dwb_valid && !dfqq_req && dram_req_ready && pref_valid;
VX_prefetcher #(
.PRFQ_SIZE (PRFQ_SIZE),
.PRFQ_STRIDE (PRFQ_STRIDE),
.BANK_LINE_SIZE(BANK_LINE_SIZE),
.WORD_SIZE (WORD_SIZE)
) prfqq (
.clk (clk),
.reset (reset),
.dram_req (dram_req_read),
.dram_req_addr(dram_req_addr),
.pref_pop (pref_pop),
.pref_valid (pref_valid),
.pref_addr (pref_addr)
);
wire[`DRAM_ADDR_WIDTH-1:0] dfqq_req_addr;
`DEBUG_BEGIN
wire dfqq_empty;
`DEBUG_END
wire dfqq_pop = !dwb_valid && dfqq_req && dram_req_ready; // If no dwb, and dfqq has valids, then pop
wire dfqq_push = (|per_bank_dram_fill_req_valid);
VX_cache_dfq_queue cache_dfq_queue(
.clk (clk),
.reset (reset),
.dfqq_push (dfqq_push),
.per_bank_dram_fill_req_valid (per_bank_dram_fill_req_valid),
.per_bank_dram_fill_req_addr (per_bank_dram_fill_req_addr),
.dfqq_pop (dfqq_pop),
.dfqq_req (dfqq_req),
.dfqq_req_addr (dfqq_req_addr),
.dfqq_empty (dfqq_empty),
.dfqq_full (dfqq_full)
);
wire [`LOG2UP(NUM_BANKS)-1:0] dwb_bank;
wire [NUM_BANKS-1:0] use_wb_valid = per_bank_dram_wb_req_valid;
VX_generic_priority_encoder #(
.N(NUM_BANKS)
) sel_dwb (
.valids(use_wb_valid),
.index (dwb_bank),
.found (dwb_valid)
);
assign per_bank_dram_wb_queue_pop = dram_req_ready ? (use_wb_valid & ((1 << dwb_bank))) : 0;
wire dram_req_valid = dwb_valid || dfqq_req || pref_pop;
assign dram_req_read = ((dfqq_req && !dwb_valid) || pref_pop) && dram_req_valid;
assign dram_req_write = dwb_valid && dram_req_valid;
assign dram_req_addr = dwb_valid ? per_bank_dram_wb_req_addr[dwb_bank] : (dfqq_req ? dfqq_req_addr : pref_addr);
assign {dram_req_data} = dwb_valid ? {per_bank_dram_wb_req_data[dwb_bank] }: 0;
endmodule