mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 12:17:19 -04:00
WIP Update serpent cache subsystem AXI plugs
This commit is contained in:
parent
0bd9c4fb2b
commit
e5719ce34e
8 changed files with 217 additions and 320 deletions
12
Makefile
12
Makefile
|
@ -131,19 +131,7 @@ else
|
|||
questa-cmd := -do " set StdArithNoWarnings 1; set NumericStdNoWarnings 1; log -r /*; run -all;"
|
||||
endif
|
||||
compile_flag_vhd += -64 -nologo -quiet -2008
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
uvm-flags += +UVM_NO_RELNOTES +UVM_VERBOSITY=LOW
|
||||
questa-flags += -t 1ns -64 -coverage -classdebug $(gui-sim)
|
||||
# if defined, calls the questa targets in batch mode
|
||||
ifdef batch-mode
|
||||
questa-flags += -c
|
||||
questa-cmd := -do "coverage save -onexit tmp/$@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]"
|
||||
else
|
||||
questa-cmd := -do " log -r /*; run -all;"
|
||||
endif
|
||||
|
||||
>>>>>>> ariane_next
|
||||
# Iterate over all include directories and write them with +incdir+ prefixed
|
||||
# +incdir+ works for Verilator and QuestaSim
|
||||
list_incdir := $(foreach dir, ${incdir}, +incdir+$(dir))
|
||||
|
|
|
@ -394,18 +394,20 @@ package ariane_pkg;
|
|||
// Atomics
|
||||
// --------------------
|
||||
typedef enum logic [3:0] {
|
||||
AMO_NONE =4'b0000,
|
||||
AMO_LR =4'b0001,
|
||||
AMO_SC =4'b0010,
|
||||
AMO_SWAP =4'b0011,
|
||||
AMO_ADD =4'b0100,
|
||||
AMO_AND =4'b0101,
|
||||
AMO_OR =4'b0110,
|
||||
AMO_XOR =4'b0111,
|
||||
AMO_MAX =4'b1000,
|
||||
AMO_MAXU =4'b1001,
|
||||
AMO_MIN =4'b1010,
|
||||
AMO_MINU =4'b1011
|
||||
AMO_NONE =4'b0000,
|
||||
AMO_LR =4'b0001,
|
||||
AMO_SC =4'b0010,
|
||||
AMO_SWAP =4'b0011,
|
||||
AMO_ADD =4'b0100,
|
||||
AMO_AND =4'b0101,
|
||||
AMO_OR =4'b0110,
|
||||
AMO_XOR =4'b0111,
|
||||
AMO_MAX =4'b1000,
|
||||
AMO_MAXU =4'b1001,
|
||||
AMO_MIN =4'b1010,
|
||||
AMO_MINU =4'b1011,
|
||||
AMO_CAS1 =4'b1100, // unused, not part of riscv spec, but provided in OpenPiton
|
||||
AMO_CAS2 =4'b1101 // unused, not part of riscv spec, but provided in OpenPiton
|
||||
} amo_t;
|
||||
|
||||
typedef struct packed {
|
||||
|
|
|
@ -24,7 +24,7 @@ package serpent_cache_pkg;
|
|||
// do not change
|
||||
localparam L15_TID_WIDTH = 2;
|
||||
localparam L15_TLB_CSM_WIDTH = 33;
|
||||
|
||||
|
||||
localparam L15_WAY_WIDTH = $clog2(L15_SET_ASSOC);
|
||||
localparam L1I_WAY_WIDTH = $clog2(ariane_pkg::ICACHE_SET_ASSOC);
|
||||
localparam L1D_WAY_WIDTH = $clog2(ariane_pkg::DCACHE_SET_ASSOC);
|
||||
|
@ -40,23 +40,23 @@ package serpent_cache_pkg;
|
|||
localparam ICACHE_OFFSET_WIDTH = $clog2(ariane_pkg::ICACHE_LINE_WIDTH/8);
|
||||
localparam ICACHE_NUM_WORDS = 2**(ariane_pkg::ICACHE_INDEX_WIDTH-ICACHE_OFFSET_WIDTH);
|
||||
localparam ICACHE_CL_IDX_WIDTH = $clog2(ICACHE_NUM_WORDS);// excluding byte offset
|
||||
|
||||
|
||||
localparam DCACHE_OFFSET_WIDTH = $clog2(ariane_pkg::DCACHE_LINE_WIDTH/8);
|
||||
localparam DCACHE_NUM_WORDS = 2**(ariane_pkg::DCACHE_INDEX_WIDTH-DCACHE_OFFSET_WIDTH);
|
||||
localparam DCACHE_CL_IDX_WIDTH = $clog2(DCACHE_NUM_WORDS);// excluding byte offset
|
||||
|
||||
localparam DCACHE_NUM_BANKS = ariane_pkg::DCACHE_LINE_WIDTH/64;
|
||||
|
||||
// write buffer parameterization
|
||||
localparam DCACHE_WBUF_DEPTH = 8;
|
||||
localparam DCACHE_MAX_TX = 4;// TODO: set to number of threads supported in
|
||||
localparam DCACHE_ID_WIDTH = $clog2(DCACHE_MAX_TX);// TODO: set to number of threads supported in
|
||||
|
||||
|
||||
localparam DCACHE_NUM_BANKS = ariane_pkg::DCACHE_LINE_WIDTH/64;
|
||||
|
||||
// write buffer parameterization
|
||||
localparam DCACHE_WBUF_DEPTH = 8;
|
||||
localparam DCACHE_MAX_TX = 2**L15_TID_WIDTH;// needs to be aligned with OpenPiton
|
||||
localparam DCACHE_ID_WIDTH = $clog2(DCACHE_MAX_TX);
|
||||
|
||||
|
||||
typedef struct packed {
|
||||
logic [ariane_pkg::DCACHE_INDEX_WIDTH+ariane_pkg::DCACHE_TAG_WIDTH-1:0] wtag;
|
||||
logic [63:0] data;
|
||||
logic [7:0] dirty; // byte is dirty
|
||||
logic [7:0] dirty; // byte is dirty
|
||||
logic [7:0] valid; // byte is valid
|
||||
logic [7:0] txblock; // byte is part of transaction in-flight
|
||||
logic checked; // if cache state of this word has been checked
|
||||
|
@ -66,27 +66,27 @@ package serpent_cache_pkg;
|
|||
// TX status registers are indexed with the transaction ID
|
||||
// they basically store which bytes from which buffer entry are part
|
||||
// of that transaction
|
||||
typedef struct packed {
|
||||
typedef struct packed {
|
||||
logic vld;
|
||||
logic [7:0] be;
|
||||
logic [$clog2(DCACHE_WBUF_DEPTH)-1:0] ptr;
|
||||
} tx_stat_t;
|
||||
|
||||
// local interfaces between caches and L15 adapter
|
||||
typedef enum logic [1:0] {
|
||||
typedef enum logic [1:0] {
|
||||
DCACHE_STORE_REQ,
|
||||
DCACHE_LOAD_REQ,
|
||||
DCACHE_ATOMIC_REQ,
|
||||
DCACHE_INT_REQ } dcache_out_t;
|
||||
|
||||
typedef enum logic [2:0] {
|
||||
typedef enum logic [2:0] {
|
||||
DCACHE_INV_REQ, // no ack from the core required
|
||||
DCACHE_STORE_ACK,// note: this may contain an invalidation vector, too
|
||||
DCACHE_LOAD_ACK,
|
||||
DCACHE_ATOMIC_ACK,
|
||||
DCACHE_INT_ACK } dcache_in_t;
|
||||
|
||||
typedef enum logic [0:0] {
|
||||
typedef enum logic [0:0] {
|
||||
ICACHE_INV_REQ, // no ack from the core required
|
||||
ICACHE_IFILL_ACK} icache_in_t;
|
||||
|
||||
|
@ -174,6 +174,8 @@ package serpent_cache_pkg;
|
|||
|
||||
|
||||
typedef struct packed {
|
||||
logic l15_val; // valid signal, asserted with request
|
||||
logic l15_req_ack; // ack for response
|
||||
l15_reqtypes_t l15_rqtype; // see below for encoding
|
||||
logic l15_nc; // non-cacheable bit
|
||||
logic [2:0] l15_size; // transaction size: 000=Byte 001=2Byte; 010=4Byte; 011=8Byte; 111=Cache line (16/32Byte)
|
||||
|
@ -191,6 +193,9 @@ package serpent_cache_pkg;
|
|||
} l15_req_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic l15_ack; // ack for request struct
|
||||
logic l15_header_ack; // ack for request struct
|
||||
logic l15_val; // valid signal for return struct
|
||||
l15_rtrntypes_t l15_returntype; // see below for encoding
|
||||
logic l15_l2miss; // unused in Ariane
|
||||
logic [1:0] l15_error; // unused in openpiton
|
||||
|
@ -225,29 +230,29 @@ package serpent_cache_pkg;
|
|||
|
||||
function automatic logic [ariane_pkg::ICACHE_SET_ASSOC-1:0] icache_way_bin2oh (
|
||||
input logic [$clog2(ariane_pkg::ICACHE_SET_ASSOC)-1:0] in
|
||||
);
|
||||
);
|
||||
logic [ariane_pkg::ICACHE_SET_ASSOC-1:0] out;
|
||||
out = '0;
|
||||
out[in] = 1'b1;
|
||||
return out;
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] dcache_way_bin2oh (
|
||||
input logic [$clog2(ariane_pkg::DCACHE_SET_ASSOC)-1:0] in
|
||||
);
|
||||
);
|
||||
logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] out;
|
||||
out = '0;
|
||||
out[in] = 1'b1;
|
||||
return out;
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
function automatic logic [DCACHE_NUM_BANKS-1:0] dcache_cl_bin2oh (
|
||||
input logic [$clog2(DCACHE_NUM_BANKS)-1:0] in
|
||||
);
|
||||
);
|
||||
logic [DCACHE_NUM_BANKS-1:0] out;
|
||||
out = '0;
|
||||
out[in] = 1'b1;
|
||||
return out;
|
||||
return out;
|
||||
endfunction
|
||||
|
||||
|
||||
|
@ -263,16 +268,16 @@ package serpent_cache_pkg;
|
|||
|
||||
function automatic logic [7:0] toByteEnable8(
|
||||
input logic [2:0] offset,
|
||||
input logic [1:0] size
|
||||
input logic [1:0] size
|
||||
);
|
||||
logic [7:0] be;
|
||||
be = '0;
|
||||
unique case(size)
|
||||
2'b00: be[offset] = '1; // byte
|
||||
2'b01: be[offset +:2 ] = '1; // hword
|
||||
2'b10: be[offset +:4 ] = '1; // word
|
||||
unique case(size)
|
||||
2'b00: be[offset] = '1; // byte
|
||||
2'b01: be[offset +:2 ] = '1; // hword
|
||||
2'b10: be[offset +:4 ] = '1; // word
|
||||
default: be = '1; // dword
|
||||
endcase // size
|
||||
endcase // size
|
||||
return be;
|
||||
endfunction : toByteEnable8
|
||||
|
||||
|
@ -280,15 +285,15 @@ package serpent_cache_pkg;
|
|||
function automatic logic [63:0] repData64(
|
||||
input logic [63:0] data,
|
||||
input logic [2:0] offset,
|
||||
input logic [1:0] size
|
||||
input logic [1:0] size
|
||||
);
|
||||
logic [63:0] out;
|
||||
unique case(size)
|
||||
unique case(size)
|
||||
2'b00: for(int k=0; k<8; k++) out[k*8 +: 8] = data[offset*8 +: 8]; // byte
|
||||
2'b01: for(int k=0; k<4; k++) out[k*16 +: 16] = data[offset*8 +: 16]; // hword
|
||||
2'b10: for(int k=0; k<2; k++) out[k*32 +: 32] = data[offset*8 +: 32]; // word
|
||||
default: out = data; // dword
|
||||
endcase // size
|
||||
endcase // size
|
||||
return out;
|
||||
endfunction : repData64
|
||||
|
||||
|
@ -304,7 +309,7 @@ package serpent_cache_pkg;
|
|||
8'b0000_1111, 8'b1111_0000: size = 2'b10; // word
|
||||
8'b1100_0000, 8'b0011_0000, 8'b0000_1100, 8'b0000_0011: size = 2'b01; // hword
|
||||
default: size = 2'b00; // individual bytes
|
||||
endcase // be
|
||||
endcase // be
|
||||
return size;
|
||||
endfunction : toSize64
|
||||
|
||||
|
@ -316,7 +321,7 @@ package serpent_cache_pkg;
|
|||
// 111: DCACHE line
|
||||
function automatic logic [63:0] paddrSizeAlign(
|
||||
input logic [63:0] paddr,
|
||||
input logic [2:0] size
|
||||
input logic [2:0] size
|
||||
);
|
||||
logic [63:0] out;
|
||||
out = paddr;
|
||||
|
@ -324,7 +329,7 @@ package serpent_cache_pkg;
|
|||
3'b001: out[0:0] = '0;
|
||||
3'b010: out[1:0] = '0;
|
||||
3'b011: out[2:0] = '0;
|
||||
3'b111: out[DCACHE_OFFSET_WIDTH-1:0] = '0;
|
||||
3'b111: out[DCACHE_OFFSET_WIDTH-1:0] = '0;
|
||||
default: ;
|
||||
endcase
|
||||
return out;
|
||||
|
|
|
@ -44,19 +44,12 @@ module ariane #(
|
|||
`ifdef AXI64_CACHE_PORTS
|
||||
// memory side, AXI Master
|
||||
output ariane_axi::req_t axi_req_o,
|
||||
input ariane_axi::resp_t axi_resp_i,
|
||||
input ariane_axi::resp_t axi_resp_i
|
||||
`else
|
||||
// L15 (memory side)
|
||||
output logic l15_val_o,
|
||||
input logic l15_ack_i,
|
||||
input logic l15_header_ack_i,
|
||||
output l15_req_t l15_data_o,
|
||||
|
||||
input logic l15_val_i,
|
||||
output logic l15_req_ack_o,
|
||||
input l15_rtrn_t l15_rtrn_i
|
||||
// L15 (memory side)
|
||||
output serpent_cache_pkg::l15_req_t l15_req_o,
|
||||
input serpent_cache_pkg::l15_rtrn_t l15_rtrn_i
|
||||
`endif
|
||||
|
||||
);
|
||||
// ------------------------------------------
|
||||
// Global Signals
|
||||
|
@ -585,9 +578,6 @@ module ariane #(
|
|||
`ifdef SERPENT_PULP
|
||||
// this is a cache subsystem that is compatible with OpenPiton
|
||||
serpent_cache_subsystem #(
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
|
||||
`endif
|
||||
.CACHE_START_ADDR ( CACHE_START_ADDR )
|
||||
) i_cache_subsystem (
|
||||
// to D$
|
||||
|
@ -616,23 +606,16 @@ module ariane #(
|
|||
.wbuffer_empty_o ( dcache_commit_wbuffer_empty ),
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
// memory side
|
||||
.icache_data_if ( instr_if ),
|
||||
.dcache_data_if ( data_if ),
|
||||
.dcache_bypass_if ( bypass_if )
|
||||
.axi_req_o ( axi_req_o ),
|
||||
.axi_resp_i ( axi_resp_i )
|
||||
`else
|
||||
.l15_val_o ( l15_val_o ),
|
||||
.l15_ack_i ( l15_ack_i ),
|
||||
.l15_header_ack_i ( l15_header_ack_i ),
|
||||
.l15_data_o ( l15_data_o ),
|
||||
.l15_val_i ( l15_val_i ),
|
||||
.l15_req_ack_o ( l15_req_ack_o ),
|
||||
.l15_req_o ( l15_req_o ),
|
||||
.l15_rtrn_i ( l15_rtrn_i )
|
||||
`endif
|
||||
);
|
||||
`else
|
||||
|
||||
std_cache_subsystem #(
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
|
||||
.CACHE_START_ADDR ( CACHE_START_ADDR )
|
||||
) i_cache_subsystem (
|
||||
// to D$
|
||||
|
|
|
@ -17,19 +17,19 @@
|
|||
// Date: 15.08.2018
|
||||
// Description: Ariane cache subsystem that is compatible with the OpenPiton
|
||||
// coherent memory system.
|
||||
//
|
||||
// Define SERPENT_PULP if you want to use this cache.
|
||||
// Define AXI64_CACHE_PORTS if you want to use this cache
|
||||
// with a standard 64bit AXI interace instead of the openpiton
|
||||
//
|
||||
// Define SERPENT_PULP if you want to use this cache.
|
||||
// Define AXI64_CACHE_PORTS if you want to use this cache
|
||||
// with a standard 64bit AXI interace instead of the openpiton
|
||||
// L1.5 interface.
|
||||
|
||||
import ariane_pkg::*;
|
||||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_cache_subsystem #(
|
||||
// `ifdef AXI64_CACHE_PORTS
|
||||
// `ifdef AXI64_CACHE_PORTS
|
||||
parameter int unsigned AXI_ID_WIDTH = 10,
|
||||
// `endif
|
||||
// `endif
|
||||
parameter logic [63:0] CACHE_START_ADDR = 64'h4000_0000
|
||||
)(
|
||||
input logic clk_i,
|
||||
|
@ -53,7 +53,7 @@ module serpent_cache_subsystem #(
|
|||
input logic dcache_flush_i, // high until acknowledged
|
||||
output logic dcache_flush_ack_o, // send a single cycle acknowledge signal when the cache is flushed
|
||||
output logic dcache_miss_o, // we missed on a ld/st
|
||||
|
||||
|
||||
// AMO interface
|
||||
input amo_req_t dcache_amo_req_i,
|
||||
output amo_resp_t dcache_amo_resp_o,
|
||||
|
@ -66,21 +66,14 @@ module serpent_cache_subsystem #(
|
|||
output logic wbuffer_empty_o,
|
||||
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
// memory side
|
||||
AXI_BUS.Master icache_data_if, // I$ refill port
|
||||
AXI_BUS.Master dcache_data_if, // D$ refill port
|
||||
AXI_BUS.Master dcache_bypass_if // bypass axi port (disabled D$ or uncacheable access)
|
||||
// memory side
|
||||
output ariane_axi::req_t axi_req_o,
|
||||
input ariane_axi::resp_t axi_resp_i
|
||||
`else
|
||||
// L15 (memory side)
|
||||
output logic l15_val_o,
|
||||
input logic l15_ack_i,
|
||||
input logic l15_header_ack_i,
|
||||
output l15_req_t l15_data_o,
|
||||
|
||||
input logic l15_val_i,
|
||||
output logic l15_req_ack_o,
|
||||
// L15 (memory side)
|
||||
output l15_req_t l15_req_o,
|
||||
input l15_rtrn_t l15_rtrn_i
|
||||
`endif
|
||||
`endif
|
||||
// TODO: interrupt interface
|
||||
);
|
||||
|
||||
|
@ -96,7 +89,7 @@ module serpent_cache_subsystem #(
|
|||
serpent_icache #(
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
.AXI64BIT_COMPLIANT ( 1'b1 ),
|
||||
.NC_ADDR_GE_LT ( 0 ),
|
||||
.NC_ADDR_GE_LT ( 0 ),
|
||||
`endif
|
||||
.NC_ADDR_BEGIN ( CACHE_START_ADDR )
|
||||
) i_serpent_icache (
|
||||
|
@ -116,40 +109,16 @@ module serpent_cache_subsystem #(
|
|||
.mem_data_o ( icache_adapter )
|
||||
);
|
||||
|
||||
// // decreasing priority
|
||||
// // Port 0: PTW
|
||||
// // Port 1: Load Unit
|
||||
// // Port 2: Store Unit
|
||||
// std_nbdcache #(
|
||||
// .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
|
||||
// .CACHE_START_ADDR ( CACHE_START_ADDR )
|
||||
// ) i_nbdcache (
|
||||
// .clk_i ( clk_i ),
|
||||
// .rst_ni ( rst_ni ),
|
||||
// .enable_i ( dcache_enable_i ),
|
||||
// .flush_i ( dcache_flush_i ),
|
||||
// .flush_ack_o ( dcache_flush_ack_o ),
|
||||
// .miss_o ( dcache_miss_o ),
|
||||
// .data_if ( dcache_data_if ),
|
||||
// .bypass_if ( dcache_bypass_if ),
|
||||
// .amo_req_i ( dcache_amo_req_i ),
|
||||
// .amo_resp_o ( dcache_amo_resp_o ),
|
||||
// .req_ports_i ( dcache_req_ports_i ),
|
||||
// .req_ports_o ( dcache_req_ports_o )
|
||||
// );
|
||||
|
||||
// assign wbuffer_empty_o = 1'b1;
|
||||
|
||||
|
||||
// Note:
|
||||
// Ports 0/1 for PTW and LD unit are read only.
|
||||
// Ports 0/1 for PTW and LD unit are read only.
|
||||
// they have equal prio and are RR arbited
|
||||
// Port 2 is write only and goes into the merging write buffer
|
||||
serpent_dcache #(
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
.NC_ADDR_GE_LT ( 0 ), // std config is for openpiton, where the upper memory region is NC
|
||||
`endif
|
||||
.NC_ADDR_BEGIN ( CACHE_START_ADDR )
|
||||
`endif
|
||||
.NC_ADDR_BEGIN ( CACHE_START_ADDR )
|
||||
) i_serpent_dcache (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -169,6 +138,26 @@ module serpent_cache_subsystem #(
|
|||
.mem_data_o ( dcache_adapter )
|
||||
);
|
||||
|
||||
// arbiter/adapter
|
||||
serpent_l15_adapter #(
|
||||
) i_adapter (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.icache_data_req_i ( icache_adapter_data_req ),
|
||||
.icache_data_ack_o ( adapter_icache_data_ack ),
|
||||
.icache_data_i ( icache_adapter ),
|
||||
.icache_rtrn_vld_o ( adapter_icache_rtrn_vld ),
|
||||
.icache_rtrn_o ( adapter_icache ),
|
||||
.dcache_data_req_i ( dcache_adapter_data_req ),
|
||||
.dcache_data_ack_o ( adapter_dcache_data_ack ),
|
||||
.dcache_data_i ( dcache_adapter ),
|
||||
.dcache_rtrn_vld_o ( adapter_dcache_rtrn_vld ),
|
||||
.dcache_rtrn_o ( adapter_dcache ),
|
||||
.l15_req_o ( l15_req_o ),
|
||||
.l15_rtrn_i ( l15_port_i )
|
||||
);
|
||||
|
||||
|
||||
|
||||
// different memory plumbing
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
|
@ -182,7 +171,7 @@ module serpent_cache_subsystem #(
|
|||
|
||||
std_cache_pkg::req_t icache_axi_req_type;
|
||||
assign icache_axi_req_type = ( icache_adapter.nc ) ? std_cache_pkg::SINGLE_REQ : std_cache_pkg::CACHE_LINE_REQ;
|
||||
|
||||
|
||||
axi_adapter #(
|
||||
.DATA_WIDTH ( ICACHE_LINE_WIDTH ),
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH )
|
||||
|
@ -203,8 +192,8 @@ module serpent_cache_subsystem #(
|
|||
.rdata_o ( adapter_icache.data ),
|
||||
.id_o ( ),
|
||||
.critical_word_o ( ),
|
||||
.critical_word_valid_o( ),
|
||||
.axi ( icache_data_if )
|
||||
.axi_req_o ( axi_data_o ),
|
||||
.axi_resp_i ( axi_data_i )
|
||||
);
|
||||
|
||||
std_cache_pkg::req_t dcache_axi_req_type;
|
||||
|
@ -232,9 +221,9 @@ module serpent_cache_subsystem #(
|
|||
assign adapter_dcache.rtype = (axi_dcache_id[0]) ? serpent_cache_pkg::DCACHE_STORE_ACK : serpent_cache_pkg::DCACHE_LOAD_ACK;
|
||||
assign adapter_dcache.nc = axi_dcache_id[1];
|
||||
assign adapter_dcache.tid = axi_dcache_id>>2;
|
||||
|
||||
|
||||
axi_adapter #(
|
||||
.DATA_WIDTH ( DCACHE_LINE_WIDTH ),
|
||||
.DATA_WIDTH ( DCACHE_LINE_WIDTH ),
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH )
|
||||
) i_dcache_axi_adapter (
|
||||
.clk_i ( clk_i ),
|
||||
|
@ -257,63 +246,6 @@ module serpent_cache_subsystem #(
|
|||
.axi ( dcache_data_if )
|
||||
);
|
||||
|
||||
// tie to zero here...
|
||||
assign dcache_bypass_if.aw_valid = '0;
|
||||
assign dcache_bypass_if.aw_addr = '0;
|
||||
assign dcache_bypass_if.aw_prot = '0;
|
||||
assign dcache_bypass_if.aw_region = '0;
|
||||
assign dcache_bypass_if.aw_len = '0;
|
||||
assign dcache_bypass_if.aw_size = '0;
|
||||
assign dcache_bypass_if.aw_burst = '0;
|
||||
assign dcache_bypass_if.aw_lock = '0;
|
||||
assign dcache_bypass_if.aw_cache = '0;
|
||||
assign dcache_bypass_if.aw_qos = '0;
|
||||
assign dcache_bypass_if.aw_id = '0;
|
||||
assign dcache_bypass_if.aw_user = '0;
|
||||
assign dcache_bypass_if.ar_valid = '0;
|
||||
assign dcache_bypass_if.ar_addr = '0;
|
||||
assign dcache_bypass_if.ar_prot = '0;
|
||||
assign dcache_bypass_if.ar_region = '0;
|
||||
assign dcache_bypass_if.ar_len = '0;
|
||||
assign dcache_bypass_if.ar_size = '0;
|
||||
assign dcache_bypass_if.ar_burst = '0;
|
||||
assign dcache_bypass_if.ar_lock = '0;
|
||||
assign dcache_bypass_if.ar_cache = '0;
|
||||
assign dcache_bypass_if.ar_qos = '0;
|
||||
assign dcache_bypass_if.ar_id = '0;
|
||||
assign dcache_bypass_if.ar_user = '0;
|
||||
assign dcache_bypass_if.w_valid = '0;
|
||||
assign dcache_bypass_if.w_data = '0;
|
||||
assign dcache_bypass_if.w_strb = '0;
|
||||
assign dcache_bypass_if.w_user = '0;
|
||||
assign dcache_bypass_if.w_last = '0;
|
||||
assign dcache_bypass_if.b_ready = '0;
|
||||
assign dcache_bypass_if.r_ready = '0;
|
||||
|
||||
`else
|
||||
|
||||
serpent_l15_adapter #(
|
||||
) i_adapter (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.icache_data_req_i ( icache_adapter_data_req ),
|
||||
.icache_data_ack_o ( adapter_icache_data_ack ),
|
||||
.icache_data_i ( icache_adapter ),
|
||||
.icache_rtrn_vld_o ( adapter_icache_rtrn_vld ),
|
||||
.icache_rtrn_o ( adapter_icache ),
|
||||
.dcache_data_req_i ( dcache_adapter_data_req ),
|
||||
.dcache_data_ack_o ( adapter_dcache_data_ack ),
|
||||
.dcache_data_i ( dcache_adapter ),
|
||||
.dcache_rtrn_vld_o ( adapter_dcache_rtrn_vld ),
|
||||
.dcache_rtrn_o ( adapter_dcache ),
|
||||
.l15_val_o ( l15_val_o ),
|
||||
.l15_ack_i ( l15_ack_i ),
|
||||
.l15_header_ack_i ( l15_header_ack_i ),
|
||||
.l15_data_o ( l15_port_o ),
|
||||
.l15_val_i ( l15_val_i ),
|
||||
.l15_req_ack_o ( l15_req_ack_o ),
|
||||
.l15_rtrn_i ( l15_port_i )
|
||||
);
|
||||
|
||||
`endif
|
||||
|
||||
|
@ -327,37 +259,37 @@ module serpent_cache_subsystem #(
|
|||
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
a_write_size: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) dcache_adapter_data_req |-> adapter_dcache_data_ack |-> dcache_axi_we |-> dcache_axi_req_type==std_cache_pkg::SINGLE_REQ)
|
||||
@(posedge clk_i) disable iff (~rst_ni) dcache_adapter_data_req |-> adapter_dcache_data_ack |-> dcache_axi_we |-> dcache_axi_req_type==std_cache_pkg::SINGLE_REQ)
|
||||
else $fatal(1,"[l1 cache] full cacheline stores not supported at the moment");
|
||||
|
||||
a_paddr_align: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) dcache_adapter_data_req |-> adapter_dcache_data_ack |-> dcache_axi_req_type==std_cache_pkg::CACHE_LINE_REQ |-> dcache_axi_paddr[2:0] == 3'b000)
|
||||
@(posedge clk_i) disable iff (~rst_ni) dcache_adapter_data_req |-> adapter_dcache_data_ack |-> dcache_axi_req_type==std_cache_pkg::CACHE_LINE_REQ |-> dcache_axi_paddr[2:0] == 3'b000)
|
||||
else $fatal(1,"[l1 cache] CL address must be aligned");
|
||||
`endif
|
||||
|
||||
a_invalid_instruction_fetch: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) icache_dreq_o.valid |-> (|icache_dreq_o.data) !== 1'hX)
|
||||
else $warning(1,"[l1 dcache] reading invalid instructions: vaddr=%08X, data=%08X",
|
||||
@(posedge clk_i) disable iff (~rst_ni) icache_dreq_o.valid |-> (|icache_dreq_o.data) !== 1'hX)
|
||||
else $warning(1,"[l1 dcache] reading invalid instructions: vaddr=%08X, data=%08X",
|
||||
icache_dreq_o.vaddr, icache_dreq_o.data);
|
||||
|
||||
a_invalid_write_data: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) dcache_req_ports_i[2].data_req |-> |dcache_req_ports_i[2].data_be |-> (|dcache_req_ports_i[2].data_wdata) !== 1'hX)
|
||||
else $warning(1,"[l1 dcache] writing invalid data: paddr=%016X, be=%02X, data=%016X",
|
||||
@(posedge clk_i) disable iff (~rst_ni) dcache_req_ports_i[2].data_req |-> |dcache_req_ports_i[2].data_be |-> (|dcache_req_ports_i[2].data_wdata) !== 1'hX)
|
||||
else $warning(1,"[l1 dcache] writing invalid data: paddr=%016X, be=%02X, data=%016X",
|
||||
{dcache_req_ports_i[2].address_tag, dcache_req_ports_i[2].address_index}, dcache_req_ports_i[2].data_be, dcache_req_ports_i[2].data_wdata);
|
||||
|
||||
generate
|
||||
generate
|
||||
for(genvar j=0; j<2; j++) begin
|
||||
a_invalid_read_data: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) dcache_req_ports_o[j].data_rvalid |-> (|dcache_req_ports_o[j].data_rdata) !== 1'hX)
|
||||
else $warning(1,"[l1 dcache] reading invalid data on port %01d: data=%016X",
|
||||
@(posedge clk_i) disable iff (~rst_ni) dcache_req_ports_o[j].data_rvalid |-> (|dcache_req_ports_o[j].data_rdata) !== 1'hX)
|
||||
else $warning(1,"[l1 dcache] reading invalid data on port %01d: data=%016X",
|
||||
j, dcache_req_ports_o[j].data_rdata);
|
||||
end
|
||||
endgenerate
|
||||
endgenerate
|
||||
|
||||
initial begin
|
||||
assert (AXI_ID_WIDTH >= $clog2(serpent_cache_pkg::DCACHE_MAX_TX)+2) else
|
||||
assert (AXI_ID_WIDTH >= $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
|
||||
end
|
||||
`endif
|
||||
//pragma translate_on
|
||||
|
||||
|
|
|
@ -14,18 +14,18 @@
|
|||
//
|
||||
// Author: Michael Schaffner (schaffner@iis.ee.ethz.ch), ETH Zurich
|
||||
// Date: 08.08.2018
|
||||
// Description: adapter module to connect the L1D$ and L1I$ to the native
|
||||
// interface of the OpenPiton L1.5 cache.
|
||||
// Description: adapter module to connect the L1D$ and L1I$ to the native
|
||||
// interface of the OpenPiton L1.5 cache.
|
||||
//
|
||||
// A couple of notes:
|
||||
// A couple of notes:
|
||||
//
|
||||
// 1) the L15 has been designed for an OpenSparc T1 core with 2 threads and can serve only
|
||||
// 1) the L15 has been designed for an OpenSparc T1 core with 2 threads and can serve only
|
||||
// 1 ld and rd request per thread. Ariane has only one hart, but the LSU can issue several write
|
||||
// requests to optimize bandwidth. hence, we reuse the threadid field to issue and track multiple
|
||||
// requests (up to 2 in this case).
|
||||
// requests to optimize bandwidth. hence, we reuse the threadid field to issue and track multiple
|
||||
// requests (up to 2 in this case).
|
||||
//
|
||||
// 2) the CSM (clumped shared memory = coherence domain restriction in OpenPiton)
|
||||
// feature is currently not supported by Ariane.
|
||||
// 2) the CSM (clumped shared memory = coherence domain restriction in OpenPiton)
|
||||
// feature is currently not supported by Ariane.
|
||||
//
|
||||
// 3) some features like blockinitstore, prefetch, ECC errors are not used (see interface below)
|
||||
//
|
||||
|
@ -33,16 +33,16 @@
|
|||
// through one streaming register, and need to be consumed unconditionally by the caches.
|
||||
//
|
||||
// 5) The L1.5 protocol is closely related to the CPX bus of openSPARC, see also [1,2]
|
||||
//
|
||||
// 6) Note on transaction data and size: if a store packet is less than 64 bits, then
|
||||
// the field is filled with copies of the data. in case of an interrupt vector,
|
||||
//
|
||||
// 6) Note on transaction data and size: if a store packet is less than 64 bits, then
|
||||
// the field is filled with copies of the data. in case of an interrupt vector,
|
||||
// an 18bit interrupt vector is expected.
|
||||
//
|
||||
// 7) L1I$ refill requests always have precedence over L1D$ requests.
|
||||
//
|
||||
// 7) L1I$ refill requests always have precedence over L1D$ requests.
|
||||
//
|
||||
// 8) L1I$ fill requests are always complete cache lines at the moment
|
||||
//
|
||||
// 9) the adapter converts from little endian (Ariane) to big endian (openpiton), and vice versa.
|
||||
// 9) the adapter converts from little endian (Ariane) to big endian (openpiton), and vice versa.
|
||||
//
|
||||
// 10) L1I$ requests to I.O space (bit39 of address = 1'b1) always return 32bit nc data
|
||||
//
|
||||
|
@ -56,38 +56,32 @@ import ariane_pkg::*;
|
|||
import serpent_cache_pkg::*;
|
||||
|
||||
module serpent_l15_adapter #(
|
||||
|
||||
)(
|
||||
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
|
||||
// icache
|
||||
input logic icache_data_req_i,
|
||||
output logic icache_data_ack_o,
|
||||
input icache_req_t icache_data_i,
|
||||
input icache_req_t icache_data_i,
|
||||
// returning packets must be consumed immediately
|
||||
output logic icache_rtrn_vld_o,
|
||||
output icache_rtrn_t icache_rtrn_o,
|
||||
|
||||
|
||||
output icache_rtrn_t icache_rtrn_o,
|
||||
|
||||
|
||||
// dcache
|
||||
input logic dcache_data_req_i,
|
||||
output logic dcache_data_ack_o,
|
||||
input dcache_req_t dcache_data_i,
|
||||
input dcache_req_t dcache_data_i,
|
||||
// returning packets must be consumed immediately
|
||||
output logic dcache_rtrn_vld_o,
|
||||
output dcache_rtrn_t dcache_rtrn_o,
|
||||
output dcache_rtrn_t dcache_rtrn_o,
|
||||
|
||||
// TODO: interrupt interface
|
||||
|
||||
// L15
|
||||
output logic l15_val_o,
|
||||
input logic l15_ack_i,
|
||||
input logic l15_header_ack_i,
|
||||
output l15_req_t l15_data_o,
|
||||
// TODO: interrupt interface
|
||||
|
||||
input logic l15_val_i,
|
||||
output logic l15_req_ack_o,
|
||||
// L15
|
||||
output l15_req_t l15_req_o,
|
||||
input l15_rtrn_t l15_rtrn_i
|
||||
);
|
||||
|
||||
|
@ -114,23 +108,23 @@ l15_rtrn_t rtrn_fifo_data;
|
|||
///////////////////////////////////////////////////////
|
||||
|
||||
// relevant l15 signals
|
||||
// l15_req_t l15_data_o.l15_rqtype; // see below for encoding
|
||||
// logic l15_data_o.l15_nc; // non-cacheable bit
|
||||
// logic [2:0] l15_data_o.l15_size; // transaction size: 000=Byte 001=2Byte; 010=4Byte; 011=8Byte; 111=Cache line (16/32Byte)
|
||||
// logic [L15_TID_WIDTH-1:0] l15_data_o.l15_threadid; // currently 0 or 1
|
||||
// logic l15_data_o.l15_invalidate_cacheline; // unused by Ariane as L1 has no ECC at the moment
|
||||
// logic [L15_WAY_WIDTH-1:0] l15_data_o.l15_l1rplway; // way to replace
|
||||
// logic [39:0] l15_data_o.l15_address; // physical address
|
||||
// logic [63:0] l15_data_o.l15_data; // word to write
|
||||
// logic [63:0] l15_data_o.l15_data_next_entry; // unused in Ariane (only used for CAS atomic requests)
|
||||
// logic [L15_TLB_CSM_WIDTH-1:0] l15_data_o.l15_csm_data;
|
||||
// l15_req_t l15_req_o.l15_rqtype; // see below for encoding
|
||||
// logic l15_req_o.l15_nc; // non-cacheable bit
|
||||
// logic [2:0] l15_req_o.l15_size; // transaction size: 000=Byte 001=2Byte; 010=4Byte; 011=8Byte; 111=Cache line (16/32Byte)
|
||||
// logic [L15_TID_WIDTH-1:0] l15_req_o.l15_threadid; // currently 0 or 1
|
||||
// logic l15_req_o.l15_invalidate_cacheline; // unused by Ariane as L1 has no ECC at the moment
|
||||
// logic [L15_WAY_WIDTH-1:0] l15_req_o.l15_l1rplway; // way to replace
|
||||
// logic [39:0] l15_req_o.l15_address; // physical address
|
||||
// logic [63:0] l15_req_o.l15_data; // word to write
|
||||
// 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;
|
||||
|
||||
// need to deassert valid signal when header is acked
|
||||
// can move on when packed is acked (need to clear header ack)
|
||||
assign l15_val_o = (|arb_req) & ~header_ack_q;
|
||||
assign header_ack_d = (l15_ack_i) ? 1'b0 : (header_ack_q | l15_header_ack_i);
|
||||
|
||||
assign arb_req = {~dcache_data_empty,
|
||||
assign l15_req_o.l15_val = (|arb_req) & ~header_ack_q;
|
||||
assign header_ack_d = (l15_rtrn_i.l15_ack) ? 1'b0 : (header_ack_q | l15_rtrn_i.l15_header_ack);
|
||||
|
||||
assign arb_req = {~dcache_data_empty,
|
||||
~icache_data_empty};
|
||||
|
||||
assign dcache_data_pop = arb_ack[1];
|
||||
|
@ -140,20 +134,20 @@ 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_data_o.l15_nc = (arb_idx) ? dcache_data.nc : icache_data.nc;
|
||||
assign l15_data_o.l15_size = (arb_idx) ? dcache_data.size : 3'b111;// always request full cache line for icache
|
||||
assign l15_data_o.l15_threadid = (arb_idx) ? dcache_data.tid : icache_data.tid;
|
||||
assign l15_data_o.l15_invalidate_cacheline = 1'b0; // unused by Ariane as L1 has no ECC at the moment
|
||||
assign l15_data_o.l15_l1rplway = (arb_idx) ? dcache_data.way : icache_data.way;
|
||||
assign l15_data_o.l15_address = (arb_idx) ? dcache_data.paddr : icache_data.paddr;
|
||||
assign l15_data_o.l15_data_next_entry = 1'b0; // unused in Ariane (only used for CAS atomic requests)
|
||||
assign l15_data_o.l15_csm_data = 1'b0; // unused in Ariane (only used for coherence domain restriction features)
|
||||
assign l15_data_o.l15_amo_op = dcache_data.amo_op;
|
||||
assign l15_req_o.l15_nc = (arb_idx) ? dcache_data.nc : icache_data.nc;
|
||||
assign l15_req_o.l15_size = (arb_idx) ? dcache_data.size : 3'b111;// always request full cache line for icache
|
||||
assign l15_req_o.l15_threadid = (arb_idx) ? dcache_data.tid : icache_data.tid;
|
||||
assign l15_req_o.l15_invalidate_cacheline = 1'b0; // unused by Ariane as L1 has no ECC at the moment
|
||||
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 l15_req_o.l15_data_next_entry = 1'b0; // unused in Ariane (only used for CAS atomic requests)
|
||||
assign l15_req_o.l15_csm_data = 1'b0; // unused in Ariane (only used for coherence domain restriction features)
|
||||
assign l15_req_o.l15_amo_op = dcache_data.amo_op;
|
||||
// swap endianess and replicate datawords if necessary
|
||||
always_comb begin : p_datarepl
|
||||
unique case(dcache_data.size)
|
||||
unique case(dcache_data.size)
|
||||
3'b000: begin // 1byte
|
||||
l15_data_o.l15_data = swendian64({dcache_data.data[0],
|
||||
l15_req_o.l15_data = swendian64({dcache_data.data[0],
|
||||
dcache_data.data[0],
|
||||
dcache_data.data[0],
|
||||
dcache_data.data[0],
|
||||
|
@ -163,17 +157,17 @@ always_comb begin : p_datarepl
|
|||
dcache_data.data[0]});
|
||||
end
|
||||
3'b001: begin // 2byte
|
||||
l15_data_o.l15_data = swendian64({dcache_data.data[1:0],
|
||||
l15_req_o.l15_data = swendian64({dcache_data.data[1:0],
|
||||
dcache_data.data[1:0],
|
||||
dcache_data.data[1:0],
|
||||
dcache_data.data[1:0]});
|
||||
end
|
||||
3'b010: begin // 4byte
|
||||
l15_data_o.l15_data = swendian64({dcache_data.data[3:0],
|
||||
l15_req_o.l15_data = swendian64({dcache_data.data[3:0],
|
||||
dcache_data.data[3:0]});
|
||||
end
|
||||
default: begin // 8 byte
|
||||
l15_data_o.l15_data = swendian64(dcache_data.data);
|
||||
l15_req_o.l15_data = swendian64(dcache_data.data);
|
||||
end
|
||||
endcase // dcache_data.size
|
||||
end
|
||||
|
@ -183,47 +177,47 @@ end
|
|||
always_comb begin : p_arb
|
||||
arb_idx = '0;
|
||||
arb_ack = '0;
|
||||
if(arb_req[0] & l15_ack_i) begin
|
||||
if(arb_req[0] & l15_rtrn_i.l15_ack) begin
|
||||
arb_ack[0] = 1'b1;
|
||||
arb_idx = 0;
|
||||
end else if (arb_req[1] & l15_ack_i) begin
|
||||
end else if (arb_req[1] & l15_rtrn_i.l15_ack) begin
|
||||
arb_ack[1] = 1'b1;
|
||||
arb_idx = 1;
|
||||
end
|
||||
end
|
||||
end // p_arb
|
||||
|
||||
// encode packet type
|
||||
always_comb begin : p_req
|
||||
l15_data_o.l15_rqtype = LOAD_RQ;
|
||||
l15_req_o.l15_rqtype = LOAD_RQ;
|
||||
|
||||
unique case (arb_idx)
|
||||
unique case (arb_idx)
|
||||
0: begin// icache
|
||||
l15_data_o.l15_rqtype = IMISS_RQ;
|
||||
l15_req_o.l15_rqtype = IMISS_RQ;
|
||||
end
|
||||
1: begin
|
||||
unique case (dcache_data.rtype)
|
||||
unique case (dcache_data.rtype)
|
||||
DCACHE_STORE_REQ: begin
|
||||
l15_data_o.l15_rqtype = STORE_RQ;
|
||||
l15_req_o.l15_rqtype = STORE_RQ;
|
||||
end
|
||||
DCACHE_LOAD_REQ: begin
|
||||
l15_req_o.l15_rqtype = LOAD_RQ;
|
||||
end
|
||||
DCACHE_LOAD_REQ: begin
|
||||
l15_data_o.l15_rqtype = LOAD_RQ;
|
||||
end
|
||||
DCACHE_ATOMIC_REQ: begin
|
||||
l15_data_o.l15_rqtype = ATOMIC_RQ;
|
||||
end
|
||||
l15_req_o.l15_rqtype = ATOMIC_RQ;
|
||||
end
|
||||
// DCACHE_INT_REQ: begin
|
||||
// //TODO
|
||||
// end
|
||||
// end
|
||||
default: begin
|
||||
;
|
||||
end
|
||||
endcase // dcache_data.rtype
|
||||
endcase // dcache_data.rtype
|
||||
end
|
||||
default: begin
|
||||
;
|
||||
end
|
||||
endcase
|
||||
end // p_req
|
||||
end // p_req
|
||||
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
||||
|
@ -238,7 +232,7 @@ end
|
|||
fifo_v2 #(
|
||||
.dtype ( icache_req_t ),
|
||||
.DEPTH ( ADAPTER_REQ_FIFO_DEPTH )
|
||||
) i_icache_data_fifo (
|
||||
) i_icache_data_fifo (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( 1'b0 ),
|
||||
|
@ -251,12 +245,12 @@ fifo_v2 #(
|
|||
.push_i ( icache_data_push ),
|
||||
.data_o ( icache_data ),
|
||||
.pop_i ( icache_data_pop )
|
||||
);
|
||||
);
|
||||
|
||||
fifo_v2 #(
|
||||
.dtype ( dcache_req_t ),
|
||||
.DEPTH ( ADAPTER_REQ_FIFO_DEPTH )
|
||||
) i_dcache_data_fifo (
|
||||
) i_dcache_data_fifo (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( 1'b0 ),
|
||||
|
@ -269,7 +263,7 @@ fifo_v2 #(
|
|||
.push_i ( dcache_data_push ),
|
||||
.data_o ( dcache_data ),
|
||||
.pop_i ( dcache_data_pop )
|
||||
);
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// return path from L15
|
||||
|
@ -279,19 +273,19 @@ fifo_v2 #(
|
|||
// l15_rtrn_i.l15_returntype; // see below for encoding
|
||||
// l15_rtrn_i.l15_noncacheable; // non-cacheable bit
|
||||
// l15_rtrn_i.l15_atomic; // asserted in load return and store ack pack
|
||||
// l15_rtrn_i.l15_threadid; // used as transaction ID
|
||||
// l15_rtrn_i.l15_f4b; // 4byte instruction fill from I/O space (nc).
|
||||
// l15_rtrn_i.l15_threadid; // used as transaction ID
|
||||
// l15_rtrn_i.l15_f4b; // 4byte instruction fill from I/O space (nc).
|
||||
// l15_rtrn_i.l15_data_0; // used for both caches
|
||||
// l15_rtrn_i.l15_data_1; // used for both caches
|
||||
// l15_rtrn_i.l15_data_2; // currently only used for I$
|
||||
// l15_rtrn_i.l15_data_3; // currently only used for I$
|
||||
// l15_rtrn_i.l15_inval_icache_all_way; // invalidate all ways
|
||||
// l15_rtrn_i.l15_inval_icache_all_way; // invalidate all ways
|
||||
// l15_rtrn_i.l15_inval_address_15_4; // invalidate selected cacheline
|
||||
// l15_rtrn_i.l15_inval_dcache_inval; // invalidate selected cacheline and way
|
||||
// l15_rtrn_i.l15_inval_way; // way to invalidate
|
||||
// l15_rtrn_i.l15_inval_way; // way to invalidate
|
||||
|
||||
// acknowledge if we have space to hold this packet
|
||||
assign l15_req_ack_o = l15_val_i & ~rtrn_fifo_full;
|
||||
assign l15_req_o.l15_req_ack = l15_rtrn_i.l15_val & ~rtrn_fifo_full;
|
||||
// packets have to be consumed immediately
|
||||
assign rtrn_fifo_pop = ~rtrn_fifo_empty;
|
||||
|
||||
|
@ -302,33 +296,33 @@ always_comb begin : p_rtrn_logic
|
|||
icache_rtrn_vld_o = 1'b0;
|
||||
dcache_rtrn_vld_o = 1'b0;
|
||||
if(~rtrn_fifo_empty) begin
|
||||
unique case (rtrn_fifo_data.l15_returntype)
|
||||
unique case (rtrn_fifo_data.l15_returntype)
|
||||
LOAD_RET: begin
|
||||
dcache_rtrn_o.rtype = DCACHE_LOAD_ACK;
|
||||
dcache_rtrn_vld_o = 1'b1;
|
||||
end
|
||||
end
|
||||
ST_ACK: begin
|
||||
dcache_rtrn_o.rtype = DCACHE_STORE_ACK;
|
||||
dcache_rtrn_vld_o = 1'b1;
|
||||
end
|
||||
end
|
||||
// INT_RET: begin
|
||||
// TODO: implement this
|
||||
// TODO: implement this
|
||||
// dcache_rtrn_o.reqType = DCACHE_INT_ACK;
|
||||
// end
|
||||
// end
|
||||
IFILL_RET: begin
|
||||
icache_rtrn_o.rtype = ICACHE_IFILL_ACK;
|
||||
icache_rtrn_vld_o = 1'b1;
|
||||
end
|
||||
end
|
||||
EVICT_REQ: begin
|
||||
icache_rtrn_o.rtype = ICACHE_INV_REQ;
|
||||
dcache_rtrn_o.rtype = DCACHE_INV_REQ;
|
||||
icache_rtrn_vld_o = 1'b1;
|
||||
dcache_rtrn_vld_o = 1'b1;
|
||||
end
|
||||
end
|
||||
CPX_RESTYPE_ATOMIC_RES: begin
|
||||
dcache_rtrn_o.rtype = DCACHE_ATOMIC_ACK;
|
||||
end
|
||||
default: begin
|
||||
default: begin
|
||||
;
|
||||
end
|
||||
endcase // rtrn_fifo_data.l15_returntype
|
||||
|
@ -368,7 +362,7 @@ assign dcache_rtrn_o.inv.all = rtrn_fifo_data.l15_inval_dcache_all_way;
|
|||
fifo_v2 #(
|
||||
.dtype ( l15_rtrn_t ),
|
||||
.DEPTH ( ADAPTER_RTRN_FIFO_DEPTH )
|
||||
) i_rtrn_fifo (
|
||||
) i_rtrn_fifo (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( 1'b0 ),
|
||||
|
@ -378,10 +372,10 @@ fifo_v2 #(
|
|||
.alm_full_o ( ),
|
||||
.alm_empty_o ( ),
|
||||
.data_i ( l15_rtrn_i ),
|
||||
.push_i ( l15_req_ack_o ),
|
||||
.push_i ( l15_req_o.l15_req_ack ),
|
||||
.data_o ( rtrn_fifo_data ),
|
||||
.pop_i ( rtrn_fifo_pop )
|
||||
);
|
||||
);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
@ -392,48 +386,48 @@ fifo_v2 #(
|
|||
`ifndef verilator
|
||||
|
||||
iospace: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) l15_val_o |-> l15_data_o.l15_address >= {40'h8000000000} |-> l15_data_o.l15_nc)
|
||||
@(posedge clk_i) disable iff (~rst_ni) l15_req_o.l15_val |-> l15_req_o.l15_address >= {40'h8000000000} |-> l15_req_o.l15_nc)
|
||||
else $fatal("[l15_adapter] accesses to I/O space must have noncacheable bit set!");
|
||||
|
||||
invalidations: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) l15_val_i |-> l15_rtrn_i.l15_returntype == EVICT_REQ |-> (l15_rtrn_i.l15_inval_icache_inval |
|
||||
@(posedge clk_i) disable iff (~rst_ni) l15_rtrn_i.l15_val |-> l15_rtrn_i.l15_returntype == EVICT_REQ |-> (l15_rtrn_i.l15_inval_icache_inval |
|
||||
l15_rtrn_i.l15_inval_dcache_inval |
|
||||
l15_rtrn_i.l15_inval_icache_all_way |
|
||||
l15_rtrn_i.l15_inval_dcache_all_way))
|
||||
l15_rtrn_i.l15_inval_dcache_all_way))
|
||||
else $fatal("[l15_adapter] got invalidation package with zero invalidation flags");
|
||||
|
||||
blockstore_o: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) l15_val_o|-> !l15_data_o.l15_blockstore)
|
||||
@(posedge clk_i) disable iff (~rst_ni) l15_req_o.l15_val|-> !l15_req_o.l15_blockstore)
|
||||
else $fatal("[l15_adapter] blockstores are not supported");
|
||||
|
||||
blockstore_i: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) l15_val_i|-> !l15_rtrn_i.l15_blockinitstore)
|
||||
@(posedge clk_i) disable iff (~rst_ni) l15_rtrn_i.l15_val|-> !l15_rtrn_i.l15_blockinitstore)
|
||||
else $fatal("[l15_adapter] blockstores are not supported");
|
||||
|
||||
instr_fill_size: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) (!l15_rtrn_i.l15_f4b))
|
||||
@(posedge clk_i) disable iff (~rst_ni) (!l15_rtrn_i.l15_f4b))
|
||||
else $fatal("[l15_adapter] 4b instruction fills not supported");
|
||||
|
||||
unsuported_rtrn_types: assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) (l15_val_i |-> l15_rtrn_i.l15_returntype inside {LOAD_RET, ST_ACK, IFILL_RET, EVICT_REQ}))
|
||||
@(posedge clk_i) disable iff (~rst_ni) (l15_rtrn_i.l15_val |-> l15_rtrn_i.l15_returntype inside {LOAD_RET, ST_ACK, IFILL_RET, EVICT_REQ}))
|
||||
else $fatal("[l15_adapter] unsupported rtrn type");
|
||||
|
||||
|
||||
initial begin
|
||||
// assert wrong parameterizations
|
||||
assert (L15_SET_ASSOC == ICACHE_SET_ASSOC)
|
||||
assert (L15_SET_ASSOC == ICACHE_SET_ASSOC)
|
||||
else $fatal("[l15_adapter] number of icache ways not aligned with L15");
|
||||
// assert wrong parameterizations
|
||||
assert (L15_SET_ASSOC == DCACHE_SET_ASSOC)
|
||||
assert (L15_SET_ASSOC == DCACHE_SET_ASSOC)
|
||||
else $fatal("[l15_adapter] number of dcache ways not aligned with L15");
|
||||
// invalidation address returned by L1.5 is 16 bit
|
||||
assert (16 >= $max(ICACHE_INDEX_WIDTH, DCACHE_INDEX_WIDTH))
|
||||
assert (16 >= $max(ICACHE_INDEX_WIDTH, DCACHE_INDEX_WIDTH))
|
||||
else $fatal("[l15_adapter] maximum number of index bits supported by L1.5 is 16");
|
||||
// assert mismatch of cache line width
|
||||
assert (ICACHE_LINE_WIDTH==256)
|
||||
else $fatal("[l15_adapter] ichache lines are currently restricted to 256 bits");
|
||||
assert (DCACHE_LINE_WIDTH==128)
|
||||
else $fatal("[l15_adapter] dchache lines are currently restricted to 128 bits");
|
||||
assert (ICACHE_LINE_WIDTH==256)
|
||||
else $fatal("[l15_adapter] ichache lines are currently restricted to 256 bits");
|
||||
assert (DCACHE_LINE_WIDTH==128)
|
||||
else $fatal("[l15_adapter] dchache lines are currently restricted to 128 bits");
|
||||
end
|
||||
`endif
|
||||
//pragma translate_on
|
||||
|
|
|
@ -18,10 +18,6 @@ import ariane_pkg::*;
|
|||
import std_cache_pkg::*;
|
||||
|
||||
module std_cache_subsystem #(
|
||||
<<<<<<< HEAD
|
||||
parameter int unsigned AXI_ID_WIDTH = 10,
|
||||
=======
|
||||
>>>>>>> ariane_next
|
||||
parameter logic [63:0] CACHE_START_ADDR = 64'h4000_0000
|
||||
)(
|
||||
input logic clk_i,
|
||||
|
@ -84,7 +80,6 @@ module std_cache_subsystem #(
|
|||
// Port 1: Load Unit
|
||||
// Port 2: Store Unit
|
||||
std_nbdcache #(
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
|
||||
.CACHE_START_ADDR ( CACHE_START_ADDR )
|
||||
) i_nbdcache (
|
||||
.clk_i,
|
||||
|
|
|
@ -16,7 +16,6 @@ import ariane_pkg::*;
|
|||
import std_cache_pkg::*;
|
||||
|
||||
module std_nbdcache #(
|
||||
parameter int unsigned AXI_ID_WIDTH = 10,
|
||||
parameter logic [63:0] CACHE_START_ADDR = 64'h8000_0000
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
|
@ -128,7 +127,6 @@ module std_nbdcache #(
|
|||
// Miss Handling Unit
|
||||
// ------------------
|
||||
miss_handler #(
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
|
||||
.NR_PORTS ( 3 )
|
||||
) i_miss_handler (
|
||||
.flush_i ( flush_i ),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue