Dev dcache 32bits (#849)

Reduce dcache data output width from 64 to 32 bits in cv32a6 configuration

Signed-off-by: sjthales <sebastien.jacq@thalesgroup.com>
This commit is contained in:
sébastien jacq 2022-04-11 14:54:09 +02:00 committed by GitHub
parent 48af8dab6e
commit 0b61544da8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 226 additions and 146 deletions

View file

@ -119,7 +119,6 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
always_comb begin : p_axi_req
// write channel
axi_wr_id_in = arb_idx;
axi_wr_data = dcache_data.data;
axi_wr_addr = {{64-riscv::PLEN{1'b0}}, dcache_data.paddr};
axi_wr_size = dcache_data.size[1:0];
axi_wr_req = 1'b0;
@ -135,6 +134,12 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
axi_rd_req = 1'b0;
axi_rd_lock = '0;
axi_rd_blen = '0;
if (dcache_data.paddr[2] == 1'b0) begin
axi_wr_data = {{64-riscv::XLEN{1'b0}}, dcache_data.data};
end else begin
axi_wr_data = {dcache_data.data, {64-riscv::XLEN{1'b0}}};
end
// arbiter mux
if (arb_idx) begin
@ -171,7 +176,7 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
//////////////////////////////////////
wt_cache_pkg::DCACHE_STORE_REQ: begin
axi_wr_req = 1'b1;
axi_wr_be = wt_cache_pkg::toByteEnable8(dcache_data.paddr[2:0], dcache_data.size[1:0]);
axi_wr_be = wt_cache_pkg::to_byte_enable8(dcache_data.paddr[2:0], dcache_data.size[1:0]);
end
//////////////////////////////////////
wt_cache_pkg::DCACHE_ATOMIC_REQ: begin
@ -182,7 +187,7 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
// an atomic, this is safe.
invalidate = arb_gnt;
axi_wr_req = 1'b1;
axi_wr_be = wt_cache_pkg::toByteEnable8(dcache_data.paddr[2:0], dcache_data.size[1:0]);
axi_wr_be = wt_cache_pkg::to_byte_enable8(dcache_data.paddr[2:0], dcache_data.size[1:0]);
amo_gen_r_d = 1'b1;
// need to use a separate ID here, so concat an additional bit
axi_wr_id_in[1] = 1'b1;
@ -212,7 +217,11 @@ module wt_axi_adapter import ariane_pkg::*; import wt_cache_pkg::*; #(
AMO_ADD: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ADD};
AMO_AND: begin
// in this case we need to invert the data to get a "CLR"
axi_wr_data = ~dcache_data.data;
if (dcache_data.paddr[2] == 1'b0) begin
axi_wr_data = {{64-riscv::XLEN{1'b1}}, ~dcache_data.data};
end else begin
axi_wr_data = {~dcache_data.data, {64-riscv::XLEN{1'b1}}};
end
axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_CLR};
end
AMO_OR: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SET};

View file

@ -66,15 +66,15 @@ module wt_dcache import ariane_pkg::*; import wt_cache_pkg::*; #(
logic wr_ack;
logic [DCACHE_CL_IDX_WIDTH-1:0] wr_idx;
logic [DCACHE_OFFSET_WIDTH-1:0] wr_off;
logic [63:0] wr_data;
logic [7:0] wr_data_be;
riscv::xlen_t wr_data;
logic [(riscv::XLEN/8)-1:0] wr_data_be;
// miss unit <-> controllers/wbuffer
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][riscv::XLEN-1:0] miss_wdata;
logic [NumPorts-1:0][riscv::PLEN-1:0] miss_paddr;
logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits;
logic [NumPorts-1:0][2:0] miss_size;
@ -91,7 +91,7 @@ module wt_dcache import ariane_pkg::*; import wt_cache_pkg::*; #(
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;
riscv::xlen_t rd_data;
logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits;
logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh;

View file

@ -27,7 +27,7 @@ module wt_dcache_ctrl import ariane_pkg::*; import wt_cache_pkg::*; #(
output logic miss_req_o,
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 riscv::xlen_t 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 [riscv::PLEN-1:0] miss_paddr_o,
output logic miss_nc_o, // request to I/O space
@ -44,7 +44,7 @@ module wt_dcache_ctrl import ariane_pkg::*; import wt_cache_pkg::*; #(
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 [63:0] rd_data_i,
input riscv::xlen_t 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
);

View file

@ -43,7 +43,7 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
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,
output riscv::xlen_t rd_data_o,
// only available on port 0, uses address signals of port 0
input logic wr_cl_vld_i,
@ -61,23 +61,23 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
output logic wr_ack_o,
input logic [DCACHE_CL_IDX_WIDTH-1:0] wr_idx_i,
input logic [DCACHE_OFFSET_WIDTH-1:0] wr_off_i,
input logic [63:0] wr_data_i,
input logic [7:0] wr_data_be_i,
input riscv::xlen_t wr_data_i,
input logic [(riscv::XLEN/8)-1:0] wr_data_be_i,
// forwarded wbuffer
input wbuffer_t [DCACHE_WBUF_DEPTH-1:0] wbuffer_data_i
);
logic [DCACHE_NUM_BANKS-1:0] bank_req;
logic [DCACHE_NUM_BANKS-1:0] bank_we;
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][7:0] bank_be;
logic [DCACHE_NUM_BANKS-1:0][DCACHE_CL_IDX_WIDTH-1:0] bank_idx;
logic [DCACHE_CL_IDX_WIDTH-1:0] bank_idx_d, bank_idx_q;
logic [DCACHE_OFFSET_WIDTH-1:0] bank_off_d, bank_off_q;
logic [DCACHE_NUM_BANKS-1:0] bank_req;
logic [DCACHE_NUM_BANKS-1:0] bank_we;
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][(riscv::XLEN/8)-1:0] bank_be;
logic [DCACHE_NUM_BANKS-1:0][DCACHE_CL_IDX_WIDTH-1:0] bank_idx;
logic [DCACHE_CL_IDX_WIDTH-1:0] bank_idx_d, bank_idx_q;
logic [DCACHE_OFFSET_WIDTH-1:0] bank_off_d, bank_off_q;
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][63:0] bank_wdata; //
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][63:0] bank_rdata; //
logic [DCACHE_SET_ASSOC-1:0][63:0] rdata_cl; // selected word from each cacheline
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] bank_wdata; //
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] bank_rdata; //
logic [DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] rdata_cl; // selected word from each cacheline
logic [DCACHE_TAG_WIDTH-1:0] rd_tag;
logic [DCACHE_SET_ASSOC-1:0] vld_req; // bit enable for valid regs
@ -89,8 +89,8 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
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;
logic [63:0] wbuffer_rdata, rdata;
logic [(riscv::XLEN/8)-1:0] wbuffer_be;
riscv::xlen_t wbuffer_rdata, rdata;
logic [riscv::PLEN-1:0] wbuffer_cmp_addr;
logic cmp_en_d, cmp_en_q;
@ -111,11 +111,11 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
// byte enable mapping
for (genvar k=0;k<DCACHE_NUM_BANKS;k++) begin : gen_bank
for (genvar j=0;j<DCACHE_SET_ASSOC;j++) begin : gen_bank_way
assign bank_be[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ? wr_cl_data_be_i[k*8 +: 8] :
assign bank_be[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ? wr_cl_data_be_i[k*(riscv::XLEN/8) +: (riscv::XLEN/8)] :
(wr_req_i[j] & wr_ack_o) ? wr_data_be_i :
'0;
assign bank_wdata[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ? wr_cl_data_i[k*64 +: 64] :
assign bank_wdata[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ? wr_cl_data_i[k*riscv::XLEN +: riscv::XLEN] :
wr_data_i;
end
end
@ -161,7 +161,7 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
bank_idx = '{default:wr_idx_i};
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];
bank_collision[k] = rd_off_i[k][DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES] == wr_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES];
end
if(wr_cl_vld_i & |wr_cl_we_i) begin
@ -171,16 +171,16 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
end else begin
if(rd_acked) begin
if(!rd_tag_only_i[vld_sel_d]) begin
bank_req = dcache_cl_bin2oh(rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:3]);
bank_idx[rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:3]] = rd_idx_i[vld_sel_d];
bank_req = dcache_cl_bin2oh(rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]);
bank_idx[rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]] = rd_idx_i[vld_sel_d];
end
end
if(|wr_req_i) begin
if(rd_tag_only_i[vld_sel_d] || !(rd_ack_o[vld_sel_d] && bank_collision[vld_sel_d])) begin
wr_ack_o = 1'b1;
bank_req |= dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:3]);
bank_we = dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:3]);
bank_req |= dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]);
bank_we = dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]);
end
end
end
@ -190,7 +190,8 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
// tag comparison, hit generatio, readoud muxes
///////////////////////////////////////////////////////
logic [DCACHE_OFFSET_WIDTH-1:0] wr_cl_off;
logic [DCACHE_OFFSET_WIDTH-riscv::XLEN_ALIGN_BYTES-1:0] wr_cl_off;
logic [DCACHE_OFFSET_WIDTH-riscv::XLEN_ALIGN_BYTES-1:0] wr_cl_nc_off;
logic [$clog2(DCACHE_WBUF_DEPTH)-1:0] wbuffer_hit_idx;
logic [$clog2(DCACHE_SET_ASSOC)-1:0] rd_hit_idx;
@ -204,11 +205,11 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
// tag comparison of ways >0
assign rd_hit_oh_o[i] = (rd_tag == tag_rdata[i]) & rd_vld_bits_o[i] & cmp_en_q;
// byte offset mux of ways >0
assign rdata_cl[i] = bank_rdata[bank_off_q[DCACHE_OFFSET_WIDTH-1:3]][i];
assign rdata_cl[i] = bank_rdata[bank_off_q[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]][i];
end
for(genvar k=0; k<DCACHE_WBUF_DEPTH; k++) begin : gen_wbuffer_hit
assign wbuffer_hit_oh[k] = (|wbuffer_data_i[k].valid) & (wbuffer_data_i[k].wtag == (wbuffer_cmp_addr >> 3));
assign wbuffer_hit_oh[k] = (|wbuffer_data_i[k].valid) & (wbuffer_data_i[k].wtag == (wbuffer_cmp_addr >> riscv::XLEN_ALIGN_BYTES));
end
lzc #(
@ -231,16 +232,17 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
assign wbuffer_be = (|wbuffer_hit_oh) ? wbuffer_data_i[wbuffer_hit_idx].valid : '0;
if (Axi64BitCompliant) begin : gen_axi_off
assign wr_cl_off = (wr_cl_nc_i) ? '0 : wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:3];
assign wr_cl_nc_off = riscv::IS_XLEN64 ? '0 : wr_cl_off_i[2];
assign wr_cl_off = (wr_cl_nc_i) ? wr_cl_nc_off : wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES];
end else begin : gen_piton_off
assign wr_cl_off = wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:3];
end
assign rdata = (wr_cl_vld_i) ? wr_cl_data_i[wr_cl_off*64 +: 64] :
assign rdata = (wr_cl_vld_i) ? wr_cl_data_i[wr_cl_off*riscv::XLEN +: riscv::XLEN] :
rdata_cl[rd_hit_idx];
// overlay bytes that hit in the write buffer
for(genvar k=0; k<8; k++) begin : gen_rd_data
for(genvar k=0; k<(riscv::XLEN/8); k++) begin : gen_rd_data
assign rd_data_o[8*k +: 8] = (wbuffer_be[k]) ? wbuffer_rdata[8*k +: 8] : rdata[8*k +: 8];
end
@ -253,7 +255,7 @@ module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
for (genvar k = 0; k < DCACHE_NUM_BANKS; k++) begin : gen_data_banks
// Data RAM
sram #(
.DATA_WIDTH ( ariane_pkg::DCACHE_SET_ASSOC * 64 ),
.DATA_WIDTH ( ariane_pkg::DCACHE_SET_ASSOC * riscv::XLEN ),
.NUM_WORDS ( wt_cache_pkg::DCACHE_NUM_WORDS )
) i_data_sram (
.clk_i ( clk_i ),

View file

@ -37,7 +37,7 @@ module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
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][riscv::XLEN-1:0] miss_wdata_i,
input logic [NumPorts-1:0][riscv::PLEN-1: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,
@ -95,7 +95,8 @@ module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
logic mask_reads, lock_reqs;
logic amo_sel, miss_is_write;
logic amo_req_d, amo_req_q;
logic [63:0] amo_data, amo_rtrn_mux;
logic [63:0] amo_rtrn_mux;
riscv::xlen_t amo_data;
logic [riscv::PLEN-1:0] tmp_paddr;
logic [$clog2(NumPorts)-1:0] miss_port_idx;
logic [DCACHE_CL_IDX_WIDTH-1:0] cnt_d, cnt_q;
@ -151,7 +152,7 @@ module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
// generate random cacheline index
lfsr #(
.LfsrWidth ( ariane_pkg::DCACHE_SET_ASSOC ),
.LfsrWidth ( 8 ),
.OutWidth ( $clog2(ariane_pkg::DCACHE_SET_ASSOC))
) i_lfsr_inv (
.clk_i ( clk_i ),
@ -200,9 +201,9 @@ module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
///////////////////////////////////////////////////////
// if size = 32bit word, select appropriate offset, replicate for openpiton...
assign amo_data = (amo_req_i.size==2'b10) ? {amo_req_i.operand_b[0 +: 32],
amo_req_i.operand_b[0 +: 32]} :
amo_req_i.operand_b;
assign amo_data = riscv::IS_XLEN64 ? (amo_req_i.size==2'b10) ? {amo_req_i.operand_b[0 +: 32],amo_req_i.operand_b[0 +: 32]} : amo_req_i.operand_b :
amo_req_i.operand_b[0 +: 32];
// note: openpiton returns a full cacheline!
if (Axi64BitCompliant) begin : gen_axi_rtrn_mux
@ -212,9 +213,10 @@ module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
end
// always sign extend 32bit values
assign amo_resp_o.result = (amo_req_i.size==2'b10) ? {{32{amo_rtrn_mux[amo_req_i.operand_a[2]*32 + 31]}},
amo_rtrn_mux[amo_req_i.operand_a[2]*32 +: 32]} :
amo_rtrn_mux;
assign amo_resp_o.result = (amo_req_i.size==2'b10) ? {{32{amo_rtrn_mux[amo_req_i.operand_a[2]*32 + 31]}},amo_rtrn_mux[amo_req_i.operand_a[2]*32 +: 32]} :
amo_rtrn_mux ;
assign amo_req_d = amo_req_i.req;

View file

@ -66,7 +66,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
output logic [riscv::PLEN-1:0] miss_paddr_o,
output logic miss_req_o,
output logic miss_we_o, // always 1 here
output logic [63:0] miss_wdata_o,
output riscv::xlen_t miss_wdata_o,
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, //
@ -81,7 +81,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
output logic rd_req_o, // read the word at offset off_i[:3] in all ways
output logic rd_tag_only_o, // set to 1 here as we do not have to read the data arrays
input logic rd_ack_i,
input logic [63:0] rd_data_i, // unused
input riscv::xlen_t rd_data_i, // unused
input logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits_i, // unused
input logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh_i,
// cacheline writes
@ -92,8 +92,8 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
input logic wr_ack_i,
output logic [DCACHE_CL_IDX_WIDTH-1:0] wr_idx_o,
output logic [DCACHE_OFFSET_WIDTH-1:0] wr_off_o,
output logic [63:0] wr_data_o,
output logic [7:0] wr_data_be_o,
output riscv::xlen_t wr_data_o,
output logic [(riscv::XLEN/8)-1:0] wr_data_be_o,
// to forwarding logic and miss unit
output wbuffer_t [DCACHE_WBUF_DEPTH-1:0] wbuffer_data_o,
output logic [DCACHE_MAX_TX-1:0][riscv::PLEN-1:0] tx_paddr_o, // used to check for address collisions with read operations
@ -106,13 +106,14 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
logic [DCACHE_WBUF_DEPTH-1:0] dirty;
logic [DCACHE_WBUF_DEPTH-1:0] tocheck;
logic [DCACHE_WBUF_DEPTH-1:0] wbuffer_hit_oh, inval_hit;
logic [DCACHE_WBUF_DEPTH-1:0][7:0] bdirty;
//logic [DCACHE_WBUF_DEPTH-1:0][7:0] bdirty;
logic [DCACHE_WBUF_DEPTH-1:0][(riscv::XLEN/8)-1:0] bdirty;
logic [$clog2(DCACHE_WBUF_DEPTH)-1:0] next_ptr, dirty_ptr, hit_ptr, wr_ptr, check_ptr_d, check_ptr_q, check_ptr_q1, rtrn_ptr;
logic [CACHE_ID_WIDTH-1:0] tx_id, rtrn_id;
logic [2:0] bdirty_off;
logic [7:0] tx_be;
logic [riscv::XLEN_ALIGN_BYTES-1:0] bdirty_off;
logic [(riscv::XLEN/8)-1:0] tx_be;
logic [riscv::PLEN-1:0] wr_paddr, rd_paddr;
logic [DCACHE_TAG_WIDTH-1:0] rd_tag_d, rd_tag_q;
logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh_d, rd_hit_oh_q;
@ -148,7 +149,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
for (genvar k=0; k<DCACHE_MAX_TX;k++) begin : gen_tx_vld
assign tx_vld_o[k] = tx_stat_q[k].vld;
assign tx_paddr_o[k] = wbuffer_q[tx_stat_q[k].ptr].wtag<<3;
assign tx_paddr_o[k] = wbuffer_q[tx_stat_q[k].ptr].wtag<<riscv::XLEN_ALIGN_BYTES;
end
///////////////////////////////////////////////////////
@ -164,7 +165,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
// get byte offset
lzc #(
.WIDTH ( 8 )
.WIDTH ( riscv::XLEN/8 )
) i_vld_bdirty (
.in_i ( bdirty[dirty_ptr] ),
.cnt_o ( bdirty_off ),
@ -182,15 +183,16 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
// note: openpiton can only handle aligned offsets + size, and hence
// we have to split unaligned data into multiple transfers (see toSize64)
// e.g. if we have the following valid bytes: 0011_1001 -> TX0: 0000_0001, TX1: 0000_1000, TX2: 0011_0000
assign miss_size_o = toSize64(bdirty[dirty_ptr]);
assign miss_size_o = riscv::IS_XLEN64 ? toSize64(bdirty[dirty_ptr]):
toSize32(bdirty[dirty_ptr]);
// replicate transfers shorter than a dword
assign miss_wdata_o = repData64(wbuffer_dirty_mux.data,
bdirty_off,
miss_size_o[1:0]);
assign miss_wdata_o = riscv::IS_XLEN64 ? repData64(wbuffer_dirty_mux.data, bdirty_off, miss_size_o[1:0]):
repData32(wbuffer_dirty_mux.data, bdirty_off, miss_size_o[1:0]);
assign tx_be = toByteEnable8(bdirty_off,
miss_size_o[1:0]);
assign tx_be = riscv::IS_XLEN64 ? to_byte_enable8(bdirty_off, miss_size_o[1:0]):
to_byte_enable4(bdirty_off, miss_size_o[1:0]);
///////////////////////////////////////////////////////
// TX status registers and ID counters
@ -273,7 +275,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
// trigger TAG readout in cache
assign rd_tag_only_o = 1'b1;
assign rd_paddr = wbuffer_check_mux.wtag<<3;
assign rd_paddr = wbuffer_check_mux.wtag<<riscv::XLEN_ALIGN_BYTES;
assign rd_req_o = |tocheck;
assign rd_tag_o = rd_tag_q;//delay by one cycle
assign rd_idx_o = rd_paddr[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH];
@ -285,7 +287,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
// if we wrote into a word while it was in-flight, we cannot write the dirty bytes to the cache
// when the TX returns
assign wr_data_be_o = tx_stat_q[rtrn_id].be & (~wbuffer_q[rtrn_ptr].dirty);
assign wr_paddr = wbuffer_q[rtrn_ptr].wtag<<3;
assign wr_paddr = wbuffer_q[rtrn_ptr].wtag<<riscv::XLEN_ALIGN_BYTES;
assign wr_idx_o = wr_paddr[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH];
assign wr_off_o = wr_paddr[DCACHE_OFFSET_WIDTH-1:0];
assign wr_data_o = wbuffer_q[rtrn_ptr].data;
@ -302,7 +304,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
for (genvar k=0; k<DCACHE_WBUF_DEPTH; k++) begin : gen_flags
// only for debug, will be pruned
assign debug_paddr[k] = wbuffer_q[k].wtag << 3;
assign debug_paddr[k] = wbuffer_q[k].wtag << riscv::XLEN_ALIGN_BYTES;
// dirty bytes that are ready for transmission.
// note that we cannot retransmit a word that is already in-flight
@ -312,12 +314,12 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
assign dirty[k] = |bdirty[k];
assign valid[k] = |wbuffer_q[k].valid;
assign wbuffer_hit_oh[k] = valid[k] & (wbuffer_q[k].wtag == {req_port_i.address_tag, req_port_i.address_index[DCACHE_INDEX_WIDTH-1:3]});
assign wbuffer_hit_oh[k] = valid[k] & (wbuffer_q[k].wtag == {req_port_i.address_tag, req_port_i.address_index[DCACHE_INDEX_WIDTH-1:riscv::XLEN_ALIGN_BYTES]});
// checks if an invalidation/cache refill hits a particular word
// note: an invalidation can hit multiple words!
// need to respect previous cycle, too, since we add a cycle of latency to the rd_hit_oh_i signal...
assign wtag_comp[k] = wbuffer_q[k].wtag[DCACHE_INDEX_WIDTH-4:DCACHE_OFFSET_WIDTH-3];
assign wtag_comp[k] = wbuffer_q[k].wtag[DCACHE_INDEX_WIDTH-riscv::XLEN_ALIGN_BYTES-1:DCACHE_OFFSET_WIDTH-riscv::XLEN_ALIGN_BYTES];
assign inval_hit[k] = (wr_cl_vld_d & valid[k] & (wtag_comp[k] == wr_cl_idx_d)) |
(wr_cl_vld_q & valid[k] & (wtag_comp[k] == wr_cl_idx_q));
@ -425,7 +427,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
// once TX write response came back, we can clear the TX block. if it was not dirty, we
// can completely evict it - otherwise we have to leave it there for retransmission
if (evict) begin
for (int k=0; k<8; k++) begin
for (int k=0; k<(riscv::XLEN/8); k++) begin
if (tx_stat_q[rtrn_id].be[k]) begin
wbuffer_d[rtrn_ptr].txblock[k] = 1'b0;
if (!wbuffer_q[rtrn_ptr].dirty[k]) begin
@ -447,7 +449,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
// mark bytes sent out to the memory system
if (miss_req_o && miss_ack_i) begin
dirty_rd_en = 1'b1;
for (int k=0; k<8; k++) begin
for (int k=0; k<(riscv::XLEN/8); k++) begin
if (tx_be[k]) begin
wbuffer_d[dirty_ptr].dirty[k] = 1'b0;
wbuffer_d[dirty_ptr].txblock[k] = 1'b1;
@ -466,10 +468,10 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
ni_pending_d[wr_ptr] = is_ni;
wbuffer_d[wr_ptr].checked = 1'b0;
wbuffer_d[wr_ptr].wtag = {req_port_i.address_tag, req_port_i.address_index[DCACHE_INDEX_WIDTH-1:3]};
wbuffer_d[wr_ptr].wtag = {req_port_i.address_tag, req_port_i.address_index[DCACHE_INDEX_WIDTH-1:riscv::XLEN_ALIGN_BYTES]};
// mark bytes as dirty
for (int k=0; k<8; k++) begin
for (int k=0; k<(riscv::XLEN/8); k++) begin
if (req_port_i.data_be[k]) begin
wbuffer_d[wr_ptr].valid[k] = 1'b1;
wbuffer_d[wr_ptr].dirty[k] = 1'b1;

View file

@ -572,16 +572,16 @@ package ariane_pkg;
default: return 1'b0;
endcase
endfunction
typedef struct packed {
logic valid;
logic [riscv::VLEN-1:0] vaddr;
logic overflow;
logic [63:0] data;
logic [7:0] be;
fu_t fu;
fu_op operator;
logic [TRANS_ID_BITS-1:0] trans_id;
logic valid;
logic [riscv::VLEN-1:0] vaddr;
logic overflow;
riscv::xlen_t data;
logic [(riscv::XLEN/8)-1:0] be;
fu_t fu;
fu_op operator;
logic [TRANS_ID_BITS-1:0] trans_id;
} lsu_ctrl_t;
// ---------------
@ -723,14 +723,14 @@ package ariane_pkg;
logic [63:0] result; // sign-extended, result
} amo_resp_t;
// D$ data requests
// D$ data requests
typedef struct packed {
logic [DCACHE_INDEX_WIDTH-1:0] address_index;
logic [DCACHE_TAG_WIDTH-1:0] address_tag;
logic [63:0] data_wdata;
riscv::xlen_t data_wdata;
logic data_req;
logic data_we;
logic [7:0] data_be;
logic [(riscv::XLEN/8)-1:0] data_be;
logic [1:0] data_size;
logic kill_req;
logic tag_valid;
@ -739,7 +739,7 @@ package ariane_pkg;
typedef struct packed {
logic data_gnt;
logic data_rvalid;
logic [63:0] data_rdata;
riscv::xlen_t data_rdata;
} dcache_req_o_t;
// ----------------------
@ -826,6 +826,32 @@ package ariane_pkg;
endcase
return 8'b0;
endfunction
function automatic logic [3:0] be_gen_32(logic [1:0] addr, logic [1:0] size);
case (size)
2'b10: begin
return 4'b1111;
end
2'b01: begin
case (addr[1:0])
2'b00: return 4'b0011;
2'b01: return 4'b0110;
2'b10: return 4'b1100;
endcase
end
2'b00: begin
case (addr[1:0])
2'b00: return 4'b0001;
2'b01: return 4'b0010;
2'b10: return 4'b0100;
2'b11: return 4'b1000;
endcase
end
default: return 4'b0;
endcase
return 4'b0;
endfunction
// ----------------------
// Extract Bytes from Op

View file

@ -37,17 +37,18 @@ package riscv;
// Warning: When using STD_CACHE, configuration must be PLEN=56 and VLEN=64
// Warning: VLEN must be superior or equal to PLEN
localparam VLEN = (XLEN == 32) ? 32 : 64; // virtual address length
localparam PLEN = (XLEN == 32) ? 34 : 56; // physical address length
localparam VLEN = (XLEN == 32) ? 32 : 64; // virtual address length
localparam PLEN = (XLEN == 32) ? 34 : 56; // physical address length
localparam IS_XLEN32 = (XLEN == 32) ? 1'b1 : 1'b0;
localparam IS_XLEN64 = (XLEN == 32) ? 1'b0 : 1'b1;
localparam ModeW = (XLEN == 32) ? 1 : 4;
localparam ASIDW = (XLEN == 32) ? 9 : 16;
localparam PPNW = (XLEN == 32) ? 22 : 44;
localparam vm_mode_t MODE_SV = (XLEN == 32) ? ModeSv32 : ModeSv39;
localparam SV = (MODE_SV == ModeSv32) ? 32 : 39;
localparam VPN2 = (VLEN-31 < 8) ? VLEN-31 : 8;
localparam IS_XLEN32 = (XLEN == 32) ? 1'b1 : 1'b0;
localparam IS_XLEN64 = (XLEN == 32) ? 1'b0 : 1'b1;
localparam ModeW = (XLEN == 32) ? 1 : 4;
localparam ASIDW = (XLEN == 32) ? 9 : 16;
localparam PPNW = (XLEN == 32) ? 22 : 44;
localparam vm_mode_t MODE_SV = (XLEN == 32) ? ModeSv32 : ModeSv39;
localparam SV = (MODE_SV == ModeSv32) ? 32 : 39;
localparam VPN2 = (VLEN-31 < 8) ? VLEN-31 : 8;
localparam XLEN_ALIGN_BYTES = $clog2(XLEN/8);
typedef logic [XLEN-1:0] xlen_t;

View file

@ -65,7 +65,7 @@ package wt_cache_pkg;
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;
localparam DCACHE_NUM_BANKS = ariane_pkg::DCACHE_LINE_WIDTH/riscv::XLEN;
localparam DCACHE_NUM_BANKS_WIDTH = $clog2(DCACHE_NUM_BANKS);
// write buffer parameterization
@ -75,21 +75,22 @@ package wt_cache_pkg;
typedef struct packed {
logic [ariane_pkg::DCACHE_TAG_WIDTH+(ariane_pkg::DCACHE_INDEX_WIDTH-3)-1:0] wtag;
logic [63:0] data;
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
logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] hit_oh; // valid way in the cache
logic [ariane_pkg::DCACHE_TAG_WIDTH+(ariane_pkg::DCACHE_INDEX_WIDTH-riscv::XLEN_ALIGN_BYTES)-1:0] wtag;
riscv::xlen_t data;
logic [(riscv::XLEN/8)-1:0] dirty; // byte is dirty
logic [(riscv::XLEN/8)-1:0] valid; // byte is valid
logic [(riscv::XLEN/8)-1:0] txblock; // byte is part of transaction in-flight
logic checked; // if cache state of this word has been checked
logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] hit_oh; // valid way in the cache
} wbuffer_t;
// 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 {
logic vld;
logic [7:0] be;
logic [(riscv::XLEN/8)-1:0] be;
logic [$clog2(DCACHE_WBUF_DEPTH)-1:0] ptr;
} tx_stat_t;
@ -149,7 +150,7 @@ package wt_cache_pkg;
logic [2:0] size; // transaction size: 000=Byte 001=2Byte; 010=4Byte; 011=8Byte; 111=Cache line (16/32Byte)
logic [L1D_WAY_WIDTH-1:0] way; // way to replace
logic [riscv::PLEN-1:0] paddr; // physical address
logic [63:0] data; // word width of processor (no block stores at the moment)
riscv::xlen_t data; // word width of processor (no block stores at the moment)
logic nc; // noncacheable
logic [CACHE_ID_WIDTH-1:0] tid; // threadi id (used as transaction id in Ariane)
ariane_pkg::amo_t amo_op; // amo opcode
@ -296,7 +297,7 @@ package wt_cache_pkg;
return cnt;
endfunction : popcnt64
function automatic logic [7:0] toByteEnable8(
function automatic logic [7:0] to_byte_enable8(
input logic [2:0] offset,
input logic [1:0] size
);
@ -309,7 +310,21 @@ package wt_cache_pkg;
default: be = '1; // dword
endcase // size
return be;
endfunction : toByteEnable8
endfunction : to_byte_enable8
function automatic logic [3:0] to_byte_enable4(
input logic [1:0] offset,
input logic [1:0] size
);
logic [3:0] be;
be = '0;
unique case(size)
2'b00: be[offset] = '1; // byte
2'b01: be[offset +:2 ] = '1; // hword
default: be = '1; // word
endcase // size
return be;
endfunction : to_byte_enable4
// openpiton requires the data to be replicated in case of smaller sizes than dwords
function automatic logic [63:0] repData64(
@ -326,6 +341,20 @@ package wt_cache_pkg;
endcase // size
return out;
endfunction : repData64
function automatic logic [31:0] repData32(
input logic [31:0] data,
input logic [1:0] offset,
input logic [1:0] size
);
logic [31:0] out;
unique case(size)
2'b00: for(int k=0; k<4; k++) out[k*8 +: 8] = data[offset*8 +: 8]; // byte
2'b01: for(int k=0; k<2; k++) out[k*16 +: 16] = data[offset*8 +: 16]; // hword
default: out = data; // word
endcase // size
return out;
endfunction : repData32
// note: this is openpiton specific. cannot transmit unaligned words.
// hence we default to individual bytes in that case, and they have to be transmitted
@ -342,6 +371,19 @@ package wt_cache_pkg;
endcase // be
return size;
endfunction : toSize64
function automatic logic [1:0] toSize32(
input logic [3:0] be
);
logic [1:0] size;
unique case(be)
4'b1111: size = 2'b10; // word
4'b1100, 4'b0011: size = 2'b01; // hword
default: size = 2'b00; // individual bytes
endcase // be
return size;
endfunction : toSize32
// align the physical address to the specified size:
// 000: bytes

View file

@ -89,10 +89,10 @@ module load_store_unit import ariane_pkg::*; #(
// Address Generation Unit (AGU)
// ------------------------------
// virtual address as calculated by the AGU in the first cycle
logic [riscv::VLEN-1:0] vaddr_i;
riscv::xlen_t vaddr_xlen;
logic overflow;
logic [7:0] be_i;
logic [riscv::VLEN-1:0] vaddr_i;
riscv::xlen_t vaddr_xlen;
logic overflow;
logic [(riscv::XLEN/8)-1:0] be_i;
assign vaddr_xlen = $unsigned($signed(fu_data_i.imm) + $signed(fu_data_i.operand_a));
assign vaddr_i = vaddr_xlen[riscv::VLEN-1:0];
@ -195,9 +195,9 @@ module load_store_unit import ariane_pkg::*; #(
assign dcache_req_ports_o[0].address_index = '0;
assign dcache_req_ports_o[0].address_tag = '0;
assign dcache_req_ports_o[0].data_wdata = 64'b0;
assign dcache_req_ports_o[0].data_wdata = '0;
assign dcache_req_ports_o[0].data_req = 1'b0;
assign dcache_req_ports_o[0].data_be = 8'hFF;
assign dcache_req_ports_o[0].data_be = '1;
assign dcache_req_ports_o[0].data_size = 2'b11;
assign dcache_req_ports_o[0].data_we = 1'b0;
assign dcache_req_ports_o[0].kill_req = '0;
@ -352,7 +352,8 @@ module load_store_unit import ariane_pkg::*; #(
// we can generate the byte enable from the virtual address since the last
// 12 bit are the same anyway
// and we can always generate the byte enable from the address at hand
assign be_i = be_gen(vaddr_i[2:0], extract_transfer_size(fu_data_i.operator));
assign be_i = riscv::IS_XLEN64 ? be_gen(vaddr_i[2:0], extract_transfer_size(fu_data_i.operator)):
be_gen_32(vaddr_i[1:0], extract_transfer_size(fu_data_i.operator));
// ------------------------
// Misaligned Exception
@ -446,7 +447,7 @@ module load_store_unit import ariane_pkg::*; #(
// new data arrives here
lsu_ctrl_t lsu_req_i;
assign lsu_req_i = {lsu_valid_i, vaddr_i, overflow, {{64-riscv::XLEN{1'b0}}, fu_data_i.operand_b}, be_i, fu_data_i.fu, fu_data_i.operator, fu_data_i.trans_id};
assign lsu_req_i = {lsu_valid_i, vaddr_i, overflow, fu_data_i.operand_b, be_i, fu_data_i.fu, fu_data_i.operator, fu_data_i.trans_id};
lsu_bypass lsu_bypass_i (
.lsu_req_i ( lsu_req_i ),

View file

@ -52,9 +52,9 @@ module load_unit import ariane_pkg::*; #(
// in order to decouple the response interface from the request interface we need a
// a queue which can hold all outstanding memory requests
struct packed {
logic [TRANS_ID_BITS-1:0] trans_id;
logic [2:0] address_offset;
fu_op operator;
logic [TRANS_ID_BITS-1:0] trans_id;
logic [riscv::XLEN_ALIGN_BYTES-1:0] address_offset;
fu_op operator;
} load_data_d, load_data_q, in_data;
// page offset is defined as the lower 12 bits, feed through for address checker
@ -65,7 +65,7 @@ module load_unit import ariane_pkg::*; #(
assign req_port_o.data_we = 1'b0;
assign req_port_o.data_wdata = '0;
// compose the queue data, control is handled in the FSM
assign in_data = {lsu_ctrl_i.trans_id, lsu_ctrl_i.vaddr[2:0], lsu_ctrl_i.operator};
assign in_data = {lsu_ctrl_i.trans_id, lsu_ctrl_i.vaddr[riscv::XLEN_ALIGN_BYTES-1:0], lsu_ctrl_i.operator};
// output address
// we can now output the lower 12 bit as the index to the cache
assign req_port_o.address_index = lsu_ctrl_i.vaddr[ariane_pkg::DCACHE_INDEX_WIDTH-1:0];
@ -313,7 +313,7 @@ module load_unit import ariane_pkg::*; #(
// ---------------
// Sign Extend
// ---------------
logic [63:0] shifted_data;
riscv::xlen_t shifted_data;
// realign as needed
assign shifted_data = req_port_i.data_rdata >> {load_data_q.address_offset, 3'b000};
@ -333,27 +333,24 @@ module load_unit import ariane_pkg::*; #(
end */
// result mux fast
logic [7:0] sign_bits;
logic [2:0] idx_d, idx_q;
logic [(riscv::XLEN/8)-1:0] sign_bits;
logic [riscv::XLEN_ALIGN_BYTES-1:0] idx_d, idx_q;
logic sign_bit, signed_d, signed_q, fp_sign_d, fp_sign_q;
// prepare these signals for faster selection in the next cycle
assign signed_d = load_data_d.operator inside {ariane_pkg::LW, ariane_pkg::LH, ariane_pkg::LB};
assign fp_sign_d = load_data_d.operator inside {ariane_pkg::FLW, ariane_pkg::FLH, ariane_pkg::FLB};
assign idx_d = (load_data_d.operator inside {ariane_pkg::LW, ariane_pkg::FLW}) ? load_data_d.address_offset + 3 :
assign idx_d = ((load_data_d.operator inside {ariane_pkg::LW, ariane_pkg::FLW}) & riscv::IS_XLEN64) ? load_data_d.address_offset + 3 :
(load_data_d.operator inside {ariane_pkg::LH, ariane_pkg::FLH}) ? load_data_d.address_offset + 1 :
load_data_d.address_offset;
assign sign_bits = { req_port_i.data_rdata[63],
req_port_i.data_rdata[55],
req_port_i.data_rdata[47],
req_port_i.data_rdata[39],
req_port_i.data_rdata[31],
req_port_i.data_rdata[23],
req_port_i.data_rdata[15],
req_port_i.data_rdata[7] };
for (genvar i = 0; i < (riscv::XLEN/8); i++) begin : gen_sign_bits
assign sign_bits[i] = req_port_i.data_rdata[(i+1)*8-1];
end
// select correct sign bit in parallel to result shifter above
// pull to 0 if unsigned

View file

@ -80,12 +80,11 @@ module cva6_ptw_sv32 import ariane_pkg::*; #(
// input registers
logic data_rvalid_q;
logic [31:0] data_rdata_q, data_rdata_n;
riscv::xlen_t data_rdata_q;
riscv::pte_sv32_t pte;
assign pte = riscv::pte_sv32_t'(data_rdata_q);
assign data_rdata_n = (req_port_o.address_index[2] == 1'b1) ? req_port_i.data_rdata[63:32] : req_port_i.data_rdata[31:0];
enum logic[2:0] {
IDLE,
@ -124,7 +123,7 @@ module cva6_ptw_sv32 import ariane_pkg::*; #(
// we are never going to kill this request
assign req_port_o.kill_req = '0;
// we are never going to write with the HPTW
assign req_port_o.data_wdata = 64'b0;
assign req_port_o.data_wdata = '0;
// -----------
// TLB Update
// -----------
@ -163,7 +162,7 @@ module cva6_ptw_sv32 import ariane_pkg::*; #(
);
assign req_port_o.data_be = be_gen(req_port_o.address_index[2:0],req_port_o.data_size );
assign req_port_o.data_be = be_gen_32(req_port_o.address_index[1:0],req_port_o.data_size );
//-------------------
// Page table walker
@ -399,7 +398,7 @@ module cva6_ptw_sv32 import ariane_pkg::*; #(
tlb_update_asid_q <= tlb_update_asid_n;
vaddr_q <= vaddr_n;
global_mapping_q <= global_mapping_n;
data_rdata_q <= data_rdata_n;
data_rdata_q <= req_port_i.data_rdata;
data_rvalid_q <= req_port_i.data_rvalid;
end
end

View file

@ -35,7 +35,7 @@ module store_buffer import ariane_pkg::*; (
input logic [riscv::PLEN-1:0] paddr_i, // physical address of store which needs to be placed in the queue
input riscv::xlen_t data_i, // data which is placed in the queue
input logic [7:0] be_i, // byte enable in
input logic [(riscv::XLEN/8)-1:0] be_i, // byte enable in
input logic [1:0] data_size_i, // type of request we are making (e.g.: bytes to write)
// D$ interface
@ -47,11 +47,11 @@ module store_buffer import ariane_pkg::*; (
// 1. Speculative queue
// 2. Commit queue which is non-speculative, e.g.: the store will definitely happen.
struct packed {
logic [riscv::PLEN-1:0] address;
riscv::xlen_t data;
logic [7:0] be;
logic [1:0] data_size;
logic valid; // this entry is valid, we need this for checking if the address offset matches
logic [riscv::PLEN-1:0] address;
riscv::xlen_t data;
logic [(riscv::XLEN/8)-1:0] be;
logic [1:0] data_size;
logic valid; // this entry is valid, we need this for checking if the address offset matches
} speculative_queue_n [DEPTH_SPEC-1:0], speculative_queue_q [DEPTH_SPEC-1:0],
commit_queue_n [DEPTH_COMMIT-1:0], commit_queue_q [DEPTH_COMMIT-1:0];
@ -133,8 +133,7 @@ module store_buffer import ariane_pkg::*; (
assign req_port_o.address_tag = commit_queue_q[commit_read_pointer_q].address[ariane_pkg::DCACHE_TAG_WIDTH +
ariane_pkg::DCACHE_INDEX_WIDTH-1 :
ariane_pkg::DCACHE_INDEX_WIDTH];
assign req_port_o.data_wdata = (req_port_o.address_index[2] == 1'b0) ? {{64-riscv::XLEN{1'b0}}, commit_queue_q[commit_read_pointer_q].data} :
{commit_queue_q[commit_read_pointer_q].data, {64-riscv::XLEN{1'b0}}};
assign req_port_o.data_wdata = commit_queue_q[commit_read_pointer_q].data;
assign req_port_o.data_be = commit_queue_q[commit_read_pointer_q].be;
assign req_port_o.data_size = commit_queue_q[commit_read_pointer_q].data_size;

View file

@ -64,7 +64,7 @@ module store_unit import ariane_pkg::*; (
assign instr_is_amo = is_amo(lsu_ctrl_i.operator);
// keep the data and the byte enable for the second cycle (after address translation)
riscv::xlen_t st_data_n, st_data_q;
logic [7:0] st_be_n, st_be_q;
logic [(riscv::XLEN/8)-1:0] st_be_n, st_be_q;
logic [1:0] st_data_size_n, st_data_size_q;
amo_t amo_op_d, amo_op_q;
@ -181,7 +181,7 @@ module store_unit import ariane_pkg::*; (
st_be_n = lsu_ctrl_i.be;
// don't shift the data if we are going to perform an AMO as we still need to operate on this data
st_data_n = instr_is_amo ? lsu_ctrl_i.data[riscv::XLEN-1:0]
: data_align(lsu_ctrl_i.vaddr[2:0], {{64-riscv::XLEN{1'b0}}, lsu_ctrl_i.data[riscv::XLEN-1:0]});
: data_align(lsu_ctrl_i.vaddr[2:0], lsu_ctrl_i.data);
st_data_size_n = extract_transfer_size(lsu_ctrl_i.operator);
// save AMO op for next cycle
case (lsu_ctrl_i.operator)