mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 21:57:11 -04:00
superscalar: duplicate decode stage (#2077)
This commit is contained in:
parent
99ea7c8610
commit
779927485d
8 changed files with 279 additions and 194 deletions
122
core/cva6.sv
122
core/cva6.sv
|
@ -361,11 +361,11 @@ module cva6
|
|||
// --------------
|
||||
// ID <-> ISSUE
|
||||
// --------------
|
||||
scoreboard_entry_t issue_entry_id_issue;
|
||||
logic [31:0] orig_instr_id_issue;
|
||||
logic issue_entry_valid_id_issue;
|
||||
logic is_ctrl_fow_id_issue;
|
||||
logic issue_instr_issue_id;
|
||||
scoreboard_entry_t [ariane_pkg::SUPERSCALAR:0] issue_entry_id_issue;
|
||||
logic [ariane_pkg::SUPERSCALAR:0][31:0] orig_instr_id_issue;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] issue_entry_valid_id_issue;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_ctrl_fow_id_issue;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] issue_instr_issue_id;
|
||||
|
||||
// --------------
|
||||
// ISSUE <-> EX
|
||||
|
@ -521,70 +521,70 @@ module cva6
|
|||
// ----------------------------
|
||||
logic [11:0] addr_csr_perf;
|
||||
logic [CVA6Cfg.XLEN-1:0] data_csr_perf, data_perf_csr;
|
||||
logic we_csr_perf;
|
||||
logic we_csr_perf;
|
||||
|
||||
logic icache_flush_ctrl_cache;
|
||||
logic itlb_miss_ex_perf;
|
||||
logic dtlb_miss_ex_perf;
|
||||
logic dcache_miss_cache_perf;
|
||||
logic icache_miss_cache_perf;
|
||||
logic [ NumPorts-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0] miss_vld_bits;
|
||||
logic stall_issue;
|
||||
logic icache_flush_ctrl_cache;
|
||||
logic itlb_miss_ex_perf;
|
||||
logic dtlb_miss_ex_perf;
|
||||
logic dcache_miss_cache_perf;
|
||||
logic icache_miss_cache_perf;
|
||||
logic [NumPorts-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0] miss_vld_bits;
|
||||
logic stall_issue;
|
||||
// --------------
|
||||
// CTRL <-> *
|
||||
// --------------
|
||||
logic set_pc_ctrl_pcgen;
|
||||
logic flush_csr_ctrl;
|
||||
logic flush_unissued_instr_ctrl_id;
|
||||
logic flush_ctrl_if;
|
||||
logic flush_ctrl_id;
|
||||
logic flush_ctrl_ex;
|
||||
logic flush_ctrl_bp;
|
||||
logic flush_tlb_ctrl_ex;
|
||||
logic flush_tlb_vvma_ctrl_ex;
|
||||
logic flush_tlb_gvma_ctrl_ex;
|
||||
logic fence_i_commit_controller;
|
||||
logic fence_commit_controller;
|
||||
logic sfence_vma_commit_controller;
|
||||
logic hfence_vvma_commit_controller;
|
||||
logic hfence_gvma_commit_controller;
|
||||
logic halt_ctrl;
|
||||
logic halt_csr_ctrl;
|
||||
logic dcache_flush_ctrl_cache;
|
||||
logic dcache_flush_ack_cache_ctrl;
|
||||
logic set_debug_pc;
|
||||
logic flush_commit;
|
||||
logic flush_acc;
|
||||
logic set_pc_ctrl_pcgen;
|
||||
logic flush_csr_ctrl;
|
||||
logic flush_unissued_instr_ctrl_id;
|
||||
logic flush_ctrl_if;
|
||||
logic flush_ctrl_id;
|
||||
logic flush_ctrl_ex;
|
||||
logic flush_ctrl_bp;
|
||||
logic flush_tlb_ctrl_ex;
|
||||
logic flush_tlb_vvma_ctrl_ex;
|
||||
logic flush_tlb_gvma_ctrl_ex;
|
||||
logic fence_i_commit_controller;
|
||||
logic fence_commit_controller;
|
||||
logic sfence_vma_commit_controller;
|
||||
logic hfence_vvma_commit_controller;
|
||||
logic hfence_gvma_commit_controller;
|
||||
logic halt_ctrl;
|
||||
logic halt_csr_ctrl;
|
||||
logic dcache_flush_ctrl_cache;
|
||||
logic dcache_flush_ack_cache_ctrl;
|
||||
logic set_debug_pc;
|
||||
logic flush_commit;
|
||||
logic flush_acc;
|
||||
|
||||
icache_areq_t icache_areq_ex_cache;
|
||||
icache_arsp_t icache_areq_cache_ex;
|
||||
icache_dreq_t icache_dreq_if_cache;
|
||||
icache_drsp_t icache_dreq_cache_if;
|
||||
icache_areq_t icache_areq_ex_cache;
|
||||
icache_arsp_t icache_areq_cache_ex;
|
||||
icache_dreq_t icache_dreq_if_cache;
|
||||
icache_drsp_t icache_dreq_cache_if;
|
||||
|
||||
amo_req_t amo_req;
|
||||
amo_resp_t amo_resp;
|
||||
logic sb_full;
|
||||
amo_req_t amo_req;
|
||||
amo_resp_t amo_resp;
|
||||
logic sb_full;
|
||||
|
||||
// ----------------
|
||||
// DCache <-> *
|
||||
// ----------------
|
||||
dcache_req_i_t [ 2:0] dcache_req_ports_ex_cache;
|
||||
dcache_req_o_t [ 2:0] dcache_req_ports_cache_ex;
|
||||
dcache_req_i_t [ 1:0] dcache_req_ports_acc_cache;
|
||||
dcache_req_o_t [ 1:0] dcache_req_ports_cache_acc;
|
||||
logic dcache_commit_wbuffer_empty;
|
||||
logic dcache_commit_wbuffer_not_ni;
|
||||
dcache_req_i_t [2:0] dcache_req_ports_ex_cache;
|
||||
dcache_req_o_t [2:0] dcache_req_ports_cache_ex;
|
||||
dcache_req_i_t [1:0] dcache_req_ports_acc_cache;
|
||||
dcache_req_o_t [1:0] dcache_req_ports_cache_acc;
|
||||
logic dcache_commit_wbuffer_empty;
|
||||
logic dcache_commit_wbuffer_not_ni;
|
||||
|
||||
//RVFI
|
||||
lsu_ctrl_t rvfi_lsu_ctrl;
|
||||
logic [CVA6Cfg.PLEN-1:0] rvfi_mem_paddr;
|
||||
logic rvfi_is_compressed;
|
||||
rvfi_probes_csr_t rvfi_csr;
|
||||
lsu_ctrl_t rvfi_lsu_ctrl;
|
||||
logic [CVA6Cfg.PLEN-1:0] rvfi_mem_paddr;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] rvfi_is_compressed;
|
||||
rvfi_probes_csr_t rvfi_csr;
|
||||
|
||||
// Accelerator port
|
||||
logic [ 63:0] inval_addr;
|
||||
logic inval_valid;
|
||||
logic inval_ready;
|
||||
logic [63:0] inval_addr;
|
||||
logic inval_valid;
|
||||
logic inval_ready;
|
||||
|
||||
// --------------
|
||||
// Frontend
|
||||
|
@ -1601,6 +1601,10 @@ module cva6
|
|||
|
||||
|
||||
//RVFI INSTR
|
||||
logic [ariane_pkg::SUPERSCALAR:0][31:0] rvfi_fetch_instr;
|
||||
for (genvar i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
|
||||
assign rvfi_fetch_instr[i] = fetch_entry_if_id[i].instruction;
|
||||
end
|
||||
|
||||
cva6_rvfi_probes #(
|
||||
.CVA6Cfg (CVA6Cfg),
|
||||
|
@ -1614,16 +1618,16 @@ module cva6
|
|||
|
||||
.flush_i (flush_ctrl_if),
|
||||
.issue_instr_ack_i (issue_instr_issue_id),
|
||||
.fetch_entry_valid_i(fetch_valid_if_id[0]),
|
||||
.instruction_i (fetch_entry_if_id[0].instruction),
|
||||
.fetch_entry_valid_i(fetch_valid_if_id),
|
||||
.instruction_i (rvfi_fetch_instr),
|
||||
.is_compressed_i (rvfi_is_compressed),
|
||||
|
||||
.issue_pointer_i (rvfi_issue_pointer),
|
||||
.commit_pointer_i(rvfi_commit_pointer),
|
||||
|
||||
.flush_unissued_instr_i(flush_unissued_instr_ctrl_id),
|
||||
.decoded_instr_valid_i (issue_entry_valid_id_issue),
|
||||
.decoded_instr_ack_i (issue_instr_issue_id),
|
||||
.decoded_instr_valid_i (issue_entry_valid_id_issue[0]),
|
||||
.decoded_instr_ack_i (issue_instr_issue_id[0]),
|
||||
|
||||
.rs1_forwarding_i(rs1_forwarding_id_ex),
|
||||
.rs2_forwarding_i(rs2_forwarding_id_ex),
|
||||
|
|
|
@ -52,9 +52,10 @@ module cva6_rvfi
|
|||
|
||||
logic flush;
|
||||
logic issue_instr_ack;
|
||||
logic fetch_entry_valid;
|
||||
logic [31:0] instruction;
|
||||
logic is_compressed;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] fetch_entry_valid;
|
||||
logic [ariane_pkg::SUPERSCALAR:0][31:0] instruction;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_compressed;
|
||||
logic [ariane_pkg::SUPERSCALAR:0][31:0] truncated;
|
||||
|
||||
logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer;
|
||||
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer;
|
||||
|
@ -158,23 +159,49 @@ module cva6_rvfi
|
|||
|
||||
//ID STAGE
|
||||
|
||||
for (genvar i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
|
||||
assign truncated[i] = (is_compressed[i]) ? {16'b0, instruction[i][15:0]} : instruction[i];
|
||||
end
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic [31:0] instr;
|
||||
} issue_struct_t;
|
||||
issue_struct_t issue_n, issue_q;
|
||||
issue_struct_t [ariane_pkg::SUPERSCALAR:0] issue_n, issue_q;
|
||||
logic took0;
|
||||
|
||||
always_comb begin
|
||||
issue_n = issue_q;
|
||||
took0 = 1'b0;
|
||||
|
||||
if (issue_instr_ack) issue_n.valid = 1'b0;
|
||||
if (issue_instr_ack) issue_n[0].valid = 1'b0;
|
||||
|
||||
if ((!issue_q.valid || issue_instr_ack) && fetch_entry_valid) begin
|
||||
issue_n.valid = 1'b1;
|
||||
issue_n.instr = (is_compressed) ? {{16{1'b0}}, instruction[15:0]} : instruction;
|
||||
if (!issue_n[ariane_pkg::SUPERSCALAR].valid) begin
|
||||
issue_n[ariane_pkg::SUPERSCALAR].valid = fetch_entry_valid[0];
|
||||
issue_n[ariane_pkg::SUPERSCALAR].instr = truncated[0];
|
||||
took0 = 1'b1;
|
||||
end
|
||||
|
||||
if (flush) issue_n.valid = 1'b0;
|
||||
if (!issue_n[0].valid) begin
|
||||
issue_n[0] = issue_n[ariane_pkg::SUPERSCALAR];
|
||||
issue_n[ariane_pkg::SUPERSCALAR].valid = 1'b0;
|
||||
end
|
||||
|
||||
if (!issue_n[ariane_pkg::SUPERSCALAR].valid) begin
|
||||
if (took0) begin
|
||||
issue_n[ariane_pkg::SUPERSCALAR].valid = fetch_entry_valid[ariane_pkg::SUPERSCALAR];
|
||||
issue_n[ariane_pkg::SUPERSCALAR].instr = truncated[ariane_pkg::SUPERSCALAR];
|
||||
end else begin
|
||||
issue_n[ariane_pkg::SUPERSCALAR].valid = fetch_entry_valid[0];
|
||||
issue_n[ariane_pkg::SUPERSCALAR].instr = truncated[0];
|
||||
end
|
||||
end
|
||||
|
||||
if (flush) begin
|
||||
for (int unsigned i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
|
||||
issue_n[i].valid = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
|
@ -210,7 +237,7 @@ module cva6_rvfi
|
|||
lsu_rmask: '0,
|
||||
lsu_wmask: '0,
|
||||
lsu_wdata: '0,
|
||||
instr: issue_q.instr
|
||||
instr: issue_q[0].instr
|
||||
};
|
||||
end
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ module cva6_rvfi_probes
|
|||
|
||||
) (
|
||||
|
||||
input logic flush_i,
|
||||
input logic issue_instr_ack_i,
|
||||
input logic fetch_entry_valid_i,
|
||||
input logic [31:0] instruction_i,
|
||||
input logic is_compressed_i,
|
||||
input logic flush_i,
|
||||
input logic [SUPERSCALAR:0] issue_instr_ack_i,
|
||||
input logic [SUPERSCALAR:0] fetch_entry_valid_i,
|
||||
input logic [SUPERSCALAR:0][31:0] instruction_i,
|
||||
input logic [SUPERSCALAR:0] is_compressed_i,
|
||||
|
||||
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer_i,
|
||||
input logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer_i,
|
||||
|
@ -63,7 +63,7 @@ module cva6_rvfi_probes
|
|||
instr = '0;
|
||||
|
||||
instr.flush = flush_i;
|
||||
instr.issue_instr_ack = issue_instr_ack_i;
|
||||
instr.issue_instr_ack = issue_instr_ack_i[0];
|
||||
instr.fetch_entry_valid = fetch_entry_valid_i;
|
||||
instr.instruction = instruction_i;
|
||||
instr.is_compressed = is_compressed_i;
|
||||
|
|
251
core/id_stage.sv
251
core/id_stage.sv
|
@ -38,17 +38,17 @@ module id_stage #(
|
|||
// Handshake's ready between fetch and decode - FRONTEND
|
||||
output logic [ariane_pkg::SUPERSCALAR:0] fetch_entry_ready_o,
|
||||
// Handshake's data between decode and issue - ISSUE
|
||||
output scoreboard_entry_t issue_entry_o,
|
||||
output scoreboard_entry_t [ariane_pkg::SUPERSCALAR:0] issue_entry_o,
|
||||
// Instruction value - ISSUE
|
||||
output logic [31:0] orig_instr_o,
|
||||
output logic [ariane_pkg::SUPERSCALAR:0][31:0] orig_instr_o,
|
||||
// Handshake's valid between decode and issue - ISSUE
|
||||
output logic issue_entry_valid_o,
|
||||
output logic [ariane_pkg::SUPERSCALAR:0] issue_entry_valid_o,
|
||||
// Report if instruction is a control flow instruction - ISSUE
|
||||
output logic is_ctrl_flow_o,
|
||||
output logic [ariane_pkg::SUPERSCALAR:0] is_ctrl_flow_o,
|
||||
// Handshake's acknowlege between decode and issue - ISSUE
|
||||
input logic issue_instr_ack_i,
|
||||
input logic [ariane_pkg::SUPERSCALAR:0] issue_instr_ack_i,
|
||||
// Information dedicated to RVFI - RVFI
|
||||
output logic rvfi_is_compressed_o,
|
||||
output logic [ariane_pkg::SUPERSCALAR:0] rvfi_is_compressed_o,
|
||||
// Current privilege level - CSR_REGFILE
|
||||
input riscv::priv_lvl_t priv_lvl_i,
|
||||
// Current virtualization mode - CSR_REGFILE
|
||||
|
@ -85,55 +85,62 @@ module id_stage #(
|
|||
logic [31:0] orig_instr;
|
||||
logic is_ctrl_flow;
|
||||
} issue_struct_t;
|
||||
issue_struct_t issue_n, issue_q;
|
||||
issue_struct_t [ariane_pkg::SUPERSCALAR:0] issue_n, issue_q;
|
||||
|
||||
logic is_control_flow_instr;
|
||||
scoreboard_entry_t decoded_instruction;
|
||||
logic [31:0] orig_instr;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_control_flow_instr;
|
||||
scoreboard_entry_t [ariane_pkg::SUPERSCALAR:0] decoded_instruction;
|
||||
logic [ariane_pkg::SUPERSCALAR:0][31:0] orig_instr;
|
||||
|
||||
logic is_illegal;
|
||||
logic is_illegal_cmp;
|
||||
logic [31:0] instruction;
|
||||
logic [31:0] compressed_instr;
|
||||
logic is_compressed;
|
||||
logic is_compressed_cmp;
|
||||
logic is_macro_instr_i;
|
||||
logic stall_instr_fetch;
|
||||
logic is_last_macro_instr_o;
|
||||
logic is_double_rd_macro_instr_o;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_illegal;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_illegal_cmp;
|
||||
logic [ariane_pkg::SUPERSCALAR:0][31:0] instruction;
|
||||
logic [ariane_pkg::SUPERSCALAR:0][31:0] compressed_instr;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_compressed;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_compressed_cmp;
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_macro_instr_i;
|
||||
logic stall_instr_fetch;
|
||||
logic is_last_macro_instr_o;
|
||||
logic is_double_rd_macro_instr_o;
|
||||
|
||||
if (CVA6Cfg.RVC) begin
|
||||
// ---------------------------------------------------------
|
||||
// 1. Check if they are compressed and expand in case they are
|
||||
// ---------------------------------------------------------
|
||||
compressed_decoder #(
|
||||
.CVA6Cfg(CVA6Cfg)
|
||||
) compressed_decoder_i (
|
||||
.instr_i (fetch_entry_i[0].instruction),
|
||||
.instr_o (compressed_instr),
|
||||
.illegal_instr_o (is_illegal),
|
||||
.is_compressed_o (is_compressed),
|
||||
.is_macro_instr_o(is_macro_instr_i)
|
||||
);
|
||||
for (genvar i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
|
||||
compressed_decoder #(
|
||||
.CVA6Cfg(CVA6Cfg)
|
||||
) compressed_decoder_i (
|
||||
.instr_i (fetch_entry_i[i].instruction),
|
||||
.instr_o (compressed_instr[i]),
|
||||
.illegal_instr_o (is_illegal[i]),
|
||||
.is_compressed_o (is_compressed[i]),
|
||||
.is_macro_instr_o(is_macro_instr_i[i])
|
||||
);
|
||||
end
|
||||
if (CVA6Cfg.RVZCMP) begin
|
||||
//sequencial decoder
|
||||
macro_decoder #(
|
||||
.CVA6Cfg(CVA6Cfg)
|
||||
) macro_decoder_i (
|
||||
.instr_i (compressed_instr),
|
||||
.is_macro_instr_i (is_macro_instr_i),
|
||||
.instr_i (compressed_instr[0]),
|
||||
.is_macro_instr_i (is_macro_instr_i[0]),
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.instr_o (instruction),
|
||||
.illegal_instr_i (is_illegal),
|
||||
.is_compressed_i (is_compressed),
|
||||
.issue_ack_i (issue_instr_ack_i),
|
||||
.illegal_instr_o (is_illegal_cmp),
|
||||
.is_compressed_o (is_compressed_cmp),
|
||||
.instr_o (instruction[0]),
|
||||
.illegal_instr_i (is_illegal[0]),
|
||||
.is_compressed_i (is_compressed[0]),
|
||||
.issue_ack_i (issue_instr_ack_i[0]),
|
||||
.illegal_instr_o (is_illegal_cmp[0]),
|
||||
.is_compressed_o (is_compressed_cmp[0]),
|
||||
.fetch_stall_o (stall_instr_fetch),
|
||||
.is_last_macro_instr_o (is_last_macro_instr_o),
|
||||
.is_double_rd_macro_instr_o(is_double_rd_macro_instr_o)
|
||||
);
|
||||
if (ariane_pkg::SUPERSCALAR > 0) begin
|
||||
assign instruction[ariane_pkg::SUPERSCALAR] = '0;
|
||||
assign is_illegal_cmp[ariane_pkg::SUPERSCALAR] = '0;
|
||||
assign is_compressed_cmp[ariane_pkg::SUPERSCALAR] = '0;
|
||||
end
|
||||
end else begin
|
||||
assign instruction = compressed_instr;
|
||||
assign is_illegal_cmp = is_illegal;
|
||||
|
@ -142,7 +149,9 @@ module id_stage #(
|
|||
assign is_double_rd_macro_instr_o = '0;
|
||||
end
|
||||
end else begin
|
||||
assign instruction = fetch_entry_i[0].instruction;
|
||||
for (genvar i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
|
||||
assign instruction[i] = fetch_entry_i[i].instruction;
|
||||
end
|
||||
assign is_illegal_cmp = '0;
|
||||
assign is_compressed_cmp = '0;
|
||||
assign is_macro_instr_i = '0;
|
||||
|
@ -154,76 +163,120 @@ module id_stage #(
|
|||
// ---------------------------------------------------------
|
||||
// 2. Decode and emit instruction to issue stage
|
||||
// ---------------------------------------------------------
|
||||
decoder #(
|
||||
.CVA6Cfg(CVA6Cfg),
|
||||
.branchpredict_sbe_t(branchpredict_sbe_t),
|
||||
.exception_t(exception_t),
|
||||
.irq_ctrl_t(irq_ctrl_t),
|
||||
.scoreboard_entry_t(scoreboard_entry_t),
|
||||
.interrupts_t(interrupts_t),
|
||||
.INTERRUPTS(INTERRUPTS)
|
||||
) decoder_i (
|
||||
.debug_req_i,
|
||||
.irq_ctrl_i,
|
||||
.irq_i,
|
||||
.pc_i (fetch_entry_i[0].address),
|
||||
.is_compressed_i (is_compressed_cmp),
|
||||
.is_macro_instr_i (is_macro_instr_i),
|
||||
.is_last_macro_instr_i (is_last_macro_instr_o),
|
||||
.is_double_rd_macro_instr_i(is_double_rd_macro_instr_o),
|
||||
.is_illegal_i (is_illegal_cmp),
|
||||
.instruction_i (instruction),
|
||||
.compressed_instr_i (fetch_entry_i[0].instruction[15:0]),
|
||||
.branch_predict_i (fetch_entry_i[0].branch_predict),
|
||||
.ex_i (fetch_entry_i[0].ex),
|
||||
.priv_lvl_i (priv_lvl_i),
|
||||
.v_i (v_i),
|
||||
.debug_mode_i (debug_mode_i),
|
||||
.fs_i,
|
||||
.vfs_i,
|
||||
.frm_i,
|
||||
.vs_i,
|
||||
.tvm_i,
|
||||
.tw_i,
|
||||
.vtw_i,
|
||||
.tsr_i,
|
||||
.hu_i,
|
||||
.instruction_o (decoded_instruction),
|
||||
.orig_instr_o (orig_instr),
|
||||
.is_control_flow_instr_o (is_control_flow_instr)
|
||||
);
|
||||
for (genvar i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
|
||||
decoder #(
|
||||
.CVA6Cfg(CVA6Cfg),
|
||||
.branchpredict_sbe_t(branchpredict_sbe_t),
|
||||
.exception_t(exception_t),
|
||||
.irq_ctrl_t(irq_ctrl_t),
|
||||
.scoreboard_entry_t(scoreboard_entry_t),
|
||||
.interrupts_t(interrupts_t),
|
||||
.INTERRUPTS(INTERRUPTS)
|
||||
) decoder_i (
|
||||
.debug_req_i,
|
||||
.irq_ctrl_i,
|
||||
.irq_i,
|
||||
.pc_i (fetch_entry_i[i].address),
|
||||
.is_compressed_i (is_compressed_cmp[i]),
|
||||
.is_macro_instr_i (is_macro_instr_i[i]),
|
||||
.is_last_macro_instr_i (is_last_macro_instr_o),
|
||||
.is_double_rd_macro_instr_i(is_double_rd_macro_instr_o),
|
||||
.is_illegal_i (is_illegal_cmp[i]),
|
||||
.instruction_i (instruction[i]),
|
||||
.compressed_instr_i (fetch_entry_i[i].instruction[15:0]),
|
||||
.branch_predict_i (fetch_entry_i[i].branch_predict),
|
||||
.ex_i (fetch_entry_i[i].ex),
|
||||
.priv_lvl_i (priv_lvl_i),
|
||||
.v_i (v_i),
|
||||
.debug_mode_i (debug_mode_i),
|
||||
.fs_i,
|
||||
.vfs_i,
|
||||
.frm_i,
|
||||
.vs_i,
|
||||
.tvm_i,
|
||||
.tw_i,
|
||||
.vtw_i,
|
||||
.tsr_i,
|
||||
.hu_i,
|
||||
.instruction_o (decoded_instruction[i]),
|
||||
.orig_instr_o (orig_instr[i]),
|
||||
.is_control_flow_instr_o (is_control_flow_instr[i])
|
||||
);
|
||||
end
|
||||
|
||||
// ------------------
|
||||
// Pipeline Register
|
||||
// ------------------
|
||||
always_comb begin
|
||||
issue_entry_o = issue_q.sbe;
|
||||
issue_entry_valid_o = issue_q.valid;
|
||||
is_ctrl_flow_o = issue_q.is_ctrl_flow;
|
||||
orig_instr_o = issue_q.orig_instr;
|
||||
for (genvar i = 0; i <= ariane_pkg::SUPERSCALAR; i++) begin
|
||||
assign issue_entry_o[i] = issue_q[i].sbe;
|
||||
assign issue_entry_valid_o[i] = issue_q[i].valid;
|
||||
assign is_ctrl_flow_o[i] = issue_q[i].is_ctrl_flow;
|
||||
assign orig_instr_o[i] = issue_q[i].orig_instr;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
issue_n = issue_q;
|
||||
fetch_entry_ready_o = '0;
|
||||
if (ariane_pkg::SUPERSCALAR) begin
|
||||
always_comb begin
|
||||
issue_n = issue_q;
|
||||
fetch_entry_ready_o = '0;
|
||||
|
||||
// Clear the valid flag if issue has acknowledged the instruction
|
||||
if (issue_instr_ack_i) issue_n.valid = 1'b0;
|
||||
|
||||
// if we have a space in the register and the fetch is valid, go get it
|
||||
// or the issue stage is currently acknowledging an instruction, which means that we will have space
|
||||
// for a new instruction
|
||||
if ((!issue_q.valid || issue_instr_ack_i) && fetch_entry_valid_i[0]) begin
|
||||
if (stall_instr_fetch) begin
|
||||
fetch_entry_ready_o[0] = 1'b0;
|
||||
end else begin
|
||||
fetch_entry_ready_o[0] = 1'b1;
|
||||
// Clear the valid flag if issue has acknowledged the instruction
|
||||
if (issue_instr_ack_i[0]) begin
|
||||
issue_n[0].valid = 1'b0;
|
||||
end
|
||||
if (issue_instr_ack_i[1]) begin
|
||||
issue_n[1].valid = 1'b0;
|
||||
end
|
||||
issue_n = '{1'b1, decoded_instruction, orig_instr, is_control_flow_instr};
|
||||
end
|
||||
|
||||
// invalidate the pipeline register on a flush
|
||||
if (flush_i) issue_n.valid = 1'b0;
|
||||
if (!issue_n[0].valid) begin
|
||||
if (issue_n[1].valid) begin
|
||||
issue_n[0] = issue_n[1];
|
||||
issue_n[1].valid = 1'b0;
|
||||
end else if (fetch_entry_valid_i[0]) begin
|
||||
fetch_entry_ready_o[0] = 1'b1;
|
||||
issue_n[0] = '{1'b1, decoded_instruction[0], orig_instr[0], is_control_flow_instr[0]};
|
||||
end
|
||||
end
|
||||
|
||||
if (!issue_n[1].valid) begin
|
||||
if (fetch_entry_ready_o[0]) begin
|
||||
if (fetch_entry_valid_i[1]) begin
|
||||
fetch_entry_ready_o[1] = 1'b1;
|
||||
issue_n[1] = '{1'b1, decoded_instruction[1], orig_instr[1], is_control_flow_instr[1]};
|
||||
end
|
||||
end else if (fetch_entry_valid_i[0]) begin
|
||||
fetch_entry_ready_o[0] = 1'b1;
|
||||
issue_n[1] = '{1'b1, decoded_instruction[0], orig_instr[0], is_control_flow_instr[0]};
|
||||
end
|
||||
end
|
||||
|
||||
if (flush_i) begin
|
||||
issue_n[0].valid = 1'b0;
|
||||
issue_n[1].valid = 1'b0;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
always_comb begin
|
||||
issue_n = issue_q;
|
||||
fetch_entry_ready_o = '0;
|
||||
|
||||
// Clear the valid flag if issue has acknowledged the instruction
|
||||
if (issue_instr_ack_i[0]) issue_n[0].valid = 1'b0;
|
||||
|
||||
// if we have a space in the register and the fetch is valid, go get it
|
||||
// or the issue stage is currently acknowledging an instruction, which means that we will have space
|
||||
// for a new instruction
|
||||
if ((!issue_q[0].valid || issue_instr_ack_i[0]) && fetch_entry_valid_i[0]) begin
|
||||
if (stall_instr_fetch) begin
|
||||
fetch_entry_ready_o[0] = 1'b0;
|
||||
end else begin
|
||||
fetch_entry_ready_o[0] = 1'b1;
|
||||
end
|
||||
issue_n[0] = '{1'b1, decoded_instruction[0], orig_instr[0], is_control_flow_instr[0]};
|
||||
end
|
||||
|
||||
// invalidate the pipeline register on a flush
|
||||
if (flush_i) issue_n[0].valid = 1'b0;
|
||||
end
|
||||
end
|
||||
// -------------------------
|
||||
// Registers (ID <-> Issue)
|
||||
|
|
|
@ -127,7 +127,7 @@ package cva6_config_pkg;
|
|||
MaxOutstandingStores: unsigned'(7),
|
||||
DebugEn: bit'(1),
|
||||
AxiBurstWriteEn: bit'(0),
|
||||
DCacheType: CVA6ConfigDcacheType,s
|
||||
DCacheType: CVA6ConfigDcacheType,
|
||||
InstrTlbEntries: int'(CVA6ConfigInstrTlbEntries),
|
||||
DataTlbEntries: int'(CVA6ConfigDataTlbEntries),
|
||||
NrLoadPipeRegs: int'(CVA6ConfigNrLoadPipeRegs),
|
||||
|
|
|
@ -100,9 +100,9 @@
|
|||
logic decoded_instr_ack; \
|
||||
logic flush; \
|
||||
logic issue_instr_ack; \
|
||||
logic fetch_entry_valid; \
|
||||
logic [31:0] instruction; \
|
||||
logic is_compressed; \
|
||||
logic [ariane_pkg::SUPERSCALAR:0] fetch_entry_valid; \
|
||||
logic [ariane_pkg::SUPERSCALAR:0][31:0] instruction; \
|
||||
logic [ariane_pkg::SUPERSCALAR:0] is_compressed; \
|
||||
logic [Cfg.XLEN-1:0] rs1_forwarding; \
|
||||
logic [Cfg.XLEN-1:0] rs2_forwarding; \
|
||||
logic [Cfg.NrCommitPorts-1:0][Cfg.VLEN-1:0] commit_instr_pc; \
|
||||
|
|
|
@ -37,15 +37,15 @@ module issue_stage
|
|||
// Stall inserted by Acc dispatcher - ACC_DISPATCHER
|
||||
input logic stall_i,
|
||||
// Handshake's data with decode stage - ID_STAGE
|
||||
input scoreboard_entry_t decoded_instr_i,
|
||||
input scoreboard_entry_t [SUPERSCALAR:0] decoded_instr_i,
|
||||
// instruction value - ID_STAGE
|
||||
input logic [31:0] orig_instr_i,
|
||||
input logic [SUPERSCALAR:0][31:0] orig_instr_i,
|
||||
// Handshake's valid with decode stage - ID_STAGE
|
||||
input logic decoded_instr_valid_i,
|
||||
input logic [SUPERSCALAR:0] decoded_instr_valid_i,
|
||||
// Is instruction a control flow instruction - ID_STAGE
|
||||
input logic is_ctrl_flow_i,
|
||||
input logic [SUPERSCALAR:0] is_ctrl_flow_i,
|
||||
// Handshake's acknowlege with decode stage - ID_STAGE
|
||||
output logic decoded_instr_ack_o,
|
||||
output logic [SUPERSCALAR:0] decoded_instr_ack_o,
|
||||
// rs1 forwarding - EX_STAGE
|
||||
output [CVA6Cfg.VLEN-1:0] rs1_forwarding_o,
|
||||
// rs2 forwarding - EX_STAGE
|
||||
|
|
|
@ -66,13 +66,13 @@ module scoreboard #(
|
|||
// instruction to put on top of scoreboard e.g.: top pointer
|
||||
// we can always put this instruction to the top unless we signal with asserted full_o
|
||||
// TO_BE_COMPLETED - TO_BE_COMPLETED
|
||||
input scoreboard_entry_t decoded_instr_i,
|
||||
input scoreboard_entry_t [ariane_pkg::SUPERSCALAR:0] decoded_instr_i,
|
||||
// TO_BE_COMPLETED - TO_BE_COMPLETED
|
||||
input logic [31:0] orig_instr_i,
|
||||
input logic [ariane_pkg::SUPERSCALAR:0][31:0] orig_instr_i,
|
||||
// TO_BE_COMPLETED - TO_BE_COMPLETED
|
||||
input logic decoded_instr_valid_i,
|
||||
input logic [ariane_pkg::SUPERSCALAR:0] decoded_instr_valid_i,
|
||||
// TO_BE_COMPLETED - TO_BE_COMPLETED
|
||||
output logic decoded_instr_ack_o,
|
||||
output logic [ariane_pkg::SUPERSCALAR:0] decoded_instr_ack_o,
|
||||
|
||||
// instruction to issue logic, if issue_instr_valid and issue_ready is asserted, advance the issue pointer
|
||||
// Issue scoreboard entry - ACC_DISPATCHER
|
||||
|
@ -125,7 +125,7 @@ module scoreboard #(
|
|||
|
||||
scoreboard_entry_t decoded_instr;
|
||||
always_comb begin
|
||||
decoded_instr = decoded_instr_i;
|
||||
decoded_instr = decoded_instr_i[0];
|
||||
end
|
||||
|
||||
// output commit instruction directly
|
||||
|
@ -138,14 +138,15 @@ module scoreboard #(
|
|||
|
||||
// an instruction is ready for issue if we have place in the issue FIFO and it the decoder says it is valid
|
||||
always_comb begin
|
||||
issue_instr_o = decoded_instr_i;
|
||||
orig_instr_o = orig_instr_i;
|
||||
decoded_instr_ack_o = '0;
|
||||
issue_instr_o = decoded_instr_i[0];
|
||||
orig_instr_o = orig_instr_i[0];
|
||||
// make sure we assign the correct trans ID
|
||||
issue_instr_o.trans_id = issue_pointer_q;
|
||||
// we are ready if we are not full and don't have any unresolved branches, but it can be
|
||||
// the case that we have an unresolved branch which is cleared in that cycle (resolved_branch_i == 1)
|
||||
issue_instr_valid_o = decoded_instr_valid_i & ~unresolved_branch_i & ~issue_full;
|
||||
decoded_instr_ack_o = issue_ack_i & ~issue_full;
|
||||
issue_instr_valid_o = decoded_instr_valid_i[0] & ~unresolved_branch_i & ~issue_full;
|
||||
decoded_instr_ack_o[0] = issue_ack_i & ~issue_full;
|
||||
end
|
||||
|
||||
// maintain a FIFO with issued instructions
|
||||
|
@ -156,14 +157,14 @@ module scoreboard #(
|
|||
issue_en = 1'b0;
|
||||
|
||||
// if we got a acknowledge from the issue stage, put this scoreboard entry in the queue
|
||||
if (decoded_instr_valid_i && decoded_instr_ack_o && !flush_unissued_instr_i) begin
|
||||
if (decoded_instr_valid_i[0] && decoded_instr_ack_o[0] && !flush_unissued_instr_i) begin
|
||||
// the decoded instruction we put in there is valid (1st bit)
|
||||
// increase the issue counter and advance issue pointer
|
||||
issue_en = 1'b1;
|
||||
mem_n[issue_pointer_q] = {
|
||||
1'b1, // valid bit
|
||||
(CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
|
||||
decoded_instr_i.op
|
||||
decoded_instr_i[0].op
|
||||
)), // whether rd goes to the fpr
|
||||
decoded_instr // decoded instruction record
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue