diff --git a/core/Flist.cva6 b/core/Flist.cva6 index 17cb6ae98..c2f9808f3 100644 --- a/core/Flist.cva6 +++ b/core/Flist.cva6 @@ -198,4 +198,10 @@ ${CVA6_REPO_DIR}/core/cva6_mmu/cva6_ptw.sv ${CVA6_REPO_DIR}/core/cva6_mmu/cva6_tlb.sv ${CVA6_REPO_DIR}/core/cva6_mmu/cva6_shared_tlb.sv +//Trace Interface +${CVA6_REPO_DIR}/core/cva6_te_connector/include/connector_pkg.sv +${CVA6_REPO_DIR}/core/cva6_te_connector/rtl/cva6_te_connector.sv +${CVA6_REPO_DIR}/core/cva6_te_connector/rtl/fsm.sv +${CVA6_REPO_DIR}/core/cva6_te_connector/rtl/itype_detector.sv + // end of manifest diff --git a/core/cva6.sv b/core/cva6.sv index eccac870c..128f246b0 100644 --- a/core/cva6.sv +++ b/core/cva6.sv @@ -1774,6 +1774,7 @@ module cva6 .exception_t (exception_t), .scoreboard_entry_t (scoreboard_entry_t), .lsu_ctrl_t (lsu_ctrl_t), + .bp_resolve_t (bp_resolve_t), .rvfi_probes_instr_t(rvfi_probes_instr_t), .rvfi_probes_csr_t (rvfi_probes_csr_t), .rvfi_probes_t (rvfi_probes_t) @@ -1809,7 +1810,7 @@ module cva6 .csr_i(rvfi_csr), .irq_i(irq_i), - + .resolved_branch_i(resolved_branch), .rvfi_probes_o(rvfi_probes_o) ); diff --git a/core/cva6_rvfi_probes.sv b/core/cva6_rvfi_probes.sv index 34b865d8d..6f1f5b74c 100644 --- a/core/cva6_rvfi_probes.sv +++ b/core/cva6_rvfi_probes.sv @@ -16,6 +16,7 @@ module cva6_rvfi_probes parameter type exception_t = logic, parameter type scoreboard_entry_t = logic, parameter type lsu_ctrl_t = logic, + parameter type bp_resolve_t = logic, parameter type rvfi_probes_instr_t = logic, parameter type rvfi_probes_csr_t = logic, parameter type rvfi_probes_t = logic @@ -52,6 +53,7 @@ module cva6_rvfi_probes input rvfi_probes_csr_t csr_i, input logic [1:0] irq_i, + input bp_resolve_t resolved_branch_i, output rvfi_probes_t rvfi_probes_o ); @@ -81,6 +83,11 @@ module cva6_rvfi_probes instr.ex_commit_cause = ex_commit_i.cause; instr.ex_commit_valid = ex_commit_i.valid; + if (CVA6Cfg.TvalEn) begin + instr.tval = ex_commit_i.tval; + end else begin + instr.tval = '0; + end instr.priv_lvl = priv_lvl_i; @@ -109,6 +116,9 @@ module cva6_rvfi_probes instr.commit_ack = commit_ack_i; instr.wdata = wdata_i; + instr.branch_valid = resolved_branch_i.valid; + instr.is_taken = resolved_branch_i.is_taken; + csr = csr_i; csr.mip_q = csr_i.mip_q | ({{CVA6Cfg.XLEN - 1{1'b0}}, CVA6Cfg.RVS && irq_i[1]} << riscv::IRQ_S_EXT); diff --git a/core/cva6_te_connector/include/connector_pkg.sv b/core/cva6_te_connector/include/connector_pkg.sv new file mode 100755 index 000000000..f293b8bac --- /dev/null +++ b/core/cva6_te_connector/include/connector_pkg.sv @@ -0,0 +1,48 @@ +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at + +// https://solderpad.org/licenses/SHL-2.1/ + +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. + +// Author: Umberto Laghi +// Contact: umberto.laghi@studio.unibo.it +// Github: @ubolakes +// Contributors: +// Darshak Sheladiya, SYSGO GmbH +// Maxime COLSON, Thales + +package connector_pkg; + // These parameters could be used in the ENCODER stage + localparam CAUSE_LEN = 5; //Size is ecause_width_p in the E-Trace SPEC + localparam ITYPE_LEN = 3; //Size is itype_width_p in the E-Trace SPEC (3 or 4) + localparam IRETIRE_LEN = 32; //Size is iretire_width_p in the E-Trace SPEC + //localparam TIME_LEN = 64; //rvfi_csr used logic [63:0] cycle_q but TIME_LEN could be used in the ENCODER stage + + // struct to save all itypes + // refer to page 21 of the spec + // The enum could be used in the ENCODER stage + typedef enum logic [ITYPE_LEN-1:0] { + STD = 0, // none of the other named itype codes + EXC = 1, // exception + INT = 2, // interrupt + ERET = 3, // exception or interrupt return + NTB = 4, // nontaken branch + TB = 5, // taken branch + UIJ = 6, // uninferable jump if ITYPE_LEN == 3, otherwise reserved + RES = 7 /*, // reserved + UC = 8, // uninferable call + IC = 9, // inferable call + UIJ = 10, // uninferable jump + IJ = 11, // inferable jump + CRS = 12, // co-routine swap + RET = 13, // return + OUIJ = 14, // other uninferable jump + OIJ = 15*/ // other inferable jump + } itype_t; + +endpackage diff --git a/core/cva6_te_connector/rtl/cva6_te_connector.sv b/core/cva6_te_connector/rtl/cva6_te_connector.sv new file mode 100755 index 000000000..b4d347b83 --- /dev/null +++ b/core/cva6_te_connector/rtl/cva6_te_connector.sv @@ -0,0 +1,399 @@ +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at + +// https://solderpad.org/licenses/SHL-2.1/ + +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. + +// Author: Umberto Laghi +// Contact: umberto.laghi@studio.unibo.it +// Github: @ubolakes +// Contributors: +// Darshak Sheladiya, SYSGO GmbH +// Maxime COLSON, Thales + +/* TOP LEVEL MODULE */ + +module cva6_te_connector #( + parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, + parameter N = 2, // max number of special inst in a cycle + parameter FIFO_DEPTH = 16 // number of entries in each FIFO +) ( + input logic clk_i, + input logic rst_ni, + + /* data from the CPU */ + // inputs + input logic [CVA6Cfg.NrCommitPorts-1:0] valid_i, // commit_ack in cva6 + // necessary inputs from scoreboard_entry_t + input logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.XLEN-1:0] pc_i, + input ariane_pkg::fu_op [CVA6Cfg.NrCommitPorts-1:0] op_i, + input logic [CVA6Cfg.NrCommitPorts-1:0] is_compressed_i, + // necessary inputs from bp_resolve_t + input logic branch_valid_i, + input logic is_taken_i, + // necessary inputs from exception_t + input logic ex_valid_i, + input logic [CVA6Cfg.XLEN-1:0] tval_i, + input logic [CVA6Cfg.XLEN-1:0] cause_i, + input riscv::priv_lvl_t priv_lvl_i, + //input logic [connector_pkg::CTX_LEN-1:0] context_i, // non mandatory + input logic [63:0] time_i, // non mandatory + //input logic [connector_pkg::CTYPE_LEN-1:0] ctype_i, // non mandatory + //input logic [CVA6Cfg.NrCommitPorts-1:0][connector_pkg::SIJ_LEN-1] sijump_i // non mandatory + + // outputs + /* the output of the module goes directly into the trace_encoder module */ + output logic [N-1:0] valid_o, + output logic [N-1:0][connector_pkg::IRETIRE_LEN-1:0] iretire_o, + output logic [N-1:0] ilastsize_o, + output logic [N-1:0][connector_pkg::ITYPE_LEN-1:0] itype_o, + output logic [connector_pkg::CAUSE_LEN-1:0] cause_o, + output logic [CVA6Cfg.XLEN-1:0] tval_o, + output riscv::priv_lvl_t priv_o, + output logic [N-1:0][CVA6Cfg.XLEN-1:0] iaddr_o, + //output logic [connector_pkg::CTX_LEN-1:0] context_o, // non mandatory + output logic [63:0] time_o // non mandatory + //output logic [connector_pkg::CTYPE_LEN-1:0] ctype_o, // non mandatory + //output logic [connector_pkg::SIJ_LEN-1] sijump_o // non mandatory +); + // struct to store data inside the uop FIFO + localparam type uop_entry_t = struct packed { + logic valid; + logic [CVA6Cfg.XLEN-1:0] pc; + logic [connector_pkg::ITYPE_LEN-1:0] itype; // determined in itype detector + logic compressed; + riscv::priv_lvl_t priv; + }; + // entries for the FIFOs + uop_entry_t [CVA6Cfg.NrCommitPorts-1:0] uop_entry_i, uop_entry_o; + uop_entry_t uop_entry_mux; + logic [CVA6Cfg.NrCommitPorts-1:0][connector_pkg::ITYPE_LEN-1:0] itype; + // FIFOs management + logic pop[CVA6Cfg.NrCommitPorts-1:0]; // signal to pop FIFOs + logic empty[CVA6Cfg.NrCommitPorts-1:0]; // signal used to enable counter + logic full[CVA6Cfg.NrCommitPorts-1:0]; + logic push_enable[CVA6Cfg.NrCommitPorts-1:0]; + // mux arbiter management + logic [$clog2(CVA6Cfg.NrCommitPorts-1):0] mux_arb_val; + logic clear_mux_arb; + logic enable_mux_arb; + // demux arbiter management + logic [$clog2(N):0] demux_arb_val; + logic clear_demux_arb; + logic enable_demux_arb; + // itype_detector + logic is_taken_d, is_taken_q; + logic interrupt; + // block counter management + logic n_blocks_full; + logic n_blocks_empty; + logic [$clog2(N):0] n_blocks_i, n_blocks_o; + logic n_blocks_push; + logic n_blocks_pop; + // struct to store exc and int infos + localparam type exc_info_t = struct packed { + logic [connector_pkg::CAUSE_LEN-1:0] cause; + logic [CVA6Cfg.XLEN-1:0] tval; + }; + // exception signals + exc_info_t exc_info_i, exc_info_o; + logic exc_info_full; + logic exc_info_empty; + logic exc_info_pop; + // signals to store blocks + logic valid_fsm; + logic [ N-1:0][connector_pkg::IRETIRE_LEN-1:0] iretire_q; + logic [ N-1:0] ilastsize_q; + logic [ N-1:0][ connector_pkg::ITYPE_LEN-1:0] itype_q; + logic [ connector_pkg::CAUSE_LEN-1:0] cause_q; + logic [ CVA6Cfg.XLEN-1:0] tval_q; + logic [ N-1:0][ CVA6Cfg.XLEN-1:0] iaddr_q; + + logic [connector_pkg::IRETIRE_LEN-1:0] iretire_d; + logic ilastsize_d; + logic [ connector_pkg::ITYPE_LEN-1:0] itype_d; + logic [ connector_pkg::CAUSE_LEN-1:0] cause_d; + logic [ CVA6Cfg.XLEN-1:0] tval_d; + logic [ CVA6Cfg.XLEN-1:0] iaddr_d; + + // assignments + assign pop[0] = (mux_arb_val == 0 || + uop_entry_o[0].itype == 1 || + uop_entry_o[0].itype == 2) && + !empty[0]; + assign pop[1] = (mux_arb_val == 1 || + uop_entry_o[1].itype == 1 || + uop_entry_o[1].itype == 2) && + !empty[1]; + + assign clear_mux_arb = (mux_arb_val == CVA6Cfg.NrCommitPorts-1 || + uop_entry_o[0].itype == 1 || + uop_entry_o[0].itype == 2) && + !empty[0]; + assign enable_mux_arb = !empty[0]; // the counter goes on if FIFOs are not empty + assign is_taken_d = is_taken_i; + assign n_blocks_push = !n_blocks_full && n_blocks_i > 0; + assign clear_demux_arb = n_blocks_pop; // demux_arb_val+1 == n_blocks_o && n_blocks_o > 0 && |valid_o; + assign enable_demux_arb = valid_fsm; // && n_blocks_o > 1; + assign exc_info_pop = valid_o[0] && (itype_o[0] == 1 || itype_o[0] == 2) && !exc_info_empty; + assign exc_info_i.tval = tval_i; + assign exc_info_i.cause = cause_i[connector_pkg::CAUSE_LEN-1:0]; + assign uop_entry_mux = empty[0] ? '0 : uop_entry_o[mux_arb_val]; + assign interrupt = cause_i[CVA6Cfg.XLEN-1]; // determinated based on the MSB of cause + + /* itype_detectors */ + for (genvar i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin + itype_detector i_itype_detector ( + .valid_i (valid_i[i]), + .exception_i (ex_valid_i), + .interrupt_i (interrupt), + .op_i (op_i[i]), + .branch_taken_i(is_taken_q), + .itype_o (itype[i]) + ); + end + + /* FIFOs */ + /* commit ports FIFOs */ + for (genvar i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin + fifo_v3 #( + .DEPTH(FIFO_DEPTH), + .dtype(uop_entry_t) + ) i_fifo_uop ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i ('0), + .testmode_i('0), + .full_o (full[i]), + .empty_o (empty[i]), + .usage_o (), + .data_i (uop_entry_i[i]), + .push_i (push_enable[i] && !full[i]), + .data_o (uop_entry_o[i]), + .pop_i (pop[i]) + ); + end + + // FIFO to store the n_blocks + fifo_v3 #( + .DEPTH(FIFO_DEPTH), + .dtype(exc_info_t) + ) i_nblock_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i ('0), + .testmode_i('0), + .full_o (exc_info_full), + .empty_o (exc_info_empty), + .usage_o (), + .data_i (exc_info_i), + .push_i ((ex_valid_i || interrupt) && !exc_info_full), + .data_o (exc_info_o), + .pop_i (exc_info_pop) + ); + + // FIFO to store exc and int info + fifo_v3 #( + .DEPTH(FIFO_DEPTH), + .DATA_WIDTH($clog2(N) + 1) + ) i_exc_info_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i ('0), + .testmode_i('0), + .full_o (n_blocks_full), + .empty_o (n_blocks_empty), + .usage_o (), + .data_i (n_blocks_i), + .push_i (n_blocks_push), + .data_o (n_blocks_o), + .pop_i (n_blocks_pop) + ); + + // mux arbiter for serialization + counter #( + .WIDTH($clog2(CVA6Cfg.NrCommitPorts)), + .STICKY_OVERFLOW('0) + ) i_mux_arbiter ( // change name? + .clk_i (clk_i), + .rst_ni (rst_ni), + .clear_i (clear_mux_arb), + .en_i (enable_mux_arb), + .load_i ('0), + .down_i ('0), + .d_i ('0), + .q_o (mux_arb_val), + .overflow_o() + ); + + // fsm to create blocks instantiation + fsm #( + .CVA6Cfg(CVA6Cfg), + .uop_entry_t(uop_entry_t) + ) i_fsm ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .uop_entry_i(uop_entry_mux), + .cause_i (exc_info_o.cause), + .tval_i (exc_info_o.tval), + .valid_o (valid_fsm), + .iretire_o (iretire_d), + .ilastsize_o(ilastsize_d), + .itype_o (itype_d), + .cause_o (cause_d), + .tval_o (tval_d), + .priv_o (priv_o), + .iaddr_o (iaddr_d) + ); + + // demux arbiter to choose register + counter #( + .WIDTH($clog2(N) + 1), + .STICKY_OVERFLOW('0) + ) i_demux_arbiter ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .clear_i (clear_demux_arb), + .en_i (enable_demux_arb), + .load_i ('0), + .down_i ('0), + .d_i ('0), + .q_o (demux_arb_val), + .overflow_o() + ); + + always_comb begin + // init + n_blocks_i = '0; + n_blocks_pop = '0; + for (int i = 0; i < N; i++) begin + // output + valid_o[i] = '0; + iretire_o[i] = '0; + ilastsize_o[i] = '0; + itype_o[i] = '0; + cause_o = '0; + tval_o = '0; + iaddr_o[i] = '0; + // uop_entry + uop_entry_i[i].valid = '0; + uop_entry_i[i].pc = '0; + uop_entry_i[i].itype = '0; + uop_entry_i[i].compressed = '0; + uop_entry_i[i].priv = riscv::PRIV_LVL_U; + end + + + // populating uop FIFO entries + for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin + uop_entry_i[i].valid = valid_i[i]; + uop_entry_i[i].pc = pc_i[i]; + uop_entry_i[i].itype = itype[i]; + uop_entry_i[i].compressed = is_compressed_i[i]; + uop_entry_i[i].priv = priv_lvl_i; + push_enable[i] = '0; + end + + // enabling push in input FIFOs + for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin + if ((uop_entry_i[i].itype == 1 || uop_entry_i[i].itype == 2) || + ((uop_entry_i[i].itype == 0 || uop_entry_i[i].itype > 2) && + uop_entry_i[i].valid)) begin + push_enable[i] = 1; + end + end + + // counting the blocks to emit in one cycle + for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin + if ((uop_entry_i[i].itype > 2 && uop_entry_i[i].valid)) begin + n_blocks_i += 1; + end else if (uop_entry_i[i].itype == 1 || uop_entry_i[i].itype == 2) begin + /* since the exc and int signal are connected to all itype detectors, + a int would require CVA6Cfg.NrCommitPorts blocks, but it's not true and breaks all + the system downstream. + That's because it would store CVA6Cfg.NrCommitPorts blocks in the FIFO, but since + the MUX allows only one uop_entry with itype == 1, the CVA6Cfg.NrCommitPorts blocks + would never be produced, causing a deadlock. */ + n_blocks_i = 1; + end + end + + // checking if blocks are ready to output + // first case: waiting for one block + // when it outputs one block can be exc or int + if (n_blocks_o == 1 && valid_fsm && !n_blocks_empty) begin + valid_o[0] = '1; + iretire_o[0] = iretire_d; + ilastsize_o[0] = ilastsize_d; + itype_o[0] = itype_d; + iaddr_o[0] = iaddr_d; + // setting cause and tval for exc or int + if (itype_o[0] == 1 || itype_o[0] == 2) begin + cause_o = cause_d; + tval_o = tval_d; + end + // popping the nblocks FIFO + n_blocks_pop = '1; + end + + // second case: waiting for N blocks + // when more blocks are output they + // are not exc or int, but other disc + if (n_blocks_o > 1 && demux_arb_val == n_blocks_o - 1 && valid_fsm && n_blocks_empty) begin + // leaving to 0 cause and tval since they are not necessary + // setting block specific data + for (int i = 0; i < n_blocks_o; i++) begin + valid_o[i] = '1; + if (i == n_blocks_o - 1) begin + iretire_o[i] = iretire_d; + ilastsize_o[i] = ilastsize_d; + itype_o[i] = itype_d; + iaddr_o[i] = iaddr_d; + end else begin + iretire_o[i] = iretire_q[i]; + ilastsize_o[i] = ilastsize_q[i]; + itype_o[i] = itype_q[i]; + iaddr_o[i] = iaddr_q[i]; + end + end + // popping the nblocks FIFO + n_blocks_pop = '1; + end + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + is_taken_q <= '0; + for (int i = 0; i < N; i++) begin + iretire_q[i] <= '0; + ilastsize_q[i] <= '0; + itype_q[i] <= '0; + cause_q <= '0; + tval_q <= '0; + iaddr_q[i] <= '0; + end + end else begin + if (branch_valid_i) begin + is_taken_q <= is_taken_d; + end + if (valid_fsm) begin + iretire_q[demux_arb_val] <= iretire_d; + ilastsize_q[demux_arb_val] <= ilastsize_d; + itype_q[demux_arb_val] <= itype_d; + cause_q <= cause_d; + tval_q <= tval_d; + iaddr_q[demux_arb_val] <= iaddr_d; + end + end + end + + + assign time_o = time_i; + + +endmodule diff --git a/core/cva6_te_connector/rtl/fsm.sv b/core/cva6_te_connector/rtl/fsm.sv new file mode 100755 index 000000000..74dc2dbc5 --- /dev/null +++ b/core/cva6_te_connector/rtl/fsm.sv @@ -0,0 +1,253 @@ +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at + +// https://solderpad.org/licenses/SHL-2.1/ + +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. + +// Author: Umberto Laghi +// Contact: umberto.laghi@studio.unibo.it +// Github: @ubolakes +// Contributors: +// Darshak Sheladiya, SYSGO GmbH +// Maxime COLSON, Thales + +/* FSM */ +/* +it determines the iaddr, ilastsize, iretire +*/ + +module fsm #( + parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, + parameter type uop_entry_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + input uop_entry_t uop_entry_i, + input logic [connector_pkg::CAUSE_LEN-1:0] cause_i, + input logic [ CVA6Cfg.XLEN-1:0] tval_i, + + output logic valid_o, + output logic [connector_pkg::IRETIRE_LEN-1:0] iretire_o, + output logic ilastsize_o, + output logic [ connector_pkg::ITYPE_LEN-1:0] itype_o, + output logic [ connector_pkg::CAUSE_LEN-1:0] cause_o, + output logic [ CVA6Cfg.XLEN-1:0] tval_o, + output riscv::priv_lvl_t priv_o, + output logic [ CVA6Cfg.XLEN-1:0] iaddr_o +); + typedef enum logic { + IDLE = 0, + COUNT = 1 + } state_t; + + /* internal signals */ + state_t current_state, next_state; + logic [CVA6Cfg.XLEN-1:0] iaddr_d, iaddr_q; + logic [CVA6Cfg.XLEN-1:0] iretire_d, iretire_q; + logic ilastsize_d, ilastsize_q; + logic exception; + logic interrupt; + logic special_inst; + logic one_cycle; + logic update_iaddr; + logic update_iretire; + + /* assignments */ + assign exception = uop_entry_i.itype == 1; + assign interrupt = uop_entry_i.itype == 2; + assign special_inst = uop_entry_i.itype > 2 && uop_entry_i.valid; + assign iretire_o = iretire_d; + assign iaddr_o = one_cycle ? iaddr_d : iaddr_q; + + // combinatorial logic for state transition + always_comb begin + // next_state default value + next_state = current_state; + // init + valid_o = '0; + iretire_d = '0; + ilastsize_d = '0; + ilastsize_o = '0; + itype_o = '0; + cause_o = '0; + tval_o = '0; + priv_o = riscv::PRIV_LVL_U; + iaddr_d = '0; + one_cycle = '0; + update_iaddr = '0; + update_iretire = '0; + + case (current_state) + IDLE: begin + if (uop_entry_i.itype == 0 && uop_entry_i.valid) begin // standard instr and valid + // sets iaddr, increases iretire + iaddr_d = uop_entry_i.pc; + update_iaddr = '1; + iretire_d = uop_entry_i.compressed ? 1 : 2; + // saving ilastsize in case next cycle + // there is an exc or int w/out retired inst + ilastsize_d = !uop_entry_i.compressed; + // saving iretire value + update_iretire = '1; + // goes to COUNT + next_state = COUNT; + end else if (special_inst) begin // special inst as first inst + // set all params for output + iaddr_d = uop_entry_i.pc; + ilastsize_o = !uop_entry_i.compressed; + itype_o = uop_entry_i.itype; + // cause and tval not necessary + priv_o = uop_entry_i.priv; + // output readable + valid_o = '1; + // read now the output + one_cycle = '1; + // remains here + next_state = IDLE; + end else if (interrupt) begin + itype_o = uop_entry_i.itype; + cause_o = cause_i; + // checks if an inst is committed in the same cycle + if (uop_entry_i.valid) begin + // setting iretire, ilastsize, iaddr + iaddr_d = uop_entry_i.pc; + iretire_d = uop_entry_i.compressed ? 1 : 2; + ilastsize_o = !uop_entry_i.compressed; + priv_o = uop_entry_i.priv; + end else begin + // setting iretire and ilastsize as the values stored + iretire_d = iretire_q; + ilastsize_o = ilastsize_q; + end + // output readable + valid_o = '1; + // read now the output + one_cycle = '1; + // remains here + next_state = IDLE; + end else if (exception) begin + itype_o = uop_entry_i.itype; + cause_o = cause_i; + tval_o = tval_i; + // checks if an inst is committed in the same cycle + if (uop_entry_i.valid) begin + // setting iretire, ilastsize, iaddr + iaddr_d = uop_entry_i.pc; + iretire_d = uop_entry_i.compressed ? 1 : 2; + ilastsize_o = !uop_entry_i.compressed; + priv_o = uop_entry_i.priv; + end else begin + // setting iretire and ilastsize as the values stored + iretire_d = iretire_q; + ilastsize_o = ilastsize_q; + end + // output readable + valid_o = '1; + // read now the output + one_cycle = '1; + // remains here + next_state = IDLE; + end else begin + next_state = IDLE; + end + end + + COUNT: begin + if (uop_entry_i.itype == 0 && uop_entry_i.valid) begin // standard inst + // increases iretire + iretire_d = uop_entry_i.compressed ? iretire_q + 1 : iretire_q + 2; + // saving ilastsize in case next cycle + // there is an exc or int w/out retired inst + ilastsize_d = !uop_entry_i.compressed; + // saving iretire value + update_iretire = '1; + // remains here + next_state = COUNT; + end else if (special_inst) begin + // set all params for output + iretire_d = uop_entry_i.compressed ? iretire_q + 1 : iretire_q + 2; + ilastsize_o = !uop_entry_i.compressed; + itype_o = uop_entry_i.itype; + // cause and tval not necessary + priv_o = uop_entry_i.priv; + // output readable + valid_o = '1; + // goes to IDLE + next_state = IDLE; + end else if (interrupt) begin + itype_o = uop_entry_i.itype; + cause_o = cause_i; + // checks if an inst is committed in the same cycle + if (uop_entry_i.valid) begin + // setting iretire, ilastsize + iretire_d = uop_entry_i.compressed ? iretire_q + 1 : iretire_q + 2; + ilastsize_o = !uop_entry_i.compressed; + priv_o = uop_entry_i.priv; + end else begin + // setting iretire and ilastsize as the values stored + iretire_d = iretire_q; + ilastsize_o = ilastsize_q; + end + // output readable + valid_o = '1; + // remains here + next_state = IDLE; + end else if (exception) begin + itype_o = uop_entry_i.itype; + cause_o = cause_i; + tval_o = tval_i; + // checks if an inst is committed in the same cycle + if (uop_entry_i.valid) begin + // setting iretire, ilastsize + iretire_d = uop_entry_i.compressed ? iretire_q + 1 : iretire_q + 2; + ilastsize_o = !uop_entry_i.compressed; + priv_o = uop_entry_i.priv; + end else begin + // setting iretire and ilastsize as the values stored + iretire_d = iretire_q; + ilastsize_o = ilastsize_q; + end + // output readable + valid_o = '1; + // remains here + next_state = IDLE; + end else begin + next_state = COUNT; + end + end + + endcase + end + + // sequential logic + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + current_state <= IDLE; + iaddr_q <= '0; + iretire_q <= '0; + ilastsize_q <= '0; + end else begin + if (valid_o) begin + iretire_q <= '0; + end + if (update_iaddr) begin + iaddr_q <= iaddr_d; + end + if (update_iretire) begin + iretire_q <= iretire_d; + end + if (uop_entry_i.valid) begin + ilastsize_q <= ilastsize_d; + end + current_state <= next_state; + end + + end + +endmodule diff --git a/core/cva6_te_connector/rtl/itype_detector.sv b/core/cva6_te_connector/rtl/itype_detector.sv new file mode 100755 index 000000000..61759b70b --- /dev/null +++ b/core/cva6_te_connector/rtl/itype_detector.sv @@ -0,0 +1,88 @@ +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at + +// https://solderpad.org/licenses/SHL-2.1/ + +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. + +// Author: Umberto Laghi +// Contact: umberto.laghi@studio.unibo.it +// Github: @ubolakes +// Contributors: +// Darshak Sheladiya, SYSGO GmbH +// Maxime COLSON, Thales + +/* ITYPE DETECTOR */ +/* +it produces the type of the instruction +*/ + +module itype_detector ( + input logic valid_i, + input logic exception_i, + input logic interrupt_i, + input ariane_pkg::fu_op op_i, + input logic branch_taken_i, + output logic [connector_pkg::ITYPE_LEN-1:0] itype_o +); + + // internal signals + logic exception; + logic interrupt; + logic eret; + logic nontaken_branch; + logic taken_branch; + logic updiscon; + + // assignments + assign exception = exception_i; + assign interrupt = interrupt_i; // no need to have an inst committed + + + + + assign eret = (op_i == ariane_pkg::MRET || op_i == ariane_pkg::SRET || op_i == ariane_pkg::DRET); + + assign nontaken_branch = ( op_i == ariane_pkg::EQ || + op_i == ariane_pkg::NE || + op_i == ariane_pkg::LTS || + op_i == ariane_pkg::GES || + op_i == ariane_pkg::LTU || + op_i == ariane_pkg::GEU) && + ~branch_taken_i; + + assign taken_branch = ( op_i == ariane_pkg::EQ || + op_i == ariane_pkg::NE || + op_i == ariane_pkg::LTS || + op_i == ariane_pkg::GES || + op_i == ariane_pkg::LTU || + op_i == ariane_pkg::GEU) && + branch_taken_i; + + assign updiscon = op_i == ariane_pkg::JALR; + + // assigning the itype + always_comb begin + // initialization + itype_o = '0; + + if (exception) begin // exception + itype_o = 1; + end else if (interrupt) begin // interrupt + itype_o = 2; + end else if (eret && valid_i) begin // exception or interrupt return + itype_o = 3; + end else if (nontaken_branch && valid_i) begin // nontaken branch + itype_o = 4; + end else if (taken_branch && valid_i) begin // taken branch + itype_o = 5; + end else if (connector_pkg::ITYPE_LEN == 3 && updiscon && valid_i) begin // uninferable discontinuity + itype_o = 6; + end + end + +endmodule diff --git a/core/include/rvfi_types.svh b/core/include/rvfi_types.svh index 69c552e7a..41e908cc8 100644 --- a/core/include/rvfi_types.svh +++ b/core/include/rvfi_types.svh @@ -126,6 +126,9 @@ logic [Cfg.PLEN-1:0] mem_paddr; \ logic debug_mode; \ logic [Cfg.NrCommitPorts-1:0][Cfg.XLEN-1:0] wdata; \ + logic branch_valid; \ + logic is_taken; \ + logic [Cfg.XLEN-1:0] tval; \ } `define RVFI_PROBES_CSR_T(Cfg) struct packed { \ diff --git a/corev_apu/tb/ariane_testharness.sv b/corev_apu/tb/ariane_testharness.sv index 1df11e757..d13429e38 100644 --- a/corev_apu/tb/ariane_testharness.sv +++ b/corev_apu/tb/ariane_testharness.sv @@ -23,21 +23,23 @@ `endif module ariane_testharness #( - parameter config_pkg::cva6_cfg_t CVA6Cfg = build_config_pkg::build_config(cva6_config_pkg::cva6_cfg), - // - parameter int unsigned AXI_USER_WIDTH = CVA6Cfg.AxiUserWidth, - parameter int unsigned AXI_USER_EN = CVA6Cfg.AXI_USER_EN, - parameter int unsigned AXI_ADDRESS_WIDTH = 64, - parameter int unsigned AXI_DATA_WIDTH = 64, - parameter bit InclSimDTM = 1'b1, - parameter int unsigned NUM_WORDS = 2**25, // memory size - parameter bit StallRandomOutput = 1'b0, - parameter bit StallRandomInput = 1'b0 + parameter config_pkg::cva6_cfg_t CVA6Cfg = build_config_pkg::build_config( + cva6_config_pkg::cva6_cfg + ), + // + parameter int unsigned AXI_USER_WIDTH = CVA6Cfg.AxiUserWidth, + parameter int unsigned AXI_USER_EN = CVA6Cfg.AXI_USER_EN, + parameter int unsigned AXI_ADDRESS_WIDTH = 64, + parameter int unsigned AXI_DATA_WIDTH = 64, + parameter bit InclSimDTM = 1'b1, + parameter int unsigned NUM_WORDS = 2 ** 25, // memory size + parameter bit StallRandomOutput = 1'b0, + parameter bit StallRandomInput = 1'b0 ) ( - input logic clk_i, - input logic rtc_i, - input logic rst_ni, - output logic [31:0] exit_o + input logic clk_i, + input logic rtc_i, + input logic rst_ni, + output logic [31:0] exit_o ); localparam [7:0] hart_id = '0; @@ -51,74 +53,74 @@ module ariane_testharness #( localparam type rvfi_probes_instr_t = `RVFI_PROBES_INSTR_T(CVA6Cfg); localparam type rvfi_probes_csr_t = `RVFI_PROBES_CSR_T(CVA6Cfg); localparam type rvfi_probes_t = struct packed { - rvfi_probes_csr_t csr; + rvfi_probes_csr_t csr; rvfi_probes_instr_t instr; }; // disable test-enable - logic test_en; - logic ndmreset; - logic ndmreset_n; - logic debug_req_core; + logic test_en; + logic ndmreset; + logic ndmreset_n; + logic debug_req_core; - int jtag_enable; - logic init_done; + int jtag_enable; + logic init_done; logic [31:0] jtag_exit, dmi_exit; - logic [31:0] rvfi_exit; - logic [31:0] tracer_exit; - logic [31:0] tandem_exit; + logic [31:0] rvfi_exit; + logic [31:0] tracer_exit; + logic [31:0] tandem_exit; - logic jtag_TCK; - logic jtag_TMS; - logic jtag_TDI; - logic jtag_TRSTn; - logic jtag_TDO_data; - logic jtag_TDO_driven; + logic jtag_TCK; + logic jtag_TMS; + logic jtag_TDI; + logic jtag_TRSTn; + logic jtag_TDO_data; + logic jtag_TDO_driven; - logic debug_req_valid; - logic debug_req_ready; - logic debug_resp_valid; - logic debug_resp_ready; + logic debug_req_valid; + logic debug_req_ready; + logic debug_resp_valid; + logic debug_resp_ready; - logic jtag_req_valid; - logic [6:0] jtag_req_bits_addr; - logic [1:0] jtag_req_bits_op; - logic [31:0] jtag_req_bits_data; - logic jtag_resp_ready; - logic jtag_resp_valid; + logic jtag_req_valid; + logic [ 6:0] jtag_req_bits_addr; + logic [ 1:0] jtag_req_bits_op; + logic [31:0] jtag_req_bits_data; + logic jtag_resp_ready; + logic jtag_resp_valid; - logic dmi_req_valid; - logic dmi_resp_ready; - logic dmi_resp_valid; + logic dmi_req_valid; + logic dmi_resp_ready; + logic dmi_resp_valid; - dm::dmi_req_t jtag_dmi_req; - dm::dmi_req_t dmi_req; + dm::dmi_req_t jtag_dmi_req; + dm::dmi_req_t dmi_req; - dm::dmi_req_t debug_req; - dm::dmi_resp_t debug_resp; + dm::dmi_req_t debug_req; + dm::dmi_resp_t debug_resp; assign test_en = 1'b0; AXI_BUS #( - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidth ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ) - ) slave[ariane_soc::NrSlaves-1:0](); + .AXI_ADDR_WIDTH(AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ID_WIDTH (ariane_axi_soc::IdWidth), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) slave[ariane_soc::NrSlaves-1:0] (); AXI_BUS #( - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ) - ) master[ariane_soc::NB_PERIPHERALS-1:0](); + .AXI_ADDR_WIDTH(AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) master[ariane_soc::NB_PERIPHERALS-1:0] (); rstgen i_rstgen_main ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni & (~ndmreset) ), - .test_mode_i ( test_en ), - .rst_no ( ndmreset_n ), - .init_no ( ) // keep open + .clk_i (clk_i), + .rst_ni (rst_ni & (~ndmreset)), + .test_mode_i(test_en), + .rst_no (ndmreset_n), + .init_no () // keep open ); // --------------- @@ -129,55 +131,56 @@ module ariane_testharness #( logic debug_enable; initial begin if (!$value$plusargs("jtag_rbb_enable=%b", jtag_enable)) jtag_enable = 'h0; - if ($test$plusargs("debug_disable")) debug_enable = 'h0; else debug_enable = 'h1; + if ($test$plusargs("debug_disable")) debug_enable = 'h0; + else debug_enable = 'h1; if (CVA6Cfg.XLEN != 32 & CVA6Cfg.XLEN != 64) $error("CVA6Cfg.XLEN different from 32 and 64"); end // debug if MUX - assign debug_req_valid = (jtag_enable[0]) ? jtag_req_valid : dmi_req_valid; - assign debug_resp_ready = (jtag_enable[0]) ? jtag_resp_ready : dmi_resp_ready; - assign debug_req = (jtag_enable[0]) ? jtag_dmi_req : dmi_req; + assign debug_req_valid = (jtag_enable[0]) ? jtag_req_valid : dmi_req_valid; + assign debug_resp_ready = (jtag_enable[0]) ? jtag_resp_ready : dmi_resp_ready; + assign debug_req = (jtag_enable[0]) ? jtag_dmi_req : dmi_req; if (ariane_pkg::RVFI) begin - assign exit_o = (jtag_enable[0]) ? jtag_exit : rvfi_exit; + assign exit_o = (jtag_enable[0]) ? jtag_exit : rvfi_exit; end else begin - assign exit_o = (jtag_enable[0]) ? jtag_exit : dmi_exit; + assign exit_o = (jtag_enable[0]) ? jtag_exit : dmi_exit; end - assign jtag_resp_valid = (jtag_enable[0]) ? debug_resp_valid : 1'b0; - assign dmi_resp_valid = (jtag_enable[0]) ? 1'b0 : debug_resp_valid; + assign jtag_resp_valid = (jtag_enable[0]) ? debug_resp_valid : 1'b0; + assign dmi_resp_valid = (jtag_enable[0]) ? 1'b0 : debug_resp_valid; // SiFive's SimJTAG Module // Converts to DPI calls SimJTAG i_SimJTAG ( - .clock ( clk_i ), - .reset ( ~rst_ni ), - .enable ( jtag_enable[0] ), - .init_done ( init_done ), - .jtag_TCK ( jtag_TCK ), - .jtag_TMS ( jtag_TMS ), - .jtag_TDI ( jtag_TDI ), - .jtag_TRSTn ( jtag_TRSTn ), - .jtag_TDO_data ( jtag_TDO_data ), - .jtag_TDO_driven ( jtag_TDO_driven ), - .exit ( jtag_exit ) + .clock (clk_i), + .reset (~rst_ni), + .enable (jtag_enable[0]), + .init_done (init_done), + .jtag_TCK (jtag_TCK), + .jtag_TMS (jtag_TMS), + .jtag_TDI (jtag_TDI), + .jtag_TRSTn (jtag_TRSTn), + .jtag_TDO_data (jtag_TDO_data), + .jtag_TDO_driven(jtag_TDO_driven), + .exit (jtag_exit) ); dmi_jtag i_dmi_jtag ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( test_en ), - .dmi_req_o ( jtag_dmi_req ), - .dmi_req_valid_o ( jtag_req_valid ), - .dmi_req_ready_i ( debug_req_ready ), - .dmi_resp_i ( debug_resp ), - .dmi_resp_ready_o ( jtag_resp_ready ), - .dmi_resp_valid_i ( jtag_resp_valid ), - .dmi_rst_no ( ), // not connected - .tck_i ( jtag_TCK ), - .tms_i ( jtag_TMS ), - .trst_ni ( jtag_TRSTn ), - .td_i ( jtag_TDI ), - .td_o ( jtag_TDO_data ), - .tdo_oe_o ( jtag_TDO_driven ) + .clk_i (clk_i), + .rst_ni (rst_ni), + .testmode_i (test_en), + .dmi_req_o (jtag_dmi_req), + .dmi_req_valid_o (jtag_req_valid), + .dmi_req_ready_i (debug_req_ready), + .dmi_resp_i (debug_resp), + .dmi_resp_ready_o(jtag_resp_ready), + .dmi_resp_valid_i(jtag_resp_valid), + .dmi_rst_no (), // not connected + .tck_i (jtag_TCK), + .tms_i (jtag_TMS), + .trst_ni (jtag_TRSTn), + .td_i (jtag_TDI), + .td_o (jtag_TDO_data), + .tdo_oe_o (jtag_TDO_driven) ); // SiFive's SimDTM Module @@ -187,18 +190,18 @@ module ariane_testharness #( if (InclSimDTM) begin SimDTM i_SimDTM ( - .clk ( clk_i ), - .reset ( ~rst_ni ), - .debug_req_valid ( dmi_req_valid ), - .debug_req_ready ( debug_req_ready ), - .debug_req_bits_addr ( dmi_req.addr ), - .debug_req_bits_op ( debug_req_bits_op ), - .debug_req_bits_data ( dmi_req.data ), - .debug_resp_valid ( dmi_resp_valid ), - .debug_resp_ready ( dmi_resp_ready ), - .debug_resp_bits_resp ( debug_resp.resp ), - .debug_resp_bits_data ( debug_resp.data ), - .exit ( dmi_exit ) + .clk (clk_i), + .reset (~rst_ni), + .debug_req_valid (dmi_req_valid), + .debug_req_ready (debug_req_ready), + .debug_req_bits_addr (dmi_req.addr), + .debug_req_bits_op (debug_req_bits_op), + .debug_req_bits_data (dmi_req.data), + .debug_resp_valid (dmi_resp_valid), + .debug_resp_ready (dmi_resp_ready), + .debug_resp_bits_resp(debug_resp.resp), + .debug_resp_bits_data(debug_resp.data), + .exit (dmi_exit) ); end else begin assign dmi_req_valid = '0; @@ -217,121 +220,120 @@ module ariane_testharness #( int dmi_del_cnt_d, dmi_del_cnt_q; assign dmi_del_cnt_d = (dmi_del_cnt_q) ? dmi_del_cnt_q - 1 : 0; - assign debug_req_core = (dmi_del_cnt_q) ? 1'b0 : - (!debug_enable) ? 1'b0 : debug_req_core_ungtd; + assign debug_req_core = (dmi_del_cnt_q) ? 1'b0 : (!debug_enable) ? 1'b0 : debug_req_core_ungtd; always_ff @(posedge clk_i or negedge rst_ni) begin : p_dmi_del_cnt - if(!rst_ni) begin + if (!rst_ni) begin dmi_del_cnt_q <= DmiDelCycles; end else begin dmi_del_cnt_q <= dmi_del_cnt_d; end end - ariane_axi::req_t dm_axi_m_req; - ariane_axi::resp_t dm_axi_m_resp; + ariane_axi::req_t dm_axi_m_req; + ariane_axi::resp_t dm_axi_m_resp; - logic dm_slave_req; - logic dm_slave_we; - logic [64-1:0] dm_slave_addr; - logic [64/8-1:0] dm_slave_be; - logic [64-1:0] dm_slave_wdata; - logic [64-1:0] dm_slave_rdata; + logic dm_slave_req; + logic dm_slave_we; + logic [ 64-1:0] dm_slave_addr; + logic [64/8-1:0] dm_slave_be; + logic [ 64-1:0] dm_slave_wdata; + logic [ 64-1:0] dm_slave_rdata; - logic dm_master_req; - logic [64-1:0] dm_master_add; - logic dm_master_we; - logic [64-1:0] dm_master_wdata; - logic [64/8-1:0] dm_master_be; - logic dm_master_gnt; - logic dm_master_r_valid; - logic [64-1:0] dm_master_r_rdata; + logic dm_master_req; + logic [ 64-1:0] dm_master_add; + logic dm_master_we; + logic [ 64-1:0] dm_master_wdata; + logic [64/8-1:0] dm_master_be; + logic dm_master_gnt; + logic dm_master_r_valid; + logic [ 64-1:0] dm_master_r_rdata; // debug module dm_top #( - .NrHarts ( 1 ), - .BusWidth ( AXI_DATA_WIDTH ), - .SelectableHarts ( 1'b1 ) + .NrHarts (1), + .BusWidth (AXI_DATA_WIDTH), + .SelectableHarts(1'b1) ) i_dm_top ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), // PoR - .testmode_i ( test_en ), - .ndmreset_o ( ndmreset ), - .dmactive_o ( ), // active debug session - .debug_req_o ( debug_req_core_ungtd ), - .unavailable_i ( '0 ), - .hartinfo_i ( {ariane_pkg::DebugHartInfo} ), - .slave_req_i ( dm_slave_req ), - .slave_we_i ( dm_slave_we ), - .slave_addr_i ( dm_slave_addr ), - .slave_be_i ( dm_slave_be ), - .slave_wdata_i ( dm_slave_wdata ), - .slave_rdata_o ( dm_slave_rdata ), - .master_req_o ( dm_master_req ), - .master_add_o ( dm_master_add ), - .master_we_o ( dm_master_we ), - .master_wdata_o ( dm_master_wdata ), - .master_be_o ( dm_master_be ), - .master_gnt_i ( dm_master_gnt ), - .master_r_valid_i ( dm_master_r_valid ), - .master_r_rdata_i ( dm_master_r_rdata ), - .dmi_rst_ni ( rst_ni ), - .dmi_req_valid_i ( debug_req_valid ), - .dmi_req_ready_o ( debug_req_ready ), - .dmi_req_i ( debug_req ), - .dmi_resp_valid_o ( debug_resp_valid ), - .dmi_resp_ready_i ( debug_resp_ready ), - .dmi_resp_o ( debug_resp ) + .clk_i (clk_i), + .rst_ni (rst_ni), // PoR + .testmode_i (test_en), + .ndmreset_o (ndmreset), + .dmactive_o (), // active debug session + .debug_req_o (debug_req_core_ungtd), + .unavailable_i ('0), + .hartinfo_i ({ariane_pkg::DebugHartInfo}), + .slave_req_i (dm_slave_req), + .slave_we_i (dm_slave_we), + .slave_addr_i (dm_slave_addr), + .slave_be_i (dm_slave_be), + .slave_wdata_i (dm_slave_wdata), + .slave_rdata_o (dm_slave_rdata), + .master_req_o (dm_master_req), + .master_add_o (dm_master_add), + .master_we_o (dm_master_we), + .master_wdata_o (dm_master_wdata), + .master_be_o (dm_master_be), + .master_gnt_i (dm_master_gnt), + .master_r_valid_i(dm_master_r_valid), + .master_r_rdata_i(dm_master_r_rdata), + .dmi_rst_ni (rst_ni), + .dmi_req_valid_i (debug_req_valid), + .dmi_req_ready_o (debug_req_ready), + .dmi_req_i (debug_req), + .dmi_resp_valid_o(debug_resp_valid), + .dmi_resp_ready_i(debug_resp_ready), + .dmi_resp_o (debug_resp) ); axi2mem #( - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .AXI_ADDR_WIDTH(AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) ) i_dm_axi2mem ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .slave ( master[ariane_soc::Debug] ), - .req_o ( dm_slave_req ), - .we_o ( dm_slave_we ), - .addr_o ( dm_slave_addr ), - .be_o ( dm_slave_be ), - .user_o ( ), - .data_o ( dm_slave_wdata ), - .user_i ( '0 ), - .data_i ( dm_slave_rdata ) + .clk_i (clk_i), + .rst_ni(rst_ni), + .slave (master[ariane_soc::Debug]), + .req_o (dm_slave_req), + .we_o (dm_slave_we), + .addr_o(dm_slave_addr), + .be_o (dm_slave_be), + .user_o(), + .data_o(dm_slave_wdata), + .user_i('0), + .data_i(dm_slave_rdata) ); `AXI_ASSIGN_FROM_REQ(slave[1], dm_axi_m_req) `AXI_ASSIGN_TO_RESP(dm_axi_m_resp, slave[1]) axi_adapter #( - .CVA6Cfg ( CVA6Cfg ), - .DATA_WIDTH ( AXI_DATA_WIDTH ), - .axi_req_t ( ariane_axi::req_t ), - .axi_rsp_t ( ariane_axi::resp_t ) + .CVA6Cfg (CVA6Cfg), + .DATA_WIDTH(AXI_DATA_WIDTH), + .axi_req_t (ariane_axi::req_t), + .axi_rsp_t (ariane_axi::resp_t) ) i_dm_axi_master ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( dm_master_req ), - .type_i ( ariane_pkg::SINGLE_REQ ), - .amo_i ( ariane_pkg::AMO_NONE ), - .gnt_o ( dm_master_gnt ), - .addr_i ( dm_master_add ), - .we_i ( dm_master_we ), - .wdata_i ( dm_master_wdata ), - .be_i ( dm_master_be ), - .size_i ( 2'b11 ), // always do 64bit here and use byte enables to gate - .id_i ( '0 ), - .valid_o ( dm_master_r_valid ), - .rdata_o ( dm_master_r_rdata ), - .id_o ( ), - .critical_word_o ( ), - .critical_word_valid_o ( ), - .axi_req_o ( dm_axi_m_req ), - .axi_resp_i ( dm_axi_m_resp ) + .clk_i(clk_i), + .rst_ni(rst_ni), + .req_i(dm_master_req), + .type_i(ariane_pkg::SINGLE_REQ), + .amo_i(ariane_pkg::AMO_NONE), + .gnt_o(dm_master_gnt), + .addr_i(dm_master_add), + .we_i(dm_master_we), + .wdata_i(dm_master_wdata), + .be_i(dm_master_be), + .size_i(2'b11), // always do 64bit here and use byte enables to gate + .id_i('0), + .valid_o(dm_master_r_valid), + .rdata_o(dm_master_r_rdata), + .id_o(), + .critical_word_o(), + .critical_word_valid_o(), + .axi_req_o(dm_axi_m_req), + .axi_resp_i(dm_axi_m_resp) ); @@ -340,32 +342,32 @@ module ariane_testharness #( // --------------- logic rom_req; logic [AXI_ADDRESS_WIDTH-1:0] rom_addr; - logic [AXI_DATA_WIDTH-1:0] rom_rdata; + logic [ AXI_DATA_WIDTH-1:0] rom_rdata; axi2mem #( - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .AXI_ADDR_WIDTH(AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) ) i_axi2rom ( - .clk_i ( clk_i ), - .rst_ni ( ndmreset_n ), - .slave ( master[ariane_soc::ROM] ), - .req_o ( rom_req ), - .we_o ( ), - .addr_o ( rom_addr ), - .be_o ( ), - .user_o ( ), - .data_o ( ), - .user_i ( '0 ), - .data_i ( rom_rdata ) + .clk_i (clk_i), + .rst_ni(ndmreset_n), + .slave (master[ariane_soc::ROM]), + .req_o (rom_req), + .we_o (), + .addr_o(rom_addr), + .be_o (), + .user_o(), + .data_o(), + .user_i('0), + .data_i(rom_rdata) ); bootrom i_bootrom ( - .clk_i ( clk_i ), - .req_i ( rom_req ), - .addr_i ( rom_addr ), - .rdata_o ( rom_rdata ) + .clk_i (clk_i), + .req_i (rom_req), + .addr_i (rom_addr), + .rdata_o(rom_rdata) ); // ------------------------------ @@ -379,15 +381,15 @@ module ariane_testharness #( `AXI_ASSIGN_TO_REQ(gpio_req, master[ariane_soc::GPIO]) `AXI_ASSIGN_FROM_RESP(master[ariane_soc::GPIO], gpio_resp) axi_err_slv #( - .AxiIdWidth ( ariane_axi_soc::IdWidthSlave ), - .req_t ( ariane_axi_soc::req_slv_t ), - .resp_t ( ariane_axi_soc::resp_slv_t ) + .AxiIdWidth(ariane_axi_soc::IdWidthSlave), + .req_t (ariane_axi_soc::req_slv_t), + .resp_t (ariane_axi_soc::resp_slv_t) ) i_gpio_err_slv ( - .clk_i ( clk_i ), - .rst_ni ( ndmreset_n ), - .test_i ( test_en ), - .slv_req_i ( gpio_req ), - .slv_resp_o ( gpio_resp ) + .clk_i (clk_i), + .rst_ni (ndmreset_n), + .test_i (test_en), + .slv_req_i (gpio_req), + .slv_resp_o(gpio_resp) ); @@ -395,98 +397,98 @@ module ariane_testharness #( // Memory + Exclusive Access // ------------------------------ AXI_BUS #( - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ) - ) dram(); + .AXI_ADDR_WIDTH(AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) dram (); logic req; logic we; logic [AXI_ADDRESS_WIDTH-1:0] addr; - logic [AXI_DATA_WIDTH/8-1:0] be; - logic [AXI_DATA_WIDTH-1:0] wdata; - logic [AXI_DATA_WIDTH-1:0] rdata; - logic [AXI_USER_WIDTH-1:0] wuser; - logic [AXI_USER_WIDTH-1:0] ruser; + logic [ AXI_DATA_WIDTH/8-1:0] be; + logic [ AXI_DATA_WIDTH-1:0] wdata; + logic [ AXI_DATA_WIDTH-1:0] rdata; + logic [ AXI_USER_WIDTH-1:0] wuser; + logic [ AXI_USER_WIDTH-1:0] ruser; axi_riscv_atomics_wrap #( - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ), - .AXI_MAX_WRITE_TXNS ( 1 ), - .RISCV_WORD_WIDTH ( 64 ) + .AXI_ADDR_WIDTH (AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH (AXI_DATA_WIDTH), + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .AXI_USER_WIDTH (AXI_USER_WIDTH), + .AXI_MAX_WRITE_TXNS(1), + .RISCV_WORD_WIDTH (64) ) i_axi_riscv_atomics ( - .clk_i, - .rst_ni ( ndmreset_n ), - .slv ( master[ariane_soc::DRAM] ), - .mst ( dram ) + .clk_i, + .rst_ni(ndmreset_n), + .slv (master[ariane_soc::DRAM]), + .mst (dram) ); AXI_BUS #( - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ) - ) dram_delayed(); + .AXI_ADDR_WIDTH(AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) dram_delayed (); axi_delayer_intf #( - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ), - .STALL_RANDOM_INPUT ( StallRandomInput ), - .STALL_RANDOM_OUTPUT ( StallRandomOutput ), - .FIXED_DELAY_INPUT ( 0 ), - .FIXED_DELAY_OUTPUT ( 0 ) + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .AXI_ADDR_WIDTH (AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH (AXI_DATA_WIDTH), + .AXI_USER_WIDTH (AXI_USER_WIDTH), + .STALL_RANDOM_INPUT (StallRandomInput), + .STALL_RANDOM_OUTPUT(StallRandomOutput), + .FIXED_DELAY_INPUT (0), + .FIXED_DELAY_OUTPUT (0) ) i_axi_delayer ( - .clk_i ( clk_i ), - .rst_ni ( ndmreset_n ), - .slv ( dram ), - .mst ( dram_delayed ) + .clk_i (clk_i), + .rst_ni(ndmreset_n), + .slv (dram), + .mst (dram_delayed) ); axi2mem #( - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .AXI_ADDR_WIDTH(AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) ) i_axi2mem ( - .clk_i ( clk_i ), - .rst_ni ( ndmreset_n ), - .slave ( dram_delayed ), - .req_o ( req ), - .we_o ( we ), - .addr_o ( addr ), - .be_o ( be ), - .user_o ( wuser ), - .data_o ( wdata ), - .user_i ( ruser ), - .data_i ( rdata ) + .clk_i (clk_i), + .rst_ni(ndmreset_n), + .slave (dram_delayed), + .req_o (req), + .we_o (we), + .addr_o(addr), + .be_o (be), + .user_o(wuser), + .data_o(wdata), + .user_i(ruser), + .data_i(rdata) ); sram #( - .DATA_WIDTH ( AXI_DATA_WIDTH ), - .USER_WIDTH ( AXI_USER_WIDTH ), - .USER_EN ( AXI_USER_EN ), + .DATA_WIDTH(AXI_DATA_WIDTH), + .USER_WIDTH(AXI_USER_WIDTH), + .USER_EN (AXI_USER_EN), `ifdef VERILATOR - .SIM_INIT ( "none" ), + .SIM_INIT ("none"), `else - .SIM_INIT ( "zeros" ), + .SIM_INIT ("zeros"), `endif - .NUM_WORDS ( NUM_WORDS ) + .NUM_WORDS (NUM_WORDS) ) i_sram ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( req ), - .we_i ( we ), - .addr_i ( addr[$clog2(NUM_WORDS)-1+$clog2(AXI_DATA_WIDTH/8):$clog2(AXI_DATA_WIDTH/8)] ), - .wuser_i ( wuser ), - .wdata_i ( wdata ), - .be_i ( be ), - .ruser_o ( ruser ), - .rdata_o ( rdata ) + .clk_i (clk_i), + .rst_ni (rst_ni), + .req_i (req), + .we_i (we), + .addr_i (addr[$clog2(NUM_WORDS)-1+$clog2(AXI_DATA_WIDTH/8):$clog2(AXI_DATA_WIDTH/8)]), + .wuser_i(wuser), + .wdata_i(wdata), + .be_i (be), + .ruser_o(ruser), + .rdata_o(rdata) ); // --------------- @@ -496,46 +498,86 @@ module ariane_testharness #( axi_pkg::xbar_rule_64_t [ariane_soc::NB_PERIPHERALS-1:0] addr_map; assign addr_map = '{ - '{ idx: ariane_soc::Debug, start_addr: ariane_soc::DebugBase, end_addr: ariane_soc::DebugBase + ariane_soc::DebugLength }, - '{ idx: ariane_soc::ROM, start_addr: ariane_soc::ROMBase, end_addr: ariane_soc::ROMBase + ariane_soc::ROMLength }, - '{ idx: ariane_soc::CLINT, start_addr: ariane_soc::CLINTBase, end_addr: ariane_soc::CLINTBase + ariane_soc::CLINTLength }, - '{ idx: ariane_soc::PLIC, start_addr: ariane_soc::PLICBase, end_addr: ariane_soc::PLICBase + ariane_soc::PLICLength }, - '{ idx: ariane_soc::UART, start_addr: ariane_soc::UARTBase, end_addr: ariane_soc::UARTBase + ariane_soc::UARTLength }, - '{ idx: ariane_soc::Timer, start_addr: ariane_soc::TimerBase, end_addr: ariane_soc::TimerBase + ariane_soc::TimerLength }, - '{ idx: ariane_soc::SPI, start_addr: ariane_soc::SPIBase, end_addr: ariane_soc::SPIBase + ariane_soc::SPILength }, - '{ idx: ariane_soc::Ethernet, start_addr: ariane_soc::EthernetBase, end_addr: ariane_soc::EthernetBase + ariane_soc::EthernetLength }, - '{ idx: ariane_soc::GPIO, start_addr: ariane_soc::GPIOBase, end_addr: ariane_soc::GPIOBase + ariane_soc::GPIOLength }, - '{ idx: ariane_soc::DRAM, start_addr: ariane_soc::DRAMBase, end_addr: ariane_soc::DRAMBase + ariane_soc::DRAMLength } - }; + '{ + idx: ariane_soc::Debug, + start_addr: ariane_soc::DebugBase, + end_addr: ariane_soc::DebugBase + ariane_soc::DebugLength + }, + '{ + idx: ariane_soc::ROM, + start_addr: ariane_soc::ROMBase, + end_addr: ariane_soc::ROMBase + ariane_soc::ROMLength + }, + '{ + idx: ariane_soc::CLINT, + start_addr: ariane_soc::CLINTBase, + end_addr: ariane_soc::CLINTBase + ariane_soc::CLINTLength + }, + '{ + idx: ariane_soc::PLIC, + start_addr: ariane_soc::PLICBase, + end_addr: ariane_soc::PLICBase + ariane_soc::PLICLength + }, + '{ + idx: ariane_soc::UART, + start_addr: ariane_soc::UARTBase, + end_addr: ariane_soc::UARTBase + ariane_soc::UARTLength + }, + '{ + idx: ariane_soc::Timer, + start_addr: ariane_soc::TimerBase, + end_addr: ariane_soc::TimerBase + ariane_soc::TimerLength + }, + '{ + idx: ariane_soc::SPI, + start_addr: ariane_soc::SPIBase, + end_addr: ariane_soc::SPIBase + ariane_soc::SPILength + }, + '{ + idx: ariane_soc::Ethernet, + start_addr: ariane_soc::EthernetBase, + end_addr: ariane_soc::EthernetBase + ariane_soc::EthernetLength + }, + '{ + idx: ariane_soc::GPIO, + start_addr: ariane_soc::GPIOBase, + end_addr: ariane_soc::GPIOBase + ariane_soc::GPIOLength + }, + '{ + idx: ariane_soc::DRAM, + start_addr: ariane_soc::DRAMBase, + end_addr: ariane_soc::DRAMBase + ariane_soc::DRAMLength + } + }; localparam axi_pkg::xbar_cfg_t AXI_XBAR_CFG = '{ - NoSlvPorts: unsigned'(ariane_soc::NrSlaves), - NoMstPorts: unsigned'(ariane_soc::NB_PERIPHERALS), - MaxMstTrans: unsigned'(1), // Probably requires update - MaxSlvTrans: unsigned'(1), // Probably requires update - FallThrough: 1'b0, - LatencyMode: axi_pkg::NO_LATENCY, - AxiIdWidthSlvPorts: unsigned'(ariane_axi_soc::IdWidth), - AxiIdUsedSlvPorts: unsigned'(ariane_axi_soc::IdWidth), - UniqueIds: 1'b0, - AxiAddrWidth: unsigned'(AXI_ADDRESS_WIDTH), - AxiDataWidth: unsigned'(AXI_DATA_WIDTH), - NoAddrRules: unsigned'(ariane_soc::NB_PERIPHERALS) + NoSlvPorts: unsigned'(ariane_soc::NrSlaves), + NoMstPorts: unsigned'(ariane_soc::NB_PERIPHERALS), + MaxMstTrans: unsigned'(1), // Probably requires update + MaxSlvTrans: unsigned'(1), // Probably requires update + FallThrough: 1'b0, + LatencyMode: axi_pkg::NO_LATENCY, + AxiIdWidthSlvPorts: unsigned'(ariane_axi_soc::IdWidth), + AxiIdUsedSlvPorts: unsigned'(ariane_axi_soc::IdWidth), + UniqueIds: 1'b0, + AxiAddrWidth: unsigned'(AXI_ADDRESS_WIDTH), + AxiDataWidth: unsigned'(AXI_DATA_WIDTH), + NoAddrRules: unsigned'(ariane_soc::NB_PERIPHERALS) }; axi_xbar_intf #( - .AXI_USER_WIDTH ( AXI_USER_WIDTH ), - .Cfg ( AXI_XBAR_CFG ), - .rule_t ( axi_pkg::xbar_rule_64_t ) + .AXI_USER_WIDTH(AXI_USER_WIDTH), + .Cfg (AXI_XBAR_CFG), + .rule_t (axi_pkg::xbar_rule_64_t) ) i_axi_xbar ( - .clk_i ( clk_i ), - .rst_ni ( ndmreset_n ), - .test_i ( test_en ), - .slv_ports ( slave ), - .mst_ports ( master ), - .addr_map_i ( addr_map ), - .en_default_mst_port_i ( '0 ), - .default_mst_port_i ( '0 ) + .clk_i (clk_i), + .rst_ni (ndmreset_n), + .test_i (test_en), + .slv_ports (slave), + .mst_ports (master), + .addr_map_i (addr_map), + .en_default_mst_port_i('0), + .default_mst_port_i ('0) ); // --------------- @@ -544,26 +586,26 @@ module ariane_testharness #( logic ipi; logic timer_irq; - ariane_axi_soc::req_slv_t axi_clint_req; + ariane_axi_soc::req_slv_t axi_clint_req; ariane_axi_soc::resp_slv_t axi_clint_resp; clint #( - .CVA6Cfg ( CVA6Cfg ), - .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ), - .NR_CORES ( 1 ), - .axi_req_t ( ariane_axi_soc::req_slv_t ), - .axi_resp_t ( ariane_axi_soc::resp_slv_t ) + .CVA6Cfg (CVA6Cfg), + .AXI_ADDR_WIDTH(AXI_ADDRESS_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ID_WIDTH (ariane_axi_soc::IdWidthSlave), + .NR_CORES (1), + .axi_req_t (ariane_axi_soc::req_slv_t), + .axi_resp_t (ariane_axi_soc::resp_slv_t) ) i_clint ( - .clk_i ( clk_i ), - .rst_ni ( ndmreset_n ), - .testmode_i ( test_en ), - .axi_req_i ( axi_clint_req ), - .axi_resp_o ( axi_clint_resp ), - .rtc_i ( rtc_i ), - .timer_irq_o ( timer_irq ), - .ipi_o ( ipi ) + .clk_i (clk_i), + .rst_ni (ndmreset_n), + .testmode_i (test_en), + .axi_req_i (axi_clint_req), + .axi_resp_o (axi_clint_resp), + .rtc_i (rtc_i), + .timer_irq_o(timer_irq), + .ipi_o (ipi) ); `AXI_ASSIGN_TO_REQ(axi_clint_req, master[ariane_soc::CLINT]) @@ -576,46 +618,53 @@ module ariane_testharness #( logic [1:0] irqs; ariane_peripherals #( - .AxiAddrWidth ( AXI_ADDRESS_WIDTH ), - .AxiDataWidth ( AXI_DATA_WIDTH ), - .AxiIdWidth ( ariane_axi_soc::IdWidthSlave ), - .AxiUserWidth ( AXI_USER_WIDTH ), + .AxiAddrWidth(AXI_ADDRESS_WIDTH), + .AxiDataWidth(AXI_DATA_WIDTH), + .AxiIdWidth (ariane_axi_soc::IdWidthSlave), + .AxiUserWidth(AXI_USER_WIDTH), `ifndef VERILATOR - .InclUART ( 1'b1 ), + .InclUART (1'b1), `else - .InclUART ( 1'b0 ), + .InclUART (1'b0), `endif - .InclSPI ( 1'b0 ), - .InclEthernet ( 1'b0 ) + .InclSPI (1'b0), + .InclEthernet(1'b0) ) i_ariane_peripherals ( - .clk_i ( clk_i ), - .rst_ni ( ndmreset_n ), - .plic ( master[ariane_soc::PLIC] ), - .uart ( master[ariane_soc::UART] ), - .spi ( master[ariane_soc::SPI] ), - .ethernet ( master[ariane_soc::Ethernet] ), - .timer ( master[ariane_soc::Timer] ), - .irq_o ( irqs ), - .rx_i ( rx ), - .tx_o ( tx ), - .eth_txck ( ), - .eth_rxck ( ), - .eth_rxctl ( ), - .eth_rxd ( ), - .eth_rst_n ( ), - .eth_tx_en ( ), - .eth_txd ( ), - .phy_mdio ( ), - .eth_mdc ( ), - .mdio ( ), - .mdc ( ), - .spi_clk_o ( ), - .spi_mosi ( ), - .spi_miso ( ), - .spi_ss ( ) + .clk_i (clk_i), + .rst_ni (ndmreset_n), + .plic (master[ariane_soc::PLIC]), + .uart (master[ariane_soc::UART]), + .spi (master[ariane_soc::SPI]), + .ethernet (master[ariane_soc::Ethernet]), + .timer (master[ariane_soc::Timer]), + .irq_o (irqs), + .rx_i (rx), + .tx_o (tx), + .eth_txck (), + .eth_rxck (), + .eth_rxctl(), + .eth_rxd (), + .eth_rst_n(), + .eth_tx_en(), + .eth_txd (), + .phy_mdio (), + .eth_mdc (), + .mdio (), + .mdc (), + .spi_clk_o(), + .spi_mosi (), + .spi_miso (), + .spi_ss () ); - uart_bus #(.BAUD_RATE(115200), .PARITY_EN(0)) i_uart_bus (.rx(tx), .tx(rx), .rx_en(1'b1)); + uart_bus #( + .BAUD_RATE(115200), + .PARITY_EN(0) + ) i_uart_bus ( + .rx(tx), + .tx(rx), + .rx_en(1'b1) + ); // --------------- // Core @@ -627,29 +676,29 @@ module ariane_testharness #( rvfi_instr_t [CVA6Cfg.NrCommitPorts-1:0] rvfi_instr; ariane #( - .CVA6Cfg ( CVA6Cfg ), - .rvfi_probes_instr_t ( rvfi_probes_instr_t ), - .rvfi_probes_csr_t ( rvfi_probes_csr_t ), - .rvfi_probes_t ( rvfi_probes_t ), - .noc_req_t ( ariane_axi::req_t ), - .noc_resp_t ( ariane_axi::resp_t ) + .CVA6Cfg (CVA6Cfg), + .rvfi_probes_instr_t(rvfi_probes_instr_t), + .rvfi_probes_csr_t (rvfi_probes_csr_t), + .rvfi_probes_t (rvfi_probes_t), + .noc_req_t (ariane_axi::req_t), + .noc_resp_t (ariane_axi::resp_t) ) i_ariane ( - .clk_i ( clk_i ), - .rst_ni ( ndmreset_n ), - .boot_addr_i ( ariane_soc::ROMBase ), // start fetching from ROM - .hart_id_i ( {56'h0, hart_id} ), - .irq_i ( irqs ), - .ipi_i ( ipi ), - .time_irq_i ( timer_irq ), - .rvfi_probes_o ( rvfi_probes ), -// Disable Debug when simulating with Spike + .clk_i (clk_i), + .rst_ni (ndmreset_n), + .boot_addr_i (ariane_soc::ROMBase), // start fetching from ROM + .hart_id_i ({56'h0, hart_id}), + .irq_i (irqs), + .ipi_i (ipi), + .time_irq_i (timer_irq), + .rvfi_probes_o(rvfi_probes), + // Disable Debug when simulating with Spike `ifdef SPIKE_TANDEM - .debug_req_i ( 1'b0 ), + .debug_req_i (1'b0), `else - .debug_req_i ( debug_req_core ), + .debug_req_i (debug_req_core), `endif - .noc_req_o ( axi_ariane_req ), - .noc_resp_i ( axi_ariane_resp ) + .noc_req_o (axi_ariane_req), + .noc_resp_i (axi_ariane_resp) ); `AXI_ASSIGN_FROM_REQ(slave[0], axi_ariane_req) @@ -673,6 +722,44 @@ module ariane_testharness #( end + cva6_te_connector #( + .CVA6Cfg (CVA6Cfg), + .N(1), // max number of special inst in a cycle + .FIFO_DEPTH(16) // number of entries in each FIFO + ) i_cva6_te_connector ( + .clk_i (clk_i), + .rst_ni (ndmreset_n), + .valid_i(rvfi_probes.instr.commit_ack), // commit_ack in cva6 + + // necessary inputs from scoreboard_entry_t + .pc_i(rvfi_probes.instr.commit_instr_pc), //{cva6_tip_o.pc[1],cva6_tip_o.pc[0]} + .op_i(rvfi_probes.instr.commit_instr_op), + .is_compressed_i(rvfi_probes.instr.is_compressed), + + // necessary inputs from bp_resolve_t + .branch_valid_i(rvfi_probes.instr.branch_valid), + .is_taken_i(rvfi_probes.instr.is_taken), + + // necessary inputs from exception_t + .ex_valid_i(rvfi_probes.instr.ex_commit_valid), + .tval_i(rvfi_probes.instr.tval), + .cause_i(rvfi_probes.instr.ex_commit_cause), + .priv_lvl_i(rvfi_probes.instr.priv_lvl), + .time_i(rvfi_probes.csr.cycle_q), + + // outputs + /* the output of the module goes directly into the trace_encoder module */ + .valid_o(), + .iretire_o(), + .ilastsize_o(), + .itype_o(), + .cause_o(), + .tval_o(), + .priv_o(), + .iaddr_o(), + .time_o() + + ); cva6_rvfi #( .CVA6Cfg (CVA6Cfg), @@ -682,79 +769,76 @@ module ariane_testharness #( .rvfi_probes_csr_t(rvfi_probes_csr_t), .rvfi_probes_t(rvfi_probes_t) ) i_cva6_rvfi ( - .clk_i (clk_i), - .rst_ni (rst_ni), + .clk_i (clk_i), + .rst_ni (rst_ni), .rvfi_probes_i(rvfi_probes), - .rvfi_instr_o(rvfi_instr), - .rvfi_csr_o(rvfi_csr) + .rvfi_instr_o (rvfi_instr), + .rvfi_csr_o (rvfi_csr) ); - rvfi_tracer #( - .CVA6Cfg(CVA6Cfg), - .rvfi_instr_t(rvfi_instr_t), - .rvfi_csr_t(rvfi_csr_t), - // - .HART_ID(hart_id), - .DEBUG_START(0), - .DEBUG_STOP(0) + rvfi_tracer #( + .CVA6Cfg(CVA6Cfg), + .rvfi_instr_t(rvfi_instr_t), + .rvfi_csr_t(rvfi_csr_t), + // + .HART_ID(hart_id), + .DEBUG_START(0), + .DEBUG_STOP(0) ) i_rvfi_tracer ( - .clk_i(clk_i), - .rst_ni(rst_ni), - .rvfi_i(rvfi_instr), - .rvfi_csr_i(rvfi_csr), - .end_of_test_o(tracer_exit) + .clk_i(clk_i), + .rst_ni(rst_ni), + .rvfi_i(rvfi_instr), + .rvfi_csr_i(rvfi_csr), + .end_of_test_o(tracer_exit) ); `ifdef SPIKE_TANDEM - spike #( - .CVA6Cfg ( CVA6Cfg ), - .rvfi_instr_t(rvfi_instr_t), - .rvfi_csr_t(rvfi_csr_t) - ) i_spike ( - .clk_i, - .rst_ni, - .clint_tick_i ( rtc_i ), - .rvfi_i ( rvfi_instr ), - .rvfi_csr_i ( rvfi_csr ), - .end_of_test_o ( tandem_exit ) - ); - initial begin - $display("Running binary in tandem mode"); + spike #( + .CVA6Cfg(CVA6Cfg), + .rvfi_instr_t(rvfi_instr_t), + .rvfi_csr_t(rvfi_csr_t) + ) i_spike ( + .clk_i, + .rst_ni, + .clint_tick_i (rtc_i), + .rvfi_i (rvfi_instr), + .rvfi_csr_i (rvfi_csr), + .end_of_test_o(tandem_exit) + ); + initial begin + $display("Running binary in tandem mode"); + end + + bit tandem_timeout_enable; + bit [31:0] tandem_timeout; + localparam TANDEM_TIMEOUT_THRESHOLD = 60; + + // Tandem timeout logic + always_ff @(posedge clk_i) begin + if (tandem_timeout > TANDEM_TIMEOUT_THRESHOLD) tandem_timeout_enable <= 0; + else if (tracer_exit) tandem_timeout_enable <= 1; + + if (tandem_timeout_enable) tandem_timeout <= tandem_timeout + 1; + end + + always_ff @(posedge clk_i) begin + if (tandem_exit || (tandem_timeout > TANDEM_TIMEOUT_THRESHOLD)) begin + rvfi_exit <= tracer_exit; end - bit tandem_timeout_enable; - bit [31:0] tandem_timeout; - localparam TANDEM_TIMEOUT_THRESHOLD = 60; - - // Tandem timeout logic - always_ff @(posedge clk_i) begin - if(tandem_timeout > TANDEM_TIMEOUT_THRESHOLD) - tandem_timeout_enable <= 0; - else if (tracer_exit) - tandem_timeout_enable <= 1; - - if (tandem_timeout_enable) - tandem_timeout <= tandem_timeout + 1; - end - - always_ff @(posedge clk_i) begin - if (tandem_exit || (tandem_timeout > TANDEM_TIMEOUT_THRESHOLD)) begin - rvfi_exit <= tracer_exit; - end - - end + end `else - assign rvfi_exit = tracer_exit; + assign rvfi_exit = tracer_exit; `endif `ifdef VERILATOR - initial begin - string verbosity; - if ($value$plusargs("UVM_VERBOSITY=%s",verbosity)) begin - uvm_set_verbosity_level(verbosity); - `uvm_info("ariane_testharness", $sformatf("Set UVM_VERBOSITY to %s", verbosity), UVM_NONE) - end + initial begin + string verbosity; + if ($value$plusargs("UVM_VERBOSITY=%s", verbosity)) begin + uvm_set_verbosity_level(verbosity); + `uvm_info("ariane_testharness", $sformatf("Set UVM_VERBOSITY to %s", verbosity), UVM_NONE) end + end `endif @@ -762,65 +846,65 @@ module ariane_testharness #( // AXI 4 Assertion IP integration - You will need to get your own copy of this IP if you want // to use it Axi4PC #( - .DATA_WIDTH(ariane_axi_soc::DataWidth), - .WID_WIDTH(ariane_axi_soc::IdWidthSlave), - .RID_WIDTH(ariane_axi_soc::IdWidthSlave), - .AWUSER_WIDTH(ariane_axi_soc::UserWidth), - .WUSER_WIDTH(ariane_axi_soc::UserWidth), - .BUSER_WIDTH(ariane_axi_soc::UserWidth), - .ARUSER_WIDTH(ariane_axi_soc::UserWidth), - .RUSER_WIDTH(ariane_axi_soc::UserWidth), - .ADDR_WIDTH(ariane_axi_soc::AddrWidth) + .DATA_WIDTH(ariane_axi_soc::DataWidth), + .WID_WIDTH(ariane_axi_soc::IdWidthSlave), + .RID_WIDTH(ariane_axi_soc::IdWidthSlave), + .AWUSER_WIDTH(ariane_axi_soc::UserWidth), + .WUSER_WIDTH(ariane_axi_soc::UserWidth), + .BUSER_WIDTH(ariane_axi_soc::UserWidth), + .ARUSER_WIDTH(ariane_axi_soc::UserWidth), + .RUSER_WIDTH(ariane_axi_soc::UserWidth), + .ADDR_WIDTH(ariane_axi_soc::AddrWidth) ) i_Axi4PC ( - .ACLK(clk_i), - .ARESETn(ndmreset_n), - .AWID(dram.aw_id), - .AWADDR(dram.aw_addr), - .AWLEN(dram.aw_len), - .AWSIZE(dram.aw_size), - .AWBURST(dram.aw_burst), - .AWLOCK(dram.aw_lock), - .AWCACHE(dram.aw_cache), - .AWPROT(dram.aw_prot), - .AWQOS(dram.aw_qos), - .AWREGION(dram.aw_region), - .AWUSER(dram.aw_user), - .AWVALID(dram.aw_valid), - .AWREADY(dram.aw_ready), - .WLAST(dram.w_last), - .WDATA(dram.w_data), - .WSTRB(dram.w_strb), - .WUSER(dram.w_user), - .WVALID(dram.w_valid), - .WREADY(dram.w_ready), - .BID(dram.b_id), - .BRESP(dram.b_resp), - .BUSER(dram.b_user), - .BVALID(dram.b_valid), - .BREADY(dram.b_ready), - .ARID(dram.ar_id), - .ARADDR(dram.ar_addr), - .ARLEN(dram.ar_len), - .ARSIZE(dram.ar_size), - .ARBURST(dram.ar_burst), - .ARLOCK(dram.ar_lock), - .ARCACHE(dram.ar_cache), - .ARPROT(dram.ar_prot), - .ARQOS(dram.ar_qos), - .ARREGION(dram.ar_region), - .ARUSER(dram.ar_user), - .ARVALID(dram.ar_valid), - .ARREADY(dram.ar_ready), - .RID(dram.r_id), - .RLAST(dram.r_last), - .RDATA(dram.r_data), - .RRESP(dram.r_resp), - .RUSER(dram.r_user), - .RVALID(dram.r_valid), - .RREADY(dram.r_ready), - .CACTIVE('0), - .CSYSREQ('0), - .CSYSACK('0) + .ACLK(clk_i), + .ARESETn(ndmreset_n), + .AWID(dram.aw_id), + .AWADDR(dram.aw_addr), + .AWLEN(dram.aw_len), + .AWSIZE(dram.aw_size), + .AWBURST(dram.aw_burst), + .AWLOCK(dram.aw_lock), + .AWCACHE(dram.aw_cache), + .AWPROT(dram.aw_prot), + .AWQOS(dram.aw_qos), + .AWREGION(dram.aw_region), + .AWUSER(dram.aw_user), + .AWVALID(dram.aw_valid), + .AWREADY(dram.aw_ready), + .WLAST(dram.w_last), + .WDATA(dram.w_data), + .WSTRB(dram.w_strb), + .WUSER(dram.w_user), + .WVALID(dram.w_valid), + .WREADY(dram.w_ready), + .BID(dram.b_id), + .BRESP(dram.b_resp), + .BUSER(dram.b_user), + .BVALID(dram.b_valid), + .BREADY(dram.b_ready), + .ARID(dram.ar_id), + .ARADDR(dram.ar_addr), + .ARLEN(dram.ar_len), + .ARSIZE(dram.ar_size), + .ARBURST(dram.ar_burst), + .ARLOCK(dram.ar_lock), + .ARCACHE(dram.ar_cache), + .ARPROT(dram.ar_prot), + .ARQOS(dram.ar_qos), + .ARREGION(dram.ar_region), + .ARUSER(dram.ar_user), + .ARVALID(dram.ar_valid), + .ARREADY(dram.ar_ready), + .RID(dram.r_id), + .RLAST(dram.r_last), + .RDATA(dram.r_data), + .RRESP(dram.r_resp), + .RUSER(dram.r_user), + .RVALID(dram.r_valid), + .RREADY(dram.r_ready), + .CACTIVE('0), + .CSYSREQ('0), + .CSYSACK('0) ); `endif endmodule