mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 21:27:10 -04:00
Use different IDs for read transactions, allow for multiple outstanding reads.
This commit is contained in:
parent
1933f066f3
commit
4431ad5edb
7 changed files with 128 additions and 125 deletions
|
@ -91,6 +91,8 @@ serpent_icache #(
|
|||
`ifdef AXI64_CACHE_PORTS
|
||||
.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 )
|
||||
) i_serpent_icache (
|
||||
|
@ -116,7 +118,10 @@ serpent_icache #(
|
|||
// they have equal prio and are RR arbited
|
||||
// Port 2 is write only and goes into the merging write buffer
|
||||
serpent_dcache #(
|
||||
.NC_ADDR_GE_LT ( CACHE_LOW_REGION ), // std config is for openpiton, where the upper memory region is NC
|
||||
// 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 )
|
||||
) i_serpent_dcache (
|
||||
.clk_i ( clk_i ),
|
||||
|
@ -163,10 +168,12 @@ serpent_l15_adapter #(
|
|||
`endif
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// different memory plumbing to allow for using the
|
||||
// serpent cache subsystem in a standard AXI setting
|
||||
// for verificaton purposes.
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
// different memory plumbing
|
||||
// note that this is a workaround that is mainly used to verify L15 adapter
|
||||
// and serpent cache system with the standard AXI-based testharness
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
|
||||
// support up to 512bit cache lines
|
||||
|
@ -186,29 +193,25 @@ logic axi_wr_valid, axi_rd_rdy, axi_wr_rdy;
|
|||
|
||||
logic ifill;
|
||||
logic [serpent_cache_pkg::L15_TID_WIDTH+2-1:0] id_tmp;
|
||||
logic rd_pending_d, rd_pending_q;
|
||||
|
||||
|
||||
// request side
|
||||
assign ifill = (l15_req.l15_rqtype==serpent_cache_pkg::L15_IMISS_RQ);
|
||||
|
||||
assign axi_rd_req = l15_req.l15_val && (l15_req.l15_rqtype==serpent_cache_pkg::L15_LOAD_RQ | ifill) && !rd_pending_q;
|
||||
assign axi_rd_req = l15_req.l15_val && (l15_req.l15_rqtype==serpent_cache_pkg::L15_LOAD_RQ | ifill);
|
||||
assign axi_wr_req = l15_req.l15_val && (l15_req.l15_rqtype==serpent_cache_pkg::L15_STORE_RQ);
|
||||
|
||||
assign axi_rd_addr = l15_req.l15_address;
|
||||
assign axi_wr_addr = axi_rd_addr;
|
||||
|
||||
// the axi interconnect does not correctly handle the ordering of read responses with same IDs that
|
||||
// go to different slaves. workaround: only allow for one outstanding TX
|
||||
assign rd_pending_d = (axi_rd_valid) ? '0 : axi_rd_gnt;
|
||||
|
||||
assign axi_rd_id_in = {l15_req.l15_threadid, ifill, l15_req.l15_nc};
|
||||
assign axi_wr_id_in = axi_rd_id_in;
|
||||
|
||||
assign axi_rd_size = (ifill) ? 2'b11 : l15_req.l15_size[1:0];// always request 64bit (fix this... at some point)
|
||||
assign axi_rd_size = (ifill) ? 2'b11 : l15_req.l15_size[1:0];// always request 64bit in this case
|
||||
assign axi_wr_size = l15_req.l15_size[1:0];
|
||||
|
||||
assign axi_rd_blen = (l15_req.l15_size[2]) ? ((ifill) ? ariane_pkg::ICACHE_LINE_WIDTH/64-1 :
|
||||
ariane_pkg::DCACHE_LINE_WIDTH/64-1) : '0;
|
||||
ariane_pkg::DCACHE_LINE_WIDTH/64-1) : '0;
|
||||
assign axi_wr_blen = '0;// single word writes
|
||||
|
||||
assign axi_wr_data = l15_req.l15_data;
|
||||
|
@ -250,13 +253,6 @@ always_comb begin : p_axi_rtrn
|
|||
l15_rtrn.l15_data_3 = axi_rd_data[3];
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
||||
if(~rst_ni) begin
|
||||
rd_pending_q <= '0;
|
||||
end else begin
|
||||
rd_pending_q <= rd_pending_d;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
axi_adapter2 #(
|
||||
|
|
|
@ -16,12 +16,15 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_dcache #(
|
||||
parameter 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
|
||||
)(
|
||||
// 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
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
||||
|
||||
// Cache management
|
||||
input logic enable_i, // from CSR
|
||||
input logic flush_i, // high until acknowledged
|
||||
|
@ -32,10 +35,10 @@ module serpent_dcache #(
|
|||
// AMO interface
|
||||
input amo_req_t amo_req_i,
|
||||
output amo_resp_t amo_resp_o,
|
||||
|
||||
|
||||
// Request ports
|
||||
input dcache_req_i_t [2:0] req_ports_i,
|
||||
output dcache_req_o_t [2:0] req_ports_o,
|
||||
input dcache_req_i_t [2:0] req_ports_i,
|
||||
output dcache_req_o_t [2:0] req_ports_o,
|
||||
|
||||
input logic mem_rtrn_vld_i,
|
||||
input dcache_rtrn_t mem_rtrn_i,
|
||||
|
@ -43,8 +46,8 @@ module serpent_dcache #(
|
|||
input logic mem_data_ack_i,
|
||||
output dcache_req_t mem_data_o
|
||||
);
|
||||
|
||||
// LD unit and PTW
|
||||
|
||||
// LD unit and PTW
|
||||
localparam NUM_PORTS = 3;
|
||||
|
||||
// miss unit <-> read controllers
|
||||
|
@ -66,7 +69,7 @@ module serpent_dcache #(
|
|||
logic [DCACHE_OFFSET_WIDTH-1:0] wr_off;
|
||||
logic [63:0] wr_data;
|
||||
logic [7:0] wr_data_be;
|
||||
|
||||
|
||||
// miss unit <-> controllers/wbuffer
|
||||
logic [NUM_PORTS-1:0] miss_req;
|
||||
logic [NUM_PORTS-1:0] miss_ack;
|
||||
|
@ -76,11 +79,11 @@ module serpent_dcache #(
|
|||
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_wr_id;
|
||||
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;
|
||||
|
||||
|
||||
// memory <-> read controllers/miss unit
|
||||
logic [NUM_PORTS-1:0] rd_prio;
|
||||
logic [NUM_PORTS-1:0] rd_tag_only;
|
||||
|
@ -93,20 +96,21 @@ module serpent_dcache #(
|
|||
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;
|
||||
|
||||
// wbuffer <-> memory
|
||||
// miss unit <-> wbuffer
|
||||
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;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// miss handling unit
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
serpent_dcache_missunit #(
|
||||
.NUM_PORTS(NUM_PORTS)
|
||||
.AMO_TX_ID( RD_AMO_TX_ID ),
|
||||
.NUM_PORTS( NUM_PORTS )
|
||||
) i_serpent_dcache_missunit (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -116,10 +120,10 @@ module serpent_dcache #(
|
|||
.miss_o ( miss_o ),
|
||||
.wbuffer_empty_i ( wbuffer_empty_o ),
|
||||
.cache_en_o ( cache_en ),
|
||||
// amo interface
|
||||
// amo interface
|
||||
.amo_req_i ( amo_req_i ),
|
||||
.amo_resp_o ( amo_resp_o ),
|
||||
// miss handling interface
|
||||
// miss handling interface
|
||||
.miss_req_i ( miss_req ),
|
||||
.miss_ack_o ( miss_ack ),
|
||||
.miss_nc_i ( miss_nc ),
|
||||
|
@ -128,14 +132,14 @@ module serpent_dcache #(
|
|||
.miss_paddr_i ( miss_paddr ),
|
||||
.miss_vld_bits_i ( miss_vld_bits ),
|
||||
.miss_size_i ( miss_size ),
|
||||
.miss_wr_id_i ( miss_wr_id ),
|
||||
.miss_id_i ( miss_id ),
|
||||
.miss_replay_o ( miss_replay ),
|
||||
.miss_rtrn_vld_o ( miss_rtrn_vld ),
|
||||
.miss_rtrn_id_o ( miss_rtrn_id ),
|
||||
// from writebuffer
|
||||
.tx_paddr_i ( tx_paddr ),
|
||||
.tx_vld_i ( tx_vld ),
|
||||
// cache memory interface
|
||||
// cache memory interface
|
||||
.wr_cl_vld_o ( wr_cl_vld ),
|
||||
.wr_cl_nc_o ( wr_cl_nc ),
|
||||
.wr_cl_we_o ( wr_cl_we ),
|
||||
|
@ -145,7 +149,7 @@ module serpent_dcache #(
|
|||
.wr_cl_data_o ( wr_cl_data ),
|
||||
.wr_cl_data_be_o ( wr_cl_data_be ),
|
||||
.wr_vld_bits_o ( wr_vld_bits ),
|
||||
// memory interface
|
||||
// memory interface
|
||||
.mem_rtrn_vld_i ( mem_rtrn_vld_i ),
|
||||
.mem_rtrn_i ( mem_rtrn_i ),
|
||||
.mem_data_req_o ( mem_data_req_o ),
|
||||
|
@ -162,10 +166,11 @@ module serpent_dcache #(
|
|||
for(genvar k=0; k<NUM_PORTS-1; k++) begin
|
||||
// set these to high prio ports
|
||||
assign rd_prio[k] = 1'b1;
|
||||
|
||||
|
||||
serpent_dcache_ctrl #(
|
||||
.NC_ADDR_BEGIN(NC_ADDR_BEGIN),
|
||||
.NC_ADDR_GE_LT(NC_ADDR_GE_LT))
|
||||
.RD_TX_ID ( RD_AMO_TX_ID ),
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.NC_ADDR_GE_LT ( NC_ADDR_GE_LT ))
|
||||
i_serpent_dcache_ctrl (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -173,7 +178,7 @@ module serpent_dcache #(
|
|||
// reqs from core
|
||||
.req_port_i ( req_ports_i [k] ),
|
||||
.req_port_o ( req_ports_o [k] ),
|
||||
// miss interface
|
||||
// miss interface
|
||||
.miss_req_o ( miss_req [k] ),
|
||||
.miss_ack_i ( miss_ack [k] ),
|
||||
.miss_we_o ( miss_we [k] ),
|
||||
|
@ -182,12 +187,12 @@ module serpent_dcache #(
|
|||
.miss_paddr_o ( miss_paddr [k] ),
|
||||
.miss_nc_o ( miss_nc [k] ),
|
||||
.miss_size_o ( miss_size [k] ),
|
||||
.miss_wr_id_o ( miss_wr_id [k] ),
|
||||
.miss_id_o ( miss_id [k] ),
|
||||
.miss_replay_i ( miss_replay [k] ),
|
||||
.miss_rtrn_vld_i ( miss_rtrn_vld [k] ),
|
||||
// used to detect readout mux collisions
|
||||
.wr_cl_vld_i ( wr_cl_vld ),
|
||||
// cache mem interface
|
||||
// cache mem interface
|
||||
.rd_tag_o ( rd_tag [k] ),
|
||||
.rd_idx_o ( rd_idx [k] ),
|
||||
.rd_off_o ( rd_off [k] ),
|
||||
|
@ -204,13 +209,13 @@ module serpent_dcache #(
|
|||
///////////////////////////////////////////////////////
|
||||
// store unit controller
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// set read port to low priority
|
||||
assign rd_prio[2] = 1'b0;
|
||||
|
||||
|
||||
serpent_dcache_wbuffer #(
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.NC_ADDR_GE_LT ( NC_ADDR_GE_LT ))
|
||||
.NC_ADDR_BEGIN ( NC_ADDR_BEGIN ),
|
||||
.NC_ADDR_GE_LT ( NC_ADDR_GE_LT ))
|
||||
i_serpent_dcache_wbuffer (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -221,7 +226,7 @@ module serpent_dcache #(
|
|||
// request ports from core (store unit)
|
||||
.req_port_i ( req_ports_i [2] ),
|
||||
.req_port_o ( req_ports_o [2] ),
|
||||
// miss unit interface
|
||||
// miss unit interface
|
||||
.miss_req_o ( miss_req [2] ),
|
||||
.miss_ack_i ( miss_ack [2] ),
|
||||
.miss_we_o ( miss_we [2] ),
|
||||
|
@ -230,10 +235,10 @@ module serpent_dcache #(
|
|||
.miss_paddr_o ( miss_paddr [2] ),
|
||||
.miss_nc_o ( miss_nc [2] ),
|
||||
.miss_size_o ( miss_size [2] ),
|
||||
.miss_wr_id_o ( miss_wr_id [2] ),
|
||||
.miss_id_o ( miss_id [2] ),
|
||||
.miss_rtrn_vld_i ( miss_rtrn_vld [2] ),
|
||||
.miss_rtrn_id_i ( miss_rtrn_id ),
|
||||
// cache read interface
|
||||
// cache read interface
|
||||
.rd_tag_o ( rd_tag [2] ),
|
||||
.rd_idx_o ( rd_idx [2] ),
|
||||
.rd_off_o ( rd_off [2] ),
|
||||
|
@ -310,13 +315,13 @@ module serpent_dcache #(
|
|||
//pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
flush: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) flush_i |-> flush_ack_o |-> wbuffer_empty_o)
|
||||
@(posedge clk_i) disable iff (~rst_ni) flush_i |-> flush_ack_o |-> wbuffer_empty_o)
|
||||
else $fatal(1,"[l1 dcache] flushed cache implies flushed wbuffer");
|
||||
|
||||
initial begin
|
||||
// assert wrong parameterizations
|
||||
assert (DCACHE_INDEX_WIDTH<=12)
|
||||
else $fatal(1,"[l1 dcache] cache index width can be maximum 12bit since VM uses 4kB pages");
|
||||
assert (DCACHE_INDEX_WIDTH<=12)
|
||||
else $fatal(1,"[l1 dcache] cache index width can be maximum 12bit since VM uses 4kB pages");
|
||||
end
|
||||
`endif
|
||||
//pragma translate_on
|
||||
|
|
|
@ -17,36 +17,37 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_dcache_ctrl #(
|
||||
parameter 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] 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
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic cache_en_i,
|
||||
// core request ports
|
||||
input dcache_req_i_t req_port_i,
|
||||
output dcache_req_o_t req_port_o,
|
||||
input dcache_req_i_t req_port_i,
|
||||
output dcache_req_o_t req_port_o,
|
||||
// interface to miss handler
|
||||
output logic miss_req_o,
|
||||
input logic miss_ack_i,
|
||||
input logic miss_ack_i,
|
||||
output logic miss_we_o, // unused (set to 0)
|
||||
output logic [63:0] miss_wdata_o, // unused (set to 0)
|
||||
output logic [DCACHE_SET_ASSOC-1:0] miss_vld_bits_o, // valid bits at the missed index
|
||||
output logic [63:0] miss_paddr_o,
|
||||
output logic [DCACHE_SET_ASSOC-1:0] miss_vld_bits_o, // valid bits at the missed index
|
||||
output logic [63:0] miss_paddr_o,
|
||||
output logic miss_nc_o, // request to I/O space
|
||||
output logic [2:0] miss_size_o, // 00: 1byte, 01: 2byte, 10: 4byte, 11: 8byte, 111: cacheline
|
||||
output logic [DCACHE_ID_WIDTH-1:0] miss_wr_id_o, // unused (set to 0)
|
||||
input logic miss_replay_i, // request collided with pending miss - have to replay the request
|
||||
output logic [2:0] miss_size_o, // 00: 1byte, 01: 2byte, 10: 4byte, 11: 8byte, 111: cacheline
|
||||
output logic [DCACHE_ID_WIDTH-1:0] miss_id_o, // set to constant ID
|
||||
input logic miss_replay_i, // request collided with pending miss - have to replay the request
|
||||
input logic miss_rtrn_vld_i, // signals that the miss has been served, asserted in the same cycle as when the data returns from memory
|
||||
// used to detect readout mux collisions
|
||||
input logic wr_cl_vld_i,
|
||||
// cache memory interface
|
||||
output logic [DCACHE_TAG_WIDTH-1:0] rd_tag_o, // tag in - comes one cycle later
|
||||
output logic [DCACHE_CL_IDX_WIDTH-1:0] rd_idx_o,
|
||||
output logic [DCACHE_OFFSET_WIDTH-1:0] rd_off_o,
|
||||
output logic [DCACHE_CL_IDX_WIDTH-1:0] rd_idx_o,
|
||||
output logic [DCACHE_OFFSET_WIDTH-1:0] rd_off_o,
|
||||
output logic rd_req_o, // read the word at offset off_i[:3] in all ways
|
||||
output logic rd_tag_only_o, // set to zero here
|
||||
input logic rd_ack_i,
|
||||
input logic rd_ack_i,
|
||||
input logic [63:0] rd_data_i,
|
||||
input logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits_i,
|
||||
input logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh_i
|
||||
|
@ -62,7 +63,7 @@ module serpent_dcache_ctrl #(
|
|||
logic [DCACHE_SET_ASSOC-1:0] vld_data_d, vld_data_q;
|
||||
logic save_tag, rd_req_d, rd_req_q, rd_ack_d, rd_ack_q;
|
||||
logic [1:0] data_size_d, data_size_q;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// misc
|
||||
///////////////////////////////////////////////////////
|
||||
|
@ -78,28 +79,28 @@ module serpent_dcache_ctrl #(
|
|||
assign rd_off_o = address_off_d;
|
||||
|
||||
assign req_port_o.data_rdata = rd_data_i;
|
||||
|
||||
|
||||
// to miss unit
|
||||
assign miss_vld_bits_o = vld_data_q;
|
||||
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
|
||||
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
|
||||
endgenerate
|
||||
|
||||
assign miss_we_o = '0;
|
||||
assign miss_wdata_o = '0;
|
||||
assign miss_wr_id_o = '0;
|
||||
assign miss_wdata_o = '0;
|
||||
assign miss_id_o = RD_TX_ID;
|
||||
assign rd_req_d = rd_req_o;
|
||||
assign rd_ack_d = rd_ack_i;
|
||||
assign rd_tag_only_o = '0;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// main control logic
|
||||
///////////////////////////////////////////////////////
|
||||
|
@ -112,13 +113,13 @@ module serpent_dcache_ctrl #(
|
|||
miss_req_o = 1'b0;
|
||||
req_port_o.data_rvalid = 1'b0;
|
||||
req_port_o.data_gnt = 1'b0;
|
||||
|
||||
// interfaces
|
||||
unique case (state_q)
|
||||
|
||||
// interfaces
|
||||
unique case (state_q)
|
||||
//////////////////////////////////
|
||||
// wait for an incoming request
|
||||
IDLE: begin
|
||||
|
||||
|
||||
if (req_port_i.data_req) begin
|
||||
rd_req_o = 1'b1;
|
||||
|
||||
|
@ -126,7 +127,7 @@ module serpent_dcache_ctrl #(
|
|||
state_d = READ;
|
||||
req_port_o.data_gnt = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
// check whether we have a hit
|
||||
|
@ -137,7 +138,7 @@ module serpent_dcache_ctrl #(
|
|||
READ, REPLAY_READ: begin
|
||||
// speculatively request cache line
|
||||
rd_req_o = 1'b1;
|
||||
|
||||
|
||||
// kill -> go back to IDLE
|
||||
if(req_port_i.kill_req) begin
|
||||
state_d = IDLE;
|
||||
|
@ -146,7 +147,7 @@ module serpent_dcache_ctrl #(
|
|||
save_tag = (state_q!=REPLAY_READ);
|
||||
if(wr_cl_vld_i | ~rd_ack_q) begin
|
||||
state_d = REPLAY_REQ;
|
||||
// we've got a hit
|
||||
// we've got a hit
|
||||
end else if((|rd_hit_oh_i) & cache_en_i) begin
|
||||
state_d = IDLE;
|
||||
req_port_o.data_rvalid = 1'b1;
|
||||
|
@ -157,9 +158,9 @@ module serpent_dcache_ctrl #(
|
|||
end
|
||||
// we've got a miss
|
||||
end else begin
|
||||
state_d = MISS_REQ;
|
||||
end
|
||||
end
|
||||
state_d = MISS_REQ;
|
||||
end
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
// issue request
|
||||
|
@ -170,18 +171,18 @@ module serpent_dcache_ctrl #(
|
|||
req_port_o.data_rvalid = 1'b1;
|
||||
if(miss_ack_i) begin
|
||||
state_d = KILL_MISS;
|
||||
end else begin
|
||||
end else begin
|
||||
state_d = IDLE;
|
||||
end
|
||||
end
|
||||
end else if(miss_replay_i) begin
|
||||
state_d = REPLAY_REQ;
|
||||
end else if(miss_ack_i) begin
|
||||
state_d = MISS_WAIT;
|
||||
end
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
// wait until the memory transaction
|
||||
// returns.
|
||||
// returns.
|
||||
MISS_WAIT: begin
|
||||
if(req_port_i.kill_req) begin
|
||||
req_port_o.data_rvalid = 1'b1;
|
||||
|
@ -189,8 +190,8 @@ module serpent_dcache_ctrl #(
|
|||
state_d = IDLE;
|
||||
end else begin
|
||||
state_d = KILL_MISS;
|
||||
end
|
||||
end else if(miss_rtrn_vld_i) begin
|
||||
end
|
||||
end else if(miss_rtrn_vld_i) begin
|
||||
state_d = IDLE;
|
||||
req_port_o.data_rvalid = 1'b1;
|
||||
end
|
||||
|
@ -204,16 +205,16 @@ module serpent_dcache_ctrl #(
|
|||
state_d = IDLE;
|
||||
end else if(rd_ack_i) begin
|
||||
state_d = REPLAY_READ;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
// killed miss,
|
||||
// wait until miss unit responds and
|
||||
// wait until miss unit responds and
|
||||
// go back to idle
|
||||
KILL_MISS: begin
|
||||
if (miss_rtrn_vld_i) begin
|
||||
state_d = IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
// we should never get here
|
||||
|
@ -229,7 +230,7 @@ module serpent_dcache_ctrl #(
|
|||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
||||
if(~rst_ni) begin
|
||||
state_q <= IDLE;
|
||||
address_tag_q <= '0;
|
||||
address_tag_q <= '0;
|
||||
address_idx_q <= '0;
|
||||
address_off_q <= '0;
|
||||
vld_data_q <= '0;
|
||||
|
@ -238,7 +239,7 @@ always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
|||
rd_ack_q <= '0;
|
||||
end else begin
|
||||
state_q <= state_d;
|
||||
address_tag_q <= address_tag_d;
|
||||
address_tag_q <= address_tag_d;
|
||||
address_idx_q <= address_idx_d;
|
||||
address_off_q <= address_off_d;
|
||||
vld_data_q <= vld_data_d;
|
||||
|
@ -255,15 +256,15 @@ end
|
|||
|
||||
//pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
|
||||
|
||||
hot1: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) (~rd_ack_i) |=> cache_en_i |-> $onehot0(rd_hit_oh_i))
|
||||
@(posedge clk_i) disable iff (~rst_ni) (~rd_ack_i) |=> cache_en_i |-> $onehot0(rd_hit_oh_i))
|
||||
else $fatal(1,"[l1 dcache ctrl] rd_hit_oh_i signal must be hot1");
|
||||
|
||||
initial begin
|
||||
// assert wrong parameterizations
|
||||
assert (DCACHE_INDEX_WIDTH<=12)
|
||||
else $fatal(1,"[l1 dcache ctrl] cache index width can be maximum 12bit since VM uses 4kB pages");
|
||||
assert (DCACHE_INDEX_WIDTH<=12)
|
||||
else $fatal(1,"[l1 dcache ctrl] cache index width can be maximum 12bit since VM uses 4kB pages");
|
||||
end
|
||||
`endif
|
||||
//pragma translate_on
|
||||
|
|
|
@ -18,8 +18,9 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_dcache_missunit #(
|
||||
parameter NUM_PORTS = 3
|
||||
)(
|
||||
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
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
// cache management, signals from/to core
|
||||
|
@ -42,7 +43,7 @@ module serpent_dcache_missunit #(
|
|||
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_wr_id_i, // only used for writes, set to zero fro reads
|
||||
input logic [NUM_PORTS-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,
|
||||
// signals response from memory
|
||||
|
@ -163,7 +164,7 @@ module serpent_dcache_missunit #(
|
|||
assign mshr_d.size = (mshr_allocate) ? miss_size_i [miss_port_idx] : mshr_q.size;
|
||||
assign mshr_d.paddr = (mshr_allocate) ? miss_paddr_i [miss_port_idx] : mshr_q.paddr;
|
||||
assign mshr_d.vld_bits = (mshr_allocate) ? miss_vld_bits_i[miss_port_idx] : mshr_q.vld_bits;
|
||||
assign mshr_d.id = (mshr_allocate) ? miss_wr_id_i [miss_port_idx] : mshr_q.id;
|
||||
assign mshr_d.id = (mshr_allocate) ? miss_id_i [miss_port_idx] : mshr_q.id;
|
||||
assign mshr_d.nc = (mshr_allocate) ? miss_nc_i [miss_port_idx] : mshr_q.nc;
|
||||
assign mshr_d.repl_way = (mshr_allocate) ? repl_way : mshr_q.repl_way;
|
||||
assign mshr_d.miss_port_idx = (mshr_allocate) ? miss_port_idx : mshr_q.miss_port_idx;
|
||||
|
@ -209,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) ? '0 : miss_wr_id_i[miss_port_idx];
|
||||
assign mem_data_o.tid = (amo_sel) ? AMO_TX_ID : 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];
|
||||
|
|
|
@ -52,9 +52,9 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_dcache_wbuffer #(
|
||||
parameter 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 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
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
||||
|
@ -72,10 +72,10 @@ module serpent_dcache_wbuffer #(
|
|||
output logic [DCACHE_SET_ASSOC-1:0] miss_vld_bits_o, // unused here (set to 0)
|
||||
output logic miss_nc_o, // request to I/O space
|
||||
output logic [2:0] miss_size_o, //
|
||||
output logic [DCACHE_ID_WIDTH-1:0] miss_wr_id_o, // id of this transaction
|
||||
output logic [DCACHE_ID_WIDTH-1:0] miss_id_o, // ID of this transaction (wbuffer uses all IDs from 0 to DCACHE_MAX_TX-1)
|
||||
// write responses from memory
|
||||
input logic miss_rtrn_vld_i,
|
||||
input logic [DCACHE_ID_WIDTH-1:0] miss_rtrn_id_i, // transaction id to clear
|
||||
input logic [DCACHE_ID_WIDTH-1:0] miss_rtrn_id_i, // transaction ID to clear
|
||||
// cache read interface
|
||||
output logic [DCACHE_TAG_WIDTH-1:0] rd_tag_o, // tag in - comes one cycle later
|
||||
output logic [DCACHE_CL_IDX_WIDTH-1:0] rd_idx_o,
|
||||
|
@ -178,7 +178,7 @@ lzc #(
|
|||
|
||||
// add the offset to the physical base address of this buffer entry
|
||||
assign miss_paddr_o = {wbuffer_q[dirty_ptr].wtag, bdirty_off};
|
||||
assign miss_wr_id_o = tx_id;
|
||||
assign miss_id_o = tx_id;
|
||||
|
||||
// is there any dirty word to be transmitted, and is there a free TX slot?
|
||||
assign miss_req_o = (|dirty) && free_tx_slots;
|
||||
|
|
|
@ -32,11 +32,12 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_icache #(
|
||||
parameter bit AXI64BIT_COMPLIANT = 1'b0, // set this to 1 when using in conjunction with 64bit AXI bus adapter
|
||||
parameter 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
|
||||
// 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] 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
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -150,8 +151,7 @@ module serpent_icache #(
|
|||
end
|
||||
endgenerate
|
||||
|
||||
// currently we can only have one outstanding tx here
|
||||
assign mem_data_o.tid = '0;
|
||||
assign mem_data_o.tid = RD_TX_ID;
|
||||
|
||||
assign mem_data_o.nc = paddr_is_nc;
|
||||
// way that is being replaced
|
||||
|
|
2
src/fpu
2
src/fpu
|
@ -1 +1 @@
|
|||
Subproject commit 00e2579173f1412f06d4eb95d6b98d0eb1cd2e94
|
||||
Subproject commit 1801c5e0ea231f83e9ba5422b9a7a4feaaad879f
|
Loading…
Add table
Add a link
Reference in a new issue