Skip to content

Commit

Permalink
acc_dispatcher: Merge issue logic
Browse files Browse the repository at this point in the history
Signed-off-by: Nils Wistoff <nwistoff@iis.ee.ethz.ch>
  • Loading branch information
niwis committed Jun 19, 2023
1 parent c430de5 commit 271ede7
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 196 deletions.
167 changes: 150 additions & 17 deletions core/acc_dispatcher.sv
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,32 @@
module acc_dispatcher import ariane_pkg::*; import riscv::*; (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
// Interface with the CSR regfile
input logic acc_cons_en_i, // Accelerator memory consistent mode
// Interface with the CSRs
input logic [2:0] fcsr_frm_i,
output logic dirty_v_state_o,
// Interface with the issue stage
input scoreboard_entry_t issue_instr_i,
input logic issue_instr_hs_i,
output logic issue_stall_o,
input fu_data_t acc_data_i,
output logic acc_ready_o, // FU is ready
input logic acc_valid_i, // Output is valid
input scoreboard_entry_t [NR_COMMIT_PORTS-1:0] commit_instr_i,
output logic acc_ld_disp_o,
output logic acc_st_disp_o,
output logic acc_flush_undisp_o,
output logic [TRANS_ID_BITS-1:0] acc_trans_id_o,
output xlen_t acc_result_o,
output logic acc_valid_o,
output exception_t acc_exception_o,
// Interface with the execute stage
output logic acc_valid_ex_o, // FU executed
// Interface with the commit stage
input logic [NR_COMMIT_PORTS-1:0] commit_ack_i,
input logic commit_st_barrier_i, // A store barrier was commited
// Interface with the load/store unit
input logic acc_no_st_pending_i,
// Interface with the controller
output logic ctrl_halt_o,
input logic flush_unissued_instr_i,
input logic flush_ex_i,
// Accelerator interface
output accelerator_req_t acc_req_o,
output logic acc_req_valid_o,
Expand All @@ -53,6 +54,13 @@ module acc_dispatcher import ariane_pkg::*; import riscv::*; (

import cf_math_pkg::idx_width;

/***********************
* Common signals *
***********************/

logic acc_ready;
logic acc_valid_d, acc_valid_q;

/***********************
* Instruction queue *
***********************/
Expand All @@ -73,10 +81,10 @@ module acc_dispatcher import ariane_pkg::*; import riscv::*; (
) i_acc_insn_queue (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i (flush_i ),
.flush_i (flush_ex_i ),
.testmode_i(1'b0 ),
.data_i (acc_data_i ),
.push_i (acc_valid_i ),
.push_i (acc_valid_q ),
.full_o (/* Unused */ ),
.data_o (acc_insn_queue_o ),
.pop_i (acc_insn_queue_pop ),
Expand All @@ -85,10 +93,7 @@ module acc_dispatcher import ariane_pkg::*; import riscv::*; (
);

// We are ready if the instruction queue is able to accept at least one more entry.
assign acc_ready_o = acc_insn_queue_usage < (InstructionQueueDepth-1);

// Flush undispatched accelerator instructions.
assign acc_flush_undisp_o = flush_i;
assign acc_ready = acc_insn_queue_usage < (InstructionQueueDepth-1);

/**********************************
* Non-speculative instructions *
Expand All @@ -110,10 +115,10 @@ module acc_dispatcher import ariane_pkg::*; import riscv::*; (
insn_ready_d = insn_ready_q;

// We received a new instruction
if (acc_valid_i)
if (acc_valid_q)
insn_pending_d[acc_data_i.trans_id] = 1'b1;
// Flush all received instructions
if (flush_i)
if (flush_ex_i)
insn_pending_d = '0;

// An accelerator instruction is no longer speculative.
Expand Down Expand Up @@ -207,12 +212,13 @@ module acc_dispatcher import ariane_pkg::*; import riscv::*; (
assign acc_resp_ready_o = 1'b1;

// Signal dispatched load/store to issue stage
assign acc_ld_disp_o = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_LOAD);
assign acc_st_disp_o = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_STORE);
assign acc_ld_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_LOAD);
assign acc_st_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_STORE);

/**************************
* Accelerator issue *
* Accelerator commit *
**************************/

// Instruction can be issued to the (in-order) back-end if
// it reached the top of the scoreboard and it hasn't been
// issued yet
Expand All @@ -239,6 +245,7 @@ module acc_dispatcher import ariane_pkg::*; import riscv::*; (
/**************************
* Accelerator barriers *
**************************/

// On a store barrier (i.e. any barrier that requires preceeding stores to complete
// before continuing execution), halt execution while there are pending stores in
// the accelerator pipeline.
Expand All @@ -249,4 +256,130 @@ module acc_dispatcher import ariane_pkg::*; import riscv::*; (
assign wait_acc_store_d = (wait_acc_store_q | commit_st_barrier_i) & acc_resp_i.store_pending;
assign ctrl_halt_o = wait_acc_store_q;

/**************************
* Accelerator issue *
**************************/

// Issue accelerator instructions
`FF(acc_valid_q, acc_valid_d, '0)

assign acc_valid_ex_o = acc_valid_q;
assign acc_valid_d = ~issue_instr_i.ex.valid &
issue_instr_hs_i &
(issue_instr_i.fu == ACCEL) &
~flush_unissued_instr_i;

// Accelerator load/store pending signals
logic acc_no_ld_pending;
logic acc_no_st_pending;

// Stall issue stage in three cases:
always_comb begin : stall_issue
unique case (issue_instr_i.fu)
ACCEL:
// 1. We're issuing an accelerator instruction but the dispatcher isn't ready yet
issue_stall_o = ~acc_ready;
LOAD:
// 2. We're issuing a scalar load but there is an inflight accelerator store.
issue_stall_o = acc_cons_en_i & ~acc_no_st_pending;
STORE:
// 3. We're issuing a scalar store but there is an inflight accelerator load or store.
issue_stall_o = acc_cons_en_i & (~acc_no_st_pending | ~acc_no_ld_pending);
default:
issue_stall_o = 1'b0;
endcase
end

/**************************
* Load/Store tracking *
**************************/

// Loads
logic acc_spec_loads_overflow;
logic [2:0] acc_spec_loads_pending;
logic acc_disp_loads_overflow;
logic [2:0] acc_disp_loads_pending;

assign acc_no_ld_pending = (acc_spec_loads_pending == 3'b0) && (acc_disp_loads_pending == 3'b0);

// Count speculative loads. These can still be flushed.
counter #(
.WIDTH (3),
.STICKY_OVERFLOW (0)
) i_acc_spec_loads (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.clear_i (flush_ex_i ),
.en_i ((acc_valid_d && issue_instr_i.op == ACCEL_OP_LOAD) ^ acc_ld_disp),
.load_i (1'b0 ),
.down_i (acc_ld_disp ),
.d_i ('0 ),
.q_o (acc_spec_loads_pending ),
.overflow_o (acc_spec_loads_overflow )
);

// Count dispatched loads. These cannot be flushed anymore.
counter #(
.WIDTH (3),
.STICKY_OVERFLOW (0)
) i_acc_disp_loads (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.clear_i (1'b0 ),
.en_i (acc_ld_disp ^ acc_resp_i.load_complete),
.load_i (1'b0 ),
.down_i (acc_resp_i.load_complete),
.d_i ('0 ),
.q_o (acc_disp_loads_pending ),
.overflow_o (acc_disp_loads_overflow )
);

acc_dispatcher_no_load_overflow: assert property (
@(posedge clk_i) disable iff (~rst_ni) (acc_spec_loads_overflow == 1'b0) && (acc_disp_loads_overflow == 1'b0) )
else $error("[acc_dispatcher] Too many pending loads.");

// Stores
logic acc_spec_stores_overflow;
logic [2:0] acc_spec_stores_pending;
logic acc_disp_stores_overflow;
logic [2:0] acc_disp_stores_pending;

assign acc_no_st_pending = (acc_spec_stores_pending == 3'b0) && (acc_disp_stores_pending == 3'b0);

// Count speculative stores. These can still be flushed.
counter #(
.WIDTH (3),
.STICKY_OVERFLOW (0)
) i_acc_spec_stores (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.clear_i (flush_ex_i ),
.en_i ((acc_valid_d && issue_instr_i.op == ACCEL_OP_STORE) ^ acc_st_disp),
.load_i (1'b0 ),
.down_i (acc_st_disp ),
.d_i ('0 ),
.q_o (acc_spec_stores_pending ),
.overflow_o (acc_spec_stores_overflow)
);

// Count dispatched stores. These cannot be flushed anymore.
counter #(
.WIDTH (3),
.STICKY_OVERFLOW (0)
) i_acc_disp_stores (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.clear_i (1'b0 ),
.en_i (acc_st_disp ^ acc_resp_i.store_complete),
.load_i (1'b0 ),
.down_i (acc_resp_i.store_complete),
.d_i ('0 ),
.q_o (acc_disp_stores_pending ),
.overflow_o (acc_disp_stores_overflow )
);

acc_dispatcher_no_store_overflow: assert property (
@(posedge clk_i) disable iff (~rst_ni) (acc_spec_stores_overflow == 1'b0) && (acc_disp_stores_overflow == 1'b0) )
else $error("[acc_dispatcher] Too many pending stores.");

endmodule : acc_dispatcher
78 changes: 36 additions & 42 deletions core/cva6.sv
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,9 @@ module cva6 import ariane_pkg::*; #(
logic fpu_valid_ex_id;
exception_t fpu_exception_ex_id;
// Accelerator
logic acc_ready_ex_id;
logic acc_valid_id_ex;
logic acc_ld_disp_ex_id;
logic acc_st_disp_ex_id;
logic stall_acc_id;
scoreboard_entry_t issue_instr_id_acc;
logic issue_instr_hs_id_acc;
logic acc_flush_undisp_ex_id;
logic [TRANS_ID_BITS-1:0] acc_trans_id_ex_id;
riscv::xlen_t acc_result_ex_id;
Expand Down Expand Up @@ -180,6 +179,7 @@ module cva6 import ariane_pkg::*; #(
logic no_st_pending_commit;
logic amo_valid_commit;
// ACCEL Commit
logic acc_valid_acc_ex;
logic acc_commit_commit_ex;
logic [TRANS_ID_BITS-1:0] acc_commit_trans_id;
// --------------
Expand Down Expand Up @@ -410,6 +410,7 @@ module cva6 import ariane_pkg::*; #(
.sb_full_o ( sb_full ),
.flush_unissued_instr_i ( flush_unissued_instr_ctrl_id ),
.flush_i ( flush_ctrl_id ),
.stall_i ( stall_acc_id ),
// ID Stage
.decoded_instr_i ( issue_entry_id_issue ),
.decoded_instr_valid_i ( issue_entry_valid_id_issue ),
Expand Down Expand Up @@ -446,14 +447,8 @@ module cva6 import ariane_pkg::*; #(
.x_issue_ready_i ( x_issue_ready_ex_id ),
.x_off_instr_o ( x_off_instr_id_ex ),
// Accelerator
.acc_ready_i ( acc_ready_ex_id ),
.acc_valid_o ( acc_valid_id_ex ),
.acc_ld_disp_i ( acc_ld_disp_ex_id ),
.acc_st_disp_i ( acc_st_disp_ex_id ),
.acc_flush_undisp_i ( acc_flush_undisp_ex_id ),
.acc_ld_complete_i ( acc_resp.load_complete ),
.acc_st_complete_i ( acc_resp.store_complete ),
.acc_cons_en_i ( acc_cons_en_csr ),
.issue_instr_o ( issue_instr_id_acc ),
.issue_instr_hs_o ( issue_instr_hs_id_acc ),
// Commit
.resolved_branch_i ( resolved_branch ),
.trans_id_i ( trans_id_ex_id ),
Expand Down Expand Up @@ -557,7 +552,7 @@ module cva6 import ariane_pkg::*; #(
.cvxif_req_o ( cvxif_req_o ),
.cvxif_resp_i ( cvxif_resp_i ),
// Accelerator
.acc_valid_i ( acc_valid_id_ex ),
.acc_valid_i ( acc_valid_acc_ex ),
// Performance counters
.itlb_miss_o ( itlb_miss_ex_perf ),
.dtlb_miss_o ( dtlb_miss_ex_perf ),
Expand Down Expand Up @@ -878,43 +873,42 @@ module cva6 import ariane_pkg::*; #(

if (ENABLE_ACCELERATOR) begin: gen_accelerator
fu_data_t acc_data;
assign acc_data = acc_valid_id_ex ? fu_data_id_ex : '0;
assign acc_data = acc_valid_acc_ex ? fu_data_id_ex : '0;

acc_dispatcher i_acc_dispatcher (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_ctrl_ex ),
.acc_cons_en_i ( acc_cons_en_csr ),
.fcsr_frm_i ( frm_csr_id_issue_ex ),
.dirty_v_state_o ( dirty_v_state ),
.acc_data_i ( acc_data ),
.acc_ready_o ( acc_ready_ex_id ),
.acc_valid_i ( acc_valid_id_ex ),
.commit_instr_i ( commit_instr_id_commit ),
.commit_st_barrier_i ( fence_i_commit_controller | fence_commit_controller ),
.acc_ld_disp_o ( acc_ld_disp_ex_id ),
.acc_st_disp_o ( acc_st_disp_ex_id ),
.acc_flush_undisp_o ( acc_flush_undisp_ex_id ),
.acc_trans_id_o ( acc_trans_id_ex_id ),
.acc_result_o ( acc_result_ex_id ),
.acc_valid_o ( acc_valid_ex_id ),
.acc_exception_o ( acc_exception_ex_id ),
.commit_ack_i ( commit_ack ),
.acc_no_st_pending_i ( no_st_pending_commit ),
.ctrl_halt_o ( halt_acc_ctrl ),
.acc_req_o ( acc_req ),
.acc_req_valid_o ( acc_req_valid ),
.acc_req_ready_i ( acc_req_ready_i ),
.acc_resp_i ( acc_resp_i ),
.acc_resp_valid_i ( acc_resp_valid_i ),
.acc_resp_ready_o ( acc_resp_ready )
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_unissued_instr_i ( flush_unissued_instr_ctrl_id ),
.flush_ex_i ( flush_ctrl_ex ),
.acc_cons_en_i ( acc_cons_en_csr ),
.fcsr_frm_i ( frm_csr_id_issue_ex ),
.dirty_v_state_o ( dirty_v_state ),
.issue_instr_i ( issue_instr_id_acc ),
.issue_instr_hs_i ( issue_instr_hs_id_acc ),
.issue_stall_o ( stall_acc_id ),
.acc_data_i ( acc_data ),
.commit_instr_i ( commit_instr_id_commit ),
.commit_st_barrier_i ( fence_i_commit_controller | fence_commit_controller ),
.acc_trans_id_o ( acc_trans_id_ex_id ),
.acc_result_o ( acc_result_ex_id ),
.acc_valid_o ( acc_valid_ex_id ),
.acc_exception_o ( acc_exception_ex_id ),
.acc_valid_ex_o ( acc_valid_acc_ex ),
.commit_ack_i ( commit_ack ),
.acc_no_st_pending_i ( no_st_pending_commit ),
.ctrl_halt_o ( halt_acc_ctrl ),
.acc_req_o ( acc_req ),
.acc_req_valid_o ( acc_req_valid ),
.acc_req_ready_i ( acc_req_ready_i ),
.acc_resp_i ( acc_resp_i ),
.acc_resp_valid_i ( acc_resp_valid_i ),
.acc_resp_ready_o ( acc_resp_ready )
);
end : gen_accelerator else begin: gen_no_accelerator
assign acc_req = '0;
assign acc_req_valid = 1'b0;
assign acc_resp_ready = 1'b0;

assign acc_ready_ex_id = '0;
assign acc_trans_id_ex_id = '0;
assign acc_result_ex_id = '0;
assign acc_valid_ex_id = '0;
Expand Down
Loading

0 comments on commit 271ede7

Please sign in to comment.