Skip to content

Commit

Permalink
Code_coverage: Add conditions for the AMO Extension (#1554)
Browse files Browse the repository at this point in the history
  • Loading branch information
AEzzejjari authored Oct 19, 2023
1 parent 74675b4 commit 29a3f14
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 184 deletions.
2 changes: 1 addition & 1 deletion .gitlab-ci/expected_synth.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
cv32a6_embedded:
gates: 129232
gates: 127005
141 changes: 59 additions & 82 deletions core/cache_subsystem/wt_axi_adapter.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;

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
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
end
end
default: ; // Do nothing
//////////////////////////////////////
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand All @@ -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
Expand All @@ -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
Expand Down
131 changes: 69 additions & 62 deletions core/cache_subsystem/wt_dcache_missunit.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;
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;
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

// 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 ;
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

// 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;

assign amo_req_d = amo_req_i.req;
end

// 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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
//////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion core/commit_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 12 additions & 6 deletions core/controller.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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

// ---------------------------------
Expand Down
Loading

0 comments on commit 29a3f14

Please sign in to comment.