cache_subsystem: Parametrise AXI interface (#982)

Parametrise the AXI interface of CVA6. With this PR, both cache subsystems support variable AXI address widths. The write-through cache furthermore supports variable AXI data widths. Moreover, this PR includes a modular AXI testbench for the WT cache to test the introduced changes. The following configurations of the WT cache have been verified:

XLEN   Cacheline Width   AXI data width   AXI address width
64                  128                     64                       64
64                  128                   128                       52
64                  512                   128                       64
32                  512                   256                       48
32                    64                     32                       48
This commit is contained in:
Nils Wistoff 2022-10-26 11:20:19 +02:00 committed by GitHub
parent f346d6604f
commit 17743bc712
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 1787 additions and 185 deletions

View file

@ -19,8 +19,12 @@
module axi_adapter #(
parameter int unsigned DATA_WIDTH = 256,
parameter logic CRITICAL_WORD_FIRST = 0, // the AXI subsystem needs to support wrapping reads for this feature
parameter int unsigned AXI_ID_WIDTH = 10,
parameter int unsigned CACHELINE_BYTE_OFFSET = 8
parameter int unsigned CACHELINE_BYTE_OFFSET = 8,
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned AXI_ID_WIDTH = 0,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
@ -31,23 +35,23 @@ module axi_adapter #(
output logic gnt_o,
input logic [riscv::XLEN-1:0] addr_i,
input logic we_i,
input logic [(DATA_WIDTH/riscv::XLEN)-1:0][riscv::XLEN-1:0] wdata_i,
input logic [(DATA_WIDTH/riscv::XLEN)-1:0][(riscv::XLEN/8)-1:0] be_i,
input logic [(DATA_WIDTH/AXI_DATA_WIDTH)-1:0][AXI_DATA_WIDTH-1:0] wdata_i,
input logic [(DATA_WIDTH/AXI_DATA_WIDTH)-1:0][(AXI_DATA_WIDTH/8)-1:0] be_i,
input logic [1:0] size_i,
input logic [AXI_ID_WIDTH-1:0] id_i,
// read port
output logic valid_o,
output logic [(DATA_WIDTH/riscv::XLEN)-1:0][riscv::XLEN-1:0] rdata_o,
output logic [(DATA_WIDTH/AXI_DATA_WIDTH)-1:0][AXI_DATA_WIDTH-1:0] rdata_o,
output logic [AXI_ID_WIDTH-1:0] id_o,
// critical word - read port
output logic [riscv::XLEN-1:0] critical_word_o,
output logic [AXI_DATA_WIDTH-1:0] critical_word_o,
output logic critical_word_valid_o,
// AXI port
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i
output axi_req_t axi_req_o,
input axi_rsp_t axi_resp_i
);
localparam BURST_SIZE = DATA_WIDTH/riscv::XLEN-1;
localparam ADDR_INDEX = ($clog2(DATA_WIDTH/riscv::XLEN) > 0) ? $clog2(DATA_WIDTH/riscv::XLEN) : 1;
localparam BURST_SIZE = (DATA_WIDTH/AXI_DATA_WIDTH)-1;
localparam ADDR_INDEX = ($clog2(DATA_WIDTH/AXI_DATA_WIDTH) > 0) ? $clog2(DATA_WIDTH/AXI_DATA_WIDTH) : 1;
enum logic [3:0] {
IDLE, WAIT_B_VALID, WAIT_AW_READY, WAIT_LAST_W_READY, WAIT_LAST_W_READY_AW_READY, WAIT_AW_READY_BURST,
@ -56,9 +60,9 @@ module axi_adapter #(
// counter for AXI transfers
logic [ADDR_INDEX-1:0] cnt_d, cnt_q;
logic [(DATA_WIDTH/riscv::XLEN)-1:0][riscv::XLEN-1:0] cache_line_d, cache_line_q;
logic [(DATA_WIDTH/AXI_DATA_WIDTH)-1:0][AXI_DATA_WIDTH-1:0] cache_line_d, cache_line_q;
// save the address for a read, as we allow for non-cacheline aligned accesses
logic [(DATA_WIDTH/riscv::XLEN)-1:0] addr_offset_d, addr_offset_q;
logic [(DATA_WIDTH/AXI_DATA_WIDTH)-1:0] addr_offset_d, addr_offset_q;
logic [AXI_ID_WIDTH-1:0] id_d, id_q;
logic [ADDR_INDEX-1:0] index;
// save the atomic operation and size
@ -68,6 +72,7 @@ module axi_adapter #(
always_comb begin : axi_fsm
// Default assignments
axi_req_o.aw_valid = 1'b0;
// Cast to AXI address width
axi_req_o.aw.addr = addr_i;
axi_req_o.aw.prot = 3'b0;
axi_req_o.aw.region = 4'b0;
@ -82,9 +87,13 @@ module axi_adapter #(
axi_req_o.aw.user = '0;
axi_req_o.ar_valid = 1'b0;
// Cast to AXI address width
axi_req_o.ar.addr = addr_i;
// in case of a single request or wrapping transfer we can simply begin at the address, if we want to request a cache-line
// with an incremental transfer we need to output the corresponding base address of the cache line
axi_req_o.ar.addr = (CRITICAL_WORD_FIRST || type_i == ariane_axi::SINGLE_REQ) ? addr_i : { addr_i[(riscv::XLEN-1):CACHELINE_BYTE_OFFSET], {{CACHELINE_BYTE_OFFSET}{1'b0}}};
if (!CRITICAL_WORD_FIRST && type_i != ariane_axi::SINGLE_REQ) begin
axi_req_o.ar.addr[CACHELINE_BYTE_OFFSET-1:0] = '0;
end
axi_req_o.ar.prot = 3'b0;
axi_req_o.ar.region = 4'b0;
axi_req_o.ar.len = 8'b0;

View file

@ -22,7 +22,11 @@
module axi_shim #(
parameter int unsigned AxiUserWidth = 64, // data width in dwords, this is also the maximum burst length, must be >=2
parameter int unsigned AxiNumWords = 4, // data width in dwords, this is also the maximum burst length, must be >=2
parameter int unsigned AxiIdWidth = 4 // stick to the spec
parameter int unsigned AxiAddrWidth = 0,
parameter int unsigned AxiDataWidth = 0,
parameter int unsigned AxiIdWidth = 0,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
) (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
@ -30,28 +34,28 @@ module axi_shim #(
// request
input logic rd_req_i,
output logic rd_gnt_o,
input logic [63:0] rd_addr_i,
input logic [AxiAddrWidth-1:0] rd_addr_i,
input logic [$clog2(AxiNumWords)-1:0] rd_blen_i, // axi convention: LEN-1
input logic [1:0] rd_size_i,
input logic [2:0] rd_size_i,
input logic [AxiIdWidth-1:0] rd_id_i, // use same ID for reads, or make sure you only have one outstanding read tx
input logic rd_lock_i,
// read response (we have to unconditionally sink the response)
input logic rd_rdy_i,
output logic rd_last_o,
output logic rd_valid_o,
output logic [63:0] rd_data_o,
output logic [AxiDataWidth-1:0] rd_data_o,
output logic [AxiUserWidth-1:0] rd_user_o,
output logic [AxiIdWidth-1:0] rd_id_o,
output logic rd_exokay_o, // indicates whether exclusive tx succeeded
// write channel
input logic wr_req_i,
output logic wr_gnt_o,
input logic [63:0] wr_addr_i,
input logic [AxiNumWords-1:0][63:0] wr_data_i,
input logic [AxiNumWords-1:0][AxiUserWidth-1:0] wr_user_i,
input logic [AxiNumWords-1:0][7:0] wr_be_i,
input logic [AxiAddrWidth-1:0] wr_addr_i,
input logic [AxiNumWords-1:0][AxiDataWidth-1:0] wr_data_i,
input logic [AxiNumWords-1:0][AxiUserWidth-1:0] wr_user_i,
input logic [AxiNumWords-1:0][(AxiDataWidth/8)-1:0] wr_be_i,
input logic [$clog2(AxiNumWords)-1:0] wr_blen_i, // axi convention: LEN-1
input logic [1:0] wr_size_i,
input logic [2:0] wr_size_i,
input logic [AxiIdWidth-1:0] wr_id_i,
input logic wr_lock_i,
input logic [5:0] wr_atop_i,
@ -61,8 +65,8 @@ module axi_shim #(
output logic [AxiIdWidth-1:0] wr_id_o,
output logic wr_exokay_o, // indicates whether exclusive tx succeeded
// AXI port
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i
output axi_req_t axi_req_o,
input axi_rsp_t axi_resp_i
);
localparam AddrIndex = ($clog2(AxiNumWords) > 0) ? $clog2(AxiNumWords) : 1;
@ -82,7 +86,7 @@ module axi_shim #(
// address
assign axi_req_o.aw.burst = axi_pkg::BURST_INCR; // Use BURST_INCR for AXI regular transaction
assign axi_req_o.aw.addr = wr_addr_i;
assign axi_req_o.aw.addr = wr_addr_i[AxiAddrWidth-1:0];
assign axi_req_o.aw.size = wr_size_i;
assign axi_req_o.aw.len = wr_blen_i;
assign axi_req_o.aw.id = wr_id_i;
@ -92,6 +96,8 @@ module axi_shim #(
assign axi_req_o.aw.cache = 4'b0;
assign axi_req_o.aw.qos = 4'b0;
assign axi_req_o.aw.atop = wr_atop_i;
assign axi_req_o.aw.user = '0;
// data
assign axi_req_o.w.data = wr_data_i[wr_cnt_q];
assign axi_req_o.w.user = wr_user_i[wr_cnt_q];
@ -239,7 +245,7 @@ module axi_shim #(
// in case of a wrapping transfer we can simply begin at the address, if we want to request a cache-line
// with an incremental transfer we need to output the corresponding base address of the cache line
assign axi_req_o.ar.burst = axi_pkg::BURST_INCR; // Use BURST_INCR for AXI regular transaction
assign axi_req_o.ar.addr = rd_addr_i;
assign axi_req_o.ar.addr = rd_addr_i[AxiAddrWidth-1:0];
assign axi_req_o.ar.size = rd_size_i;
assign axi_req_o.ar.len = rd_blen_i;
assign axi_req_o.ar.id = rd_id_i;
@ -248,6 +254,7 @@ module axi_shim #(
assign axi_req_o.ar.lock = rd_lock_i;
assign axi_req_o.ar.cache = 4'b0;
assign axi_req_o.ar.qos = 4'b0;
assign axi_req_o.ar.user = '0;
// make the read request
assign axi_req_o.ar_valid = rd_req_i;
@ -285,7 +292,9 @@ module axi_shim #(
`ifndef VERILATOR
initial begin
assert (AxiNumWords >= 1) else
$fatal(1,"[axi adapter] AxiNumWords must be >= 1");
$fatal(1, "[axi adapter] AxiNumWords must be >= 1");
assert (AxiIdWidth >= 2) else
$fatal(1, "[axi adapter] AXI id width must be at least 2 bit wide");
end
`endif
//pragma translate_on

View file

@ -201,11 +201,7 @@ module cache_ctrl import ariane_pkg::*; import std_cache_pkg::*; #(
end
// this is timing critical
// req_port_o.data_rdata = cl_i[cl_offset +: 64];
case (mem_req_q.index[3])
1'b0: req_port_o.data_rdata = cl_i[63:0];
1'b1: req_port_o.data_rdata = cl_i[127:64];
endcase
req_port_o.data_rdata = cl_i[cl_offset +: 64];
// report data for a read
if (!mem_req_q.we) begin

View file

@ -116,7 +116,7 @@ module cva6_icache import ariane_pkg::*; import wt_cache_pkg::*; #(
assign cl_index = vaddr_d[ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH];
if (ArianeCfg.Axi64BitCompliant) begin : gen_axi_offset
if (ArianeCfg.AxiCompliant) begin : gen_axi_offset
// if we generate a noncacheable access, the word will be at offset 0 or 4 in the cl coming from memory
assign cl_offset_d = ( dreq_o.ready & dreq_i.req) ? {dreq_i.vaddr>>2, 2'b0} :
( paddr_is_nc & mem_data_req_o ) ? cl_offset_q[2]<<2 : // needed since we transfer 32bit over a 64bit AXI bus in this case

View file

@ -14,7 +14,12 @@
//
module cva6_icache_axi_wrapper import ariane_pkg::*; import wt_cache_pkg::*; #(
parameter ariane_cfg_t ArianeCfg = ArianeDefaultConfig // contains cacheable regions
parameter ariane_cfg_t ArianeCfg = ArianeDefaultConfig, // contains cacheable regions
parameter int unsigned AxiAddrWidth = 0,
parameter int unsigned AxiDataWidth = 0,
parameter int unsigned AxiIdWidth = 0,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
) (
input logic clk_i,
input logic rst_ni,
@ -30,12 +35,12 @@ module cva6_icache_axi_wrapper import ariane_pkg::*; import wt_cache_pkg::*; #(
input icache_dreq_i_t dreq_i,
output icache_dreq_o_t dreq_o,
// AXI refill port
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i
output axi_req_t axi_req_o,
input axi_rsp_t axi_resp_i
);
localparam AxiNumWords = (ICACHE_LINE_WIDTH/64) * (ICACHE_LINE_WIDTH > DCACHE_LINE_WIDTH) +
(DCACHE_LINE_WIDTH/64) * (ICACHE_LINE_WIDTH <= DCACHE_LINE_WIDTH) ;
localparam AxiNumWords = (ICACHE_LINE_WIDTH/AxiDataWidth) * (ICACHE_LINE_WIDTH > DCACHE_LINE_WIDTH) +
(DCACHE_LINE_WIDTH/AxiDataWidth) * (ICACHE_LINE_WIDTH <= DCACHE_LINE_WIDTH) ;
logic icache_mem_rtrn_vld;
icache_rtrn_t icache_mem_rtrn;
@ -47,20 +52,20 @@ module cva6_icache_axi_wrapper import ariane_pkg::*; import wt_cache_pkg::*; #(
logic axi_rd_gnt;
logic [63:0] axi_rd_addr;
logic [$clog2(AxiNumWords)-1:0] axi_rd_blen;
logic [1:0] axi_rd_size;
logic [2:0] axi_rd_size;
logic [$size(axi_resp_i.r.id)-1:0] axi_rd_id_in;
logic axi_rd_rdy;
logic axi_rd_lock;
logic axi_rd_last;
logic axi_rd_valid;
logic [63:0] axi_rd_data;
logic [AxiDataWidth-1:0] axi_rd_data;
logic [$size(axi_resp_i.r.id)-1:0] axi_rd_id_out;
logic axi_rd_exokay;
logic req_valid_d, req_valid_q;
icache_req_t req_data_d, req_data_q;
logic first_d, first_q;
logic [ICACHE_LINE_WIDTH/64-1:0][63:0] rd_shift_d, rd_shift_q;
logic [ICACHE_LINE_WIDTH/AxiDataWidth-1:0][AxiDataWidth-1:0] rd_shift_d, rd_shift_q;
// Keep read request asserted until we have an AXI grant. This is not guaranteed by icache (but
// required by AXI).
@ -75,7 +80,7 @@ module cva6_icache_axi_wrapper import ariane_pkg::*; import wt_cache_pkg::*; #(
// Fetch a full cache line on a cache miss, or a single word on a bypassed access
assign axi_rd_blen = (req_data_d.nc) ? '0 : ariane_pkg::ICACHE_LINE_WIDTH/64-1;
assign axi_rd_size = 2'b11;
assign axi_rd_size = $clog2(AxiDataWidth/8); // Maximum
assign axi_rd_id_in = req_data_d.tid;
assign axi_rd_rdy = 1'b1;
assign axi_rd_lock = 1'b0;
@ -118,9 +123,13 @@ module cva6_icache_axi_wrapper import ariane_pkg::*; import wt_cache_pkg::*; #(
// AXI shim
// --------
axi_shim #(
.AxiUserWidth ( AXI_USER_WIDTH ),
.AxiNumWords ( AxiNumWords ),
.AxiIdWidth ( $size(axi_resp_i.r.id) )
.AxiNumWords ( AxiNumWords ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.AxiIdWidth ( AxiIdWidth ),
.AxiUserWidth ( AXI_USER_WIDTH ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_axi_shim (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
@ -164,7 +173,11 @@ module cva6_icache_axi_wrapper import ariane_pkg::*; import wt_cache_pkg::*; #(
if (axi_rd_valid) begin
first_d = axi_rd_last;
rd_shift_d = {axi_rd_data, rd_shift_q[ICACHE_LINE_WIDTH/64-1:1]};
if (ICACHE_LINE_WIDTH == AxiDataWidth) begin
rd_shift_d = axi_rd_data;
end else begin
rd_shift_d = {axi_rd_data, rd_shift_q[ICACHE_LINE_WIDTH/AxiDataWidth-1:1]};
end
// If this is a single word transaction, we need to make sure that word is placed at offset 0
if (first_q) begin

View file

@ -17,7 +17,12 @@
// --------------
module miss_handler import ariane_pkg::*; import std_cache_pkg::*; #(
parameter int unsigned NR_PORTS = 3
parameter int unsigned NR_PORTS = 3,
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned AXI_ID_WIDTH = 0,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
)(
input logic clk_i,
input logic rst_ni,
@ -33,8 +38,8 @@ module miss_handler import ariane_pkg::*; import std_cache_pkg::*; #(
output logic [NR_PORTS-1:0][63:0] bypass_data_o,
// AXI port
output ariane_axi::req_t axi_bypass_o,
input ariane_axi::resp_t axi_bypass_i,
output axi_req_t axi_bypass_o,
input axi_rsp_t axi_bypass_i,
// Miss handling (~> cacheline refill)
output logic [NR_PORTS-1:0] miss_gnt_o,
@ -42,8 +47,8 @@ module miss_handler import ariane_pkg::*; import std_cache_pkg::*; #(
output logic [63:0] critical_word_o,
output logic critical_word_valid_o,
output ariane_axi::req_t axi_data_o,
input ariane_axi::resp_t axi_data_i,
output axi_req_t axi_data_o,
input axi_rsp_t axi_data_i,
input logic [NR_PORTS-1:0][55:0] mshr_addr_i,
output logic [NR_PORTS-1:0] mshr_addr_matches_o,
@ -559,18 +564,26 @@ module miss_handler import ariane_pkg::*; import std_cache_pkg::*; #(
// ----------------------
// Bypass AXI Interface
// ----------------------
// Cast bypass_adapter_req.addr to axi_adapter port size
logic [riscv::XLEN-1:0] bypass_addr;
assign bypass_addr = bypass_adapter_req.addr;
axi_adapter #(
.DATA_WIDTH (64),
.AXI_ID_WIDTH (4),
.CACHELINE_BYTE_OFFSET(DCACHE_BYTE_OFFSET)
.DATA_WIDTH ( 64 ),
.CACHELINE_BYTE_OFFSET ( DCACHE_BYTE_OFFSET ),
.AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_bypass_axi_adapter (
.clk_i (clk_i),
.rst_ni (rst_ni),
.req_i (bypass_adapter_req.req),
.type_i (bypass_adapter_req.reqtype),
.amo_i (bypass_adapter_req.amo),
.id_i (bypass_adapter_req.id),
.addr_i (bypass_adapter_req.addr),
.id_i (({{AXI_ID_WIDTH-4{1'b0}}, bypass_adapter_req.id})),
.addr_i (bypass_addr),
.wdata_i (bypass_adapter_req.wdata),
.we_i (bypass_adapter_req.we),
.be_i (bypass_adapter_req.be),
@ -588,10 +601,18 @@ module miss_handler import ariane_pkg::*; import std_cache_pkg::*; #(
// ----------------------
// Cache Line AXI Refill
// ----------------------
// Cast req_fsm_miss_addr to axi_adapter port size
logic [riscv::XLEN-1:0] miss_addr;
assign miss_addr = req_fsm_miss_addr;
axi_adapter #(
.DATA_WIDTH ( DCACHE_LINE_WIDTH ),
.AXI_ID_WIDTH ( 4 ),
.CACHELINE_BYTE_OFFSET ( DCACHE_BYTE_OFFSET )
.CACHELINE_BYTE_OFFSET ( DCACHE_BYTE_OFFSET ),
.AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_miss_axi_adapter (
.clk_i,
.rst_ni,
@ -599,12 +620,12 @@ module miss_handler import ariane_pkg::*; import std_cache_pkg::*; #(
.type_i ( req_fsm_miss_req ),
.amo_i ( AMO_NONE ),
.gnt_o ( gnt_miss_fsm ),
.addr_i ( req_fsm_miss_addr ),
.addr_i ( miss_addr ),
.we_i ( req_fsm_miss_we ),
.wdata_i ( req_fsm_miss_wdata ),
.be_i ( req_fsm_miss_be ),
.size_i ( req_fsm_miss_size ),
.id_i ( 4'b1100 ),
.id_i ( {{AXI_ID_WIDTH-4{1'b0}}, 4'b1100} ),
.valid_o ( valid_miss_fsm ),
.rdata_o ( data_miss_fsm ),
.id_o ( ),

View file

@ -16,7 +16,15 @@
module std_cache_subsystem import ariane_pkg::*; import std_cache_pkg::*; #(
parameter ariane_cfg_t ArianeCfg = ArianeDefaultConfig // contains cacheable regions
parameter ariane_cfg_t ArianeCfg = ArianeDefaultConfig, // contains cacheable regions
parameter int unsigned AxiAddrWidth = 0,
parameter int unsigned AxiDataWidth = 0,
parameter int unsigned AxiIdWidth = 0,
parameter type axi_ar_chan_t = ariane_axi::ar_chan_t,
parameter type axi_aw_chan_t = ariane_axi::aw_chan_t,
parameter type axi_w_chan_t = ariane_axi::w_chan_t,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
) (
input logic clk_i,
input logic rst_ni,
@ -45,21 +53,26 @@ module std_cache_subsystem import ariane_pkg::*; import std_cache_pkg::*; #(
input dcache_req_i_t [2:0] dcache_req_ports_i, // to/from LSU
output dcache_req_o_t [2:0] dcache_req_ports_o, // to/from LSU
// memory side
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i
output axi_req_t axi_req_o,
input axi_rsp_t axi_resp_i
);
assign wbuffer_empty_o = 1'b1;
ariane_axi::req_t axi_req_icache;
ariane_axi::resp_t axi_resp_icache;
ariane_axi::req_t axi_req_bypass;
ariane_axi::resp_t axi_resp_bypass;
ariane_axi::req_t axi_req_data;
ariane_axi::resp_t axi_resp_data;
axi_req_t axi_req_icache;
axi_rsp_t axi_resp_icache;
axi_req_t axi_req_bypass;
axi_rsp_t axi_resp_bypass;
axi_req_t axi_req_data;
axi_rsp_t axi_resp_data;
cva6_icache_axi_wrapper #(
.ArianeCfg ( ArianeCfg )
.ArianeCfg ( ArianeCfg ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.AxiIdWidth ( AxiIdWidth ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_cva6_icache_axi_wrapper (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
@ -80,7 +93,12 @@ module std_cache_subsystem import ariane_pkg::*; import std_cache_pkg::*; #(
// Port 1: Load Unit
// Port 2: Store Unit
std_nbdcache #(
.ArianeCfg ( ArianeCfg )
.ArianeCfg ( ArianeCfg ),
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_ID_WIDTH ( AxiIdWidth ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_nbdcache (
.clk_i,
.rst_ni,
@ -107,7 +125,7 @@ module std_cache_subsystem import ariane_pkg::*; import std_cache_pkg::*; #(
// AR Channel
stream_arbiter #(
.DATA_T ( ariane_axi::ar_chan_t ),
.DATA_T ( axi_ar_chan_t ),
.N_INP ( 3 )
) i_stream_arbiter_ar (
.clk_i,
@ -122,7 +140,7 @@ module std_cache_subsystem import ariane_pkg::*; import std_cache_pkg::*; #(
// AW Channel
stream_arbiter #(
.DATA_T ( ariane_axi::aw_chan_t ),
.DATA_T ( axi_aw_chan_t ),
.N_INP ( 3 )
) i_stream_arbiter_aw (
.clk_i,
@ -174,7 +192,7 @@ module std_cache_subsystem import ariane_pkg::*; import std_cache_pkg::*; #(
assign w_select_arbiter = (w_fifo_empty) ? 0 : w_select_fifo;
stream_mux #(
.DATA_T ( ariane_axi::w_chan_t ),
.DATA_T ( axi_w_chan_t ),
.N_INP ( 3 )
) i_stream_mux_w (
.inp_data_i ( {axi_req_data.w, axi_req_bypass.w, axi_req_icache.w} ),

View file

@ -14,7 +14,12 @@
module std_nbdcache import std_cache_pkg::*; import ariane_pkg::*; #(
parameter ariane_cfg_t ArianeCfg = ArianeDefaultConfig // contains cacheable regions
parameter ariane_cfg_t ArianeCfg = ArianeDefaultConfig, // contains cacheable regions
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned AXI_ID_WIDTH = 0,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
@ -30,10 +35,10 @@ module std_nbdcache import std_cache_pkg::*; import ariane_pkg::*; #(
input dcache_req_i_t [2:0] req_ports_i, // request ports
output dcache_req_o_t [2:0] req_ports_o, // request ports
// Cache AXI refill port
output ariane_axi::req_t axi_data_o,
input ariane_axi::resp_t axi_data_i,
output ariane_axi::req_t axi_bypass_o,
input ariane_axi::resp_t axi_bypass_i
output axi_req_t axi_data_o,
input axi_rsp_t axi_data_i,
output axi_req_t axi_bypass_o,
input axi_rsp_t axi_bypass_i
);
import std_cache_pkg::*;
@ -127,7 +132,12 @@ import std_cache_pkg::*;
// Miss Handling Unit
// ------------------
miss_handler #(
.NR_PORTS ( 3 )
.NR_PORTS ( 3 ),
.AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_miss_handler (
.flush_i ( flush_i ),
.busy_i ( |busy ),
@ -261,8 +271,7 @@ import std_cache_pkg::*;
//pragma translate_off
initial begin
assert ($bits(axi_data_o.aw.addr) == 64) else $fatal(1, "Ariane needs a 64-bit bus");
assert (DCACHE_LINE_WIDTH/64 inside {2, 4, 8, 16}) else $fatal(1, "Cache line size needs to be a power of two multiple of 64");
assert (DCACHE_LINE_WIDTH/AXI_DATA_WIDTH inside {2, 4, 8, 16}) else $fatal(1, "Cache line size needs to be a power of two multiple of AXI_DATA_WIDTH");
end
//pragma translate_on
endmodule

View file

@ -16,7 +16,12 @@
module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
parameter int unsigned ReqFifoDepth = 2,
parameter int unsigned MetaFifoDepth = wt_cache_pkg::DCACHE_MAX_TX
parameter int unsigned MetaFifoDepth = wt_cache_pkg::DCACHE_MAX_TX,
parameter int unsigned AxiAddrWidth = 0,
parameter int unsigned AxiDataWidth = 0,
parameter int unsigned AxiIdWidth = 0,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
) (
input logic clk_i,
input logic rst_ni,
@ -38,13 +43,13 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
output dcache_rtrn_t dcache_rtrn_o,
// AXI port
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i
output axi_req_t axi_req_o,
input axi_rsp_t axi_resp_i
);
// support up to 512bit cache lines
localparam AxiNumWords = (ariane_pkg::ICACHE_LINE_WIDTH/64) * (ariane_pkg::ICACHE_LINE_WIDTH > ariane_pkg::DCACHE_LINE_WIDTH) +
(ariane_pkg::DCACHE_LINE_WIDTH/64) * (ariane_pkg::ICACHE_LINE_WIDTH <= ariane_pkg::DCACHE_LINE_WIDTH) ;
localparam AxiNumWords = (ariane_pkg::ICACHE_LINE_WIDTH/AxiDataWidth) * (ariane_pkg::ICACHE_LINE_WIDTH > ariane_pkg::DCACHE_LINE_WIDTH) +
(ariane_pkg::DCACHE_LINE_WIDTH/AxiDataWidth) * (ariane_pkg::ICACHE_LINE_WIDTH <= ariane_pkg::DCACHE_LINE_WIDTH) ;
///////////////////////////////////////////////////////
@ -63,18 +68,18 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
logic axi_wr_req, axi_wr_gnt;
logic axi_wr_valid, axi_rd_valid, axi_rd_rdy, axi_wr_rdy;
logic axi_rd_lock, axi_wr_lock, axi_rd_exokay, axi_wr_exokay, wr_exokay;
logic [63:0] axi_rd_addr, axi_wr_addr;
logic [AxiAddrWidth-1:0] axi_rd_addr, axi_wr_addr;
logic [$clog2(AxiNumWords)-1:0] axi_rd_blen, axi_wr_blen;
logic [1:0] axi_rd_size, axi_wr_size;
logic [$size(axi_resp_i.r.id)-1:0] axi_rd_id_in, axi_wr_id_in, axi_rd_id_out, axi_wr_id_out, wr_id_out;
logic [AxiNumWords-1:0][63:0] axi_wr_data;
logic [2:0] axi_rd_size, axi_wr_size;
logic [AxiIdWidth-1:0] axi_rd_id_in, axi_wr_id_in, axi_rd_id_out, axi_wr_id_out, wr_id_out;
logic [AxiNumWords-1:0][AxiDataWidth-1:0] axi_wr_data;
logic [AxiNumWords-1:0][AXI_USER_WIDTH-1:0] axi_wr_user;
logic [63:0] axi_rd_data;
logic [AxiDataWidth-1:0] axi_rd_data;
logic [AXI_USER_WIDTH-1:0] axi_rd_user;
logic [AxiNumWords-1:0][7:0] axi_wr_be;
logic [AxiNumWords-1:0][(AxiDataWidth/8)-1:0] axi_wr_be;
logic [5:0] axi_wr_atop;
logic invalidate;
logic [2:0] amo_off_d, amo_off_q;
logic [$clog2(AxiDataWidth/8)-1:0] amo_off_d, amo_off_q;
// AMO generates r beat
logic amo_gen_r_d, amo_gen_r_q;
@ -121,10 +126,11 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
always_comb begin : p_axi_req
// write channel
axi_wr_id_in = arb_idx;
axi_wr_data = dcache_data.data;
axi_wr_data = {(AxiDataWidth/riscv::XLEN){dcache_data.data}};
axi_wr_user = dcache_data.user;
axi_wr_addr = {{64-riscv::PLEN{1'b0}}, dcache_data.paddr};
axi_wr_size = dcache_data.size[1:0];
// Cast to AXI address width
axi_wr_addr = dcache_data.paddr;
axi_wr_size = dcache_data.size;
axi_wr_req = 1'b0;
axi_wr_blen = '0;// single word writes
axi_wr_be = '0;
@ -140,25 +146,26 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
axi_rd_blen = '0;
if (dcache_data.paddr[2] == 1'b0) begin
axi_wr_data = {{64-riscv::XLEN{1'b0}}, dcache_data.data};
axi_wr_user = {{64-AXI_USER_WIDTH{1'b0}}, dcache_data.user};
end else begin
axi_wr_data = {dcache_data.data, {64-riscv::XLEN{1'b0}}};
axi_wr_user = {dcache_data.user, {64-AXI_USER_WIDTH{1'b0}}};
end
// arbiter mux
if (arb_idx) begin
axi_rd_addr = {{64-riscv::PLEN{1'b0}}, dcache_data.paddr};
axi_rd_size = dcache_data.size[1:0];
// Cast to AXI address width
axi_rd_addr = dcache_data.paddr;
// If dcache_data.size MSB is set, we want to read as much as possible
axi_rd_size = dcache_data.size[2] ? $clog2(AxiDataWidth/8) : dcache_data.size;
if (dcache_data.size[2]) begin
axi_rd_blen = ariane_pkg::DCACHE_LINE_WIDTH/64-1;
axi_rd_blen = ariane_pkg::DCACHE_LINE_WIDTH/AxiDataWidth-1;
end
end else begin
axi_rd_addr = {{64-riscv::PLEN{1'b0}}, icache_data.paddr};
axi_rd_size = 2'b11;// always request 64bit words in case of ifill
// Cast to AXI address width
axi_rd_addr = icache_data.paddr;
axi_rd_size = $clog2(AxiDataWidth/8); // always request max number of words in case of ifill
if (!icache_data.nc) begin
axi_rd_blen = ariane_pkg::ICACHE_LINE_WIDTH/64-1;
axi_rd_blen = ariane_pkg::ICACHE_LINE_WIDTH/AxiDataWidth-1;
end
end
@ -182,7 +189,13 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
//////////////////////////////////////
wt_cache_pkg::DCACHE_STORE_REQ: begin
axi_wr_req = 1'b1;
axi_wr_be = wt_cache_pkg::to_byte_enable8(dcache_data.paddr[2:0], dcache_data.size[1:0]);
axi_wr_be = '0;
unique case(dcache_data.size[1:0])
2'b00: axi_wr_be[0][dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0]] = '1; // byte
2'b01: axi_wr_be[0][dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0] +:2 ] = '1; // hword
2'b10: axi_wr_be[0][dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0] +:4 ] = '1; // word
default: axi_wr_be[0][dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0] +:8 ] = '1; // dword = '1; // dword
endcase
end
//////////////////////////////////////
wt_cache_pkg::DCACHE_ATOMIC_REQ: begin
@ -193,7 +206,13 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
// an atomic, this is safe.
invalidate = arb_gnt;
axi_wr_req = 1'b1;
axi_wr_be = wt_cache_pkg::to_byte_enable8(dcache_data.paddr[2:0], dcache_data.size[1:0]);
axi_wr_be = '0;
unique case(dcache_data.size[1:0])
2'b00: axi_wr_be[0][dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0]] = '1; // byte
2'b01: axi_wr_be[0][dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0] +:2 ] = '1; // hword
2'b10: axi_wr_be[0][dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0] +:4 ] = '1; // word
default: axi_wr_be[0][dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0] +:8 ] = '1; // dword
endcase
amo_gen_r_d = 1'b1;
// need to use a separate ID here, so concat an additional bit
axi_wr_id_in[1] = 1'b1;
@ -210,26 +229,17 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
AMO_SC: begin
axi_wr_lock = 1'b1;
amo_gen_r_d = 1'b0;
// needed to properly encode success
unique case (dcache_data.size[1:0])
2'b00: amo_off_d = dcache_data.paddr[2:0];
2'b01: amo_off_d = {dcache_data.paddr[2:1], 1'b0};
2'b10: amo_off_d = {dcache_data.paddr[2], 2'b00};
2'b11: amo_off_d = '0;
endcase
// needed to properly encode success. store the result at offset within the returned
// AXI data word aligned with the requested word size.
amo_off_d = dcache_data.paddr[$clog2(AxiDataWidth/8)-1:0] & ~((1 << dcache_data.size[1:0]) - 1);
end
// RISC-V atops have a load semantic
AMO_SWAP: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ATOMICSWAP};
AMO_ADD: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ADD};
AMO_AND: begin
// in this case we need to invert the data to get a "CLR"
if (dcache_data.paddr[2] == 1'b0) begin
axi_wr_data = {{64-riscv::XLEN{1'b1}}, ~dcache_data.data};
axi_wr_user = {{64-riscv::XLEN{1'b1}}, ~dcache_data.user};
end else begin
axi_wr_data = {~dcache_data.data, {64-riscv::XLEN{1'b1}}};
axi_wr_user = {~dcache_data.user, {64-riscv::XLEN{1'b1}}};
end
axi_wr_data = ~{(AxiDataWidth/riscv::XLEN){dcache_data.data}};
axi_wr_user = ~{(AxiDataWidth/riscv::XLEN){dcache_data.user}};
axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_CLR};
end
AMO_OR: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SET};
@ -351,7 +361,7 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
assign b_push = axi_wr_valid & axi_wr_rdy;
fifo_v3 #(
.DATA_WIDTH ( $size(axi_resp_i.r.id) + 1 ),
.DATA_WIDTH ( AxiIdWidth + 1 ),
.DEPTH ( MetaFifoDepth ),
.FALL_THROUGH ( 1'b1 )
) i_b_fifo (
@ -370,10 +380,10 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
// buffer read responses in shift regs
logic icache_first_d, icache_first_q, dcache_first_d, dcache_first_q;
logic [ICACHE_LINE_WIDTH/64-1:0][63:0] icache_rd_shift_d, icache_rd_shift_q;
logic [ICACHE_USER_LINE_WIDTH/AXI_USER_WIDTH-1:0][AXI_USER_WIDTH-1:0] icache_rd_shift_user_d, icache_rd_shift_user_q;
logic [DCACHE_LINE_WIDTH/64-1:0][63:0] dcache_rd_shift_d, dcache_rd_shift_q;
logic [DCACHE_USER_LINE_WIDTH/AXI_USER_WIDTH-1:0][AXI_USER_WIDTH-1:0] dcache_rd_shift_user_d, dcache_rd_shift_user_q;
logic [ICACHE_LINE_WIDTH/AxiDataWidth-1:0][AxiDataWidth-1:0] icache_rd_shift_d, icache_rd_shift_q;
logic [DCACHE_LINE_WIDTH/AxiDataWidth-1:0][AxiDataWidth-1:0] dcache_rd_shift_d, dcache_rd_shift_q;
wt_cache_pkg::dcache_in_t dcache_rtrn_type_d, dcache_rtrn_type_q;
wt_cache_pkg::dcache_inval_t dcache_rtrn_inv_d, dcache_rtrn_inv_q;
logic dcache_sc_rtrn, axi_rd_last;
@ -405,7 +415,11 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
if (icache_rtrn_rd_en) begin
icache_first_d = axi_rd_last;
icache_rd_shift_d = {axi_rd_data, icache_rd_shift_q[ICACHE_LINE_WIDTH/64-1:1]};
if (ICACHE_LINE_WIDTH == AxiDataWidth) begin
icache_rd_shift_d = axi_rd_data;
end else begin
icache_rd_shift_d = {axi_rd_data, icache_rd_shift_q[ICACHE_LINE_WIDTH/AxiDataWidth-1:1]};
end
icache_rd_shift_user_d = {axi_rd_user, icache_rd_shift_user_q[ICACHE_USER_LINE_WIDTH/AXI_USER_WIDTH-1:1]};
// if this is a single word transaction, we need to make sure that word is placed at offset 0
if (icache_first_q) begin
@ -416,7 +430,11 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
if (dcache_rtrn_rd_en) begin
dcache_first_d = axi_rd_last;
dcache_rd_shift_d = {axi_rd_data, dcache_rd_shift_q[DCACHE_LINE_WIDTH/64-1:1]};
if (DCACHE_LINE_WIDTH == AxiDataWidth) begin
dcache_rd_shift_d = axi_rd_data;
end else begin
dcache_rd_shift_d = {axi_rd_data, dcache_rd_shift_q[DCACHE_LINE_WIDTH/AxiDataWidth-1:1]};
end
dcache_rd_shift_user_d = {axi_rd_user, dcache_rd_shift_user_q[DCACHE_USER_LINE_WIDTH/AXI_USER_WIDTH-1:1]};
// if this is a single word transaction, we need to make sure that word is placed at offset 0
if (dcache_first_q) begin
@ -571,9 +589,13 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
///////////////////////////////////////////////////////
axi_shim #(
.AxiUserWidth ( AXI_USER_WIDTH ),
.AxiNumWords ( AxiNumWords ),
.AxiIdWidth ( $size(axi_resp_i.r.id) )
.AxiNumWords ( AxiNumWords ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.AxiIdWidth ( AxiIdWidth ),
.AxiUserWidth ( AXI_USER_WIDTH ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_axi_shim (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),

View file

@ -20,7 +20,12 @@
module wt_cache_subsystem import ariane_pkg::*; import wt_cache_pkg::*; #(
parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig // contains cacheable regions
parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig, // contains cacheable regions
parameter int unsigned AxiAddrWidth = 0,
parameter int unsigned AxiDataWidth = 0,
parameter int unsigned AxiIdWidth = 0,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
) (
input logic clk_i,
input logic rst_ni,
@ -55,8 +60,8 @@ module wt_cache_subsystem import ariane_pkg::*; import wt_cache_pkg::*; #(
input l15_rtrn_t l15_rtrn_i
`else
// memory side
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i
output axi_req_t axi_req_o,
input axi_rsp_t axi_resp_i
`endif
// TODO: interrupt interface
);
@ -97,6 +102,7 @@ module wt_cache_subsystem import ariane_pkg::*; import wt_cache_pkg::*; #(
// they have equal prio and are RR arbited
// Port 2 is write only and goes into the merging write buffer
wt_dcache #(
.AxiDataWidth ( AxiDataWidth ),
// use ID 1 for dcache reads and amos. note that the writebuffer
// uses all IDs up to DCACHE_MAX_TX-1 for write transactions.
.RdAmoTxId ( 1 ),
@ -147,7 +153,13 @@ module wt_cache_subsystem import ariane_pkg::*; import wt_cache_pkg::*; #(
.l15_rtrn_i ( l15_rtrn_i )
);
`else
wt_axi_adapter i_adapter (
wt_axi_adapter #(
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.AxiIdWidth ( AxiIdWidth ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_adapter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.icache_data_req_i ( icache_adapter_data_req ),
@ -176,10 +188,12 @@ module wt_cache_subsystem import ariane_pkg::*; import wt_cache_pkg::*; #(
else $warning(1,"[l1 dcache] reading invalid instructions: vaddr=%08X, data=%08X",
icache_dreq_o.vaddr, icache_dreq_o.data);
a_invalid_write_data: assert property (
@(posedge clk_i) disable iff (!rst_ni) dcache_req_ports_i[2].data_req |-> |dcache_req_ports_i[2].data_be |-> (|dcache_req_ports_i[2].data_wdata) !== 1'hX)
else $warning(1,"[l1 dcache] writing invalid data: paddr=%016X, be=%02X, data=%016X",
{dcache_req_ports_i[2].address_tag, dcache_req_ports_i[2].address_index}, dcache_req_ports_i[2].data_be, dcache_req_ports_i[2].data_wdata);
for (genvar j=0; j<riscv::XLEN/8; j++) begin : gen_invalid_write_assertion
a_invalid_write_data: assert property (
@(posedge clk_i) disable iff (!rst_ni) dcache_req_ports_i[2].data_req |-> dcache_req_ports_i[2].data_be[j] |-> (|dcache_req_ports_i[2].data_wdata[j*8+:8] !== 1'hX))
else $warning(1,"[l1 dcache] writing invalid data: paddr=%016X, be=%02X, data=%016X, databe=%016X",
{dcache_req_ports_i[2].address_tag, dcache_req_ports_i[2].address_index}, dcache_req_ports_i[2].data_be, dcache_req_ports_i[2].data_wdata, dcache_req_ports_i[2].data_be & dcache_req_ports_i[2].data_wdata);
end
for (genvar j=0; j<2; j++) begin : gen_assertion

View file

@ -14,6 +14,7 @@
module wt_dcache import ariane_pkg::*; import wt_cache_pkg::*; #(
parameter int unsigned AxiDataWidth = 0,
// ID to be used for read and AMO transactions.
// note that the write buffer uses all IDs up to DCACHE_MAX_TX-1 for write transactions
parameter logic [CACHE_ID_WIDTH-1:0] RdAmoTxId = 1,
@ -112,9 +113,10 @@ module wt_dcache import ariane_pkg::*; import wt_cache_pkg::*; #(
///////////////////////////////////////////////////////
wt_dcache_missunit #(
.Axi64BitCompliant ( ArianeCfg.Axi64BitCompliant ),
.AmoTxId ( RdAmoTxId ),
.NumPorts ( NumPorts )
.AxiCompliant ( ArianeCfg.AxiCompliant ),
.AmoTxId ( RdAmoTxId ),
.NumPorts ( NumPorts ),
.AxiDataWidth ( AxiDataWidth )
) i_wt_dcache_missunit (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
@ -275,8 +277,9 @@ module wt_dcache import ariane_pkg::*; import wt_cache_pkg::*; #(
///////////////////////////////////////////////////////
wt_dcache_mem #(
.Axi64BitCompliant ( ArianeCfg.Axi64BitCompliant ),
.NumPorts ( NumPorts )
.AxiCompliant ( ArianeCfg.AxiCompliant ),
.AxiDataWidth ( AxiDataWidth ),
.NumPorts ( NumPorts )
) i_wt_dcache_mem (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),

View file

@ -27,8 +27,9 @@
module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
parameter bit Axi64BitCompliant = 1'b0, // set this to 1 when using in conjunction with 64bit AXI bus adapter
parameter int unsigned NumPorts = 3
parameter bit AxiCompliant = 1'b0, // set this to 1 when using in conjunction with AXI bus adapter
parameter int unsigned AxiDataWidth = 0,
parameter int unsigned NumPorts = 3
) (
input logic clk_i,
input logic rst_ni,
@ -71,6 +72,10 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
input wbuffer_t [DCACHE_WBUF_DEPTH-1:0] wbuffer_data_i
);
// number of bits needed to address AXI data. If AxiDataWidth equals XLEN this parameter
// is not needed. Therefore, increment it by one to avoid reverse range select during elaboration.
localparam AXI_OFFSET_WIDTH = AxiDataWidth == riscv::XLEN ? $clog2(AxiDataWidth/8)+1 : $clog2(AxiDataWidth/8);
logic [DCACHE_NUM_BANKS-1:0] bank_req;
logic [DCACHE_NUM_BANKS-1:0] bank_we;
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][(riscv::XLEN/8)-1:0] bank_be;
@ -241,9 +246,11 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
assign wbuffer_ruser = wbuffer_data_i[wbuffer_hit_idx].user;
assign wbuffer_be = (|wbuffer_hit_oh) ? wbuffer_data_i[wbuffer_hit_idx].valid : '0;
if (Axi64BitCompliant) begin : gen_axi_off
assign wr_cl_nc_off = riscv::IS_XLEN64 ? '0 : wr_cl_off_i[2];
assign wr_cl_off = (wr_cl_nc_i) ? wr_cl_nc_off : wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES];
if (AxiCompliant) begin : gen_axi_off
// In case of an uncached read, return the desired XLEN-bit segment of the most recent AXI read
assign wr_cl_off = (wr_cl_nc_i) ? (AxiDataWidth == riscv::XLEN) ? '0 :
wr_cl_off_i[AXI_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES] :
wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES];
end else begin : gen_piton_off
assign wr_cl_off = wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:3];
end
@ -337,6 +344,20 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
//pragma translate_off
`ifndef VERILATOR
initial begin
cach_line_width_axi: assert (DCACHE_LINE_WIDTH >= AxiDataWidth)
else $fatal(1, "[l1 dcache] cache line size needs to be greater or equal AXI data width");
end
initial begin
axi_xlen: assert (AxiDataWidth >= riscv::XLEN)
else $fatal(1, "[l1 dcache] AXI data width needs to be greater or equal XLEN");
end
initial begin
cach_line_width_xlen: assert (DCACHE_LINE_WIDTH > riscv::XLEN)
else $fatal(1, "[l1 dcache] cache_line_size needs to be greater than XLEN");
end
hit_hot1: assert property (
@(posedge clk_i) disable iff (!rst_ni) &vld_req |-> !vld_we |=> $onehot0(rd_hit_oh_o))

View file

@ -15,9 +15,10 @@
module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
parameter bit Axi64BitCompliant = 1'b0, // set this to 1 when using in conjunction with 64bit AXI bus adapter
parameter logic [CACHE_ID_WIDTH-1:0] AmoTxId = 1, // TX id to be used for AMOs
parameter int unsigned NumPorts = 3 // number of miss ports
parameter bit AxiCompliant = 1'b0, // set this to 1 when using in conjunction with AXI bus adapter
parameter logic [CACHE_ID_WIDTH-1:0] AmoTxId = 1, // TX id to be used for AMOs
parameter int unsigned NumPorts = 3, // number of miss ports
parameter int AxiDataWidth = 0
) (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
@ -220,8 +221,12 @@ module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
end
// note: openpiton returns a full cacheline!
if (Axi64BitCompliant) begin : gen_axi_rtrn_mux
assign amo_rtrn_mux = mem_rtrn_i.data[0 +: 64];
if (AxiCompliant) begin : gen_axi_rtrn_mux
if (AxiDataWidth > 64) begin
assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[$clog2(AxiDataWidth/8)-1:3]*64 +: 64];
end else begin
assign amo_rtrn_mux = mem_rtrn_i.data[0 +: 64];
end
end else begin : gen_piton_rtrn_mux
assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[DCACHE_OFFSET_WIDTH-1:3]*64 +: 64];
end

View file

@ -1201,7 +1201,7 @@ module csr_regfile import ariane_pkg::*; #(
`ifndef VERILATOR
// check that eret and ex are never valid together
assert property (
@(posedge clk_i) !(eret_o && ex_i.valid))
@(posedge clk_i) disable iff (!rst_ni !== '0) !(eret_o && ex_i.valid))
else begin $error("eret and exception should never be valid at the same time"); $stop(); end
`endif
//pragma translate_on

View file

@ -24,7 +24,15 @@ import "DPI-C" function void init_dromajo(string cfg_f_name);
module cva6 import ariane_pkg::*; #(
parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig
parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig,
parameter int unsigned AxiAddrWidth = ariane_axi::AddrWidth,
parameter int unsigned AxiDataWidth = ariane_axi::DataWidth,
parameter int unsigned AxiIdWidth = ariane_axi::IdWidth,
parameter type axi_ar_chan_t = ariane_axi::ar_chan_t,
parameter type axi_aw_chan_t = ariane_axi::aw_chan_t,
parameter type axi_w_chan_t = ariane_axi::w_chan_t,
parameter type axi_req_t = ariane_axi::req_t,
parameter type axi_rsp_t = ariane_axi::resp_t
) (
input logic clk_i,
input logic rst_ni,
@ -55,8 +63,8 @@ module cva6 import ariane_pkg::*; #(
input wt_cache_pkg::l15_rtrn_t l15_rtrn_i
`else
// memory side, AXI Master
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i
output axi_req_t axi_req_o,
input axi_rsp_t axi_resp_i
`endif
);
@ -674,7 +682,12 @@ module cva6 import ariane_pkg::*; #(
`ifdef WT_DCACHE
// this is a cache subsystem that is compatible with OpenPiton
wt_cache_subsystem #(
.ArianeCfg ( ArianeCfg )
.ArianeCfg ( ArianeCfg ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.AxiIdWidth ( AxiIdWidth ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_cache_subsystem (
// to D$
.clk_i ( clk_i ),
@ -716,7 +729,15 @@ module cva6 import ariane_pkg::*; #(
// note: this only works with one cacheable region
// not as important since this cache subsystem is about to be
// deprecated
.ArianeCfg ( ArianeCfg )
.ArianeCfg ( ArianeCfg ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.AxiIdWidth ( AxiIdWidth ),
.axi_ar_chan_t ( axi_ar_chan_t ),
.axi_aw_chan_t ( axi_aw_chan_t ),
.axi_w_chan_t ( axi_w_chan_t ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_rsp_t )
) i_cache_subsystem (
// to D$
.clk_i ( clk_i ),

View file

@ -48,7 +48,7 @@ package ariane_pkg;
logic [NrMaxRules-1:0][63:0] CachedRegionAddrBase; // base which needs to match
logic [NrMaxRules-1:0][63:0] CachedRegionLength; // bit mask which bits to consider when matching the rule
// cache config
bit Axi64BitCompliant; // set to 1 when using in conjunction with 64bit AXI bus adapter
bit AxiCompliant; // set to 1 when using in conjunction with 64bit AXI bus adapter
bit SwapEndianess; // set to 1 to swap endianess inside L1.5 openpiton adapter
//
logic [63:0] DmBaseAddress; // offset of the debug module
@ -72,7 +72,7 @@ package ariane_pkg;
CachedRegionAddrBase: {64'h8000_0000},
CachedRegionLength: {64'h40000000},
// cache config
Axi64BitCompliant: 1'b1,
AxiCompliant: 1'b1,
SwapEndianess: 1'b0,
// debug
DmBaseAddress: 64'h0,
@ -96,6 +96,7 @@ package ariane_pkg;
function automatic logic range_check(logic[63:0] base, logic[63:0] len, logic[63:0] address);
// if len is a power of two, and base is properly aligned, this check could be simplified
// Extend base by one bit to prevent an overflow.
return (address >= base) && (address < (65'(base)+len));
endfunction : range_check

View file

@ -559,7 +559,12 @@ logic [1:0] axi_adapter_size;
assign axi_adapter_size = (riscv::XLEN == 64) ? 2'b11 : 2'b10;
axi_adapter #(
.DATA_WIDTH ( riscv::XLEN )
.DATA_WIDTH ( riscv::XLEN ),
.AXI_ADDR_WIDTH ( ariane_axi::AddrWidth ),
.AXI_DATA_WIDTH ( ariane_axi::DataWidth ),
.AXI_ID_WIDTH ( ariane_axi::IdWidth ),
.axi_req_t ( ariane_axi::req_t ),
.axi_rsp_t ( ariane_axi::resp_t )
) i_dm_axi_master (
.clk_i ( clk ),
.rst_ni ( rst_n ),

View file

@ -186,7 +186,7 @@ module ariane_verilog_wrap
CachedRegionAddrBase: CachedRegionAddrBase,
CachedRegionLength: CachedRegionLength,
// cache config
Axi64BitCompliant: 1'b0,
AxiCompliant: 1'b0,
SwapEndianess: SwapEndianess,
// debug
DmBaseAddress: DmBaseAddress,

View file

@ -85,7 +85,7 @@ package ariane_soc;
CachedRegionAddrBase: {DRAMBase},
CachedRegionLength: {DRAMLength},
// cache config
Axi64BitCompliant: 1'b1,
AxiCompliant: 1'b1,
SwapEndianess: 1'b0,
// debug
DmBaseAddress: DebugBase,

View file

@ -284,7 +284,11 @@ module ariane_testharness #(
axi_adapter #(
.DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_soc::IdWidth )
.AXI_ADDR_WIDTH ( ariane_axi_soc::AddrWidth ),
.AXI_DATA_WIDTH ( ariane_axi_soc::DataWidth ),
.AXI_ID_WIDTH ( ariane_soc::IdWidth ),
.axi_req_t ( ariane_axi_soc::req_t ),
.axi_rsp_t ( ariane_axi_soc::resp_t )
) i_dm_axi_master (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),

View file

@ -16,7 +16,7 @@
`include "tb.svh"
program tb_amoport import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg::*; #(
program tb_amoport import ariane_pkg::*; import tb_pkg::*; #(
parameter string PortName = "atomics port 0",
parameter MemWords = 1024*1024,// in 64bit words
parameter logic [63:0] CachedAddrBeg = 0,
@ -82,7 +82,10 @@ program tb_amoport import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg:
// Apply random stimuli, choose random AMO operand
void'(randomize(amo_op) with {!(amo_op inside {AMO_NONE, AMO_CAS1, AMO_CAS2});});
void'(randomize(data));
void'(randomize(size) with {size >= 2; size <= 3;});
if (riscv::XLEN == 64)
void'(randomize(size) with {size >= 2; size <= 3;});
else
size = 'h2;
// For LRs/SCs, choose from only 4 adresses,
// so that valid LR/SC combinations become more likely.
@ -190,7 +193,7 @@ program tb_amoport import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg:
if(Verbose | !ok) begin
tmpstr0 = $psprintf("vector: %02d - %06d -- paddr: %16X -- AMO: 0x%2X -- size: %X -- op_a: %16X -- op_b: %16X",
n, k, dut_amo_req_port_o.operand_a, dut_amo_req_port_o.amo_op, 2**dut_amo_req_port_o.size, exp_result_i, dut_amo_req_port_o.operand_b);
n, k, dut_amo_req_port_o.operand_a, dut_amo_req_port_o.amo_op, 2**dut_amo_req_port_o.size, dut_amo_req_port_o.operand_a, dut_amo_req_port_o.operand_b);
tmpstr1 = $psprintf("vector: %02d - %06d -- exp_res: %16X -- exp_mem: %16X",
n, k, exp_result_i, exp_mem_i);
tmpstr2 = $psprintf("vector: %02d - %06d -- result: %16X -- memory: %16X",

View file

@ -190,6 +190,7 @@ package tb_pkg;
rand_ax_beat_queue_t ar_queue;
ax_beat_t aw_queue[$];
int unsigned b_wait_cnt;
ax_beat_t b_aw_queue[$];
static byte_t memory_q[MEM_BYTES-1:0]; // Main memory
static byte_t shadow_q[MEM_BYTES-1:0]; // Shadow of main memory for verification.
@ -353,12 +354,12 @@ package tb_pkg;
forever begin
automatic ax_beat_t aw_beat;
automatic addr_t byte_addr;
wait (aw_queue.size() > 0);
aw_beat = aw_queue.pop_front();
forever begin
automatic w_beat_t w_beat;
rand_wait(RESP_MIN_WAIT_CYCLES, RESP_MAX_WAIT_CYCLES);
drv.recv_w(w_beat);
wait (aw_queue.size() > 0);
aw_beat = aw_queue[0];
byte_addr = (aw_beat.ax_addr >> $clog2(DW/8)) << $clog2(DW/8);
assert (min_paddr != max_paddr && byte_addr inside {[min_paddr:max_paddr]}) else
@ -376,11 +377,10 @@ package tb_pkg;
aw_beat.ax_addr = ((aw_beat.ax_addr >> aw_beat.ax_size) << aw_beat.ax_size) +
2**aw_beat.ax_size;
end
aw_queue[0] = aw_beat;
if (w_beat.w_last)
break;
end
b_wait_cnt++;
b_aw_queue.push_back(aw_beat);
end
endtask
@ -389,8 +389,8 @@ package tb_pkg;
automatic ax_beat_t aw_beat;
automatic b_beat_t b_beat = new;
automatic logic rand_success;
wait (b_wait_cnt > 0 && (aw_queue.size() != 0));
aw_beat = aw_queue.pop_front();
wait (b_aw_queue.size() > 0);
aw_beat = b_aw_queue.pop_front();
rand_success = std::randomize(b_beat); assert(rand_success);
b_beat.b_id = aw_beat.ax_id;
if (aw_beat.ax_lock) begin

View file

@ -47,7 +47,7 @@ program tb_readport import tb_pkg::*; import ariane_pkg::*; #(
// expresp interface
output logic [63:0] exp_paddr_o,
input logic [1:0] exp_size_i,
input logic [63:0] exp_rdata_i,
input riscv::xlen_t exp_rdata_i,
input logic [63:0] exp_paddr_i,
input logic [63:0] act_paddr_i,

View file

@ -54,7 +54,7 @@ module tb import tb_pkg::*; import ariane_pkg::*; import wt_cache_pkg::*; #()();
CachedRegionAddrBase: {CachedAddrBeg},
CachedRegionLength: {CachedAddrEnd-CachedAddrBeg+64'b1},
// cache config
Axi64BitCompliant: 1'b0,
AxiCompliant: 1'b0,
SwapEndianess: 1'b0,
// debug
DmBaseAddress: 64'h0,

View file

@ -15,6 +15,7 @@
`include "tb.svh"
`include "assign.svh"
`include "axi/typedef.svh"
module tb import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg::*; #()();
@ -47,7 +48,7 @@ module tb import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg::*; #()()
CachedRegionAddrBase: {CachedAddrBeg},//1/8th of the memory is NC
CachedRegionLength: {CachedAddrEnd-CachedAddrBeg+64'b1},
// cache config
Axi64BitCompliant: 1'b1,
AxiCompliant: 1'b1,
SwapEndianess: 1'b0,
// debug
DmBaseAddress: 64'h0,
@ -87,6 +88,13 @@ module tb import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg::*; #()()
// MUT signal declarations
///////////////////////////////////////////////////////////////////////////////
`AXI_TYPEDEF_ALL(axi,
logic [ TbAxiAddrWidthFull-1:0],
logic [ TbAxiIdWidthFull-1:0],
logic [ TbAxiDataWidthFull-1:0],
logic [(TbAxiDataWidthFull/8)-1:0],
logic [ TbAxiUserWidthFull-1:0])
logic enable_i;
logic flush_i;
logic flush_ack_o;
@ -95,10 +103,10 @@ module tb import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg::*; #()()
amo_resp_t amo_resp_o;
dcache_req_i_t [2:0] req_ports_i;
dcache_req_o_t [2:0] req_ports_o;
ariane_axi::req_t axi_data_o;
ariane_axi::resp_t axi_data_i;
ariane_axi::req_t axi_bypass_o;
ariane_axi::resp_t axi_bypass_i;
axi_req_t axi_data_o;
axi_resp_t axi_data_i;
axi_req_t axi_bypass_o;
axi_resp_t axi_bypass_i;
///////////////////////////////////////////////////////////////////////////////
// TB signal declarations
@ -410,7 +418,12 @@ module tb import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg::*; #()()
///////////////////////////////////////////////////////////////////////////////
std_nbdcache #(
.ArianeCfg ( ArianeDefaultConfig )
.ArianeCfg ( ArianeDefaultConfig ),
.AXI_ADDR_WIDTH ( TbAxiAddrWidthFull ),
.AXI_DATA_WIDTH ( TbAxiDataWidthFull ),
.AXI_ID_WIDTH ( TbAxiIdWidthFull ),
.axi_req_t ( axi_req_t ),
.axi_rsp_t ( axi_resp_t )
) i_dut (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),

View file

@ -45,5 +45,5 @@
../common/tb_dcache_pkg.sv
../common/tb_readport.sv
../common/tb_writeport.sv
hdl/tb_amoport.sv
../common/tb_amoport.sv
hdl/tb.sv

View file

@ -57,7 +57,8 @@ add wave -noupdate -group i_missunit /tb/i_dut/i_miss_handler/*
add wave -noupdate -group i_ctrl0 {/tb/i_dut/master_ports[0]/i_cache_ctrl/*}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/master_ports[1]/i_cache_ctrl/*}
add wave -noupdate -group i_ctrl2 {/tb/i_dut/master_ports[2]/i_cache_ctrl/*}
add wave -noupdate -group i_miss_axi_adapter0 /tb/i_dut/i_miss_handler/i_miss_axi_adapter/*
add wave -noupdate -group i_bypass_axi_adapter /tb/i_dut/i_miss_handler/i_bypass_axi_adapter/*
add wave -noupdate -group i_miss_axi_adapter /tb/i_dut/i_miss_handler/i_miss_axi_adapter/*
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {31432807547 ps} 0} {{Cursor 2} {17675291 ps} 0} {{Cursor 3} {1027790000 ps} 0}
quietly wave cursor active 2

View file

@ -0,0 +1,7 @@
work
*.rep
transcript
*.ini
*.wlf
*.log

View file

@ -0,0 +1,46 @@
# Copyright 2018 ETH Zurich and University of Bologna.
# Copyright and related rights are licensed under the Solderpad Hardware
# License, Version 0.51 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
# or agreed to in writing, software, hardware and materials distributed under
# this 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.
#
# Author: Michael Schaffner <schaffner@iis.ee.ethz.ch>, ETH Zurich
# Date: 15.08.2018
# Description: Makefile for the dcache testbench.
library ?= work
toplevel ?= tb
src-list := tb.list
inc-path := $(shell pwd)/hdl/
src := $(shell xargs printf '\n%s' < $(src-list) | cut -b 1-)
compile_flag += +cover+i_dut -incr -64 -nologo -svinputport=compat -override_timescale 1ns/1ps -suppress 2583 -suppress 13262 +cover
sim_opts += -64 -coverage -classdebug -voptargs="+acc"
incdir += ../common/
incdir += ../../axi/include/
# Iterate over all include directories and write them with +incdir+ prefixed
# +incdir+ works for Verilator and QuestaSim
list_incdir := $(foreach dir, ${incdir}, +incdir+$(dir))
build: clean
vlib $(library)
vlog -work $(library) -pedanticerrors $(src) $(compile_flag) $(list_incdir)
touch $(library)/.build
# this starts modelsim with gui
sim: build
vsim -lib $(library) $(toplevel) -do "do wave.do" $(sim_opts)
# batch mode without gui
simc: build
vsim -lib $(library) $(toplevel) -c -do "run -all; exit" $(sim_opts)
clean:
rm -rf $(library)
.PHONY: clean simc sim build

View file

@ -0,0 +1,954 @@
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Michael Schaffner <schaffner@iis.ee.ethz.ch>, ETH Zurich
// Nils Wistoff <nwistoff@iis.ee.ethz.ch>, ETH Zurich
// Date: 04.09.2020
// Description: testbench for nonblocking write-back L1 dcache.
`include "tb.svh"
`include "assign.svh"
`include "axi/typedef.svh"
module tb import ariane_pkg::*; import wt_cache_pkg::*; import tb_pkg::*; #()();
// leave this
timeunit 1ps;
timeprecision 1ps;
// memory configuration (64bit words)
parameter MemBytes = 2**DCACHE_INDEX_WIDTH * 4 * 32;
parameter MemWords = MemBytes>>3;
// noncacheable portion
parameter logic [63:0] CachedAddrBeg = MemBytes>>3;//1/8th of the memory is NC
parameter logic [63:0] CachedAddrEnd = 64'hFFFF_FFFF_FFFF_FFFF;
// contention and invalidation rates (in %)
parameter MemRandHitRate = 75;
parameter MemRandInvRate = 10;
parameter TlbHitRate = 95;
// parameters for random read sequences (in %)
parameter FlushRate = 10;
parameter KillRate = 5;
parameter Verbose = 0;
// number of vectors per test
parameter nReadVectors = 20000;
parameter nWriteVectors = 20000;
parameter nAMOs = 20000;
/// ID width of the Full AXI slave port, master port has ID `AxiIdWidthFull + 32'd1`
parameter int unsigned TbAxiIdWidthFull = 32'd6;
/// Address width of the full AXI bus
parameter int unsigned TbAxiAddrWidthFull = 32'd64;
/// Data width of the full AXI bus
parameter int unsigned TbAxiDataWidthFull = 32'd64;
localparam int unsigned TbAxiUserWidthFull = AXI_USER_WIDTH;
/// Application time to the DUT
parameter time TbApplTime = 2ns;
/// Test time of the DUT
parameter time TbTestTime = 8ns;
///////////////////////////////////////////////////////////////////////////////
// MUT signal declarations
///////////////////////////////////////////////////////////////////////////////
`AXI_TYPEDEF_ALL(axi_data,
logic [ TbAxiAddrWidthFull-1:0],
logic [ TbAxiIdWidthFull-1:0],
logic [ TbAxiDataWidthFull-1:0],
logic [(TbAxiDataWidthFull/8)-1:0],
logic [ TbAxiUserWidthFull-1:0])
logic enable_i;
logic flush_i;
logic flush_ack_o;
logic miss_o;
amo_req_t amo_req_i;
amo_resp_t amo_resp_o;
dcache_req_i_t [2:0] req_ports_i;
dcache_req_o_t [2:0] req_ports_o;
axi_data_req_t axi_data_o;
axi_data_resp_t axi_data_i;
///////////////////////////////////////////////////////////////////////////////
// TB signal declarations
///////////////////////////////////////////////////////////////////////////////
string test_name;
logic clk_i, rst_ni;
logic [31:0] seq_num_resp, seq_num_write, seq_num_amo;
seq_t [2:0] seq_type;
logic [3:0] seq_done;
logic [6:0] req_rate[2:0];
logic seq_run, seq_last;
logic end_of_sim;
logic mem_rand_en;
logic inv_rand_en;
logic amo_rand_en;
logic tlb_rand_en;
logic write_en;
logic [63:0] write_paddr, write_data;
logic [7:0] write_be;
typedef struct packed {
logic [1:0] size;
logic [63:0] paddr;
} resp_fifo_t;
typedef struct packed {
logic valid;
logic [63:0] paddr;
} reservation_t;
logic [63:0] act_paddr[1:0];
riscv::xlen_t exp_rdata[1:0];
logic [63:0] exp_paddr[1:0];
logic [63:0] amo_act_mem;
logic [63:0] amo_shadow;
logic [63:0] amo_exp_result;
resp_fifo_t fifo_data_in[1:0];
resp_fifo_t fifo_data[1:0];
logic [1:0] fifo_push, fifo_pop, fifo_flush;
logic [2:0] flush;
logic flush_rand_en;
AXI_BUS_DV #(
.AXI_ADDR_WIDTH ( TbAxiAddrWidthFull ),
.AXI_DATA_WIDTH ( TbAxiDataWidthFull ),
.AXI_ID_WIDTH ( TbAxiIdWidthFull + 32'd1 ),
.AXI_USER_WIDTH ( TbAxiUserWidthFull )
) axi_data_dv (
.clk_i ( clk_i )
);
`AXI_ASSIGN_FROM_REQ(axi_data_dv, axi_data_o)
`AXI_ASSIGN_TO_RESP(axi_data_i, axi_data_dv)
typedef tb_mem_port #(
.AW ( TbAxiAddrWidthFull ),
.DW ( TbAxiDataWidthFull ),
.IW ( TbAxiIdWidthFull + 32'd1 ),
.UW ( TbAxiUserWidthFull ),
.TA ( TbApplTime ),
.TT ( TbTestTime ),
.AX_MIN_WAIT_CYCLES ( 0 ),
.AX_MAX_WAIT_CYCLES ( 50 ),
.R_MIN_WAIT_CYCLES ( 10 ),
.R_MAX_WAIT_CYCLES ( 20 ),
.RESP_MIN_WAIT_CYCLES ( 10 ),
.RESP_MAX_WAIT_CYCLES ( 20 ),
.MEM_BYTES ( MemBytes )
) tb_mem_port_t;
tb_mem_port_t data_mem_port;
AXI_BUS #(
.AXI_ADDR_WIDTH ( TbAxiAddrWidthFull ),
.AXI_DATA_WIDTH ( TbAxiDataWidthFull ),
.AXI_ID_WIDTH ( TbAxiIdWidthFull + 32'd1 ),
.AXI_USER_WIDTH ( TbAxiUserWidthFull )
) axi_data ();
AXI_BUS #(
.AXI_ADDR_WIDTH ( TbAxiAddrWidthFull ),
.AXI_DATA_WIDTH ( TbAxiDataWidthFull ),
.AXI_ID_WIDTH ( TbAxiIdWidthFull + 32'd1 ),
.AXI_USER_WIDTH ( TbAxiUserWidthFull )
) axi_amo_adapter ();
AXI_BUS_DV #(
.AXI_ADDR_WIDTH ( TbAxiAddrWidthFull ),
.AXI_DATA_WIDTH ( TbAxiDataWidthFull ),
.AXI_ID_WIDTH ( TbAxiIdWidthFull + 32'd1 ),
.AXI_USER_WIDTH ( TbAxiUserWidthFull )
) axi_amo_adapter_dv (
.clk_i ( clk_i )
);
`AXI_ASSIGN(axi_data, axi_data_dv)
`AXI_ASSIGN(axi_amo_adapter_dv, axi_amo_adapter)
///////////////////////////////////////////////////////////////////////////////
// Helper tasks
///////////////////////////////////////////////////////////////////////////////
// Run a sequence of read (and write) vectors
task automatic runSeq(input int nReadVectors, input int nWriteVectors = 0, input logic last =1'b0);
seq_last = last;
seq_run = 1'b1;
seq_num_resp = nReadVectors;
seq_num_write = nWriteVectors;
seq_num_amo = 0;
`APPL_WAIT_CYC(clk_i, 1)
seq_run = 1'b0;
`APPL_WAIT_SIG(clk_i, &seq_done)
`APPL_WAIT_CYC(clk_i, 1)
endtask : runSeq
// Run a sequence of AMOs
task automatic runAMOs(input int nAMOs, input logic last =1'b0);
seq_last = last;
seq_run = 1'b1;
seq_num_resp = 0;
seq_num_write = 0;
seq_num_amo = nAMOs;
`APPL_WAIT_CYC(clk_i, 1)
seq_run = 1'b0;
`APPL_WAIT_SIG(clk_i, &seq_done)
`APPL_WAIT_CYC(clk_i, 1)
endtask : runAMOs
// Flush the cache
task automatic flushCache();
flush[2] = 1'b1;
`APPL_WAIT_SIG(clk_i, flush_ack_o);
flush[2] = 0'b0;
`APPL_WAIT_CYC(clk_i, 1)
endtask : flushCache
///////////////////////////////////////////////////////////////////////////////
// Clock Process
///////////////////////////////////////////////////////////////////////////////
always @*
begin
do begin
clk_i = 1; #(CLK_HI);
clk_i = 0; #(CLK_LO);
end while (end_of_sim == 1'b0);
repeat (100) begin
// generate a few extra cycle to allow
// response acquisition to complete
clk_i = 1; #(CLK_HI);
clk_i = 0; #(CLK_LO);
end
end
///////////////////////////////////////////////////////////////////////////////
// memory emulation
///////////////////////////////////////////////////////////////////////////////
// listen to the write/AMO ports and keep shadow memory up-to-date
initial begin : p_mem
automatic logic[63:0] amo_result, amo_op_a, amo_op_b, amo_op_a_u, amo_op_b_u;
reservation_t reservation;
// Initialize
reservation = '0;
amo_exp_result = 'x;
`APPL_WAIT_SIG(clk_i, ~rst_ni)
`APPL_WAIT_CYC(clk_i, 1)
forever begin
`ACQ_WAIT_CYC(clk_i, 1)
amo_exp_result = 'x;
// Regular stores. These are directly written to shadow memory.
if(write_en) begin
for(int k=0; k<8; k++) begin
if(write_be[k]) begin
tb_mem_port_t::shadow_q[write_paddr + k] <= write_data[k*8 +: 8];
end
end
end
// AMOs. Here, we perform the AMO on shadow memory to keep it consistent with the memory and
// deliver to an expected response.
if (amo_req_i.req) begin
// 32-bit AMO
if (amo_req_i.size == 2'h2) begin
// Sign-extended operands
amo_op_a = $signed(amo_shadow[31:0]);
amo_op_b = $signed(amo_req_i.operand_b[31:0]);
// Zero-extended operands
amo_op_a_u = $unsigned(amo_shadow[31:0]);
amo_op_b_u = $unsigned(amo_req_i.operand_b[31:0]);
// The result that is expected to be returned by AMO and evantually to be stored in rd.
// For most AMOs, this is the previous memory content.
// RISC-V spec requires: "For RV64, 32-bit AMOs always sign-extend the value placed in rd."
amo_exp_result = amo_op_a;
// 64-bit AMO
end else begin
// Sign-extended operands
amo_op_a = $signed(amo_shadow);
amo_op_b = $signed(amo_req_i.operand_b);
// Zero-extended operands
amo_op_a_u = $unsigned(amo_shadow);
amo_op_b_u = $unsigned(amo_req_i.operand_b);
// The result that is expected to be returned by AMO and evantually to be stored in rd.
// For most AMOs, this is the previous memory content.
amo_exp_result = amo_shadow;
end
// Perform actual AMO.
case (amo_req_i.amo_op)
// LR instruction
AMO_LR: begin
// Mark a reservation for requested memory location.
reservation.valid = 1'b1;
reservation.paddr = amo_req_i.operand_a;
// The memory contents remain unchanged (old contents == new contents)
amo_result = amo_shadow;
end
// SC instruction
AMO_SC: begin
// Check whether we have a valid reservation. If so, do the store and return 0.
if (reservation.valid && reservation.paddr == amo_req_i.operand_a) begin
amo_result = amo_op_b;
amo_exp_result = 64'b0;
// Else, leave the memory unchanged and return 1.
end else begin
amo_result = amo_shadow;
amo_exp_result = 64'b1;
end
// Either way, invalidate the reservation.
reservation.valid = 1'b0;
end
// AMOs
AMO_SWAP: amo_result = amo_op_b;
AMO_ADD: amo_result = amo_op_a + amo_op_b;
AMO_AND: amo_result = amo_op_a & amo_op_b;
AMO_OR: amo_result = amo_op_a | amo_op_b;
AMO_XOR: amo_result = amo_op_a ^ amo_op_b;
AMO_MAX: amo_result = ($signed(amo_op_a) > $signed(amo_op_b)) ? amo_op_a : amo_op_b;
AMO_MIN: amo_result = ($signed(amo_op_a) < $signed(amo_op_b)) ? amo_op_a : amo_op_b;
AMO_MAXU: amo_result = (amo_op_a_u > amo_op_b_u) ? amo_op_a : amo_op_b;
AMO_MINU: amo_result = (amo_op_a_u < amo_op_b_u) ? amo_op_a : amo_op_b;
// Default: Leave memory unchanged.
default: amo_result = amo_shadow;
endcase
`ACQ_WAIT_CYC(clk_i,1)
// Write back arithmetic result of AMO to shadow memory.
for (int k = 0; k < 2**amo_req_i.size; k++) begin
tb_mem_port_t::shadow_q[amo_req_i.operand_a + k] <= amo_result[k*8 +: 8];
end
`ACQ_WAIT_SIG(clk_i,amo_resp_o.ack)
end
end
end
// Instantiate memory and AXI ports
initial begin : p_sim_mem
// Create AXI ports
data_mem_port = new(axi_amo_adapter_dv, CACHED);
// Initialize AXI ports and memory
data_mem_port.reset();
tb_mem_port_t::init_mem();
@(posedge rst_ni);
// Start AXI port emulation
fork
data_mem_port.run();
join
end
///////////////////////////////////////////////////////////////////////////////
// MUT
///////////////////////////////////////////////////////////////////////////////
localparam ariane_cfg_t ArianeDefaultConfig = '{
RASDepth: 2,
BTBEntries: 32,
BHTEntries: 128,
// idempotent region
NrNonIdempotentRules: 0,
NonIdempotentAddrBase: {64'b0},
NonIdempotentLength: {64'b0},
// executable region
NrExecuteRegionRules: 0,
ExecuteRegionAddrBase: {64'h0},
ExecuteRegionLength: {64'h0},
// cached region
NrCachedRegionRules: 1,
CachedRegionAddrBase: {CachedAddrBeg},//1/8th of the memory is NC
CachedRegionLength: {CachedAddrEnd-CachedAddrBeg+64'b1},
// cache config
AxiCompliant: 1'b1,
SwapEndianess: 1'b0,
// debug
DmBaseAddress: 64'h0,
NrPMPEntries: 0
};
wt_cache_subsystem #(
.ArianeCfg ( ArianeDefaultConfig ),
.AxiAddrWidth ( TbAxiAddrWidthFull ),
.AxiDataWidth ( TbAxiDataWidthFull ),
.AxiIdWidth ( TbAxiIdWidthFull ),
.axi_req_t ( axi_data_req_t ),
.axi_rsp_t ( axi_data_resp_t )
) i_dut (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.icache_en_i ( '0 ),
.icache_flush_i ( '0 ),
.icache_miss_o ( ),
.icache_areq_i ( '0 ),
.icache_areq_o ( ),
.icache_dreq_i ( '0 ),
.icache_dreq_o ( ),
.dcache_enable_i ( 1'b1 ),
.dcache_flush_i ( flush_i ),
.dcache_flush_ack_o ( flush_ack_o ),
.dcache_amo_req_i ( amo_req_i ),
.dcache_amo_resp_o ( amo_resp_o ),
.dcache_miss_o ( ),
.dcache_req_ports_i ( req_ports_i ),
.dcache_req_ports_o ( req_ports_o ),
.wbuffer_empty_o ( ),
.wbuffer_not_ni_o ( ),
.axi_req_o ( axi_data_o ),
.axi_resp_i ( axi_data_i )
);
///////////////////////////////////////////////////////////////////////////////
// AXI Atomics Adapter
///////////////////////////////////////////////////////////////////////////////
axi_riscv_atomics_wrap #(
.AXI_ADDR_WIDTH ( TbAxiAddrWidthFull ),
.AXI_DATA_WIDTH ( TbAxiDataWidthFull ),
.AXI_ID_WIDTH ( TbAxiIdWidthFull + 32'd1 ),
.AXI_USER_WIDTH ( TbAxiUserWidthFull ),
.AXI_MAX_WRITE_TXNS ( 1 ),
.RISCV_WORD_WIDTH ( riscv::XLEN )
) i_amo_adapter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.mst ( axi_amo_adapter.Master ),
.slv ( axi_data.Slave )
);
///////////////////////////////////////////////////////////////////////////////
// port emulation programs
///////////////////////////////////////////////////////////////////////////////
// get actual paddr from read controllers
assign act_paddr[0] = {i_dut.i_wt_dcache.gen_rd_ports[0].i_wt_dcache_ctrl.address_tag_d,
i_dut.i_wt_dcache.gen_rd_ports[0].i_wt_dcache_ctrl.address_idx_q,
i_dut.i_wt_dcache.gen_rd_ports[0].i_wt_dcache_ctrl.address_off_q};
assign act_paddr[1] = {i_dut.i_wt_dcache.gen_rd_ports[1].i_wt_dcache_ctrl.address_tag_d,
i_dut.i_wt_dcache.gen_rd_ports[1].i_wt_dcache_ctrl.address_idx_q,
i_dut.i_wt_dcache.gen_rd_ports[1].i_wt_dcache_ctrl.address_off_q};
// generate fifo queues for expected responses
generate
for(genvar k=0; k<2;k++) begin
assign fifo_data_in[k] = {req_ports_i[k].data_size,
exp_paddr[k]};
for (genvar l=0; l<riscv::XLEN/8; l++)
assign exp_rdata[k][l*8 +: 8] = tb_mem_port_t::shadow_q[{fifo_data[k].paddr[63:3], 3'b0} + l];
assign fifo_push[k] = req_ports_i[k].data_req & req_ports_o[k].data_gnt;
assign fifo_flush[k] = req_ports_i[k].kill_req;
assign fifo_pop[k] = req_ports_o[k].data_rvalid & ~req_ports_i[k].kill_req;
fifo_v3 #(
.dtype(resp_fifo_t)
) i_resp_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( fifo_flush[k] ),
.testmode_i ( '0 ),
.full_o ( ),
.empty_o ( ),
.usage_o ( ),
.data_i ( fifo_data_in[k] ),
.push_i ( fifo_push[k] ),
.data_o ( fifo_data[k] ),
.pop_i ( fifo_pop[k] )
);
end
endgenerate
// memory and shadow memory region that are addressed by current AMO
for (genvar k=0; k<8; k++) begin
assign amo_act_mem[k*8 +: 8] = tb_mem_port_t::memory_q[amo_req_i.operand_a + k];
assign amo_shadow[k*8 +: 8] = tb_mem_port_t::shadow_q[amo_req_i.operand_a + k];
end
tb_readport #(
.PortName ( "RD0" ),
.FlushRate ( FlushRate ),
.KillRate ( KillRate ),
.TlbHitRate ( TlbHitRate ),
.MemWords ( MemWords ),
.CachedAddrBeg ( CachedAddrBeg ),
.CachedAddrEnd ( CachedAddrEnd ),
.RndSeed ( 5555555 ),
.Verbose ( Verbose )
) i_tb_readport0 (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_name_i ( test_name ),
.req_rate_i ( req_rate[0] ),
.seq_type_i ( seq_type[0] ),
.tlb_rand_en_i ( tlb_rand_en ),
.flush_rand_en_i ( flush_rand_en ),
.seq_run_i ( seq_run ),
.seq_num_resp_i ( seq_num_resp ),
.seq_last_i ( seq_last ),
.seq_done_o ( seq_done[0] ),
.exp_paddr_o ( exp_paddr[0] ),
.exp_size_i ( fifo_data[0].size ),
.exp_paddr_i ( fifo_data[0].paddr ),
.exp_rdata_i ( exp_rdata[0] ),
.act_paddr_i ( act_paddr[0] ),
.flush_o ( flush[0] ),
.flush_ack_i ( flush_ack_o ),
.dut_req_port_o ( req_ports_i[0] ),
.dut_req_port_i ( req_ports_o[0] )
);
tb_readport #(
.PortName ( "RD1" ),
.FlushRate ( FlushRate ),
.KillRate ( KillRate ),
.TlbHitRate ( TlbHitRate ),
.MemWords ( MemWords ),
.CachedAddrBeg ( CachedAddrBeg ),
.CachedAddrEnd ( CachedAddrEnd ),
.RndSeed ( 3333333 ),
.Verbose ( Verbose )
) i_tb_readport1 (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_name_i ( test_name ),
.req_rate_i ( req_rate[1] ),
.seq_type_i ( seq_type[1] ),
.tlb_rand_en_i ( tlb_rand_en ),
.flush_rand_en_i ( flush_rand_en ),
.seq_run_i ( seq_run ),
.seq_num_resp_i ( seq_num_resp ),
.seq_last_i ( seq_last ),
.exp_paddr_o ( exp_paddr[1] ),
.exp_size_i ( fifo_data[1].size ),
.exp_paddr_i ( fifo_data[1].paddr ),
.exp_rdata_i ( exp_rdata[1] ),
.act_paddr_i ( act_paddr[1] ),
.seq_done_o ( seq_done[1] ),
.flush_o ( flush[1] ),
.flush_ack_i ( flush_ack_o ),
.dut_req_port_o ( req_ports_i[1] ),
.dut_req_port_i ( req_ports_o[1] )
);
tb_writeport #(
.PortName ( "WR0" ),
.MemWords ( MemWords ),
.CachedAddrBeg ( CachedAddrBeg ),
.CachedAddrEnd ( CachedAddrEnd ),
.RndSeed ( 7777777 ),
.Verbose ( Verbose )
) i_tb_writeport (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_name_i ( test_name ),
.req_rate_i ( req_rate[2] ),
.seq_type_i ( seq_type[2] ),
.seq_run_i ( seq_run ),
.seq_num_vect_i ( seq_num_write ),
.seq_last_i ( seq_last ),
.seq_done_o ( seq_done[2] ),
.dut_req_port_o ( req_ports_i[2] ),
.dut_req_port_i ( req_ports_o[2] )
);
tb_amoport #(
.PortName ("AMO0"),
.MemWords ( MemWords ),
.CachedAddrBeg ( CachedAddrBeg ),
.CachedAddrEnd ( CachedAddrEnd ),
.RndSeed ( 1111111 ),
.Verbose ( Verbose )
) i_tb_amoport (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_name_i ( test_name ),
.seq_run_i ( seq_run ),
.seq_num_amo_i ( seq_num_amo ),
.seq_last_i ( seq_last ),
.seq_done_o ( seq_done[3] ),
.act_mem_i ( amo_act_mem ),
.exp_mem_i ( amo_shadow ),
.exp_result_i ( amo_exp_result ),
.dut_amo_req_port_o ( amo_req_i ),
.dut_amo_resp_port_i ( amo_resp_o )
);
// Translate write requests for shadow memory.
initial begin
forever begin
`WAIT_CYC(clk_i,1)
write_en = req_ports_i[2].data_req & req_ports_o[2].data_gnt & req_ports_i[2].data_we;
write_paddr = {req_ports_i[2].address_tag, req_ports_i[2].address_index};
write_data = req_ports_i[2].data_wdata;
write_be = req_ports_i[2].data_be;
end
end
assign flush_i = |flush;
///////////////////////////////////////////////////////////////////////////////
// simulation coordinator process
///////////////////////////////////////////////////////////////////////////////
// TODO: implement CSR / controller
// flush_i, flush_ack_o, enable_i, miss_o, wbuffer_empty_o
initial begin : p_stim
test_name = "";
seq_type = '{default: RANDOM_SEQ};
req_rate = '{default: 7'd75};
seq_run = 1'b0;
seq_last = 1'b0;
seq_num_resp = '0;
seq_num_write = '0;
// seq_done
end_of_sim = 0;
rst_ni = 0;
// randomization settings
mem_rand_en = 0;
tlb_rand_en = 0;
inv_rand_en = 0;
amo_rand_en = 0;
flush_rand_en = 0;
// cache ctrl
flush[2] = 0;
// flush_ack_o
enable_i = 0;
// miss_o
// Print some info
$display("TB> current configuration:");
$display("TB> MemWords %d", MemWords);
$display("TB> CachedAddrBeg %16X", CachedAddrBeg);
$display("TB> CachedAddrEnd %16X", CachedAddrEnd);
$display("TB> MemRandHitRate %d", MemRandHitRate);
$display("TB> MemRandInvRate %d", MemRandInvRate);
// Reset cycles
`APPL_WAIT_CYC(clk_i,100)
rst_ni = 1'b1;
`APPL_WAIT_CYC(clk_i,100)
$display("TB> start with test sequences");
// Apply each test until seq_num_resp memory requests have successfully completed
///////////////////////////////////////////////
test_name = "TEST 0 -- random read -- disabled cache";
// Config
enable_i = 0;
seq_type = '{default: RANDOM_SEQ};
req_rate = '{default: 7'd50};
// Cache disabled ~> all requests should use bypass port
data_mem_port.set_region(0, MemBytes - 1);
runSeq(nReadVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 1 -- linear read -- disabled cache";
// Config
enable_i = 0;
seq_type = '{default: LINEAR_SEQ};
req_rate = '{default: 7'd50};
runSeq(nReadVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 2 -- random read -- enabled cache";
// Config
enable_i = 1;
seq_type = '{default: RANDOM_SEQ};
req_rate = '{default: 7'd50};
runSeq(nReadVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 3 -- linear read -- enabled cache";
// Config
enable_i = 1;
seq_type = '{default: LINEAR_SEQ};
req_rate = '{default: 7'd50};
runSeq(nReadVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 4 -- random read -- enabled cache + tlb, mem contentions";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 1;
seq_type = '{default: RANDOM_SEQ};
req_rate = '{default: 7'd50};
runSeq(nReadVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 5 -- linear read -- enabled cache + tlb, mem contentions";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 1;
seq_type = '{default: LINEAR_SEQ};
req_rate = '{default: 7'd50};
runSeq(nReadVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 6 -- random read -- enabled cache + tlb, mem contentions + invalidations";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 1;
inv_rand_en = 1;
seq_type = '{default: RANDOM_SEQ};
req_rate = '{default: 7'd50};
runSeq(nReadVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 7 -- random read/write -- disabled cache";
// Config
enable_i = 0;
tlb_rand_en = 0;
mem_rand_en = 0;
inv_rand_en = 0;
seq_type = '{default: RANDOM_SEQ};
req_rate = '{default: 7'd25};
runSeq(nReadVectors,nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 8 -- random read/write -- enabled cache";
// Config
enable_i = 1;
tlb_rand_en = 0;
mem_rand_en = 0;
inv_rand_en = 0;
seq_type = '{default: RANDOM_SEQ};
req_rate = '{default: 7'd25};
runSeq(nReadVectors,2*nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 9 -- random read/write -- enabled cache + tlb, mem contentions + invalidations";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 1;
inv_rand_en = 1;
seq_type = '{default: RANDOM_SEQ};
req_rate = '{default: 7'd25};
runSeq(nReadVectors,2*nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 10 -- linear burst write -- enabled cache";
// Config
enable_i = 1;
tlb_rand_en = 0;
mem_rand_en = 0;
inv_rand_en = 0;
seq_type = '{LINEAR_SEQ, IDLE_SEQ, IDLE_SEQ};
req_rate = '{100, 0, 0};
runSeq(0,nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 11 -- linear burst write with hot cache";
// Config
enable_i = 1;
tlb_rand_en = 0;
mem_rand_en = 0;
inv_rand_en = 0;
seq_type = '{IDLE_SEQ, IDLE_SEQ, LINEAR_SEQ};
req_rate = '{default:100};
runSeq((CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
seq_type = '{LINEAR_SEQ, IDLE_SEQ, IDLE_SEQ};
runSeq(0,(CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 12 -- random write bursts -- enabled cache";
// Config
enable_i = 1;
tlb_rand_en = 0;
mem_rand_en = 0;
inv_rand_en = 0;
seq_type = '{BURST_SEQ, RANDOM_SEQ, RANDOM_SEQ};
req_rate = '{75, 0, 0};
runSeq(0,nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 13 -- random write bursts -- enabled cache + tlb, mem contentions + invalidations";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 1;
inv_rand_en = 1;
seq_type = '{BURST_SEQ, IDLE_SEQ, IDLE_SEQ};
req_rate = '{75, 0, 0};
runSeq(0,nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 14 -- random write/read-- enabled cache + tlb, mem contentions + invalidations";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 1;
inv_rand_en = 1;
seq_type = '{RANDOM_SEQ, RANDOM_SEQ, RANDOM_SEQ};
req_rate = '{default:25};
runSeq(nReadVectors,nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 15 -- short wrapping sequences to provoke writebuffer hits";
// Config
enable_i = 1;
tlb_rand_en = 0;
mem_rand_en = 0;
inv_rand_en = 0;
seq_type = '{WRAP_SEQ, IDLE_SEQ, WRAP_SEQ};
req_rate = '{100,0,20};
runSeq(nReadVectors,nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 16 -- random write/read-- enabled cache + tlb, mem contentions + invalidations + random flushes";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 1;
inv_rand_en = 1;
flush_rand_en = 1;
seq_type = '{RANDOM_SEQ, RANDOM_SEQ, RANDOM_SEQ};
req_rate = '{default:25};
runSeq(nReadVectors,nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 17 -- set contention -- enabled cache";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 0;
inv_rand_en = 0;
seq_type = '{CONST_SEQ, IDLE_SEQ, SET_SEQ};
req_rate = '{50,0,2};
runSeq(0.2*nReadVectors,2*nWriteVectors);
flushCache();
tb_mem_port_t::check_mem();
///////////////////////////////////////////////
test_name = "TEST 18 -- AMOs";
// Config
enable_i = 1;
tlb_rand_en = 1;
mem_rand_en = 0;
inv_rand_en = 0;
seq_type = '{CONST_SEQ, IDLE_SEQ, SET_SEQ};
req_rate = '{50,0,2};
runAMOs(nAMOs,1); // Last sequence flag, terminates agents
flushCache();
tb_mem_port_t::check_mem();
/////////////////////////////////////////////
end_of_sim = 1;
$display("TB> end test sequences");
tb_mem_port_t::report_mem();
end
endmodule

View file

@ -0,0 +1,54 @@
../../../core/include/cv64a6_imafdc_sv39_config_pkg.sv
../../../core/include/riscv_pkg.sv
../common_verification/src/clk_rst_gen.sv
../common_verification/src/rand_id_queue.sv
../common_verification/src/rand_stream_mst.sv
../common_verification/src/rand_synch_holdable_driver.sv
../common_verification/src/rand_verif_pkg.sv
../common_verification/src/sim_timeout.sv
../common_verification/src/rand_synch_driver.sv
../common_verification/src/rand_stream_slv.sv
../../riscv-dbg/src/dm_pkg.sv
../../axi/src/axi_pkg.sv
../../axi/src/axi_intf.sv
../../axi/src/axi_test.sv
../../../core/fpu/src/fpnew_pkg.sv
../../../core/include/ariane_pkg.sv
../ariane_soc_pkg.sv
../ariane_axi_soc_pkg.sv
../../../core/include/ariane_axi_pkg.sv
../../../core/include/wt_cache_pkg.sv
../../fpga-support/rtl/SyncSpRamBeNx64.sv
../../../core/cache_subsystem/wt_dcache_ctrl.sv
../../../core/cache_subsystem/wt_dcache_mem.sv
../../../core/cache_subsystem/wt_dcache_missunit.sv
../../../core/cache_subsystem/wt_dcache_wbuffer.sv
../../../core/cache_subsystem/wt_dcache.sv
../../../core/cache_subsystem/cva6_icache.sv
../../../core/axi_shim.sv
../../../core/cache_subsystem/wt_axi_adapter.sv
../../../core/cache_subsystem/wt_cache_subsystem.sv
../../../common/submodules/common_cells/src/cf_math_pkg.sv
../../../common/submodules/common_cells/src/lfsr.sv
../../../common/submodules/common_cells/src/fifo_v3.sv
../../../common/submodules/common_cells/src/lzc.sv
../../../common/submodules/common_cells/src/rr_arb_tree.sv
../../../common/submodules/common_cells/src/exp_backoff.sv
../../../common/submodules/common_cells/src/stream_arbiter.sv
../../../common/submodules/common_cells/src/stream_arbiter_flushable.sv
../../../common/submodules/common_cells/src/stream_mux.sv
../../src/tech_cells_generic/src/rtl/tc_sram.sv
../../../common/local/util/tc_sram_wrapper.sv
../../../common/local/util/sram.sv
../../src/axi_riscv_atomics/src/axi_res_tbl.sv
../../src/axi_riscv_atomics/src/axi_riscv_amos.sv
../../src/axi_riscv_atomics/src/axi_riscv_amos_alu.sv
../../src/axi_riscv_atomics/src/axi_riscv_lrsc.sv
../../src/axi_riscv_atomics/src/axi_riscv_atomics.sv
../../src/axi_riscv_atomics/src/axi_riscv_atomics_wrap.sv
../common/tb_dcache_pkg.sv
../common/tb_readport.sv
../common/tb_writeport.sv
../common/tb_amoport.sv
hdl/tb.sv

View file

@ -0,0 +1,348 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /tb/*
add wave -noupdate -divider Modules
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/clk_i
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rst_ni
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/enable_i
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/flush_i
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/amo_req_i
add wave -noupdate -expand -group i_dut -expand -subitemconfig {{/tb/i_dut/i_wt_dcache/req_ports_i[1]} -expand} /tb/i_dut/i_wt_dcache/req_ports_i
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/mem_rtrn_vld_i
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/mem_rtrn_i
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/mem_data_ack_i
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/cache_en
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_cl_vld
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_cl_tag
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_cl_idx
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_cl_off
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_cl_data
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_cl_data_be
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_vld_bits
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_req
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_ack
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_idx
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_off
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_data
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wr_data_be
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_req
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_ack
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_nc
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_we
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_wdata
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_paddr
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_vld_bits
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_size
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_rtrn_vld
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_rtrn_id
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rd_req
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rd_ack
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rd_tag
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rd_idx
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rd_off
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rd_data
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rd_vld_bits
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/rd_hit_oh
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wbuffer_data
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/flush_ack_o
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/miss_o
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/wbuffer_empty_o
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/req_ports_o
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/mem_data_req_o
add wave -noupdate -expand -group i_dut /tb/i_dut/i_wt_dcache/mem_data_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/clk_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rst_ni
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/cache_en_i
add wave -noupdate -group i_wbuffer -color Magenta /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/req_port_i
add wave -noupdate -group i_wbuffer -color Magenta /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/req_port_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_ack_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_rtrn_vld_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_rtrn_id_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_ack_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_data_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_vld_bits_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_hit_oh_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wr_ack_i
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/empty_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_paddr_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_req_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_we_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_wdata_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_vld_bits_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_nc_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/miss_size_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_tag_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_idx_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_off_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_req_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wr_req_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wr_idx_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wr_off_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wr_data_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wr_data_be_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wbuffer_data_o
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/tx_stat_d
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/tx_stat_q
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wbuffer_q
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wbuffer_d
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/valid
add wave -noupdate -group i_wbuffer -color Magenta /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/debug_paddr
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/dirty
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/tocheck
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wbuffer_hit_oh
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/inval_hit
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/bdirty
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/next_ptr
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/dirty_ptr
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/hit_ptr
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wr_ptr
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/check_ptr_d
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/check_ptr_q
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rtrn_ptr
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rtrn_id
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/bdirty_off
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/tx_be
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/wr_paddr
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rd_paddr
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/check_en_d
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/check_en_q
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/full
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/dirty_rd_en
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rdy
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/rtrn_empty
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/evict
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/ni_pending_d
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/ni_pending_q
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/is_ni
add wave -noupdate -group i_wbuffer /tb/i_dut/i_wt_dcache/i_wt_dcache_wbuffer/is_nc_miss
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/clk_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/rst_ni
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/enable_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/flush_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wbuffer_empty_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/amo_req_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_req_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_nc_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_we_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_wdata_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_paddr_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_vld_bits_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_size_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_id_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/tx_paddr_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/tx_vld_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mem_rtrn_vld_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mem_rtrn_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mem_data_ack_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/AxiCompliant
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/AmoTxId
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/NumPorts
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/state_d
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/state_q
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_d
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_q
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/repl_way
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/inv_way
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/rnd_way
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_vld_d
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_vld_q
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_vld_q1
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_allocate
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/update_lfsr
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/all_ways_valid
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/enable_d
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/enable_q
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/flush_ack_d
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/flush_ack_q
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/flush_en
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/flush_done
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mask_reads
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/lock_reqs
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/amo_sel
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_is_write
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/amo_data
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/tmp_paddr
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/amo_rtrn_mux
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_port_idx
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/cnt_d
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/cnt_q
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_req_masked_d
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_req_masked_q
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/inv_vld
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/inv_vld_all
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/cl_write_en
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/load_ack
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/store_ack
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/amo_ack
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_rdrd_collision_d
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_rdrd_collision_q
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_rdrd_collision
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/tx_rdwr_collision
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mshr_rdwr_collision
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/flush_ack_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/cache_en_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/amo_resp_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_ack_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_replay_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_rtrn_vld_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/miss_rtrn_id_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_cl_vld_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_cl_nc_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_cl_we_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_cl_tag_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_cl_idx_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_cl_off_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_cl_data_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_cl_data_be_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/wr_vld_bits_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mem_data_req_o
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache/i_wt_dcache_missunit/mem_data_o
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/clk_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rst_ni
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rd_tag_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rd_idx_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rd_off_i
add wave -noupdate -group i_mem -expand /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rd_req_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_cl_vld_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_cl_tag_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_cl_idx_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_cl_off_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_cl_data_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_cl_data_be_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_vld_bits_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_req_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_idx_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_off_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_data_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_data_be_i
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wbuffer_data_i
add wave -noupdate -group i_mem -expand /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rd_ack_o
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rd_vld_bits_o
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rd_hit_oh_o
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rd_data_o
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wr_ack_o
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_req
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_we
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_be
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_idx
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_idx_d
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_idx_q
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_off_d
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_off_q
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_wdata
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/bank_rdata
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rdata_cl
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/vld_req
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/vld_we
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/vld_wdata
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/tag_rdata
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/vld_addr
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/vld_sel_d
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/vld_sel_q
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wbuffer_hit_oh
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wbuffer_be
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wbuffer_rdata
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/rdata
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/wbuffer_cmp_addr
add wave -noupdate -group i_mem /tb/i_dut/i_wt_dcache/i_wt_dcache_mem/vld_tag_rdata
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/clk_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rst_ni}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/cache_en_i}
add wave -noupdate -group i_ctrl0 -expand {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/req_port_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_ack_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_replay_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_rtrn_vld_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_ack_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_data_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_vld_bits_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_hit_oh_i}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/req_port_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_req_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_we_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_wdata_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_vld_bits_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_paddr_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_nc_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/miss_size_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_tag_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_idx_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_off_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_req_o}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/state_d}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/state_q}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/address_tag_d}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/address_tag_q}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/address_idx_d}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/address_idx_q}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/address_off_d}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/address_off_q}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/vld_data_d}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/vld_data_q}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/save_tag}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_req_d}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/rd_req_q}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/data_size_d}
add wave -noupdate -group i_ctrl0 {/tb/i_dut/i_wt_dcache/gen_rd_ports[0]/i_wt_dcache_ctrl/data_size_q}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/clk_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rst_ni}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/cache_en_i}
add wave -noupdate -group i_ctrl1 -expand {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/req_port_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_ack_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_replay_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_rtrn_vld_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_ack_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_data_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_vld_bits_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_hit_oh_i}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/req_port_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_req_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_we_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_wdata_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_vld_bits_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_paddr_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_nc_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/miss_size_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_tag_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_idx_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_off_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_req_o}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/state_d}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/state_q}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/address_tag_d}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/address_tag_q}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/address_idx_d}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/address_idx_q}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/address_off_d}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/address_off_q}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/vld_data_d}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/vld_data_q}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/save_tag}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_req_d}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/rd_req_q}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/data_size_d}
add wave -noupdate -group i_ctrl1 {/tb/i_dut/i_wt_dcache/gen_rd_ports[1]/i_wt_dcache_ctrl/data_size_q}
add wave -noupdate -group i_axi_adapter {/tb/i_dut/i_adapter/*}
add wave -noupdate -group i_axi_shim {/tb/i_dut/i_adapter/i_axi_shim/*}
TreeUpdate [SetDefaultTree]
quietly WaveActivateNextPane
add wave -position insertpoint {sim:/tb_pkg::tb_mem_port::tb_mem_port__1::memory_q[8]}
add wave -position insertpoint {sim:/tb_pkg::tb_mem_port::tb_mem_port__1::shadow_q[8]}
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {31432807547 ps} 0} {{Cursor 2} {17675291 ps} 0} {{Cursor 3} {1027790000 ps} 0}
quietly wave cursor active 2
configure wave -namecolwidth 375
configure wave -valuecolwidth 224
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ps
update
WaveRestoreZoom {0 ps} {56623104 ps}

View file

@ -55,7 +55,7 @@ module tb import tb_pkg::*; import ariane_pkg::*; import wt_cache_pkg::*; #()();
CachedRegionAddrBase: {CachedAddrBeg},//1/8th of the memory is NC
CachedRegionLength: {CachedAddrEnd-CachedAddrBeg+64'b1},
// cache config
Axi64BitCompliant: 1'b1,
AxiCompliant: 1'b1,
SwapEndianess: 1'b0,
// debug
DmBaseAddress: 64'h0,

View file

@ -6,6 +6,9 @@
../../axi/src/axi_intf.sv
../../axi/src/axi_test.sv
../../../core/include/ariane_pkg.sv
../ariane_soc_pkg.sv
../ariane_axi_soc_pkg.sv
../../../core/include/ariane_axi_pkg.sv
../../../core/include/wt_cache_pkg.sv
../../fpga-support/rtl/SyncSpRamBeNx64.sv
../../../core/cache_subsystem/wt_dcache_ctrl.sv
@ -19,6 +22,8 @@
../../../common/submodules/common_cells/src/lzc.sv
../../../common/submodules/common_cells/src/rr_arb_tree.sv
../../../common/submodules/common_cells/src/exp_backoff.sv
../../src/tech_cells_generic/src/rtl/tc_sram.sv
../../../common/local/util/tc_sram_wrapper.sv
../../../common/local/util/sram.sv
../common/tb_dcache_pkg.sv
hdl/tb_mem.sv

View file

@ -246,7 +246,7 @@ add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/tx_vld_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/mem_rtrn_vld_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/mem_rtrn_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/mem_data_ack_i
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/Axi64BitCompliant
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/AxiCompliant
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/AmoTxId
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/NumPorts
add wave -noupdate -group i_missunit /tb/i_dut/i_wt_dcache_missunit/state_d