diff --git a/hw/vendor/esl_epfl_cv32e40px.lock.hjson b/hw/vendor/esl_epfl_cv32e40px.lock.hjson index 2871b8ed4..e307c5ae8 100644 --- a/hw/vendor/esl_epfl_cv32e40px.lock.hjson +++ b/hw/vendor/esl_epfl_cv32e40px.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/esl-epfl/cv32e40px.git - rev: 15b9dd6077513342cf44e6853a5fc33098f2e73b + rev: 10b08065c50d44b5355c1535cb8f740e68e4f106 } } diff --git a/hw/vendor/esl_epfl_cv32e40px.vendor.hjson b/hw/vendor/esl_epfl_cv32e40px.vendor.hjson index d0e289ae0..4fc67fa65 100644 --- a/hw/vendor/esl_epfl_cv32e40px.vendor.hjson +++ b/hw/vendor/esl_epfl_cv32e40px.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/esl-epfl/cv32e40px.git", - rev: "15b9dd6077513342cf44e6853a5fc33098f2e73b", + rev: "10b08065c50d44b5355c1535cb8f740e68e4f106", }, exclude_from_upstream: [ diff --git a/hw/vendor/esl_epfl_cv32e40px/README.md b/hw/vendor/esl_epfl_cv32e40px/README.md index 0b23f8412..2272b6807 100644 --- a/hw/vendor/esl_epfl_cv32e40px/README.md +++ b/hw/vendor/esl_epfl_cv32e40px/README.md @@ -1,8 +1,8 @@ [![Build Status](https://travis-ci.com/pulp-platform/riscv.svg?branch=master)](https://travis-ci.com/pulp-platform/riscv) -# OpenHW Group CORE-V CV32E40P RISC-V IP +# OpenHW Group CORE-V CV32E40PX RISC-V IP -CV32E40P is a small and efficient, 32-bit, in-order RISC-V core with a 4-stage pipeline that implements +CV32E40PX is a small and efficient, 32-bit, in-order RISC-V core with a 4-stage pipeline that implements the RV32IM\[F|Zfinx\]C instruction set architecture, and the PULP custom extensions for achieving higher code density, performance, and energy efficiency \[[1](https://doi.org/10.1109/TVLSI.2017.2654506)\], \[[2](https://doi.org/10.1109/PATMOS.2017.8106976)\]. It started its life as a fork of the OR10N CPU core that is based on the OpenRISC ISA. @@ -14,12 +14,12 @@ when it has been contributed to [OpenHW Group](https://www.openhwgroup.org/). ## Documentation -The CV32E40P user manual can be found in the _docs_ folder and it is +The CV32E40PX user manual can be found in the _docs_ folder and it is captured in reStructuredText, rendered to html using [Sphinx](https://docs.readthedocs.io/en/stable/intro/getting-started-with-sphinx.html). These documents are viewable using readthedocs and can be viewed [here](https://docs.openhwgroup.org/projects/cv32e40p-user-manual/). ## Verification -The verification environment for the CV32E40P is _not_ in this Repository. There is a small, simple testbench here which is +The verification environment for the CV32E40PX is _not_ in this Repository. There is a small, simple testbench here which is useful for experimentation only and should not be used to validate any changes to the RTL prior to pushing to the master branch of this repo. @@ -31,7 +31,7 @@ The Makefiles supported in the **core-v-verif** project automatically clone the ## Changelog A changelog is generated automatically in the documentation from the individual pull requests. -In order to enable automatic changelog generation within the CV32E40P documentation, the committer is required to label each pull request +In order to enable automatic changelog generation within the CV32E40PX documentation, the committer is required to label each pull request that touches any file in 'rtl' (or any of its subdirectories) with *Component:RTL* and label each pull request that touches any file in 'docs' (or any of its subdirectories) with *Component:Doc*. Pull requests that are not labeled or labeled with *ignore-for-release* are ignored for the changelog generation. @@ -40,7 +40,7 @@ Only the person who actually performs the merge can add these labels (you need c 1 label is applied and therefore pull requests that touches both RTL and documentation files in the same pull request are not allowed. ## Constraints -Example synthesis constraints for the CV32E40P are provided. +Example synthesis constraints for the CV32E40PX are provided. ## Contributing @@ -71,7 +71,7 @@ Run `./util/format-verible` to format all the files. ## Issues and Troubleshooting -If you find any problems or issues with CV32E40P or the documentation, please check out the [issue +If you find any problems or issues with CV32E40PX or the documentation, please check out the [issue tracker](https://github.com/openhwgroup/cv32e40p/issues) and create a new issue if your problem is not yet tracked. diff --git a/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv b/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv index e9807a381..19e210670 100644 --- a/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv +++ b/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv @@ -110,6 +110,10 @@ module cv32e40px_controller import cv32e40px_pkg::*; output logic apu_stall_o, + // X-IF signals + output logic x_branch_or_async_taken_o, + output logic x_control_illegal_reset_o, + // jump/branch signals input logic branch_taken_ex_i, // branch taken signal from EX ALU input logic [1:0] ctrl_transfer_insn_in_id_i, // jump is being calculated in ALU @@ -240,7 +244,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; logic debug_req_q; logic debug_req_pending; - // qualify wfi vs nosleep locally + // qualify wfi vs nosleep locally logic wfi_active; @@ -327,6 +331,9 @@ module cv32e40px_controller import cv32e40px_pkg::*; // ensures that the target is kept constant even if pc_id is no more HWLP_END hwlp_targ_addr_o = ((hwlp_start1_leq_pc && hwlp_end1_geq_pc) && !(hwlp_start0_leq_pc && hwlp_end0_geq_pc)) ? hwlp_start_addr_i[1] : hwlp_start_addr_i[0]; + x_branch_or_async_taken_o = 1'b0; + x_control_illegal_reset_o = 1'b0; + unique case (ctrl_fsm_cs) // We were just reset, wait for fetch_enable RESET: @@ -438,6 +445,8 @@ module cv32e40px_controller import cv32e40px_pkg::*; pc_mux_o = PC_BRANCH; pc_set_o = 1'b1; + x_branch_or_async_taken_o = 1'b1; + // if we want to debug, flush the pipeline // the current_pc_if will take the value of the next instruction to // be executed (NPC) @@ -496,6 +505,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; debug_req_entry_n = 1'b1; + x_branch_or_async_taken_o = 1'b1; end else if (irq_req_ctrl_i && ~debug_mode_q) begin @@ -511,6 +521,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; exc_pc_mux_o = EXC_PC_IRQ; exc_cause_o = irq_id_ctrl_i; csr_irq_sec_o = irq_sec_ctrl_i; + x_branch_or_async_taken_o = 1'b1; // IRQ interface irq_ack_o = 1'b1; @@ -534,6 +545,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; halt_id_o = 1'b0; ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; illegal_insn_n = 1'b1; + x_control_illegal_reset_o = 1'b1; end else begin @@ -679,6 +691,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; illegal_insn_i | ecall_insn_i: begin ctrl_fsm_ns = FLUSH_EX; + x_control_illegal_reset_o = illegal_insn_i; end (~ebrk_force_debug_mode & ebrk_insn_i): @@ -728,6 +741,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; debug_req_entry_n = 1'b1; + x_branch_or_async_taken_o = 1'b1; end else if (irq_req_ctrl_i && ~debug_mode_q) begin @@ -743,6 +757,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; exc_pc_mux_o = EXC_PC_IRQ; exc_cause_o = irq_id_ctrl_i; csr_irq_sec_o = irq_sec_ctrl_i; + x_branch_or_async_taken_o = 1'b1; // IRQ interface irq_ack_o = 1'b1; @@ -768,6 +783,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; halt_id_o = 1'b1; ctrl_fsm_ns = FLUSH_EX; illegal_insn_n = 1'b1; + x_control_illegal_reset_o = 1'b1; end else begin @@ -865,6 +881,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; illegal_insn_i | ecall_insn_i: begin ctrl_fsm_ns = FLUSH_EX; + x_control_illegal_reset_o = illegal_insn_i; end (~ebrk_force_debug_mode & ebrk_insn_i): @@ -1207,7 +1224,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; exc_pc_mux_o = EXC_PC_DBD; csr_save_cause_o = 1'b1; debug_csr_save_o = 1'b1; - if (debug_force_wakeup_q) + if (debug_force_wakeup_q) debug_cause_o = DBG_CAUSE_HALTREQ; else if (debug_single_step_i) debug_cause_o = DBG_CAUSE_STEP; // pri 0 @@ -1479,7 +1496,7 @@ endgenerate assign debug_wfi_no_sleep_o = debug_mode_q || debug_req_pending || debug_single_step_i || trigger_match_i || COREV_CLUSTER; - // Gate off wfi + // Gate off wfi assign wfi_active = wfi_i & ~debug_wfi_no_sleep_o; // sticky version of debug_req (must be on clk_ungated_i such that incoming pulse before core is enabled is not missed) @@ -1600,7 +1617,7 @@ endgenerate // Ensure DBG_TAKEN_IF can only be enterred if in single step mode or woken // up from sleep by debug_req_i - + a_single_step_dbg_taken_if : assert property (@(posedge clk) disable iff (!rst_n) (ctrl_fsm_ns==DBG_TAKEN_IF) |-> ((~debug_mode_q && debug_single_step_i) || debug_force_wakeup_n)); // Ensure DBG_FLUSH state is only one cycle. This implies that cause is either trigger, debug_req_entry, or ebreak diff --git a/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv b/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv index 9f1f668b5..883b5ff1c 100644 --- a/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv +++ b/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv @@ -436,6 +436,8 @@ module cv32e40px_id_stage // X-Interface logic illegal_insn; logic x_illegal_insn; + logic x_branch_or_async_taken; + logic x_control_illegal_reset; logic [4:0] waddr_id; logic [4:0] waddr_ex; logic [4:0] waddr_wb; @@ -1124,7 +1126,7 @@ module cv32e40px_id_stage .mem_instr_waddr_ex_i(regfile_waddr_ex_o[4:0]), .mem_instr_we_ex_i (regfile_we_ex_o), .regs_used_i (regs_used), - .branch_or_jump_i (pc_set_o), + .branch_or_jump_i (x_branch_or_async_taken), .instr_valid_i (instr_valid_i), .x_rs_addr_i (x_rs_addr), .x_ex_fwd_o (x_ex_fwd), @@ -1136,14 +1138,15 @@ module cv32e40px_id_stage .wb_ready_i (wb_ready_i), // additional status signals - .x_stall_o (x_stall), - .x_illegal_insn_o (x_illegal_insn), - .x_illegal_insn_dec_i(illegal_insn_dec), - .id_ready_i (id_ready_o), - .ex_valid_i (ex_valid_i), - .ex_ready_i (ex_ready_i), - .current_priv_lvl_i (current_priv_lvl_i), - .data_req_dec_i (data_req_id) + .x_stall_o (x_stall), + .x_illegal_insn_o (x_illegal_insn), + .x_illegal_insn_dec_i (illegal_insn_dec), + .x_control_illegal_reset_i(x_control_illegal_reset), + .id_ready_i (id_ready_o), + .ex_valid_i (ex_valid_i), + .ex_ready_i (ex_ready_i), + .current_priv_lvl_i (current_priv_lvl_i), + .data_req_dec_i (data_req_id) ); @@ -1445,6 +1448,8 @@ module cv32e40px_id_stage .apu_write_dep_i (apu_write_dep_i), .apu_stall_o(apu_stall), + .x_branch_or_async_taken_o(x_branch_or_async_taken), + .x_control_illegal_reset_o(x_control_illegal_reset), // jump/branch control .branch_taken_ex_i (branch_taken_ex), diff --git a/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv b/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv index dc8907979..f326b3f90 100644 --- a/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv +++ b/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv @@ -90,6 +90,7 @@ module cv32e40px_x_disp output logic x_stall_o, output logic x_illegal_insn_o, input logic x_illegal_insn_dec_i, + input logic x_control_illegal_reset_i, input logic id_ready_i, input logic ex_valid_i, input logic ex_ready_i, @@ -108,6 +109,7 @@ module cv32e40px_x_disp logic x_if_memory_instr; logic illegal_forwarding_prevention; logic x_issue_illegal; + logic x_illegal_insn_q, x_illegal_insn_n; // issue interface assign x_issue_valid_o = x_illegal_insn_dec_i & ~branch_or_jump_i & ~instr_offloaded_q & instr_valid_i & ~illegal_forwarding_prevention; @@ -182,7 +184,7 @@ module cv32e40px_x_disp assign x_wb_fwd_o[3] = (x_rs_addr_i[0] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[0]; assign x_wb_fwd_o[4] = (x_rs_addr_i[1] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[1]; assign x_wb_fwd_o[5] = (x_rs_addr_i[2] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[2]; - assign dep = ~x_illegal_insn_o & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) + assign dep = ~x_illegal_insn_n & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) | (regs_used_i[1] & scoreboard_q[x_rs_addr_i[1]] & (x_result_rd_i != x_rs_addr_i[1])) | (regs_used_i[2] & scoreboard_q[x_rs_addr_i[2]] & (x_result_rd_i != x_rs_addr_i[2])) | (((regs_used_i[0] & x_issue_resp_dualread_i[0]) & scoreboard_q[x_rs_addr_i[0] | 5'b00001] & (x_result_rd_i != (x_rs_addr_i[0] | 5'b00001))) & x_issue_resp_dualread_i[0]) @@ -195,7 +197,7 @@ module cv32e40px_x_disp assign x_wb_fwd_o[0] = x_rs_addr_i[0] == waddr_wb_i & we_wb_i & ex_valid_i; assign x_wb_fwd_o[1] = x_rs_addr_i[1] == waddr_wb_i & we_wb_i & ex_valid_i; assign x_wb_fwd_o[2] = x_rs_addr_i[2] == waddr_wb_i & we_wb_i & ex_valid_i; - assign dep = ~x_illegal_insn_o & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) + assign dep = ~x_illegal_insn_n & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) | (regs_used_i[1] & scoreboard_q[x_rs_addr_i[1]] & (x_result_rd_i != x_rs_addr_i[1])) | (regs_used_i[2] & scoreboard_q[x_rs_addr_i[2]] & (x_result_rd_i != x_rs_addr_i[2]))); end @@ -247,11 +249,12 @@ module cv32e40px_x_disp // illegal instruction assignment assign x_issue_illegal = x_illegal_insn_dec_i & ~instr_offloaded_q & instr_valid_i; always_comb begin - x_illegal_insn_o = 1'b0; + x_illegal_insn_n = 1'b0; if (x_issue_illegal & x_issue_ready_i & ~x_issue_resp_accept_i) begin - x_illegal_insn_o = 1'b1; + x_illegal_insn_n = 1'b1; end end + assign x_illegal_insn_o = x_illegal_insn_q; // scoreboard and status signal register always_ff @(posedge clk_i or negedge rst_ni) begin @@ -260,11 +263,17 @@ module cv32e40px_x_disp instr_offloaded_q <= 1'b0; id_q <= '0; mem_counter_q <= '0; + x_illegal_insn_q <= 1'b0; end else begin scoreboard_q <= scoreboard_d; instr_offloaded_q <= instr_offloaded_d; id_q <= id_d; mem_counter_q <= mem_counter_d; + if (x_control_illegal_reset_i) begin + x_illegal_insn_q <= 1'b0; + end else begin + x_illegal_insn_q <= x_illegal_insn_n; + end end end