diff --git a/core/Flist.cva6 b/core/Flist.cva6 index de27ed54d3a..47676de10d6 100644 --- a/core/Flist.cva6 +++ b/core/Flist.cva6 @@ -192,4 +192,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 + + +//For TIP +${CVA6_REPO_DIR}/core/cva6_tip.sv +${CVA6_REPO_DIR}/core/encoder_16_4.sv + // end of manifest diff --git a/core/cva6.sv b/core/cva6.sv index e63601d3cb4..53c32549c10 100644 --- a/core/cva6.sv +++ b/core/cva6.sv @@ -30,6 +30,20 @@ module cva6 rvfi_probes_instr_t instr; }, + + //TIP + parameter bit IsTIP = bit'(1), + + parameter type tip_instr_t = struct packed { + logic [config_pkg::NRET-1:0] iretire; + logic [config_pkg::NRET*riscv::XLEN-1:0] iaddr; //PC address + logic [config_pkg::NRET*riscv::XLEN-1:0] time_t; + logic [config_pkg::NRET*3-1:0] priv; + logic [config_pkg::NRET*riscv::XLEN-1:0] cause; + logic [config_pkg::NRET*riscv::XLEN-1:0] tval; + logic [config_pkg::NRET*(riscv::XLEN/2)-1:0] itype; + }, + // branchpredict scoreboard entry // this is the struct which we will inject into the pipeline to guide the various // units towards the correct branch decision and resolve @@ -293,6 +307,8 @@ module cva6 input logic debug_req_i, // Probes to build RVFI, can be left open when not used - RVFI output rvfi_probes_t rvfi_probes_o, + //TIP interface + output tip_instr_t [CVA6Cfg.NrCommitPorts-1:0] tip_o, // CVXIF request - SUBSYSTEM output cvxif_req_t cvxif_req_o, // CVXIF response - SUBSYSTEM @@ -1656,4 +1672,35 @@ module cva6 end //pragma translate_on + +if (IsTIP) begin + +//CVA6 Trace Ingress Port + cva6_tip #( + .CVA6Cfg (CVA6Cfg), + .exception_t (exception_t), + .scoreboard_entry_t (scoreboard_entry_t), + .rvfi_probes_csr_t (rvfi_probes_csr_t), + .bp_resolve_t(bp_resolve_t), + .tip_instr_t(tip_instr_t), + .rvfi_probes_instr_t(rvfi_probes_instr_t), + .rvfi_probes_t (rvfi_probes_t) + ) i_cva6_tip ( + .clk_i (clk_i), + .commit_instr_i(commit_instr_id_commit), + .ex_commit_i (ex_commit), + .priv_lvl_i (priv_lvl), + .commit_ack_i(commit_macro_ack), + .debug_mode_i(debug_mode), + .csr_i(rvfi_csr), + .eret_i (eret), + .ipi_i(ipi_i), + .debug_req_i(debug_req_i), + .resolved_branch_i (resolved_branch), + .rvfi_probes_i(rvfi_probes_o), + .tip_o(tip_o) + ); + +end + endmodule // ariane diff --git a/core/cva6_tip.sv b/core/cva6_tip.sv new file mode 100644 index 00000000000..d557c4d36c0 --- /dev/null +++ b/core/cva6_tip.sv @@ -0,0 +1,139 @@ +module cva6_tip + import ariane_pkg::*; +#( + parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, + parameter type exception_t = logic, + parameter type scoreboard_entry_t = logic, + parameter type rvfi_probes_csr_t = logic, + parameter type bp_resolve_t = logic, + parameter type rvfi_probes_instr_t = logic, + parameter type rvfi_probes_t = logic, + parameter type tip_instr_t = logic + +) ( + input logic clk_i, + input scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr_i, + input exception_t ex_commit_i, + input riscv::priv_lvl_t priv_lvl_i, + input logic [CVA6Cfg.NrCommitPorts-1:0] commit_ack_i, + input logic debug_mode_i, + input rvfi_probes_csr_t csr_i, + input logic eret_i, + input logic ipi_i, + input logic debug_req_i, // debug request (async) + input bp_resolve_t resolved_branch_i, + input rvfi_probes_t rvfi_probes_i, + output tip_instr_t [CVA6Cfg.NrCommitPorts-1:0] tip_o +); + + + +rvfi_probes_instr_t instr= rvfi_probes_i.instr; +logic debug_mode; + +logic [15:0] itype_signals[0:1]; +reg [3:0] itype_o[0:1]; + +riscv::priv_lvl_t priv_lvl; +//debug_mode +assign debug_mode = instr.debug_mode; +assign priv_lvl = instr.priv_lvl; + + +logic [63:0] taken_branch_pc_reg,not_taken_branch_pc_reg,uninforable_jump_pc_reg; + +// branch +always@(posedge clk_i) begin +if(resolved_branch_i.cf_type == Branch && resolved_branch_i.is_taken == 1) begin + taken_branch_pc_reg <= resolved_branch_i.pc;// taken branch +end +else if(resolved_branch_i.cf_type == Branch && resolved_branch_i.is_taken == 0)begin + not_taken_branch_pc_reg <= resolved_branch_i.pc; //not taken branch +end +else if(resolved_branch_i.cf_type == JumpR)begin + uninforable_jump_pc_reg <= resolved_branch_i.pc; //JumpR +end +end + + +// itype signals encoding +generate + for (genvar i = 0; i < cva6_config_pkg::CVA6ConfigNrCommitPorts; i++) begin + assign itype_signals [i][1] = commit_instr_i[i].valid && ex_commit_i.valid; + assign itype_signals [i][2] = ( ipi_i || debug_req_i ); //time_irq_i (commit_ack_i[0] && !ex_commit_i.valid) && + assign itype_signals [i][3] = eret_i; + assign itype_signals [i][4] = ((not_taken_branch_pc_reg == commit_instr_i[i].pc) && ~(commit_instr_i[i].pc == 0)); + assign itype_signals [i][5] = ( (taken_branch_pc_reg == commit_instr_i[i].pc) && ~(commit_instr_i[i].pc == 0)); + assign itype_signals [i][6] = ( (uninforable_jump_pc_reg == commit_instr_i[i].pc) && ~(commit_instr_i[i].pc == 0)); + end +endgenerate + +generate + for (genvar i = 0; i < cva6_config_pkg::CVA6ConfigNrCommitPorts; i++) begin + + encoder_16_4 ec_0(.in(itype_signals[i]),.out(itype_o[i]),.valid()); + + end +endgenerate + + + + +//TIP signals +always_comb begin + for (int i = 0; i < cva6_config_pkg::CVA6ConfigNrCommitPorts; i++) begin + logic exception, mem_exception; + exception = commit_instr_i[i].valid && ex_commit_i.valid; + mem_exception = exception && + (ex_commit_i.cause == riscv::INSTR_ADDR_MISALIGNED || + ex_commit_i.cause == riscv::INSTR_ACCESS_FAULT || + ex_commit_i.cause == riscv::ILLEGAL_INSTR || + ex_commit_i.cause == riscv::LD_ADDR_MISALIGNED || + ex_commit_i.cause == riscv::LD_ACCESS_FAULT || + ex_commit_i.cause == riscv::ST_ADDR_MISALIGNED || + ex_commit_i.cause == riscv::ST_ACCESS_FAULT || + ex_commit_i.cause == riscv::INSTR_PAGE_FAULT || + ex_commit_i.cause == riscv::LOAD_PAGE_FAULT || + ex_commit_i.cause == riscv::STORE_PAGE_FAULT); + tip_o[i].iretire = (commit_ack_i[i] && !ex_commit_i.valid) || + (exception && (ex_commit_i.cause == riscv::ENV_CALL_MMODE || + ex_commit_i.cause == riscv::ENV_CALL_SMODE || + ex_commit_i.cause == riscv::ENV_CALL_UMODE)); + tip_o[i].iaddr = commit_instr_i[i].pc; + tip_o[i].time_t = csr_i.cycle_q; + tip_o[i].priv = (((CVA6Cfg.DebugEn && debug_mode) ? 2'b10 : priv_lvl) == 2'b10) ? 2'b01:((CVA6Cfg.DebugEn && debug_mode) ? 2'b10 : priv_lvl) ;//(CVA6Cfg.DebugEn && debug_mode) ? 2'b10 : priv_lvl;//debug_mode_i ? 3'b100 : priv_lvl_i; + tip_o[i].cause = ex_commit_i.cause; + tip_o[i].tval = csr_i.mtval_q; + tip_o[i].itype = itype_o[i]; + + end +end + + + +//*************************** TIP Signal dumping **************************// + +// int fd = $fopen("./tip_port_0_signals_dump.txt", "w"); +// int fj = $fopen("./tip_port_1_signals_dump.txt", "w"); + +// always@(tip_o[0].iretire == 1) begin + +// if (fd) begin +// $fwrite(fd, "tip_o_[0].iretire= 0x%h, tip_o_[0].iaddr= 0x%h, tip_o_[0].time_t= 0x%h, tip_o_[0].priv= 0x%h, tip_o_[0].cause= 0x%h, tip_o_[0].tval= 0x%h, tip_o_[0].itype= %h\n", tip_o[0].iretire, tip_o[0].iaddr,tip_o[0].time_t, tip_o[0].priv, tip_o[0].cause, tip_o[0].tval, tip_o[0].itype ); +// end else begin +// $display("Error opening the file."); +// end +// end + +// always@(tip_o[1].iretire == 1) begin + +// if (fj) begin +// $fwrite(fj, "tip_o_[1].iretire= 0x%h, tip_o_[1].iaddr= 0x%h, tip_o_[1].time_t= 0x%h, tip_o_[1].priv= 0x%h, tip_o_[1].cause= 0x%h, tip_o_[1].tval= 0x%h, tip_o_[1].itype= %h\n", tip_o[1].iretire, tip_o[1].iaddr,tip_o[1].time_t, tip_o[1].priv, tip_o[1].cause, tip_o[1].tval, tip_o[1].itype ); +// end else begin +// $display("Error opening the file."); +// end +// end + + + +endmodule \ No newline at end of file diff --git a/core/encoder_16_4.sv b/core/encoder_16_4.sv new file mode 100644 index 00000000000..437824cabad --- /dev/null +++ b/core/encoder_16_4.sv @@ -0,0 +1,65 @@ +module encoder_16_4 ( + input logic [15:0] in, // 16-bit input + output logic [3:0] out, // 4-bit output + output logic valid // Indicates if there is any active input +); + + always_comb begin + // Initialize output and valid signal + out = 4'b0000; + valid = 1'b0; + + // Priority encoding (highest priority at the highest bit) + if (in[15]) begin + out = 4'b1111; + valid = 1'b1; + end else if (in[14]) begin + out = 4'b1110; + valid = 1'b1; + end else if (in[13]) begin + out = 4'b1101; + valid = 1'b1; + end else if (in[12]) begin + out = 4'b1100; + valid = 1'b1; + end else if (in[11]) begin + out = 4'b1011; + valid = 1'b1; + end else if (in[10]) begin + out = 4'b1010; + valid = 1'b1; + end else if (in[9]) begin + out = 4'b1001; + valid = 1'b1; + end else if (in[8]) begin + out = 4'b1000; + valid = 1'b1; + end else if (in[7]) begin + out = 4'b0111; + valid = 1'b1; + end else if (in[6]) begin + out = 4'b0110; + valid = 1'b1; + end else if (in[5]) begin + out = 4'b0101; + valid = 1'b1; + end else if (in[4]) begin + out = 4'b0100; + valid = 1'b1; + end else if (in[3]) begin + out = 4'b0011; + valid = 1'b1; + end else if (in[2]) begin + out = 4'b0010; + valid = 1'b1; + end else if (in[1]) begin + out = 4'b0001; + valid = 1'b1; + end else if (in[0]) begin + out = 4'b0000; + valid = 1'b1; + end else begin + valid = 1'b0; // No active input + end + end +endmodule diff --git a/corev_apu/src/ariane.sv b/corev_apu/src/ariane.sv index 38b3281bb9c..c009ce70cf6 100644 --- a/corev_apu/src/ariane.sv +++ b/corev_apu/src/ariane.sv @@ -21,6 +21,7 @@ module ariane import ariane_pkg::*; #( logic csr; logic instr; }, + parameter type tip_instr_t = logic, parameter int unsigned AxiAddrWidth = ariane_axi::AddrWidth, parameter int unsigned AxiDataWidth = ariane_axi::DataWidth, parameter int unsigned AxiIdWidth = ariane_axi::IdWidth, @@ -45,6 +46,10 @@ module ariane import ariane_pkg::*; #( // RISC-V formal interface port (`rvfi`): // Can be left open when formal tracing is not needed. output rvfi_probes_t rvfi_probes_o, + + //Tracing port: TIP + output tip_instr_t [CVA6Cfg.NrCommitPorts-1:0] tip_o, + // memory side output noc_req_t noc_req_o, input noc_resp_t noc_resp_i @@ -76,7 +81,8 @@ module ariane import ariane_pkg::*; #( .cvxif_req_o ( cvxif_req ), .cvxif_resp_i ( cvxif_resp ), .noc_req_o ( noc_req_o ), - .noc_resp_i ( noc_resp_i ) + .noc_resp_i ( noc_resp_i ), + .tip_o (tip_o ) ); if (CVA6Cfg.CvxifEn) begin : gen_example_coprocessor diff --git a/corev_apu/tb/ariane_testharness.sv b/corev_apu/tb/ariane_testharness.sv index 336def732ee..261a5043d03 100644 --- a/corev_apu/tb/ariane_testharness.sv +++ b/corev_apu/tb/ariane_testharness.sv @@ -55,6 +55,17 @@ module ariane_testharness #( rvfi_probes_instr_t instr; }; + //TIP parameter + parameter type tip_instr_t = struct packed { + logic [config_pkg::NRET-1:0] iretire; + logic [config_pkg::NRET*riscv::XLEN-1:0] iaddr; //PC address + logic [config_pkg::NRET*riscv::XLEN-1:0] time_t; + logic [config_pkg::NRET*3-1:0] priv; + logic [config_pkg::NRET*riscv::XLEN-1:0] cause; + logic [config_pkg::NRET*riscv::XLEN-1:0] tval; + logic [config_pkg::NRET*(riscv::XLEN/2)-1:0] itype; + }; + // disable test-enable logic test_en; logic ndmreset; @@ -625,6 +636,7 @@ module ariane_testharness #( rvfi_probes_t rvfi_probes; rvfi_csr_t rvfi_csr; rvfi_instr_t [CVA6Cfg.NrCommitPorts-1:0] rvfi_instr; + tip_instr_t [CVA6Cfg.NrCommitPorts-1:0] tip_out; ariane #( .CVA6Cfg ( CVA6Cfg ), @@ -632,7 +644,8 @@ module ariane_testharness #( .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 ) + .noc_resp_t ( ariane_axi::resp_t ), + .tip_instr_t ( tip_instr_t ) ) i_ariane ( .clk_i ( clk_i ), .rst_ni ( ndmreset_n ), @@ -649,7 +662,8 @@ module ariane_testharness #( .debug_req_i ( debug_req_core ), `endif .noc_req_o ( axi_ariane_req ), - .noc_resp_i ( axi_ariane_resp ) + .noc_resp_i ( axi_ariane_resp ), + .tip_o ( tip_out ) ); `AXI_ASSIGN_FROM_REQ(slave[0], axi_ariane_req) @@ -823,4 +837,7 @@ module ariane_testharness #( .CSYSACK('0) ); `endif + + + endmodule