mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 13:47:13 -04:00
Code_coverage: Add conditions for the AMO Extension (#1554)
This commit is contained in:
parent
74675b400c
commit
29a3f14868
6 changed files with 186 additions and 187 deletions
|
@ -1,2 +1,2 @@
|
|||
cv32a6_embedded:
|
||||
gates: 129232
|
||||
gates: 127005
|
||||
|
|
|
@ -209,82 +209,59 @@ module wt_axi_adapter
|
|||
end
|
||||
//////////////////////////////////////
|
||||
wt_cache_pkg::DCACHE_ATOMIC_REQ: begin
|
||||
// default
|
||||
// push back an invalidation here.
|
||||
// since we only keep one read tx in flight, and since
|
||||
// the dcache drains all writes/reads before executing
|
||||
// an atomic, this is safe.
|
||||
invalidate = arb_gnt;
|
||||
axi_wr_req = 1'b1;
|
||||
axi_wr_be = '0;
|
||||
unique case (dcache_data.size[1:0])
|
||||
2'b00:
|
||||
axi_wr_be[0][dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0]] = '1; // byte
|
||||
2'b01:
|
||||
axi_wr_be[0][dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0]+:2] = '1; // hword
|
||||
2'b10:
|
||||
axi_wr_be[0][dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0]+:4] = '1; // word
|
||||
default:
|
||||
axi_wr_be[0][dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0]+:8] = '1; // dword
|
||||
endcase
|
||||
amo_gen_r_d = 1'b1;
|
||||
// need to use a separate ID here, so concat an additional bit
|
||||
axi_wr_id_in[1] = 1'b1;
|
||||
if(CVA6Cfg.RVA) begin
|
||||
// default
|
||||
// push back an invalidation here.
|
||||
// since we only keep one read tx in flight, and since
|
||||
// the dcache drains all writes/reads before executing
|
||||
// an atomic, this is safe.
|
||||
invalidate = arb_gnt;
|
||||
axi_wr_req = 1'b1;
|
||||
axi_wr_be = '0;
|
||||
unique case(dcache_data.size[1:0])
|
||||
2'b00: axi_wr_be[0][dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0]] = '1; // byte
|
||||
2'b01: axi_wr_be[0][dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0] +:2 ] = '1; // hword
|
||||
2'b10: axi_wr_be[0][dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0] +:4 ] = '1; // word
|
||||
default: axi_wr_be[0][dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0] +:8 ] = '1; // dword
|
||||
endcase
|
||||
amo_gen_r_d = 1'b1;
|
||||
// need to use a separate ID here, so concat an additional bit
|
||||
axi_wr_id_in[1] = 1'b1;
|
||||
|
||||
unique case (dcache_data.amo_op)
|
||||
AMO_LR: begin
|
||||
axi_rd_lock = 1'b1;
|
||||
axi_rd_req = 1'b1;
|
||||
axi_rd_id_in[1] = 1'b1;
|
||||
// tie to zero in this special case
|
||||
axi_wr_req = 1'b0;
|
||||
axi_wr_be = '0;
|
||||
end
|
||||
AMO_SC: begin
|
||||
axi_wr_lock = 1'b1;
|
||||
amo_gen_r_d = 1'b0;
|
||||
// needed to properly encode success. store the result at offset within the returned
|
||||
// AXI data word aligned with the requested word size.
|
||||
amo_off_d = dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-
|
||||
1:0] & ~((1 << dcache_data.size[1:0]) - 1);
|
||||
end
|
||||
// RISC-V atops have a load semantic
|
||||
AMO_SWAP:
|
||||
axi_wr_atop = {
|
||||
axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ATOMICSWAP
|
||||
};
|
||||
AMO_ADD:
|
||||
axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ADD};
|
||||
AMO_AND: begin
|
||||
// in this case we need to invert the data to get a "CLR"
|
||||
axi_wr_data = ~{(CVA6Cfg.AxiDataWidth / riscv::XLEN) {dcache_data.data}};
|
||||
axi_wr_user = ~{(CVA6Cfg.AxiDataWidth / riscv::XLEN) {dcache_data.user}};
|
||||
axi_wr_atop = {
|
||||
axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_CLR
|
||||
};
|
||||
end
|
||||
AMO_OR:
|
||||
axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SET};
|
||||
AMO_XOR:
|
||||
axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_EOR};
|
||||
AMO_MAX:
|
||||
axi_wr_atop = {
|
||||
axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SMAX
|
||||
};
|
||||
AMO_MAXU:
|
||||
axi_wr_atop = {
|
||||
axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_UMAX
|
||||
};
|
||||
AMO_MIN:
|
||||
axi_wr_atop = {
|
||||
axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SMIN
|
||||
};
|
||||
AMO_MINU:
|
||||
axi_wr_atop = {
|
||||
axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_UMIN
|
||||
};
|
||||
default: ; // Do nothing
|
||||
endcase
|
||||
unique case (dcache_data.amo_op)
|
||||
AMO_LR: begin
|
||||
axi_rd_lock = 1'b1;
|
||||
axi_rd_req = 1'b1;
|
||||
axi_rd_id_in[1] = 1'b1;
|
||||
// tie to zero in this special case
|
||||
axi_wr_req = 1'b0;
|
||||
axi_wr_be = '0;
|
||||
end
|
||||
AMO_SC: begin
|
||||
axi_wr_lock = 1'b1;
|
||||
amo_gen_r_d = 1'b0;
|
||||
// needed to properly encode success. store the result at offset within the returned
|
||||
// AXI data word aligned with the requested word size.
|
||||
amo_off_d = dcache_data.paddr[$clog2(CVA6Cfg.AxiDataWidth/8)-1:0] & ~((1 << dcache_data.size[1:0]) - 1);
|
||||
end
|
||||
// RISC-V atops have a load semantic
|
||||
AMO_SWAP: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ATOMICSWAP};
|
||||
AMO_ADD: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ADD};
|
||||
AMO_AND: begin
|
||||
// in this case we need to invert the data to get a "CLR"
|
||||
axi_wr_data = ~{(CVA6Cfg.AxiDataWidth/riscv::XLEN){dcache_data.data}};
|
||||
axi_wr_user = ~{(CVA6Cfg.AxiDataWidth/riscv::XLEN){dcache_data.user}};
|
||||
axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_CLR};
|
||||
end
|
||||
AMO_OR: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SET};
|
||||
AMO_XOR: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_EOR};
|
||||
AMO_MAX: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SMAX};
|
||||
AMO_MAXU: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_UMAX};
|
||||
AMO_MIN: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SMIN};
|
||||
AMO_MINU: axi_wr_atop = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_UMIN};
|
||||
default: ; // Do nothing
|
||||
endcase
|
||||
end
|
||||
end
|
||||
default: ; // Do nothing
|
||||
//////////////////////////////////////
|
||||
|
@ -490,7 +467,7 @@ module wt_axi_adapter
|
|||
dcache_rd_shift_d[0] = axi_rd_data;
|
||||
dcache_rd_shift_user_d[0] = axi_rd_user;
|
||||
end
|
||||
end else if (dcache_sc_rtrn) begin
|
||||
end else if (CVA6Cfg.RVA && dcache_sc_rtrn) begin
|
||||
// encode lr/sc success
|
||||
dcache_rd_shift_d[0] = '0;
|
||||
dcache_rd_shift_user_d[0] = '0;
|
||||
|
@ -541,9 +518,9 @@ module wt_axi_adapter
|
|||
// note that this self invalidation is handled in this way due to the
|
||||
// write-through cache architecture, which is aligned with the openpiton
|
||||
// cache subsystem.
|
||||
end else if (invalidate) begin
|
||||
dcache_rtrn_type_d = wt_cache_pkg::DCACHE_INV_REQ;
|
||||
dcache_rtrn_vld_d = 1'b1;
|
||||
end else if (CVA6Cfg.RVA && invalidate) begin
|
||||
dcache_rtrn_type_d = wt_cache_pkg::DCACHE_INV_REQ;
|
||||
dcache_rtrn_vld_d = 1'b1;
|
||||
|
||||
dcache_rtrn_inv_d.all = 1'b1;
|
||||
dcache_rtrn_inv_d.idx = dcache_data.paddr[ariane_pkg::DCACHE_INDEX_WIDTH-1:0];
|
||||
|
@ -556,7 +533,7 @@ module wt_axi_adapter
|
|||
dcache_rtrn_vld_d = axi_rd_last;
|
||||
|
||||
// if this was an atomic op
|
||||
if (axi_rd_id_out[1]) begin
|
||||
if (CVA6Cfg.RVA && axi_rd_id_out[1]) begin
|
||||
dcache_rtrn_type_d = wt_cache_pkg::DCACHE_ATOMIC_ACK;
|
||||
|
||||
// check if transaction was issued over write channel and pop that ID
|
||||
|
@ -575,7 +552,7 @@ module wt_axi_adapter
|
|||
b_pop = 1'b1;
|
||||
|
||||
// this was an atomic
|
||||
if (wr_id_out[1]) begin
|
||||
if (CVA6Cfg.RVA && wr_id_out[1]) begin
|
||||
dcache_rtrn_type_d = wt_cache_pkg::DCACHE_ATOMIC_ACK;
|
||||
|
||||
// silently discard b response if we already popped the fifo
|
||||
|
|
|
@ -243,54 +243,55 @@ module wt_dcache_missunit
|
|||
|
||||
// if size = 32bit word, select appropriate offset, replicate for openpiton...
|
||||
always_comb begin
|
||||
if (riscv::IS_XLEN64) begin
|
||||
if (amo_req_i.size == 2'b10) begin
|
||||
amo_data = {amo_req_i.operand_b[0+:32], amo_req_i.operand_b[0+:32]};
|
||||
end else begin
|
||||
amo_data = amo_req_i.operand_b;
|
||||
if (CVA6Cfg.RVA) begin
|
||||
if (riscv::IS_XLEN64) begin
|
||||
if (amo_req_i.size==2'b10) begin
|
||||
amo_data = {amo_req_i.operand_b[0 +: 32], amo_req_i.operand_b[0 +: 32]};
|
||||
end else begin
|
||||
amo_data = amo_req_i.operand_b;
|
||||
end
|
||||
end else begin
|
||||
amo_data = amo_req_i.operand_b[0 +: 32];
|
||||
end
|
||||
if (ariane_pkg::DATA_USER_EN) begin
|
||||
amo_user = amo_data;
|
||||
end else begin
|
||||
amo_user = '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (CVA6Cfg.RVA) begin
|
||||
// note: openpiton returns a full cacheline!
|
||||
if (CVA6Cfg.NOCType == config_pkg::NOC_TYPE_AXI4_ATOP) begin : gen_axi_rtrn_mux
|
||||
if (CVA6Cfg.AxiDataWidth > 64) begin
|
||||
assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[$clog2(CVA6Cfg.AxiDataWidth/8)-1:3]*64 +: 64];
|
||||
end else begin
|
||||
assign amo_rtrn_mux = mem_rtrn_i.data[0 +: 64];
|
||||
end
|
||||
end else begin : gen_piton_rtrn_mux
|
||||
assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[DCACHE_OFFSET_WIDTH-1:3]*64 +: 64];
|
||||
end
|
||||
end else begin
|
||||
amo_data = amo_req_i.operand_b[0+:32];
|
||||
end
|
||||
if (ariane_pkg::DATA_USER_EN) begin
|
||||
amo_user = amo_data;
|
||||
end else begin
|
||||
amo_user = '0;
|
||||
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_req_d = amo_req_i.req;
|
||||
|
||||
end
|
||||
|
||||
// note: openpiton returns a full cacheline!
|
||||
if (CVA6Cfg.NOCType == config_pkg::NOC_TYPE_AXI4_ATOP) begin : gen_axi_rtrn_mux
|
||||
if (CVA6Cfg.AxiDataWidth > 64) begin
|
||||
assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[$clog2(
|
||||
CVA6Cfg.AxiDataWidth/8
|
||||
)-1:3]*64+:64];
|
||||
end else begin
|
||||
assign amo_rtrn_mux = mem_rtrn_i.data[0+:64];
|
||||
end
|
||||
end else begin : gen_piton_rtrn_mux
|
||||
assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[DCACHE_OFFSET_WIDTH-1:3]*64+:64];
|
||||
end
|
||||
|
||||
// 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_req_d = amo_req_i.req;
|
||||
|
||||
// outgoing memory requests (AMOs are always uncached)
|
||||
assign mem_data_o.tid = (amo_sel) ? AmoTxId : miss_id_i[miss_port_idx];
|
||||
assign mem_data_o.nc = (amo_sel) ? 1'b1 : miss_nc_i[miss_port_idx];
|
||||
assign mem_data_o.way = (amo_sel) ? '0 : repl_way;
|
||||
assign mem_data_o.data = (amo_sel) ? amo_data : miss_wdata_i[miss_port_idx];
|
||||
assign mem_data_o.user = (amo_sel) ? amo_user : miss_wuser_i[miss_port_idx];
|
||||
assign mem_data_o.size = (amo_sel) ? amo_req_i.size : miss_size_i[miss_port_idx];
|
||||
assign mem_data_o.amo_op = (amo_sel) ? amo_req_i.amo_op : AMO_NONE;
|
||||
assign mem_data_o.tid = (CVA6Cfg.RVA && amo_sel) ? AmoTxId : miss_id_i[miss_port_idx];
|
||||
assign mem_data_o.nc = (CVA6Cfg.RVA && amo_sel) ? 1'b1 : miss_nc_i[miss_port_idx];
|
||||
assign mem_data_o.way = (CVA6Cfg.RVA && amo_sel) ? '0 : repl_way;
|
||||
assign mem_data_o.data = (CVA6Cfg.RVA && amo_sel) ? amo_data : miss_wdata_i[miss_port_idx];
|
||||
assign mem_data_o.user = (CVA6Cfg.RVA && amo_sel) ? amo_user : miss_wuser_i[miss_port_idx];
|
||||
assign mem_data_o.size = (CVA6Cfg.RVA && amo_sel) ? amo_req_i.size : miss_size_i [miss_port_idx];
|
||||
assign mem_data_o.amo_op = (CVA6Cfg.RVA && amo_sel) ? amo_req_i.amo_op : AMO_NONE;
|
||||
|
||||
assign tmp_paddr = (amo_sel) ? amo_req_i.operand_a[riscv::PLEN-1:0] : miss_paddr_i[miss_port_idx];
|
||||
assign mem_data_o.paddr = paddrSizeAlign(tmp_paddr, mem_data_o.size);
|
||||
assign tmp_paddr = (CVA6Cfg.RVA && amo_sel) ? amo_req_i.operand_a[riscv::PLEN-1:0] : miss_paddr_i[miss_port_idx];
|
||||
assign mem_data_o.paddr = paddrSizeAlign(tmp_paddr, mem_data_o.size);
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// back-off mechanism for LR/SC completion guarantee
|
||||
|
@ -347,17 +348,19 @@ module wt_dcache_missunit
|
|||
end
|
||||
end
|
||||
DCACHE_ATOMIC_ACK: begin
|
||||
if (amo_req_q) begin
|
||||
amo_ack = 1'b1;
|
||||
// need to set SC backoff counter if
|
||||
// this op failed
|
||||
if (amo_req_i.amo_op == AMO_SC) begin
|
||||
if (amo_resp_o.result > 0) begin
|
||||
sc_fail = 1'b1;
|
||||
end else begin
|
||||
sc_pass = 1'b1;
|
||||
if(CVA6Cfg.RVA) begin
|
||||
if (amo_req_q) begin
|
||||
amo_ack = 1'b1;
|
||||
// need to set SC backoff counter if
|
||||
// this op failed
|
||||
if (amo_req_i.amo_op == AMO_SC) begin
|
||||
if (amo_resp_o.result>0) begin
|
||||
sc_fail = 1'b1;
|
||||
end else begin
|
||||
sc_pass = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
DCACHE_INV_REQ: begin
|
||||
|
@ -443,7 +446,7 @@ module wt_dcache_missunit
|
|||
end else begin
|
||||
state_d = DRAIN;
|
||||
end
|
||||
end else if (amo_req_i.req) begin
|
||||
end else if (CVA6Cfg.RVA && amo_req_i.req) begin
|
||||
if (wbuffer_empty_i && !mshr_vld_q) begin
|
||||
state_d = AMO;
|
||||
end else begin
|
||||
|
@ -533,23 +536,27 @@ module wt_dcache_missunit
|
|||
//////////////////////////////////
|
||||
// send out amo op request
|
||||
AMO: begin
|
||||
mem_data_o.rtype = DCACHE_ATOMIC_REQ;
|
||||
amo_sel = 1'b1;
|
||||
// if this is an LR, we need to consult the backoff counter
|
||||
if ((amo_req_i.amo_op != AMO_LR) || sc_backoff_over) begin
|
||||
mem_data_req_o = 1'b1;
|
||||
if (mem_data_ack_i) begin
|
||||
state_d = AMO_WAIT;
|
||||
end
|
||||
if(CVA6Cfg.RVA) begin
|
||||
mem_data_o.rtype = DCACHE_ATOMIC_REQ;
|
||||
amo_sel = 1'b1;
|
||||
// if this is an LR, we need to consult the backoff counter
|
||||
if ((amo_req_i.amo_op != AMO_LR) || sc_backoff_over) begin
|
||||
mem_data_req_o = 1'b1;
|
||||
if (mem_data_ack_i) begin
|
||||
state_d = AMO_WAIT;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
// block and wait until AMO OP returns
|
||||
AMO_WAIT: begin
|
||||
amo_sel = 1'b1;
|
||||
if (amo_ack) begin
|
||||
amo_resp_o.ack = 1'b1;
|
||||
state_d = IDLE;
|
||||
if(CVA6Cfg.RVA) begin
|
||||
amo_sel = 1'b1;
|
||||
if (amo_ack) begin
|
||||
amo_resp_o.ack = 1'b1;
|
||||
state_d = IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
|
|
|
@ -106,7 +106,7 @@ module commit_stage
|
|||
commit_lsu_o = 1'b0;
|
||||
commit_csr_o = 1'b0;
|
||||
// amos will commit on port 0
|
||||
wdata_o[0] = (amo_resp_i.ack) ? amo_resp_i.result[riscv::XLEN-1:0] : commit_instr_i[0].result;
|
||||
wdata_o[0] = (CVA6Cfg.RVA && amo_resp_i.ack) ? amo_resp_i.result[riscv::XLEN-1:0] : commit_instr_i[0].result;
|
||||
csr_op_o = ADD; // this corresponds to a CSR NOP
|
||||
csr_wdata_o = {riscv::XLEN{1'b0}};
|
||||
fence_i_o = 1'b0;
|
||||
|
|
|
@ -136,12 +136,18 @@ module controller
|
|||
end
|
||||
|
||||
// Set PC to commit stage and flush pipeline
|
||||
if (flush_csr_i || flush_commit_i || flush_acc_i) begin
|
||||
set_pc_commit_o = 1'b1;
|
||||
flush_if_o = 1'b1;
|
||||
flush_unissued_instr_o = 1'b1;
|
||||
flush_id_o = 1'b1;
|
||||
flush_ex_o = 1'b1;
|
||||
if (flush_csr_i || flush_acc_i) begin
|
||||
set_pc_commit_o = 1'b1;
|
||||
flush_if_o = 1'b1;
|
||||
flush_unissued_instr_o = 1'b1;
|
||||
flush_id_o = 1'b1;
|
||||
flush_ex_o = 1'b1;
|
||||
end else if (CVA6Cfg.RVA && flush_commit_i) begin
|
||||
set_pc_commit_o = 1'b1;
|
||||
flush_if_o = 1'b1;
|
||||
flush_unissued_instr_o = 1'b1;
|
||||
flush_id_o = 1'b1;
|
||||
flush_ex_o = 1'b1;
|
||||
end
|
||||
|
||||
// ---------------------------------
|
||||
|
|
|
@ -187,24 +187,28 @@ module store_unit
|
|||
always_comb begin
|
||||
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] :
|
||||
st_data_n = (CVA6Cfg.RVA && instr_is_amo) ? 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.operation);
|
||||
// save AMO op for next cycle
|
||||
case (lsu_ctrl_i.operation)
|
||||
AMO_LRW, AMO_LRD: amo_op_d = AMO_LR;
|
||||
AMO_SCW, AMO_SCD: amo_op_d = AMO_SC;
|
||||
AMO_SWAPW, AMO_SWAPD: amo_op_d = AMO_SWAP;
|
||||
AMO_ADDW, AMO_ADDD: amo_op_d = AMO_ADD;
|
||||
AMO_ANDW, AMO_ANDD: amo_op_d = AMO_AND;
|
||||
AMO_ORW, AMO_ORD: amo_op_d = AMO_OR;
|
||||
AMO_XORW, AMO_XORD: amo_op_d = AMO_XOR;
|
||||
AMO_MAXW, AMO_MAXD: amo_op_d = AMO_MAX;
|
||||
AMO_MAXWU, AMO_MAXDU: amo_op_d = AMO_MAXU;
|
||||
AMO_MINW, AMO_MIND: amo_op_d = AMO_MIN;
|
||||
AMO_MINWU, AMO_MINDU: amo_op_d = AMO_MINU;
|
||||
default: amo_op_d = AMO_NONE;
|
||||
endcase
|
||||
if(CVA6Cfg.RVA) begin
|
||||
case (lsu_ctrl_i.operation)
|
||||
AMO_LRW, AMO_LRD: amo_op_d = AMO_LR;
|
||||
AMO_SCW, AMO_SCD: amo_op_d = AMO_SC;
|
||||
AMO_SWAPW, AMO_SWAPD: amo_op_d = AMO_SWAP;
|
||||
AMO_ADDW, AMO_ADDD: amo_op_d = AMO_ADD;
|
||||
AMO_ANDW, AMO_ANDD: amo_op_d = AMO_AND;
|
||||
AMO_ORW, AMO_ORD: amo_op_d = AMO_OR;
|
||||
AMO_XORW, AMO_XORD: amo_op_d = AMO_XOR;
|
||||
AMO_MAXW, AMO_MAXD: amo_op_d = AMO_MAX;
|
||||
AMO_MAXWU, AMO_MAXDU: amo_op_d = AMO_MAXU;
|
||||
AMO_MINW, AMO_MIND: amo_op_d = AMO_MIN;
|
||||
AMO_MINWU, AMO_MINDU: amo_op_d = AMO_MINU;
|
||||
default: amo_op_d = AMO_NONE;
|
||||
endcase
|
||||
end else begin
|
||||
amo_op_d = AMO_NONE;
|
||||
end
|
||||
end
|
||||
|
||||
logic store_buffer_valid, amo_buffer_valid;
|
||||
|
@ -249,23 +253,28 @@ module store_unit
|
|||
.req_port_o (req_port_o)
|
||||
);
|
||||
|
||||
amo_buffer #(
|
||||
.CVA6Cfg(CVA6Cfg)
|
||||
) i_amo_buffer (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.flush_i,
|
||||
.valid_i (amo_buffer_valid),
|
||||
.ready_o (amo_buffer_ready),
|
||||
.paddr_i (paddr_i),
|
||||
.amo_op_i (amo_op_q),
|
||||
.data_i (st_data_q),
|
||||
.data_size_i (st_data_size_q),
|
||||
.amo_req_o (amo_req_o),
|
||||
.amo_resp_i (amo_resp_i),
|
||||
.amo_valid_commit_i(amo_valid_commit_i),
|
||||
.no_st_pending_i (no_st_pending_o)
|
||||
);
|
||||
if(CVA6Cfg.RVA) begin
|
||||
amo_buffer #(
|
||||
.CVA6Cfg ( CVA6Cfg )
|
||||
) i_amo_buffer (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.flush_i,
|
||||
.valid_i ( amo_buffer_valid ),
|
||||
.ready_o ( amo_buffer_ready ),
|
||||
.paddr_i ( paddr_i ),
|
||||
.amo_op_i ( amo_op_q ),
|
||||
.data_i ( st_data_q ),
|
||||
.data_size_i ( st_data_size_q ),
|
||||
.amo_req_o ( amo_req_o ),
|
||||
.amo_resp_i ( amo_resp_i ),
|
||||
.amo_valid_commit_i ( amo_valid_commit_i ),
|
||||
.no_st_pending_i ( no_st_pending_o )
|
||||
);
|
||||
end else begin
|
||||
assign amo_buffer_ready = '1;
|
||||
assign amo_req_o = '0;
|
||||
end
|
||||
|
||||
// ---------------
|
||||
// Registers
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue