mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 04:07:36 -04:00
Change NC range definition in caches, rename parameters.
This commit is contained in:
parent
92634285f6
commit
93b51793f2
19 changed files with 376 additions and 399 deletions
|
@ -21,9 +21,9 @@
|
|||
`endif
|
||||
|
||||
module ariane_verilog_wrap #(
|
||||
parameter bit SWAP_ENDIANESS = 0, // swap endianess in l15 adapter
|
||||
parameter bit CACHE_LOW_REGION = 0, // cached region is below CACHE_START_ADDR
|
||||
parameter logic [63:0] CACHE_START_ADDR = 64'h8000_0000 // address on which to decide whether the request is cache-able or not
|
||||
parameter bit SwapEndianess = 1, // swap endianess in l15 adapter
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000 // begin of cached region
|
||||
) (
|
||||
input clk_i,
|
||||
input reset_l, // this is an openpiton-specific name, do not change (hier. paths in TB use this)
|
||||
|
@ -105,9 +105,9 @@ module ariane_verilog_wrap #(
|
|||
|
||||
|
||||
ariane #(
|
||||
.SWAP_ENDIANESS ( SWAP_ENDIANESS ),
|
||||
.CACHE_LOW_REGION ( CACHE_LOW_REGION ),
|
||||
.CACHE_START_ADDR ( CACHE_START_ADDR )
|
||||
.SwapEndianess ( SwapEndianess ),
|
||||
.CachedAddrEnd ( CachedAddrEnd ),
|
||||
.CachedAddrBeg ( CachedAddrBeg )
|
||||
) ariane (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_n ),
|
||||
|
|
|
@ -86,7 +86,7 @@ module serpent_peripherals #(
|
|||
);
|
||||
|
||||
localparam int unsigned AxiIdWidth = 0;
|
||||
localparam int unsigned AxiAddrWidth = 40;
|
||||
localparam int unsigned AxiAddrWidth = 64;
|
||||
localparam int unsigned AxiDataWidth = 64;
|
||||
localparam int unsigned AxiUserWidth = 0;
|
||||
|
||||
|
@ -129,7 +129,7 @@ module serpent_peripherals #(
|
|||
// debug module
|
||||
dm_top #(
|
||||
// current implementation only supports 1 hart
|
||||
.NumHarts ( NumHarts ),
|
||||
.NrHarts ( NumHarts ),
|
||||
.AxiIdWidth ( AxiIdWidth ),
|
||||
.AxiAddrWidth ( AxiAddrWidth ),
|
||||
.AxiDataWidth ( AxiDataWidth ),
|
||||
|
@ -218,9 +218,9 @@ module serpent_peripherals #(
|
|||
assign dm_axi_s_req.ar.prot = '0;
|
||||
assign dm_axi_s_req.ar.qos = '0;
|
||||
assign dm_axi_s_req.ar.region = '0;
|
||||
assign dm_axi_s_resp.r.id = '0;
|
||||
assign dm_axi_s_resp.r.last = 1'b1;
|
||||
assign dm_axi_s_resp.b.id = '0;
|
||||
// assign dm_axi_s_resp.r.id = '0;
|
||||
// assign dm_axi_s_resp.r.last = 1'b1;
|
||||
// assign dm_axi_s_resp.b.id = '0;
|
||||
|
||||
/////////////////////////////
|
||||
// Bootrom
|
||||
|
@ -233,15 +233,15 @@ module serpent_peripherals #(
|
|||
AXI_BUS #(
|
||||
.AXI_ID_WIDTH ( AxiIdWidth ),
|
||||
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
|
||||
.AxiDataWidth ( AxiDataWidth ),
|
||||
.AxiUserWidth ( AxiUserWidth )
|
||||
.AXI_DATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI_USER_WIDTH ( AxiUserWidth )
|
||||
) br_master();
|
||||
|
||||
axi2mem #(
|
||||
.AXI_ID_WIDTH ( AxiIdWidth ),
|
||||
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
|
||||
.AxiDataWidth ( AxiDataWidth ),
|
||||
.AxiUserWidth ( AxiUserWidth )
|
||||
.AXI_DATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI_USER_WIDTH ( AxiUserWidth )
|
||||
) i_axi2rom (
|
||||
.clk_i ,
|
||||
.rst_ni ( ndmreset_n ),
|
||||
|
@ -319,10 +319,9 @@ module serpent_peripherals #(
|
|||
assign br_master.ar_prot = '0;
|
||||
assign br_master.ar_qos = '0;
|
||||
assign br_master.ar_region = '0;
|
||||
assign br_master.r_id = '0;
|
||||
assign br_master.r_last = 1'b1;
|
||||
assign br_master.b_id = '0;
|
||||
assign br_master.b_last = 1'b1;
|
||||
// assign br_master.r_id = '0;
|
||||
// assign br_master.r_last = 1'b1;
|
||||
// assign br_master.b_id = '0;
|
||||
|
||||
/////////////////////////////
|
||||
// CLINT
|
||||
|
@ -332,10 +331,10 @@ module serpent_peripherals #(
|
|||
ariane_axi::resp_t clint_axi_resp;
|
||||
|
||||
clint #(
|
||||
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
|
||||
.AxiDataWidth ( AxiDataWidth ),
|
||||
.AXI_ID_WIDTH ( AxiIdWidth ),
|
||||
.NR_CORES ( 1 )
|
||||
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
|
||||
.AXI_DATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI_ID_WIDTH ( AxiIdWidth ),
|
||||
.NR_CORES ( NumHarts )
|
||||
) i_clint (
|
||||
.clk_i ,
|
||||
.rst_ni ,
|
||||
|
@ -406,9 +405,6 @@ module serpent_peripherals #(
|
|||
assign clint_axi_req.ar.prot = '0;
|
||||
assign clint_axi_req.ar.qos = '0;
|
||||
assign clint_axi_req.ar.region = '0;
|
||||
assign clint_axi_resp.r.id = '0;
|
||||
assign clint_axi_resp.r.last = 1'b1;
|
||||
assign clint_axi_resp.b.id = '0;
|
||||
|
||||
|
||||
// /////////////////////////////
|
||||
|
@ -490,10 +486,9 @@ module serpent_peripherals #(
|
|||
// assign plic_master.ar_prot = '0;
|
||||
// assign plic_master.ar_qos = '0;
|
||||
// assign plic_master.ar_region = '0;
|
||||
// assign plic_master.r_id = '0;
|
||||
// assign plic_master.r_last = 1'b1;
|
||||
// assign plic_master.b_id = '0;
|
||||
// assign plic_master.b_last = 1'b1;
|
||||
// //assign plic_master.r_id = '0;
|
||||
// //assign plic_master.r_last = 1'b1;
|
||||
// //assign plic_master.b_id = '0;
|
||||
|
||||
// REG_BUS #(
|
||||
// .ADDR_WIDTH ( 40 ),
|
||||
|
|
|
@ -29,10 +29,10 @@ import instruction_tracer_pkg::*;
|
|||
|
||||
module ariane #(
|
||||
`ifdef SERPENT_PULP
|
||||
parameter bit SWAP_ENDIANESS = 0, // swap endianess in l15 adapter
|
||||
parameter bit CACHE_LOW_REGION = 0, // cached region is below CACHE_START_ADDR
|
||||
parameter bit SwapEndianess = 0, // swap endianess in l15 adapter
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
|
||||
`endif
|
||||
parameter logic [63:0] CACHE_START_ADDR = 64'h8000_0000 // address on which to decide whether the request is cache-able or not
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000 // begin of cached region
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -580,9 +580,9 @@ module ariane #(
|
|||
`ifdef SERPENT_PULP
|
||||
// this is a cache subsystem that is compatible with OpenPiton
|
||||
serpent_cache_subsystem #(
|
||||
.CACHE_START_ADDR ( CACHE_START_ADDR ),
|
||||
.CACHE_LOW_REGION ( CACHE_LOW_REGION ),
|
||||
.SWAP_ENDIANESS ( SWAP_ENDIANESS )
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd ),
|
||||
.SwapEndianess ( SwapEndianess )
|
||||
) i_cache_subsystem (
|
||||
// to D$
|
||||
.clk_i ( clk_i ),
|
||||
|
@ -620,7 +620,7 @@ module ariane #(
|
|||
`else
|
||||
|
||||
std_cache_subsystem #(
|
||||
.CACHE_START_ADDR ( CACHE_START_ADDR )
|
||||
.CACHE_START_ADDR ( CachedAddrBeg )
|
||||
) i_cache_subsystem (
|
||||
// to D$
|
||||
.clk_i ( clk_i ),
|
||||
|
|
|
@ -28,11 +28,11 @@ import serpent_cache_pkg::*;
|
|||
|
||||
module serpent_cache_subsystem #(
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
parameter int unsigned AXI_ID_WIDTH = 10,
|
||||
parameter int unsigned AxiIdWidth = 10,
|
||||
`endif
|
||||
parameter logic [63:0] CACHE_START_ADDR = 64'h4000_0000, // threshold that determines where the cached region begins
|
||||
parameter bit CACHE_LOW_REGION = 0, // cached region is below CACHE_START_ADDR
|
||||
parameter bit SWAP_ENDIANESS = 0 // swap endianess in l15 adapter
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
|
||||
parameter bit SwapEndianess = 0 // swap endianess in l15 adapter
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -89,12 +89,12 @@ l15_rtrn_t l15_rtrn;
|
|||
|
||||
serpent_icache #(
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
.AXI64BIT_COMPLIANT ( 1'b1 ),
|
||||
.AXI64BIT_COMPLIANT ( 1'b1 ),
|
||||
`endif
|
||||
// use ID 0 for icache reads
|
||||
.RD_TX_ID ( 0 ),
|
||||
.NC_ADDR_GE_LT ( CACHE_LOW_REGION ),
|
||||
.NC_ADDR_BEGIN ( CACHE_START_ADDR )
|
||||
.RdTxId ( 0 ),
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd )
|
||||
) i_serpent_icache (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -120,9 +120,9 @@ serpent_icache #(
|
|||
serpent_dcache #(
|
||||
// use ID 1 for dcache reads and amos. note that the writebuffer
|
||||
// uses all IDs up to DCACHE_MAX_TX-1 for write transactions.
|
||||
.RD_AMO_TX_ID ( 1 ),
|
||||
.NC_ADDR_GE_LT ( CACHE_LOW_REGION ),
|
||||
.NC_ADDR_BEGIN ( CACHE_START_ADDR )
|
||||
.RdAmoTxId ( 1 ),
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd )
|
||||
) i_serpent_dcache (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -145,7 +145,9 @@ serpent_dcache #(
|
|||
|
||||
// arbiter/adapter
|
||||
serpent_l15_adapter #(
|
||||
.SWAP_ENDIANESS ( SWAP_ENDIANESS )
|
||||
.SwapEndianess ( SwapEndianess ),
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd )
|
||||
) i_adapter (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -177,17 +179,17 @@ serpent_l15_adapter #(
|
|||
`ifdef AXI64_CACHE_PORTS
|
||||
|
||||
// support up to 512bit cache lines
|
||||
localparam AXI_NUM_WORDS = 8;
|
||||
localparam AxiNumWords = 8;
|
||||
|
||||
logic axi_rd_req, axi_rd_gnt;
|
||||
logic [63:0] axi_rd_addr, axi_wr_addr;
|
||||
logic [$clog2(AXI_NUM_WORDS)-1:0] axi_rd_blen, axi_wr_blen;
|
||||
logic [$clog2(AxiNumWords)-1:0] axi_rd_blen, axi_wr_blen;
|
||||
logic [1:0] axi_rd_size, axi_wr_size;
|
||||
logic [AXI_ID_WIDTH-1:0] axi_rd_id_in, axi_wr_id_in, axi_rd_id_out, axi_wr_id_out;
|
||||
logic [AxiIdWidth-1:0] axi_rd_id_in, axi_wr_id_in, axi_rd_id_out, axi_wr_id_out;
|
||||
logic axi_rd_valid;
|
||||
logic [AXI_NUM_WORDS-1:0][63:0] axi_rd_data, axi_wr_data;
|
||||
logic [AxiNumWords-1:0][63:0] axi_rd_data, axi_wr_data;
|
||||
logic [63:0] axi_rd_word;
|
||||
logic [AXI_NUM_WORDS-1:0][7:0] axi_wr_be;
|
||||
logic [AxiNumWords-1:0][7:0] axi_wr_be;
|
||||
logic axi_rd_word_valid, axi_rd_word_cnt, axi_wr_req, axi_wr_gnt;
|
||||
logic axi_wr_valid, axi_rd_rdy, axi_wr_rdy;
|
||||
|
||||
|
@ -253,8 +255,8 @@ always_comb begin : p_axi_rtrn
|
|||
end
|
||||
|
||||
axi_adapter2 #(
|
||||
.DATA_WORDS ( AXI_NUM_WORDS ),
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH )
|
||||
.DATA_WORDS ( AxiNumWords ),
|
||||
.AXI_ID_WIDTH ( AxiIdWidth )
|
||||
) i_axi_adapter (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -298,7 +300,7 @@ axi_adapter2 #(
|
|||
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
initial begin
|
||||
assert (AXI_ID_WIDTH >= $clog2(serpent_cache_pkg::DCACHE_MAX_TX)+2) else
|
||||
assert (AxiIdWidth >= $clog2(serpent_cache_pkg::DCACHE_MAX_TX)+2) else
|
||||
$fatal(1,$psprintf("[l1 cache] AXI ID must be at least %01d bit wide", $clog2(serpent_cache_pkg::DCACHE_MAX_TX)+2));
|
||||
end
|
||||
`endif
|
||||
|
|
|
@ -18,9 +18,9 @@ import serpent_cache_pkg::*;
|
|||
module serpent_dcache #(
|
||||
// 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 [DCACHE_ID_WIDTH-1:0] RD_AMO_TX_ID = 1,
|
||||
parameter int unsigned NC_ADDR_BEGIN = 40'h8000000000, // start address of noncacheable I/O region
|
||||
parameter bit NC_ADDR_GE_LT = 1'b1 // determines how the physical address is compared with NC_ADDR_BEGIN
|
||||
parameter logic [DCACHE_ID_WIDTH-1:0] RdAmoTxId = 1,
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000 // end of cached region
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
@ -48,7 +48,7 @@ module serpent_dcache #(
|
|||
);
|
||||
|
||||
// LD unit and PTW
|
||||
localparam NUM_PORTS = 3;
|
||||
localparam NumPorts = 3;
|
||||
|
||||
// miss unit <-> read controllers
|
||||
logic cache_en;
|
||||
|
@ -71,37 +71,37 @@ module serpent_dcache #(
|
|||
logic [7:0] wr_data_be;
|
||||
|
||||
// miss unit <-> controllers/wbuffer
|
||||
logic [NUM_PORTS-1:0] miss_req;
|
||||
logic [NUM_PORTS-1:0] miss_ack;
|
||||
logic [NUM_PORTS-1:0] miss_nc;
|
||||
logic [NUM_PORTS-1:0] miss_we;
|
||||
logic [NUM_PORTS-1:0][63:0] miss_wdata;
|
||||
logic [NUM_PORTS-1:0][63:0] miss_paddr;
|
||||
logic [NUM_PORTS-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits;
|
||||
logic [NUM_PORTS-1:0][2:0] miss_size;
|
||||
logic [NUM_PORTS-1:0][DCACHE_ID_WIDTH-1:0] miss_id;
|
||||
logic [NUM_PORTS-1:0] miss_replay;
|
||||
logic [NUM_PORTS-1:0] miss_rtrn_vld;
|
||||
logic [DCACHE_ID_WIDTH-1:0] miss_rtrn_id;
|
||||
logic [NumPorts-1:0] miss_req;
|
||||
logic [NumPorts-1:0] miss_ack;
|
||||
logic [NumPorts-1:0] miss_nc;
|
||||
logic [NumPorts-1:0] miss_we;
|
||||
logic [NumPorts-1:0][63:0] miss_wdata;
|
||||
logic [NumPorts-1:0][63:0] miss_paddr;
|
||||
logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits;
|
||||
logic [NumPorts-1:0][2:0] miss_size;
|
||||
logic [NumPorts-1:0][DCACHE_ID_WIDTH-1:0] miss_id;
|
||||
logic [NumPorts-1:0] miss_replay;
|
||||
logic [NumPorts-1:0] miss_rtrn_vld;
|
||||
logic [DCACHE_ID_WIDTH-1:0] miss_rtrn_id;
|
||||
|
||||
// memory <-> read controllers/miss unit
|
||||
logic [NUM_PORTS-1:0] rd_prio;
|
||||
logic [NUM_PORTS-1:0] rd_tag_only;
|
||||
logic [NUM_PORTS-1:0] rd_req;
|
||||
logic [NUM_PORTS-1:0] rd_ack;
|
||||
logic [NUM_PORTS-1:0][DCACHE_TAG_WIDTH-1:0] rd_tag;
|
||||
logic [NUM_PORTS-1:0][DCACHE_CL_IDX_WIDTH-1:0] rd_idx;
|
||||
logic [NUM_PORTS-1:0][DCACHE_OFFSET_WIDTH-1:0] rd_off;
|
||||
logic [63:0] rd_data;
|
||||
logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits;
|
||||
logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh;
|
||||
logic [NumPorts-1:0] rd_prio;
|
||||
logic [NumPorts-1:0] rd_tag_only;
|
||||
logic [NumPorts-1:0] rd_req;
|
||||
logic [NumPorts-1:0] rd_ack;
|
||||
logic [NumPorts-1:0][DCACHE_TAG_WIDTH-1:0] rd_tag;
|
||||
logic [NumPorts-1:0][DCACHE_CL_IDX_WIDTH-1:0] rd_idx;
|
||||
logic [NumPorts-1:0][DCACHE_OFFSET_WIDTH-1:0] rd_off;
|
||||
logic [63:0] rd_data;
|
||||
logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits;
|
||||
logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh;
|
||||
|
||||
// miss unit <-> wbuffer
|
||||
logic [DCACHE_MAX_TX-1:0][63:0] tx_paddr;
|
||||
logic [DCACHE_MAX_TX-1:0] tx_vld;
|
||||
logic [DCACHE_MAX_TX-1:0][63:0] tx_paddr;
|
||||
logic [DCACHE_MAX_TX-1:0] tx_vld;
|
||||
|
||||
// wbuffer <-> memory
|
||||
wbuffer_t [DCACHE_WBUF_DEPTH-1:0] wbuffer_data;
|
||||
wbuffer_t [DCACHE_WBUF_DEPTH-1:0] wbuffer_data;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
@ -109,8 +109,8 @@ module serpent_dcache #(
|
|||
///////////////////////////////////////////////////////
|
||||
|
||||
serpent_dcache_missunit #(
|
||||
.AMO_TX_ID( RD_AMO_TX_ID ),
|
||||
.NUM_PORTS( NUM_PORTS )
|
||||
.AmoTxId ( RdAmoTxId ),
|
||||
.NumPorts ( NumPorts )
|
||||
) i_serpent_dcache_missunit (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -163,14 +163,14 @@ module serpent_dcache #(
|
|||
|
||||
generate
|
||||
// note: last read port is used by the write buffer
|
||||
for(genvar k=0; k<NUM_PORTS-1; k++) begin
|
||||
for(genvar k=0; k<NumPorts-1; k++) begin
|
||||
// set these to high prio ports
|
||||
assign rd_prio[k] = 1'b1;
|
||||
|
||||
serpent_dcache_ctrl #(
|
||||
.RD_TX_ID ( RD_AMO_TX_ID ),
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.NC_ADDR_GE_LT ( NC_ADDR_GE_LT ))
|
||||
.RdTxId ( RdAmoTxId ),
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd ))
|
||||
i_serpent_dcache_ctrl (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -214,8 +214,8 @@ module serpent_dcache #(
|
|||
assign rd_prio[2] = 1'b0;
|
||||
|
||||
serpent_dcache_wbuffer #(
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.NC_ADDR_GE_LT ( NC_ADDR_GE_LT ))
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd ))
|
||||
i_serpent_dcache_wbuffer (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -269,7 +269,7 @@ module serpent_dcache #(
|
|||
///////////////////////////////////////////////////////
|
||||
|
||||
serpent_dcache_mem #(
|
||||
.NUM_PORTS(NUM_PORTS)
|
||||
.NumPorts(NumPorts)
|
||||
) i_serpent_dcache_mem (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
|
|
@ -17,9 +17,9 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_dcache_ctrl #(
|
||||
parameter logic [DCACHE_ID_WIDTH-1:0] RD_TX_ID = 1, // ID to use for read transactions
|
||||
parameter int unsigned NC_ADDR_BEGIN = 40'h8000000000, // start address of noncacheable I/O region
|
||||
parameter bit NC_ADDR_GE_LT = 1'b1 // determines how the physical address is compared with NC_ADDR_BEGIN
|
||||
parameter logic [DCACHE_ID_WIDTH-1:0] RdTxId = 1, // ID to use for read transactions
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000 // end of cached region
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
@ -85,18 +85,13 @@ module serpent_dcache_ctrl #(
|
|||
assign miss_paddr_o = {address_tag_q, address_idx_q, address_off_q};
|
||||
assign miss_size_o = (miss_nc_o) ? data_size_q : 3'b111;
|
||||
|
||||
generate
|
||||
if (NC_ADDR_GE_LT) begin : g_nc_addr_high
|
||||
assign miss_nc_o = (address_tag_q >= (NC_ADDR_BEGIN>>DCACHE_INDEX_WIDTH)) | ~cache_en_i;
|
||||
end
|
||||
if (~NC_ADDR_GE_LT) begin : g_nc_addr_low
|
||||
assign miss_nc_o = (address_tag_q < (NC_ADDR_BEGIN>>DCACHE_INDEX_WIDTH)) | ~cache_en_i;
|
||||
end
|
||||
endgenerate
|
||||
assign miss_nc_o = (address_tag_q < (CachedAddrBeg>>DCACHE_INDEX_WIDTH)) ||
|
||||
(address_tag_q >= (CachedAddrEnd>>DCACHE_INDEX_WIDTH)) ||
|
||||
(!cache_en_i);
|
||||
|
||||
assign miss_we_o = '0;
|
||||
assign miss_wdata_o = '0;
|
||||
assign miss_id_o = RD_TX_ID;
|
||||
assign miss_id_o = RdTxId;
|
||||
assign rd_req_d = rd_req_o;
|
||||
assign rd_ack_d = rd_ack_i;
|
||||
assign rd_tag_only_o = '0;
|
||||
|
|
|
@ -29,19 +29,19 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_dcache_mem #(
|
||||
parameter int unsigned NUM_PORTS = 3
|
||||
parameter int unsigned NumPorts = 3
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
// ports
|
||||
input logic [NUM_PORTS-1:0][DCACHE_TAG_WIDTH-1:0] rd_tag_i, // tag in - comes one cycle later
|
||||
input logic [NUM_PORTS-1:0][DCACHE_CL_IDX_WIDTH-1:0] rd_idx_i,
|
||||
input logic [NUM_PORTS-1:0][DCACHE_OFFSET_WIDTH-1:0] rd_off_i,
|
||||
input logic [NUM_PORTS-1:0] rd_req_i, // read the word at offset off_i[:3] in all ways
|
||||
input logic [NUM_PORTS-1:0] rd_tag_only_i, // only do a tag/valid lookup, no access to data arrays
|
||||
input logic [NUM_PORTS-1:0] rd_prio_i, // 0: low prio, 1: high prio
|
||||
output logic [NUM_PORTS-1:0] rd_ack_o,
|
||||
input logic [NumPorts-1:0][DCACHE_TAG_WIDTH-1:0] rd_tag_i, // tag in - comes one cycle later
|
||||
input logic [NumPorts-1:0][DCACHE_CL_IDX_WIDTH-1:0] rd_idx_i,
|
||||
input logic [NumPorts-1:0][DCACHE_OFFSET_WIDTH-1:0] rd_off_i,
|
||||
input logic [NumPorts-1:0] rd_req_i, // read the word at offset off_i[:3] in all ways
|
||||
input logic [NumPorts-1:0] rd_tag_only_i, // only do a tag/valid lookup, no access to data arrays
|
||||
input logic [NumPorts-1:0] rd_prio_i, // 0: low prio, 1: high prio
|
||||
output logic [NumPorts-1:0] rd_ack_o,
|
||||
output logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits_o,
|
||||
output logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh_o,
|
||||
output logic [63:0] rd_data_o,
|
||||
|
@ -88,7 +88,7 @@ module serpent_dcache_mem #(
|
|||
logic [DCACHE_SET_ASSOC-1:0][DCACHE_TAG_WIDTH-1:0] tag_rdata; // these are the tags coming from the tagmem
|
||||
logic [DCACHE_CL_IDX_WIDTH-1:0] vld_addr; // valid bit
|
||||
|
||||
logic [$clog2(NUM_PORTS)-1:0] vld_sel_d, vld_sel_q;
|
||||
logic [$clog2(NumPorts)-1:0] vld_sel_d, vld_sel_q;
|
||||
|
||||
logic [DCACHE_WBUF_DEPTH-1:0] wbuffer_hit_oh;
|
||||
logic [7:0] wbuffer_be;
|
||||
|
@ -97,7 +97,7 @@ module serpent_dcache_mem #(
|
|||
|
||||
logic cmp_en_d, cmp_en_q;
|
||||
logic rd_acked;
|
||||
logic [NUM_PORTS-1:0] bank_collision, rd_req_masked, rd_req_prio;
|
||||
logic [NumPorts-1:0] bank_collision, rd_req_masked, rd_req_prio;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// arbiter
|
||||
|
@ -139,7 +139,7 @@ module serpent_dcache_mem #(
|
|||
|
||||
// read port arbiter
|
||||
rrarbiter #(
|
||||
.NUM_REQ(NUM_PORTS)
|
||||
.NUM_REQ(NumPorts)
|
||||
) i_rrarbiter (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -159,7 +159,7 @@ module serpent_dcache_mem #(
|
|||
bank_we = '0;
|
||||
bank_idx = '{default:wr_idx_i};
|
||||
|
||||
for(int k=0; k<NUM_PORTS; k++) begin
|
||||
for(int k=0; k<NumPorts; k++) begin
|
||||
bank_collision[k] = rd_off_i[k][DCACHE_OFFSET_WIDTH-1:3] == wr_off_i[DCACHE_OFFSET_WIDTH-1:3];
|
||||
end
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_dcache_missunit #(
|
||||
parameter logic [DCACHE_ID_WIDTH-1:0] AMO_TX_ID = 1, // TX id to be used for AMOs
|
||||
parameter int unsigned NUM_PORTS = 3 // number of miss ports
|
||||
parameter logic [DCACHE_ID_WIDTH-1:0] AmoTxId = 1, // TX id to be used for AMOs
|
||||
parameter int unsigned NumPorts = 3 // number of miss ports
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
@ -35,19 +35,19 @@ module serpent_dcache_missunit #(
|
|||
input amo_req_t amo_req_i,
|
||||
output amo_resp_t amo_resp_o,
|
||||
// miss handling interface (ld, ptw, wbuffer)
|
||||
input logic [NUM_PORTS-1:0] miss_req_i,
|
||||
output logic [NUM_PORTS-1:0] miss_ack_o,
|
||||
input logic [NUM_PORTS-1:0] miss_nc_i,
|
||||
input logic [NUM_PORTS-1:0] miss_we_i,
|
||||
input logic [NUM_PORTS-1:0][63:0] miss_wdata_i,
|
||||
input logic [NUM_PORTS-1:0][63:0] miss_paddr_i,
|
||||
input logic [NUM_PORTS-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits_i,
|
||||
input logic [NUM_PORTS-1:0][2:0] miss_size_i,
|
||||
input logic [NUM_PORTS-1:0][DCACHE_ID_WIDTH-1:0] miss_id_i, // used as transaction ID
|
||||
input logic [NumPorts-1:0] miss_req_i,
|
||||
output logic [NumPorts-1:0] miss_ack_o,
|
||||
input logic [NumPorts-1:0] miss_nc_i,
|
||||
input logic [NumPorts-1:0] miss_we_i,
|
||||
input logic [NumPorts-1:0][63:0] miss_wdata_i,
|
||||
input logic [NumPorts-1:0][63:0] miss_paddr_i,
|
||||
input logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits_i,
|
||||
input logic [NumPorts-1:0][2:0] miss_size_i,
|
||||
input logic [NumPorts-1:0][DCACHE_ID_WIDTH-1:0] miss_id_i, // used as transaction ID
|
||||
// signals that the request collided with a pending read
|
||||
output logic [NUM_PORTS-1:0] miss_replay_o,
|
||||
output logic [NumPorts-1:0] miss_replay_o,
|
||||
// signals response from memory
|
||||
output logic [NUM_PORTS-1:0] miss_rtrn_vld_o,
|
||||
output logic [NumPorts-1:0] miss_rtrn_vld_o,
|
||||
output logic [DCACHE_ID_WIDTH-1:0] miss_rtrn_id_o, // only used for writes, set to zero fro reads
|
||||
// from writebuffer
|
||||
input logic [DCACHE_MAX_TX-1:0][63:0] tx_paddr_i, // used to check for address collisions with read operations
|
||||
|
@ -82,7 +82,7 @@ module serpent_dcache_missunit #(
|
|||
logic [DCACHE_ID_WIDTH-1:0] id ;
|
||||
logic nc ;
|
||||
logic [$clog2(DCACHE_SET_ASSOC)-1:0] repl_way;
|
||||
logic [$clog2(NUM_PORTS)-1:0] miss_port_idx;
|
||||
logic [$clog2(NumPorts)-1:0] miss_port_idx;
|
||||
} mshr_t;
|
||||
|
||||
mshr_t mshr_d, mshr_q;
|
||||
|
@ -98,15 +98,15 @@ module serpent_dcache_missunit #(
|
|||
logic amo_sel, miss_is_write;
|
||||
logic [63:0] amo_data, tmp_paddr;
|
||||
|
||||
logic [$clog2(NUM_PORTS)-1:0] miss_port_idx;
|
||||
logic [$clog2(NumPorts)-1:0] miss_port_idx;
|
||||
logic [DCACHE_CL_IDX_WIDTH-1:0] cnt_d, cnt_q;
|
||||
logic [NUM_PORTS-1:0] miss_req_masked_d, miss_req_masked_q;
|
||||
logic [NumPorts-1:0] miss_req_masked_d, miss_req_masked_q;
|
||||
|
||||
logic inv_vld, inv_vld_all, cl_write_en;
|
||||
logic load_ack, store_ack, amo_ack;
|
||||
|
||||
logic [NUM_PORTS-1:0] mshr_rdrd_collision_d, mshr_rdrd_collision_q;
|
||||
logic [NUM_PORTS-1:0] mshr_rdrd_collision;
|
||||
logic [NumPorts-1:0] mshr_rdrd_collision_d, mshr_rdrd_collision_q;
|
||||
logic [NumPorts-1:0] mshr_rdrd_collision;
|
||||
logic tx_rdwr_collision, mshr_rdwr_collision;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
@ -123,7 +123,7 @@ module serpent_dcache_missunit #(
|
|||
|
||||
// read port arbiter
|
||||
lzc #(
|
||||
.WIDTH ( NUM_PORTS )
|
||||
.WIDTH ( NumPorts )
|
||||
) i_lzc_reqs (
|
||||
.in_i ( miss_req_masked_d ),
|
||||
.cnt_o ( miss_port_idx ),
|
||||
|
@ -178,7 +178,7 @@ module serpent_dcache_missunit #(
|
|||
|
||||
|
||||
generate
|
||||
for(genvar k=0; k<NUM_PORTS; k++) begin
|
||||
for(genvar k=0; k<NumPorts; k++) begin
|
||||
assign mshr_rdrd_collision[k] = (mshr_q.paddr[63:DCACHE_OFFSET_WIDTH] == miss_paddr_i[k][63:DCACHE_OFFSET_WIDTH]) && (mshr_vld_q | mshr_vld_q1);
|
||||
assign mshr_rdrd_collision_d[k] = (~miss_req_i[k]) ? 1'b0 : mshr_rdrd_collision_q[k] | mshr_rdrd_collision[k];
|
||||
end
|
||||
|
@ -186,7 +186,7 @@ module serpent_dcache_missunit #(
|
|||
|
||||
// read/write collision, stalls the corresponding request
|
||||
// write collides with MSHR
|
||||
assign mshr_rdwr_collision = (mshr_q.paddr[63:DCACHE_OFFSET_WIDTH] == miss_paddr_i[NUM_PORTS-1][63:DCACHE_OFFSET_WIDTH]) && mshr_vld_q;
|
||||
assign mshr_rdwr_collision = (mshr_q.paddr[63:DCACHE_OFFSET_WIDTH] == miss_paddr_i[NumPorts-1][63:DCACHE_OFFSET_WIDTH]) && mshr_vld_q;
|
||||
|
||||
// read collides with inflight TX
|
||||
always_comb begin : p_tx_coll
|
||||
|
@ -210,7 +210,7 @@ module serpent_dcache_missunit #(
|
|||
mem_rtrn_i.data[63:0];
|
||||
|
||||
// outgoing memory requests (AMOs are always uncached)
|
||||
assign mem_data_o.tid = (amo_sel) ? AMO_TX_ID : miss_id_i[miss_port_idx];
|
||||
assign mem_data_o.tid = (amo_sel) ? AmoTxId : miss_id_i[miss_port_idx];
|
||||
assign mem_data_o.nc = (amo_sel) ? 1'b1 : miss_nc_i[miss_port_idx];
|
||||
assign mem_data_o.way = (amo_sel) ? '0 : repl_way;
|
||||
assign mem_data_o.data = (amo_sel) ? amo_data : miss_wdata_i[miss_port_idx];
|
||||
|
@ -240,7 +240,7 @@ module serpent_dcache_missunit #(
|
|||
end
|
||||
DCACHE_STORE_ACK: begin
|
||||
store_ack = 1'b1;
|
||||
miss_rtrn_vld_o[NUM_PORTS-1] = 1'b1;
|
||||
miss_rtrn_vld_o[NumPorts-1] = 1'b1;
|
||||
end
|
||||
DCACHE_ATOMIC_ACK: begin
|
||||
amo_ack = 1'b1;
|
||||
|
@ -486,16 +486,16 @@ end
|
|||
else $fatal(1,"[l1 dcache missunit] TID of load response doesn't match");
|
||||
|
||||
read_ports : assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) |miss_req_i[NUM_PORTS-2:0] |-> miss_we_i[NUM_PORTS-2:0] == 0)
|
||||
@(posedge clk_i) disable iff (~rst_ni) |miss_req_i[NumPorts-2:0] |-> miss_we_i[NumPorts-2:0] == 0)
|
||||
else $fatal(1,"[l1 dcache missunit] only last port can issue write requests");
|
||||
|
||||
write_port : assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) miss_req_i[NUM_PORTS-1] |-> miss_we_i[NUM_PORTS-1])
|
||||
@(posedge clk_i) disable iff (~rst_ni) miss_req_i[NumPorts-1] |-> miss_we_i[NumPorts-1])
|
||||
else $fatal(1,"[l1 dcache missunit] last port can only issue write requests");
|
||||
|
||||
initial begin
|
||||
// assert wrong parameterizations
|
||||
assert (NUM_PORTS>=2)
|
||||
assert (NumPorts>=2)
|
||||
else $fatal(1,"[l1 dcache missunit] at least two ports are required (one read port, one write port)");
|
||||
end
|
||||
`endif
|
||||
|
|
|
@ -52,8 +52,8 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_dcache_wbuffer #(
|
||||
parameter int unsigned NC_ADDR_BEGIN = 40'h8000000000, // start address of noncacheable I/O region
|
||||
parameter bit NC_ADDR_GE_LT = 1'b1 // determines how the physical address is compared with NC_ADDR_BEGIN
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000 // end of cached region
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
@ -136,14 +136,9 @@ logic [63:0] debug_paddr [DCACHE_WBUF_DEPTH-1:0];
|
|||
|
||||
assign miss_nc_o = nc_pending_q;
|
||||
|
||||
generate
|
||||
if (NC_ADDR_GE_LT) begin : g_nc_addr_high
|
||||
assign addr_is_nc = (req_port_i.address_tag >= (NC_ADDR_BEGIN>>DCACHE_INDEX_WIDTH)) | ~cache_en_i;
|
||||
end
|
||||
if (~NC_ADDR_GE_LT) begin : g_nc_addr_low
|
||||
assign addr_is_nc = (req_port_i.address_tag < (NC_ADDR_BEGIN>>DCACHE_INDEX_WIDTH)) | ~cache_en_i;
|
||||
end
|
||||
endgenerate
|
||||
assign addr_is_nc = (req_port_i.address_tag < (CachedAddrBeg>>DCACHE_INDEX_WIDTH)) ||
|
||||
(req_port_i.address_tag >= (CachedAddrEnd>>DCACHE_INDEX_WIDTH)) ||
|
||||
(!cache_en_i);
|
||||
|
||||
assign miss_we_o = 1'b1;
|
||||
assign miss_vld_bits_o = '0;
|
||||
|
|
|
@ -32,13 +32,11 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_icache #(
|
||||
parameter logic [DCACHE_ID_WIDTH-1:0] RD_TX_ID = 0, // ID to be used for read transactions
|
||||
parameter int unsigned NC_ADDR_BEGIN = 40'h8000000000, // start address of noncacheable I/O region
|
||||
parameter bit AXI64BIT_COMPLIANT = 1'b0, // set this to 1 when using in conjunction with 64bit AXI bus adapter
|
||||
parameter bit NC_ADDR_GE_LT = 1'b1 // determines how the physical address is compared with NC_ADDR_BEGIN
|
||||
// NC_ADDR_GE_LT == 0 -> if paddr < NC_ADDR_BEGIN -> NC
|
||||
// NC_ADDR_GE_LT == 1 -> if paddr >= NC_ADDR_BEGIN -> NC
|
||||
)(
|
||||
parameter logic [DCACHE_ID_WIDTH-1:0] RdTxId = 0, // ID to be used for read transactions
|
||||
parameter bit Axi64BitCompliant = 1'b0, // set this to 1 when using in conjunction with 64bit AXI bus adapter
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000 // end of cached region
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
|
@ -109,14 +107,9 @@ module serpent_icache #(
|
|||
assign cl_tag_d = (areq_i.fetch_valid) ? areq_i.fetch_paddr[ICACHE_TAG_WIDTH+ICACHE_INDEX_WIDTH-1:ICACHE_INDEX_WIDTH] : cl_tag_q;
|
||||
|
||||
// noncacheable if request goes to I/O space, or if cache is disabled
|
||||
generate
|
||||
if (NC_ADDR_GE_LT) begin : g_nc_addr_high
|
||||
assign paddr_is_nc = (cl_tag_d >= (NC_ADDR_BEGIN>>ICACHE_INDEX_WIDTH)) | ~cache_en_q;
|
||||
end
|
||||
if (~NC_ADDR_GE_LT) begin : g_nc_addr_low
|
||||
assign paddr_is_nc = (cl_tag_d < (NC_ADDR_BEGIN>>ICACHE_INDEX_WIDTH)) | ~cache_en_q;
|
||||
end
|
||||
endgenerate
|
||||
assign paddr_is_nc = (cl_tag_d < (CachedAddrBeg>>ICACHE_INDEX_WIDTH)) ||
|
||||
(cl_tag_d >= (CachedAddrEnd>>ICACHE_INDEX_WIDTH)) ||
|
||||
(!cache_en_q);
|
||||
|
||||
// pass exception through
|
||||
assign dreq_o.ex = areq_i.fetch_exception;
|
||||
|
@ -130,19 +123,19 @@ module serpent_icache #(
|
|||
assign cl_index = vaddr_d[ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH];
|
||||
|
||||
generate
|
||||
if(AXI64BIT_COMPLIANT)begin
|
||||
if(Axi64BitCompliant)begin
|
||||
// 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
|
||||
cl_offset_q;
|
||||
// request word address instead of cl address in case of NC access
|
||||
assign mem_data_o.paddr = (paddr_is_nc) ? {cl_tag_d, vaddr_q[ICACHE_INDEX_WIDTH-1:2], 2'b0} : // align to 32bit
|
||||
assign mem_data_o.paddr = (paddr_is_nc) ? {cl_tag_d, vaddr_q[ICACHE_INDEX_WIDTH-1:3], 3'b0} : // align to 32bit
|
||||
{cl_tag_d, vaddr_q[ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH], {ICACHE_OFFSET_WIDTH{1'b0}}}; // align to cl
|
||||
end
|
||||
if(!AXI64BIT_COMPLIANT)begin
|
||||
// if we generate a noncacheable access, the word will be at offset 0 in the cl coming from memory
|
||||
if(!Axi64BitCompliant)begin
|
||||
// icache fills are either cachelines or 4byte fills, depending on whether they go to the Piton I/O space or not.
|
||||
// since the piton cache system replicates the data, we can always index the full CL
|
||||
assign cl_offset_d = ( dreq_o.ready & dreq_i.req) ? {dreq_i.vaddr>>2, 2'b0} :
|
||||
( paddr_is_nc & mem_data_req_o ) ? '0 :
|
||||
cl_offset_q;
|
||||
|
||||
// request word address instead of cl address in case of NC access
|
||||
|
@ -151,7 +144,7 @@ module serpent_icache #(
|
|||
end
|
||||
endgenerate
|
||||
|
||||
assign mem_data_o.tid = RD_TX_ID;
|
||||
assign mem_data_o.tid = RdTxId;
|
||||
|
||||
assign mem_data_o.nc = paddr_is_nc;
|
||||
// way that is being replaced
|
||||
|
|
|
@ -56,8 +56,11 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_l15_adapter #(
|
||||
parameter SWAP_ENDIANESS = 1
|
||||
)(
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000, // begin of cached region
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
|
||||
parameter bit SwapEndianess = 1 ,
|
||||
parameter bit PitonRemapIO = 1 // for OpenPiton
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
|
@ -116,20 +119,29 @@ l15_rtrn_t rtrn_fifo_data;
|
|||
// logic [63:0] l15_req_o.l15_data_next_entry; // unused in Ariane (only used for CAS atomic requests)
|
||||
// logic [L15_TLB_CSM_WIDTH-1:0] l15_req_o.l15_csm_data;
|
||||
|
||||
logic [63:0] tmp_paddr;
|
||||
|
||||
assign icache_data_ack_o = icache_data_req_i & ~icache_data_full;
|
||||
assign dcache_data_ack_o = dcache_data_req_i & ~dcache_data_full;
|
||||
|
||||
// data mux
|
||||
assign l15_req_o.l15_nc = (arb_idx) ? dcache_data.nc : icache_data.nc;
|
||||
// icache fills are either cachelines or 4byte fills, depending on whether they go to the Piton I/O space or not.
|
||||
assign l15_req_o.l15_size = (arb_idx) ? dcache_data.size :
|
||||
(icache_data.nc) ? 3'b10 : 3'b111;// NC ifills are always 4byte
|
||||
assign l15_req_o.l15_threadid = (arb_idx) ? dcache_data.tid : icache_data.tid;
|
||||
(icache_data.nc) ? 3'b010 : 3'b111;
|
||||
assign l15_req_o.l15_threadid = (arb_idx) ? dcache_data.tid : icache_data.tid;
|
||||
assign l15_req_o.l15_prefetch = '0; // unused in openpiton
|
||||
assign l15_req_o.l15_invalidate_cacheline = '0; // unused by Ariane as L1 has no ECC at the moment
|
||||
assign l15_req_o.l15_blockstore = '0; // unused in openpiton
|
||||
assign l15_req_o.l15_blockinitstore = '0; // unused in openpiton
|
||||
assign l15_req_o.l15_l1rplway = (arb_idx) ? dcache_data.way : icache_data.way;
|
||||
assign l15_req_o.l15_address = (arb_idx) ? dcache_data.paddr : icache_data.paddr;
|
||||
// assign tmp_paddr = (arb_idx) ? dcache_data.paddr :
|
||||
// icache_data.paddr;
|
||||
|
||||
// assign l15_req_o.l15_address = ((tmp_paddr < CachedAddrBeg) && PitonRemapIO) ? {25'b1, tmp_paddr[38:0]} : tmp_paddr;
|
||||
assign l15_req_o.l15_address = (arb_idx) ? dcache_data.paddr :
|
||||
icache_data.paddr;
|
||||
|
||||
assign l15_req_o.l15_data_next_entry = '0; // unused in Ariane (only used for CAS atomic requests)
|
||||
assign l15_req_o.l15_csm_data = '0; // unused in Ariane (only used for coherence domain restriction features)
|
||||
assign l15_req_o.l15_amo_op = dcache_data.amo_op;
|
||||
|
@ -137,8 +149,8 @@ assign l15_req_o.l15_amo_op = dcache_data.amo_op;
|
|||
|
||||
// openpiton is big endian
|
||||
generate
|
||||
if (SWAP_ENDIANESS) assign l15_req_o.l15_data = swendian64(dcache_data.data);
|
||||
else assign l15_req_o.l15_data = dcache_data.data;
|
||||
if (SwapEndianess) assign l15_req_o.l15_data = swendian64(dcache_data.data);
|
||||
else assign l15_req_o.l15_data = dcache_data.data;
|
||||
endgenerate
|
||||
|
||||
// arbiter
|
||||
|
@ -295,7 +307,7 @@ end
|
|||
|
||||
// openpiton is big endian
|
||||
generate
|
||||
if (SWAP_ENDIANESS) begin
|
||||
if (SwapEndianess) begin
|
||||
assign dcache_rtrn_o.data = { swendian64(rtrn_fifo_data.l15_data_1),
|
||||
swendian64(rtrn_fifo_data.l15_data_0) };
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// Instantiates an AXI-Bus and memories
|
||||
|
||||
module ariane_testharness #(
|
||||
parameter logic [63:0] CACHE_START_ADDR = 64'h8000_0000, // address on which to decide whether the request is cache-able or not
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h8000_0000, // address on which to decide whether the request is cache-able or not
|
||||
parameter int unsigned AXI_ID_WIDTH = 4,
|
||||
parameter int unsigned AXI_USER_WIDTH = 1,
|
||||
parameter int unsigned AXI_ADDRESS_WIDTH = 64,
|
||||
|
@ -329,7 +329,7 @@ module ariane_testharness #(
|
|||
ariane_axi::resp_t axi_ariane_resp;
|
||||
|
||||
ariane #(
|
||||
.CACHE_START_ADDR ( CACHE_START_ADDR )
|
||||
.CachedAddrBeg ( CachedAddrBeg )
|
||||
) i_ariane (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( ndmreset_n ),
|
||||
|
|
|
@ -38,22 +38,22 @@ module tb;
|
|||
timeprecision 1ps;
|
||||
|
||||
// memory configuration (64bit words)
|
||||
parameter MEM_BYTES = 2**DCACHE_INDEX_WIDTH * 4 * 32;
|
||||
parameter MEM_WORDS = MEM_BYTES>>3;
|
||||
parameter MemBytes = 2**DCACHE_INDEX_WIDTH * 4 * 32;
|
||||
parameter MemWords = MemBytes>>3;
|
||||
// noncacheable portion
|
||||
parameter NC_ADDR_BEGIN = MEM_BYTES>>3;//1/8th of the memory is NC
|
||||
parameter NC_ADDR_GE_LT = 0;
|
||||
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 MEM_RAND_HIT_RATE = 75;
|
||||
parameter MEM_RAND_INV_RATE = 10;
|
||||
parameter TLB_HIT_RATE = 95;
|
||||
parameter MemRandHitRate = 75;
|
||||
parameter MemRandInvRate = 10;
|
||||
parameter TlbHitRate = 95;
|
||||
|
||||
// parameters for random read sequences (in %)
|
||||
parameter FLUSH_RATE = 10;
|
||||
parameter KILL_RATE = 5;
|
||||
parameter FlushRate = 10;
|
||||
parameter KillRate = 5;
|
||||
|
||||
parameter VERBOSE = 0;
|
||||
parameter Verbose = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MUT signal declarations
|
||||
|
@ -78,7 +78,7 @@ module tb;
|
|||
// TB signal declarations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
logic [63:0] mem_array[MEM_WORDS-1:0];
|
||||
logic [63:0] mem_array[MemWords-1:0];
|
||||
|
||||
string test_name;
|
||||
logic clk_i, rst_ni;
|
||||
|
@ -170,11 +170,11 @@ module tb;
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tb_mem #(
|
||||
.MEM_RAND_HIT_RATE ( MEM_RAND_HIT_RATE ),
|
||||
.MEM_RAND_INV_RATE ( MEM_RAND_INV_RATE ),
|
||||
.MEM_WORDS ( MEM_WORDS ),
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.NC_ADDR_GE_LT ( NC_ADDR_GE_LT )
|
||||
.MemRandHitRate ( MemRandHitRate ),
|
||||
.MemRandInvRate ( MemRandInvRate ),
|
||||
.MemWords ( MemWords ),
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd )
|
||||
) i_tb_mem (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -204,8 +204,8 @@ module tb;
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
serpent_dcache #(
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.NC_ADDR_GE_LT ( NC_ADDR_GE_LT )
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd )
|
||||
) i_dut (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -268,14 +268,15 @@ module tb;
|
|||
endgenerate
|
||||
|
||||
tb_readport #(
|
||||
.PORT_NAME ( "RD0" ),
|
||||
.FLUSH_RATE ( FLUSH_RATE ),
|
||||
.KILL_RATE ( KILL_RATE ),
|
||||
.TLB_HIT_RATE ( TLB_HIT_RATE ),
|
||||
.MEM_WORDS ( MEM_WORDS ),
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.RND_SEED ( 5555555 ),
|
||||
.VERBOSE ( VERBOSE )
|
||||
.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 ),
|
||||
|
@ -300,14 +301,15 @@ module tb;
|
|||
);
|
||||
|
||||
tb_readport #(
|
||||
.PORT_NAME ( "RD1" ),
|
||||
.FLUSH_RATE ( FLUSH_RATE ),
|
||||
.KILL_RATE ( KILL_RATE ),
|
||||
.TLB_HIT_RATE ( TLB_HIT_RATE ),
|
||||
.MEM_WORDS ( MEM_WORDS ),
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.RND_SEED ( 3333333 ),
|
||||
.VERBOSE ( VERBOSE )
|
||||
.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 ),
|
||||
|
@ -332,11 +334,12 @@ module tb;
|
|||
);
|
||||
|
||||
tb_writeport #(
|
||||
.PORT_NAME ( "WR0" ),
|
||||
.MEM_WORDS ( MEM_WORDS ),
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.RND_SEED ( 7777777 ),
|
||||
.VERBOSE ( VERBOSE )
|
||||
.PortName ( "WR0" ),
|
||||
.MemWords ( MemWords ),
|
||||
.CachedAddrBeg ( CachedAddrBeg ),
|
||||
.CachedAddrEnd ( CachedAddrEnd ),
|
||||
.RndSeed ( 7777777 ),
|
||||
.Verbose ( Verbose )
|
||||
) i_tb_writeport (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -406,10 +409,11 @@ module tb;
|
|||
|
||||
// print some info
|
||||
$display("TB> current configuration:");
|
||||
$display("TB> MEM_WORDS %d", MEM_WORDS);
|
||||
$display("TB> NC_ADDR_BEGIN %16X", NC_ADDR_BEGIN);
|
||||
$display("TB> MEM_RAND_HIT_RATE %d", MEM_RAND_HIT_RATE);
|
||||
$display("TB> MEM_RAND_INV_RATE %d", MEM_RAND_INV_RATE);
|
||||
$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)
|
||||
|
@ -546,9 +550,9 @@ module tb;
|
|||
inv_rand_en = 0;
|
||||
seq_type = '{IDLE_SEQ, IDLE_SEQ, LINEAR_SEQ};
|
||||
req_rate = '{default:100};
|
||||
runSeq((NC_ADDR_BEGIN>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC,0);
|
||||
runSeq((CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC,0);
|
||||
seq_type = '{LINEAR_SEQ, IDLE_SEQ, IDLE_SEQ};
|
||||
runSeq(0,(NC_ADDR_BEGIN>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC,1);
|
||||
runSeq(0,(CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC,1);
|
||||
flushCache();
|
||||
memCheck();
|
||||
///////////////////////////////////////////////
|
||||
|
|
|
@ -25,13 +25,13 @@ import serpent_cache_pkg::*;
|
|||
import tb_pkg::*;
|
||||
|
||||
module tb_mem #(
|
||||
parameter string MEM_NAME = "TB_MEM",
|
||||
parameter MEM_RAND_HIT_RATE = 10, //in percent
|
||||
parameter MEM_RAND_INV_RATE = 5, //in percent
|
||||
parameter MEM_WORDS = 1024*1024,// in 64bit words
|
||||
parameter NC_ADDR_BEGIN = MEM_WORDS/2,
|
||||
parameter NC_ADDR_GE_LT = 1'b1
|
||||
)(
|
||||
parameter string MemName = "TB_MEM",
|
||||
parameter MemRandHitRate = 10, //in percent
|
||||
parameter MemRandInvRate = 5, //in percent
|
||||
parameter MemWords = 1024*1024,// in 64bit words
|
||||
parameter logic [63:0] CachedAddrBeg = MemWords/2,
|
||||
parameter logic [63:0] CachedAddrEnd = 64'hFFFF_FFFF_FFFF_FFFF
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
// randomization settings
|
||||
|
@ -54,7 +54,7 @@ module tb_mem #(
|
|||
input logic [7:0] write_be_i,
|
||||
input logic [63:0] write_data_i,
|
||||
input logic [63:0] write_paddr_i,
|
||||
output logic [63:0] mem_array_o[MEM_WORDS-1:0]
|
||||
output logic [63:0] mem_array_o[MemWords-1:0]
|
||||
);
|
||||
|
||||
// leave this
|
||||
|
@ -72,13 +72,13 @@ module tb_mem #(
|
|||
logic initialized_q;
|
||||
logic write_en;
|
||||
|
||||
logic [63:0] mem_array_q[MEM_WORDS-1:0];
|
||||
logic [63:0] mem_array_q[MemWords-1:0];
|
||||
|
||||
// this shadow memory provides a view that is consistent with the one from the core
|
||||
// i.e., pending writes are present in this view, and invalidations will not overwrite
|
||||
// the corresponding bytes until they have been commited to the normal memory.
|
||||
logic [63:0] mem_array_shadow_q[MEM_WORDS-1:0];
|
||||
logic [7:0] mem_array_dirty_q[MEM_WORDS-1:0];
|
||||
logic [63:0] mem_array_shadow_q[MemWords-1:0];
|
||||
logic [7:0] mem_array_dirty_q[MemWords-1:0];
|
||||
|
||||
assign mem_array_o = mem_array_shadow_q;
|
||||
|
||||
|
@ -132,7 +132,7 @@ module tb_mem #(
|
|||
end else begin
|
||||
mem_array_dirty_q <= '{default:'0};
|
||||
|
||||
for (int k=0; k<MEM_WORDS; k++) begin
|
||||
for (int k=0; k<MemWords; k++) begin
|
||||
void'(randomize(val));
|
||||
mem_array_q[k] <= val;
|
||||
mem_array_shadow_q[k] <= val;
|
||||
|
@ -144,7 +144,7 @@ module tb_mem #(
|
|||
// generate random contentions
|
||||
if (mem_rand_en_i) begin
|
||||
void'(randomize(rnd) with {rnd > 0; rnd <= 100;});
|
||||
if(rnd < MEM_RAND_HIT_RATE) begin
|
||||
if(rnd < MemRandHitRate) begin
|
||||
mem_ready_q <= '1;
|
||||
end else begin
|
||||
mem_ready_q <= '0;
|
||||
|
@ -156,9 +156,9 @@ module tb_mem #(
|
|||
// generate random invalidations
|
||||
if (inv_rand_en_i) begin
|
||||
void'(randomize(rnd) with {rnd > 0; rnd <= 100;});
|
||||
if(rnd < MEM_RAND_INV_RATE) begin
|
||||
if(rnd < MemRandInvRate) begin
|
||||
mem_inv_q <= '1;
|
||||
void'(randomize(lval) with {lval>=0; lval<(MEM_WORDS>>3);});
|
||||
void'(randomize(lval) with {lval>=0; lval<(MemWords>>3);});
|
||||
void'(randomize(val));
|
||||
rand_addr_q <= lval<<3;
|
||||
|
||||
|
@ -300,35 +300,35 @@ module tb_mem #(
|
|||
initial begin
|
||||
bit ok;
|
||||
progress status;
|
||||
status = new(MEM_NAME);
|
||||
status = new(MemName);
|
||||
|
||||
`ACQ_WAIT_CYC(clk_i,10)
|
||||
`ACQ_WAIT_SIG(clk_i,~rst_ni)
|
||||
|
||||
while(~seq_last_i) begin
|
||||
`ACQ_WAIT_SIG(clk_i,check_en_i)
|
||||
status.reset(MEM_WORDS);
|
||||
status.reset(MemWords);
|
||||
// crosscheck whether shadow and real memory arrays still match
|
||||
for(int k=0; k<MEM_WORDS; k++) begin
|
||||
for(int k=0; k<MemWords; k++) begin
|
||||
ok = (mem_array_q[k] == mem_array_shadow_q[k]) && !(|mem_array_dirty_q[k]);
|
||||
if(!ok) begin
|
||||
$display("%s> dirty bytes at k=%016X: real[k>>3]=%016X, shadow[k>>3]=%016X, dirty[k>>3]=%02X",
|
||||
MEM_NAME, k<<3, mem_array_q[k], mem_array_shadow_q[k], mem_array_dirty_q[k]);
|
||||
MemName, k<<3, mem_array_q[k], mem_array_shadow_q[k], mem_array_dirty_q[k]);
|
||||
end
|
||||
status.addRes(!ok);
|
||||
status.print();
|
||||
end
|
||||
end
|
||||
status.printToFile({MEM_NAME, "_summary.rep"}, 1);
|
||||
status.printToFile({MemName, "_summary.rep"}, 1);
|
||||
|
||||
if(status.totErrCnt == 0) begin
|
||||
$display("%s> ----------------------------------------------------------------------", MEM_NAME);
|
||||
$display("%s> PASSED %0d VECTORS", MEM_NAME, status.totAcqCnt);
|
||||
$display("%s> ----------------------------------------------------------------------\n", MEM_NAME);
|
||||
$display("%s> ----------------------------------------------------------------------", MemName);
|
||||
$display("%s> PASSED %0d VECTORS", MemName, status.totAcqCnt);
|
||||
$display("%s> ----------------------------------------------------------------------\n", MemName);
|
||||
end else begin
|
||||
$display("%s> ----------------------------------------------------------------------\n", MEM_NAME);
|
||||
$display("%s> FAILED %0d OF %0d VECTORS\n", MEM_NAME , status.totErrCnt, status.totAcqCnt);
|
||||
$display("%s> ----------------------------------------------------------------------\n", MEM_NAME);
|
||||
$display("%s> ----------------------------------------------------------------------\n", MemName);
|
||||
$display("%s> FAILED %0d OF %0d VECTORS\n", MemName , status.totErrCnt, status.totAcqCnt);
|
||||
$display("%s> ----------------------------------------------------------------------\n", MemName);
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -342,18 +342,9 @@ module tb_mem #(
|
|||
//pragma translate_off
|
||||
`ifndef verilator
|
||||
|
||||
generate
|
||||
if (NC_ADDR_GE_LT) begin : g_nc_addr_high
|
||||
nc_region: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) mem_data_req_i |-> mem_data_i.paddr >= NC_ADDR_BEGIN |-> mem_data_i.nc)
|
||||
else $fatal(1, "cached access into noncached region");
|
||||
end
|
||||
if (~NC_ADDR_GE_LT) begin : g_nc_addr_low
|
||||
nc_region: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) mem_data_req_i |-> mem_data_i.paddr < NC_ADDR_BEGIN |-> mem_data_i.nc)
|
||||
else $fatal(1, "cached access into noncached region");
|
||||
end
|
||||
endgenerate
|
||||
nc_region: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) mem_data_req_i |-> mem_data_i.paddr >= CachedAddrEnd || mem_data_i.paddr < CachedAddrBeg |-> mem_data_i.nc)
|
||||
else $fatal(1, "cached access into noncached region");
|
||||
|
||||
cached_reads: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) mem_data_req_i |-> mem_data_i.rtype==DCACHE_LOAD_REQ |-> ~mem_data_i.nc |-> mem_data_i.size == 3'b111)
|
||||
|
@ -368,19 +359,10 @@ module tb_mem #(
|
|||
else $fatal(1, "write size can only be one of the following: byte, halfword, word, dword");
|
||||
|
||||
addr_range: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) mem_data_req_i |-> mem_data_i.rtype inside {DCACHE_STORE_REQ, DCACHE_STORE_REQ} |-> mem_data_i.paddr < (MEM_WORDS<<3))
|
||||
@(posedge clk_i) disable iff (~rst_ni) mem_data_req_i |-> mem_data_i.rtype inside {DCACHE_STORE_REQ, DCACHE_STORE_REQ} |-> mem_data_i.paddr < (MemWords<<3))
|
||||
else $fatal(1, "address is out of bounds");
|
||||
|
||||
`endif
|
||||
//pragma translate_on
|
||||
|
||||
// align0: assert property (
|
||||
// @(posedge clk_i) disable iff (~rst_ni) ~exp_empty |-> stim_addr[1:0] == 0)
|
||||
// else $fatal(1,"stim_addr is not 32bit word aligned");
|
||||
|
||||
// align1: assert property (
|
||||
// @(posedge clk_i) disable iff (~rst_ni) ~outfifo_empty |-> outfifo_data.paddr[1:0] == 0)
|
||||
// else $fatal(1,"paddr is not 32bit word aligned");
|
||||
|
||||
|
||||
endmodule // mem_emul
|
||||
|
|
|
@ -26,15 +26,16 @@ import serpent_cache_pkg::*;
|
|||
import tb_pkg::*;
|
||||
|
||||
program tb_readport #(
|
||||
parameter string PORT_NAME = "read port 0",
|
||||
parameter FLUSH_RATE = 1,
|
||||
parameter KILL_RATE = 5,
|
||||
parameter TLB_HIT_RATE = 95,
|
||||
parameter MEM_WORDS = 1024*1024,// in 64bit words
|
||||
parameter NC_ADDR_BEGIN = 0,
|
||||
parameter RND_SEED = 1110,
|
||||
parameter VERBOSE = 0
|
||||
)(
|
||||
parameter string PortName = "read port 0",
|
||||
parameter FlushRate = 1,
|
||||
parameter KillRate = 5,
|
||||
parameter TlbHitRate = 95,
|
||||
parameter MemWords = 1024*1024,// in 64bit words
|
||||
parameter logic [63:0] CachedAddrBeg = 0,
|
||||
parameter logic [63:0] CachedAddrEnd = 0,
|
||||
parameter RndSeed = 1110,
|
||||
parameter Verbose = 0
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
|
@ -111,7 +112,7 @@ program tb_readport #(
|
|||
|
||||
if(tlb_rand_en_i) begin
|
||||
void'(randomize(val) with {val>0; val<=100;});
|
||||
if(val>=TLB_HIT_RATE) begin
|
||||
if(val>=TlbHitRate) begin
|
||||
void'(randomize(cnt) with {cnt>0; cnt<=50;});
|
||||
end
|
||||
end
|
||||
|
@ -152,7 +153,7 @@ program tb_readport #(
|
|||
automatic logic [63:0] val;
|
||||
automatic logic [1:0] size;
|
||||
|
||||
void'($urandom(RND_SEED));
|
||||
void'($urandom(RndSeed));
|
||||
|
||||
paddr = '0;
|
||||
dut_req_port_o.data_req = '0;
|
||||
|
@ -164,20 +165,20 @@ program tb_readport #(
|
|||
dut_req_port_o.data_req = '0;
|
||||
// generate random control events
|
||||
void'(randomize(val) with {val > 0; val <= 100;});
|
||||
if(val < KILL_RATE) begin
|
||||
if(val < KillRate) begin
|
||||
dut_req_port_o.kill_req = 1'b1;
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
dut_req_port_o.kill_req = 1'b0;
|
||||
end else begin
|
||||
void'(randomize(val) with {val > 0; val <= 100;});
|
||||
if(val < FLUSH_RATE && flush_rand_en_i) begin
|
||||
if(val < FlushRate && flush_rand_en_i) begin
|
||||
flushCache();
|
||||
end else begin
|
||||
void'(randomize(val) with {val > 0; val <= 100;});
|
||||
if(val < req_rate_i) begin
|
||||
dut_req_port_o.data_req = 1'b1;
|
||||
// generate random address
|
||||
void'(randomize(val) with {val >= 0; val < (MEM_WORDS<<3);});
|
||||
void'(randomize(val) with {val >= 0; val < (MemWords<<3);});
|
||||
void'(randomize(size));
|
||||
|
||||
dut_req_port_o.data_size = size;
|
||||
|
@ -216,7 +217,7 @@ program tb_readport #(
|
|||
dut_req_port_o.data_size = 2'b11;
|
||||
paddr = val;
|
||||
// generate linear read
|
||||
val = (val + 8) % (MEM_WORDS<<3);
|
||||
val = (val + 8) % (MemWords<<3);
|
||||
`APPL_WAIT_COMB_SIG(clk_i, dut_req_port_i.data_gnt)
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
end
|
||||
|
@ -227,7 +228,7 @@ program tb_readport #(
|
|||
|
||||
task automatic genWrapSeq();
|
||||
automatic logic [63:0] val;
|
||||
paddr = NC_ADDR_BEGIN;
|
||||
paddr = CachedAddrBeg;
|
||||
dut_req_port_o.data_req = '0;
|
||||
dut_req_port_o.data_size = '0;
|
||||
dut_req_port_o.kill_req = '0;
|
||||
|
@ -237,7 +238,7 @@ program tb_readport #(
|
|||
dut_req_port_o.data_size = 2'b11;
|
||||
paddr = val;
|
||||
// generate wrapping read of 1 cachelines
|
||||
paddr = NC_ADDR_BEGIN + val;
|
||||
paddr = CachedAddrBeg + val;
|
||||
val = (val + 8) % (1*(DCACHE_LINE_WIDTH/64)*8);
|
||||
`APPL_WAIT_COMB_SIG(clk_i, dut_req_port_i.data_gnt)
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
|
@ -264,29 +265,29 @@ program tb_readport #(
|
|||
flush_o = '0;
|
||||
|
||||
// print some info
|
||||
$display("%s> current configuration:", PORT_NAME);
|
||||
$display("%s> KILL_RATE %d", PORT_NAME, KILL_RATE);
|
||||
$display("%s> FLUSH_RATE %d", PORT_NAME, FLUSH_RATE);
|
||||
$display("%s> TLB_HIT_RATE %d", PORT_NAME, TLB_HIT_RATE);
|
||||
$display("%s> RND_SEED %d", PORT_NAME, RND_SEED);
|
||||
$display("%s> current configuration:", PortName);
|
||||
$display("%s> KillRate %d", PortName, KillRate);
|
||||
$display("%s> FlushRate %d", PortName, FlushRate);
|
||||
$display("%s> TlbHitRate %d", PortName, TlbHitRate);
|
||||
$display("%s> RndSeed %d", PortName, RndSeed);
|
||||
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
`APPL_WAIT_SIG(clk_i,~rst_ni)
|
||||
|
||||
$display("%s> starting application", PORT_NAME);
|
||||
$display("%s> starting application", PortName);
|
||||
while(~seq_last_i) begin
|
||||
`APPL_WAIT_SIG(clk_i,seq_run_i)
|
||||
unique case(seq_type_i)
|
||||
RANDOM_SEQ: begin
|
||||
$display("%s> start random sequence with %04d responses and req_rate %03d", PORT_NAME, seq_num_resp_i, req_rate_i);
|
||||
$display("%s> start random sequence with %04d responses and req_rate %03d", PortName, seq_num_resp_i, req_rate_i);
|
||||
genRandReq();
|
||||
end
|
||||
LINEAR_SEQ: begin
|
||||
$display("%s> start linear sequence with %04d responses and req_rate %03d", PORT_NAME, seq_num_resp_i, req_rate_i);
|
||||
$display("%s> start linear sequence with %04d responses and req_rate %03d", PortName, seq_num_resp_i, req_rate_i);
|
||||
genSeqRead();
|
||||
end
|
||||
WRAP_SEQ: begin
|
||||
$display("%s> start wrapping sequence with %04d responses and req_rate %03d", PORT_NAME, seq_num_resp_i, req_rate_i);
|
||||
$display("%s> start wrapping sequence with %04d responses and req_rate %03d", PortName, seq_num_resp_i, req_rate_i);
|
||||
genWrapSeq();
|
||||
end
|
||||
IDLE_SEQ: begin
|
||||
|
@ -297,11 +298,11 @@ program tb_readport #(
|
|||
end
|
||||
endcase // seq_type_i
|
||||
seq_end_ack = 1'b1;
|
||||
$display("%s> stop sequence", PORT_NAME);
|
||||
$display("%s> stop sequence", PortName);
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
seq_end_ack = 1'b0;
|
||||
end
|
||||
$display("%s> ending application", PORT_NAME);
|
||||
$display("%s> ending application", PortName);
|
||||
end
|
||||
|
||||
|
||||
|
@ -317,7 +318,7 @@ program tb_readport #(
|
|||
logic [63:0] exp_rdata, exp_paddr;
|
||||
logic [1:0] exp_size;
|
||||
|
||||
status = new(PORT_NAME);
|
||||
status = new(PortName);
|
||||
failingTests = "";
|
||||
seq_done_o = 1'b0;
|
||||
seq_end_req = 1'b0;
|
||||
|
@ -333,7 +334,7 @@ program tb_readport #(
|
|||
`ACQ_WAIT_SIG(clk_i,seq_run_i)
|
||||
seq_done_o = 1'b0;
|
||||
|
||||
$display("%s> %s", PORT_NAME, test_name_i);
|
||||
$display("%s> %s", PortName, test_name_i);
|
||||
status.reset(seq_num_resp_i);
|
||||
for (int k=0;k<seq_num_resp_i && seq_type_i != IDLE_SEQ;k++) begin
|
||||
`ACQ_WAIT_SIG(clk_i, (dut_req_port_i.data_rvalid & ~dut_req_port_o.kill_req))
|
||||
|
@ -349,17 +350,17 @@ program tb_readport #(
|
|||
// note: wildcard as defined in right operand!
|
||||
ok=(dut_req_port_i.data_rdata ==? exp_rdata) && (exp_paddr_i == act_paddr_i);
|
||||
|
||||
if(VERBOSE | !ok) begin
|
||||
if(Verbose | !ok) begin
|
||||
tmpstr1 = $psprintf("vector: %02d - %06d -- exp_paddr: %16X -- exp_data: %16X -- access size: %01d Byte",
|
||||
n, k, exp_paddr_i, exp_rdata, 2**exp_size_i);
|
||||
tmpstr2 = $psprintf("vector: %02d - %06d -- act_paddr: %16X -- act_data: %16X -- access size: %01d Byte",
|
||||
n, k, act_paddr_i, dut_req_port_i.data_rdata, 2**exp_size_i);
|
||||
$display("%s> %s", PORT_NAME, tmpstr1);
|
||||
$display("%s> %s", PORT_NAME, tmpstr2);
|
||||
$display("%s> %s", PortName, tmpstr1);
|
||||
$display("%s> %s", PortName, tmpstr2);
|
||||
end
|
||||
|
||||
if(!ok) begin
|
||||
failingTests = $psprintf("%s%s> %s\n%s> %s\n", failingTests, PORT_NAME, tmpstr1, PORT_NAME, tmpstr2);
|
||||
failingTests = $psprintf("%s%s> %s\n%s> %s\n", failingTests, PortName, tmpstr1, PortName, tmpstr2);
|
||||
end
|
||||
status.addRes(!ok);
|
||||
status.print();
|
||||
|
@ -374,18 +375,18 @@ program tb_readport #(
|
|||
end
|
||||
///////////////////////////////////////////////
|
||||
|
||||
status.printToFile({PORT_NAME, "_summary.rep"}, 1);
|
||||
status.printToFile({PortName, "_summary.rep"}, 1);
|
||||
|
||||
if(status.totErrCnt == 0) begin
|
||||
$display("%s> ----------------------------------------------------------------------", PORT_NAME);
|
||||
$display("%s> PASSED %0d VECTORS", PORT_NAME, status.totAcqCnt);
|
||||
$display("%s> ----------------------------------------------------------------------\n", PORT_NAME);
|
||||
$display("%s> ----------------------------------------------------------------------", PortName);
|
||||
$display("%s> PASSED %0d VECTORS", PortName, status.totAcqCnt);
|
||||
$display("%s> ----------------------------------------------------------------------\n", PortName);
|
||||
end else begin
|
||||
$display("%s> ----------------------------------------------------------------------\n", PORT_NAME);
|
||||
$display("%s> FAILED %0d OF %0d VECTORS\n", PORT_NAME , status.totErrCnt, status.totAcqCnt);
|
||||
$display("%s> failing tests:", PORT_NAME);
|
||||
$display("%s> ----------------------------------------------------------------------\n", PortName);
|
||||
$display("%s> FAILED %0d OF %0d VECTORS\n", PortName , status.totErrCnt, status.totAcqCnt);
|
||||
$display("%s> failing tests:", PortName);
|
||||
$display("%s", failingTests);
|
||||
$display("%s> ----------------------------------------------------------------------\n", PORT_NAME);
|
||||
$display("%s> ----------------------------------------------------------------------\n", PortName);
|
||||
end
|
||||
prog_end = 1'b1;
|
||||
end
|
||||
|
|
|
@ -25,12 +25,13 @@ import serpent_cache_pkg::*;
|
|||
import tb_pkg::*;
|
||||
|
||||
program tb_writeport #(
|
||||
parameter string PORT_NAME = "write port 0",
|
||||
parameter MEM_WORDS = 1024*1024,// in 64bit words
|
||||
parameter NC_ADDR_BEGIN = 0,
|
||||
parameter RND_SEED = 1110,
|
||||
parameter VERBOSE = 0
|
||||
)(
|
||||
parameter string PortName = "write port 0",
|
||||
parameter MemWords = 1024*1024,// in 64bit words
|
||||
parameter logic [63:0] CachedAddrBeg = 0,
|
||||
parameter logic [63:0] CachedAddrEnd = 0,
|
||||
parameter RndSeed = 1110,
|
||||
parameter Verbose = 0
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
|
@ -96,7 +97,7 @@ program tb_writeport #(
|
|||
task automatic genRandReq();
|
||||
automatic logic [63:0] val;
|
||||
|
||||
void'($urandom(RND_SEED));
|
||||
void'($urandom(RndSeed));
|
||||
|
||||
paddr = '0;
|
||||
dut_req_port_o.data_req = '0;
|
||||
|
@ -113,7 +114,7 @@ program tb_writeport #(
|
|||
if(val < req_rate_i) begin
|
||||
dut_req_port_o.data_req = 1'b1;
|
||||
// generate random address
|
||||
void'(randomize(paddr) with {paddr >= 0; paddr < (MEM_WORDS<<3);});
|
||||
void'(randomize(paddr) with {paddr >= 0; paddr < (MemWords<<3);});
|
||||
applyRandData();
|
||||
`APPL_WAIT_COMB_SIG(clk_i, dut_req_port_i.data_gnt)
|
||||
end
|
||||
|
@ -143,7 +144,7 @@ program tb_writeport #(
|
|||
dut_req_port_o.data_wdata = val;
|
||||
paddr = val;
|
||||
// generate linear read
|
||||
val = (val + 8) % (MEM_WORDS<<3);
|
||||
val = (val + 8) % (MemWords<<3);
|
||||
`APPL_WAIT_COMB_SIG(clk_i, dut_req_port_i.data_gnt)
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
end
|
||||
|
@ -157,9 +158,9 @@ program tb_writeport #(
|
|||
|
||||
task automatic genWrapSeq();
|
||||
automatic logic [63:0] val;
|
||||
void'($urandom(RND_SEED));
|
||||
void'($urandom(RndSeed));
|
||||
|
||||
paddr = NC_ADDR_BEGIN;
|
||||
paddr = CachedAddrBeg;
|
||||
dut_req_port_o.data_req = '0;
|
||||
dut_req_port_o.data_size = '0;
|
||||
dut_req_port_o.data_be = '0;
|
||||
|
@ -169,7 +170,7 @@ program tb_writeport #(
|
|||
dut_req_port_o.data_req = 1'b1;
|
||||
applyRandData();
|
||||
// generate wrapping read of 1 cacheline
|
||||
paddr = NC_ADDR_BEGIN + val;
|
||||
paddr = CachedAddrBeg + val;
|
||||
val = (val + 8) % (1*(DCACHE_LINE_WIDTH/64)*8);
|
||||
`APPL_WAIT_COMB_SIG(clk_i, dut_req_port_i.data_gnt)
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
|
@ -188,7 +189,7 @@ program tb_writeport #(
|
|||
automatic logic [1:0] size;
|
||||
automatic int cnt, burst_len;
|
||||
|
||||
void'($urandom(RND_SEED));
|
||||
void'($urandom(RndSeed));
|
||||
|
||||
paddr = '0;
|
||||
dut_req_port_o.data_req = '0;
|
||||
|
@ -205,11 +206,11 @@ program tb_writeport #(
|
|||
if(val < req_rate_i) begin
|
||||
dut_req_port_o.data_req = 1'b1;
|
||||
// generate random address base
|
||||
void'(randomize(paddr) with {paddr >= 0; paddr < (MEM_WORDS<<3);});
|
||||
void'(randomize(paddr) with {paddr >= 0; paddr < (MemWords<<3);});
|
||||
|
||||
// do a random burst
|
||||
void'(randomize(burst_len) with {burst_len >= 0; burst_len < 100;});
|
||||
for(int k=0; k<burst_len && cnt < seq_num_vect_i && paddr < ((MEM_WORDS-1)<<3); k++) begin
|
||||
for(int k=0; k<burst_len && cnt < seq_num_vect_i && paddr < ((MemWords-1)<<3); k++) begin
|
||||
applyRandData();
|
||||
`APPL_WAIT_COMB_SIG(clk_i, dut_req_port_i.data_gnt)
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
|
@ -247,40 +248,40 @@ program tb_writeport #(
|
|||
seq_done_o = 1'b0;
|
||||
|
||||
// print some info
|
||||
$display("%s> current configuration:", PORT_NAME);
|
||||
$display("%s> RND_SEED %d", PORT_NAME, RND_SEED);
|
||||
$display("%s> current configuration:", PortName);
|
||||
$display("%s> RndSeed %d", PortName, RndSeed);
|
||||
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
`APPL_WAIT_SIG(clk_i,~rst_ni)
|
||||
|
||||
$display("%s> starting application", PORT_NAME);
|
||||
$display("%s> starting application", PortName);
|
||||
while(~seq_last_i) begin
|
||||
`APPL_WAIT_SIG(clk_i,seq_run_i)
|
||||
seq_done_o = 1'b0;
|
||||
unique case(seq_type_i)
|
||||
RANDOM_SEQ: begin
|
||||
$display("%s> start random sequence with %04d vectors and req_rate %03d", PORT_NAME, seq_num_vect_i, req_rate_i);
|
||||
$display("%s> start random sequence with %04d vectors and req_rate %03d", PortName, seq_num_vect_i, req_rate_i);
|
||||
genRandReq();
|
||||
end
|
||||
LINEAR_SEQ: begin
|
||||
$display("%s> start linear sequence with %04d vectors and req_rate %03d", PORT_NAME, seq_num_vect_i, req_rate_i);
|
||||
$display("%s> start linear sequence with %04d vectors and req_rate %03d", PortName, seq_num_vect_i, req_rate_i);
|
||||
genSeqWrite();
|
||||
end
|
||||
WRAP_SEQ: begin
|
||||
$display("%s> start wrapping sequence with %04d vectors and req_rate %03d", PORT_NAME, seq_num_vect_i, req_rate_i);
|
||||
$display("%s> start wrapping sequence with %04d vectors and req_rate %03d", PortName, seq_num_vect_i, req_rate_i);
|
||||
genWrapSeq();
|
||||
end
|
||||
IDLE_SEQ: ;// do nothing
|
||||
BURST_SEQ: begin
|
||||
$display("%s> start burst sequence with %04d vectors and req_rate %03d", PORT_NAME, seq_num_vect_i, req_rate_i);
|
||||
$display("%s> start burst sequence with %04d vectors and req_rate %03d", PortName, seq_num_vect_i, req_rate_i);
|
||||
genSeqBurst();
|
||||
end
|
||||
endcase // seq_type_i
|
||||
seq_done_o = 1'b1;
|
||||
$display("%s> stop sequence", PORT_NAME);
|
||||
$display("%s> stop sequence", PortName);
|
||||
`APPL_WAIT_CYC(clk_i,1)
|
||||
end
|
||||
$display("%s> ending application", PORT_NAME);
|
||||
$display("%s> ending application", PortName);
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
|
|
@ -21,10 +21,10 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module mem_emul #(
|
||||
parameter MEM_RAND_HIT_RATE = 10, //in percent
|
||||
parameter MEM_RAND_INV_RATE = 5, //in percent
|
||||
parameter MEM_DEPTH = 1024*1024,// in 32bit words
|
||||
parameter NC_ADDR_BEGIN = MEM_DEPTH/2
|
||||
parameter MemRandHitRate = 10, //in percent
|
||||
parameter MemRandInvRate = 5, //in percent
|
||||
parameter MemWords = 1024*1024,// in 32bit words
|
||||
parameter logic [63:0] CachedAddrBeg = MemWords/2
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -61,8 +61,8 @@ module mem_emul #(
|
|||
logic [63:0] stim_addr;
|
||||
logic exp_empty;
|
||||
|
||||
logic [31:0] mem_array [MEM_DEPTH-1:0];
|
||||
logic [31:0] mem_array_shadow [MEM_DEPTH-1:0];
|
||||
logic [31:0] mem_array [MemWords-1:0];
|
||||
logic [31:0] mem_array_shadow [MemWords-1:0];
|
||||
logic initialized_q;
|
||||
|
||||
logic [31:0] inval_addr_queue[$];
|
||||
|
@ -84,7 +84,7 @@ module mem_emul #(
|
|||
|
||||
// fill the memory once with random data
|
||||
if (~initialized_q) begin
|
||||
for (int k=0; k<MEM_DEPTH; k++) begin
|
||||
for (int k=0; k<MemWords; k++) begin
|
||||
ok=randomize(val);
|
||||
mem_array[k] <= val;
|
||||
mem_array_shadow[k] <= val;
|
||||
|
@ -94,7 +94,7 @@ module mem_emul #(
|
|||
|
||||
// re-randomize noncacheable I/O space if requested
|
||||
if (io_rand_en_i) begin
|
||||
for (int k=0; k<NC_ADDR_BEGIN; k++) begin
|
||||
for (int k=0; k<CachedAddrBeg; k++) begin
|
||||
ok = randomize(val);
|
||||
mem_array[k] <= val;
|
||||
end
|
||||
|
@ -103,7 +103,7 @@ module mem_emul #(
|
|||
// generate random contentions
|
||||
if (mem_rand_en_i) begin
|
||||
ok = randomize(rnd) with {rnd > 0; rnd <= 100;};
|
||||
if(rnd < MEM_RAND_HIT_RATE) begin
|
||||
if(rnd < MemRandHitRate) begin
|
||||
mem_ready_q <= '1;
|
||||
end else
|
||||
mem_ready_q <= '0;
|
||||
|
@ -124,9 +124,9 @@ module mem_emul #(
|
|||
end
|
||||
|
||||
ok = randomize(rnd) with {rnd > 0; rnd <= 100;};
|
||||
if(rnd < MEM_RAND_INV_RATE) begin
|
||||
if(rnd < MemRandInvRate) begin
|
||||
mem_inv_q = '1;
|
||||
ok = randomize(lval) with {lval>=0; lval<MEM_DEPTH;};
|
||||
ok = randomize(lval) with {lval>=0; lval<MemWords;};
|
||||
ok = randomize(val);
|
||||
// save for coherent view above
|
||||
inval_addr_queue.push_front(lval);
|
||||
|
|
|
@ -36,21 +36,22 @@ module tb;
|
|||
timeprecision 1ps;
|
||||
|
||||
// number of 32bit words
|
||||
parameter MEM_BYTES = 2**ICACHE_INDEX_WIDTH * 4 * 32;
|
||||
parameter MEM_WORDS = MEM_BYTES>>2;
|
||||
parameter NC_ADDR_BEGIN = MEM_BYTES/4;
|
||||
parameter MemBytes = 2**ICACHE_INDEX_WIDTH * 4 * 32;
|
||||
parameter MemWords = MemBytes>>2;
|
||||
parameter logic [63:0] CachedAddrBeg = MemBytes/4;
|
||||
parameter logic [63:0] CachedAddrEnd = 64'hFFFF_FFFF_FFFF_FFFF;
|
||||
|
||||
// rates are in percent
|
||||
parameter TLB_RAND_HIT_RATE = 50;
|
||||
parameter MEM_RAND_HIT_RATE = 50;
|
||||
parameter MEM_RAND_INV_RATE = 10;
|
||||
parameter TlbRandHitRate = 50;
|
||||
parameter MemRandHitRate = 50;
|
||||
parameter MemRandInvRate = 10;
|
||||
|
||||
parameter REQ_RATE = 90;
|
||||
parameter S1_KILL_RATE = 5;
|
||||
parameter S2_KILL_RATE = 5;
|
||||
parameter FLUSH_RATE = 1;
|
||||
parameter SeqRate = 90;
|
||||
parameter S1KillRate = 5;
|
||||
parameter S2KillRate = 5;
|
||||
parameter FlushRate = 1;
|
||||
|
||||
parameter TLB_OFFSET = 4*1024;//use multiples of 4kB pages!
|
||||
parameter logic [63:0] TlbOffset = 4*1024;//use multiples of 4kB pages!
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -86,7 +87,6 @@ module tb;
|
|||
logic io_rand_en;
|
||||
logic tlb_rand_en;
|
||||
logic exception_en;
|
||||
logic [63:0] tlb_offset;
|
||||
|
||||
logic [63:0] stim_vaddr;
|
||||
logic [63:0] exp_data;
|
||||
|
@ -141,18 +141,18 @@ module tb;
|
|||
// randomize request
|
||||
dreq_i.req = 0;
|
||||
ok = randomize(val) with {val > 0; val <= 100;};
|
||||
if (val < REQ_RATE) begin
|
||||
if (val < SeqRate) begin
|
||||
dreq_i.req = 1;
|
||||
// generate random address
|
||||
ok = randomize(val) with {val >= 0; val < (MEM_BYTES-tlb_offset)>>2;};
|
||||
ok = randomize(val) with {val >= 0; val < (MemBytes-TlbOffset)>>2;};
|
||||
dreq_i.vaddr = val<<2;// align to 4Byte
|
||||
// generate random control events
|
||||
ok = randomize(val) with {val > 0; val <= 100;};
|
||||
dreq_i.kill_s1 = (val < S1_KILL_RATE);
|
||||
dreq_i.kill_s1 = (val < S1KillRate);
|
||||
ok = randomize(val) with {val > 0; val <= 100;};
|
||||
dreq_i.kill_s2 = (val < S2_KILL_RATE);
|
||||
dreq_i.kill_s2 = (val < S2KillRate);
|
||||
ok = randomize(val) with {val > 0; val <= 100;};
|
||||
flush_i = (val < FLUSH_RATE);
|
||||
flush_i = (val < FlushRate);
|
||||
applWait(clk_i, dut_in_rdy);
|
||||
end else begin
|
||||
applWaitCyc(clk_i,1);
|
||||
|
@ -186,7 +186,7 @@ module tb;
|
|||
dreq_i.req = 1;
|
||||
dreq_i.vaddr = addr;
|
||||
// generate linear read
|
||||
addr = (addr + 4) % (MEM_BYTES - tlb_offset);
|
||||
addr = (addr + 4) % (MemBytes - TlbOffset);
|
||||
applWait(clk_i, dut_in_rdy);
|
||||
end
|
||||
stim_end = 1;
|
||||
|
@ -198,30 +198,30 @@ module tb;
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tlb_emul #(
|
||||
.TLB_RAND_HIT_RATE(TLB_RAND_HIT_RATE)
|
||||
.TlbRandHitRate(TlbRandHitRate)
|
||||
) i_tlb_emul (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.tlb_rand_en_i ( tlb_rand_en ),
|
||||
.exception_en_i ( exception_en ),
|
||||
.tlb_offset_i ( tlb_offset ),
|
||||
.tlb_offset_i ( TlbOffset ),
|
||||
// icache interface
|
||||
.req_i ( areq_o ),
|
||||
.req_o ( areq_i )
|
||||
);
|
||||
|
||||
mem_emul #(
|
||||
.MEM_RAND_HIT_RATE ( MEM_RAND_HIT_RATE ),
|
||||
.MEM_RAND_INV_RATE ( MEM_RAND_INV_RATE ),
|
||||
.MEM_DEPTH ( MEM_WORDS ),
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN )
|
||||
.MemRandHitRate ( MemRandHitRate ),
|
||||
.MemRandInvRate ( MemRandInvRate ),
|
||||
.MemWords ( MemWords ),
|
||||
.CachedAddrBeg ( CachedAddrBeg )
|
||||
) i_mem_emul (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.mem_rand_en_i ( mem_rand_en ),
|
||||
.io_rand_en_i ( io_rand_en ),
|
||||
.inv_rand_en_i ( inv_rand_en ),
|
||||
.tlb_offset_i ( tlb_offset ),
|
||||
.tlb_offset_i ( TlbOffset ),
|
||||
.stim_vaddr_i ( stim_vaddr ),
|
||||
.stim_push_i ( stim_push ),
|
||||
.stim_flush_i ( stim_flush ),
|
||||
|
@ -242,8 +242,8 @@ mem_emul #(
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
serpent_icache #(
|
||||
.NC_ADDR_BEGIN(NC_ADDR_BEGIN),
|
||||
.NC_ADDR_GE_LT(0)
|
||||
.CachedAddrBeg(CachedAddrBeg),
|
||||
.CachedAddrEnd(CachedAddrEnd)
|
||||
) dut (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -288,8 +288,6 @@ assign exp_pop = (dreq_o.valid | dreq_i.kill_s2) & (~exp_empty);
|
|||
exception_en = 0;
|
||||
io_rand_en = 0;
|
||||
|
||||
tlb_offset = 0;
|
||||
|
||||
dreq_i.req = 0;
|
||||
dreq_i.kill_s1 = 0;
|
||||
dreq_i.kill_s2 = 0;
|
||||
|
@ -299,18 +297,17 @@ assign exp_pop = (dreq_o.valid | dreq_i.kill_s2) & (~exp_empty);
|
|||
|
||||
// print some info
|
||||
$display("TB> current configuration:");
|
||||
$display("TB> MEM_WORDS %d", MEM_WORDS);
|
||||
$display("TB> NC_ADDR_BEGIN %16X", NC_ADDR_BEGIN);
|
||||
$display("TB> TLB_RAND_HIT_RATE %d", TLB_RAND_HIT_RATE);
|
||||
$display("TB> MEM_RAND_HIT_RATE %d", MEM_RAND_HIT_RATE);
|
||||
$display("TB> MEM_RAND_INV_RATE %d", MEM_RAND_INV_RATE);
|
||||
$display("TB> S1_KILL_RATE %d", S1_KILL_RATE);
|
||||
$display("TB> S2_KILL_RATE %d", S2_KILL_RATE);
|
||||
$display("TB> FLUSH_RATE %d", FLUSH_RATE);
|
||||
$display("TB> MemWords %d", MemWords);
|
||||
$display("TB> CachedAddrBeg %16X", CachedAddrBeg);
|
||||
$display("TB> TlbRandHitRate %d", TlbRandHitRate);
|
||||
$display("TB> MemRandHitRate %d", MemRandHitRate);
|
||||
$display("TB> MemRandInvRate %d", MemRandInvRate);
|
||||
$display("TB> S1KillRate %d", S1KillRate);
|
||||
$display("TB> S2KillRate %d", S2KillRate);
|
||||
$display("TB> FlushRate %d", FlushRate);
|
||||
|
||||
applWaitCyc(clk_i,100);
|
||||
tlb_offset = TLB_OFFSET;
|
||||
$display("TB> choose TLB offset %16X", tlb_offset);
|
||||
$display("TB> choose TLB offset %16X", TlbOffset);
|
||||
|
||||
// reset cycles
|
||||
applWaitCyc(clk_i,100);
|
||||
|
|
|
@ -21,7 +21,7 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module tlb_emul #(
|
||||
parameter TLB_RAND_HIT_RATE = 10 //in percent
|
||||
parameter TlbRandHitRate = 10 //in percent
|
||||
)(
|
||||
|
||||
input logic clk_i,
|
||||
|
@ -42,15 +42,15 @@ always_ff @(posedge clk_i or negedge rst_ni) begin : p_tlb_rand
|
|||
automatic bit ok = 0;
|
||||
automatic int rnd = 0;
|
||||
|
||||
assert(TLB_RAND_HIT_RATE<=100 && TLB_RAND_HIT_RATE>=0) else
|
||||
$fatal("TLB_RAND_HIT_RATE must be a percentage");
|
||||
assert(TlbRandHitRate<=100 && TlbRandHitRate>=0) else
|
||||
$fatal("TlbRandHitRate must be a percentage");
|
||||
|
||||
if(~rst_ni) begin
|
||||
tlb_ready_q <= '0;
|
||||
end else begin
|
||||
if (tlb_rand_en_i) begin
|
||||
ok = randomize(rnd) with {rnd > 0; rnd <= 100;};
|
||||
if(rnd < TLB_RAND_HIT_RATE) begin
|
||||
if(rnd < TlbRandHitRate) begin
|
||||
tlb_ready_q = '1;
|
||||
end else
|
||||
tlb_ready_q = '0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue