diff --git a/doc/宣传彩页/VLSI前端开发工具集成化平台宣传彩页.png b/doc/宣传彩页/VLSI前端开发工具集成化平台宣传彩页.png new file mode 100644 index 0000000..98613aa Binary files /dev/null and b/doc/宣传彩页/VLSI前端开发工具集成化平台宣传彩页.png differ diff --git a/doc/宣传彩页/VLSI前端开发工具集成化平台宣传彩页2.png b/doc/宣传彩页/VLSI前端开发工具集成化平台宣传彩页2.png new file mode 100644 index 0000000..d953821 Binary files /dev/null and b/doc/宣传彩页/VLSI前端开发工具集成化平台宣传彩页2.png differ diff --git a/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台构思与描述.docx b/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台构思与描述.docx new file mode 100644 index 0000000..1b0ff11 Binary files /dev/null and b/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台构思与描述.docx differ diff --git a/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台构思与描述缺现有资料.docx b/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台构思与描述缺现有资料.docx deleted file mode 100644 index 1a34056..0000000 Binary files a/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台构思与描述缺现有资料.docx and /dev/null differ diff --git a/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台软件需求规格说明书缺现有资料.docx b/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台软件需求规格说明书.docx similarity index 58% rename from doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台软件需求规格说明书缺现有资料.docx rename to doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台软件需求规格说明书.docx index 238a14f..b2a900a 100644 Binary files a/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台软件需求规格说明书缺现有资料.docx and b/doc/平台构思与需求规格说明书/VLSI前端开发工具集成化平台软件需求规格说明书.docx differ diff --git a/doc/平台设计规格说明书/VLSI前端开发工具集成化平台-软件设计规格说明书需完善(6月20日).doc b/doc/平台设计规格说明书/VLSI前端开发工具集成化平台-软件设计规格说明书.doc similarity index 66% rename from doc/平台设计规格说明书/VLSI前端开发工具集成化平台-软件设计规格说明书需完善(6月20日).doc rename to doc/平台设计规格说明书/VLSI前端开发工具集成化平台-软件设计规格说明书.doc index 00358c4..8a8daa2 100644 Binary files a/doc/平台设计规格说明书/VLSI前端开发工具集成化平台-软件设计规格说明书需完善(6月20日).doc and b/doc/平台设计规格说明书/VLSI前端开发工具集成化平台-软件设计规格说明书.doc differ diff --git a/doc/演示视频/VLSI前端开发工具集成化平台演示视频.mp4 b/doc/演示视频/VLSI前端开发工具集成化平台演示视频.mp4 new file mode 100644 index 0000000..3f7ede9 Binary files /dev/null and b/doc/演示视频/VLSI前端开发工具集成化平台演示视频.mp4 differ diff --git a/doc/自评表/实践资源-软件开发项目的个人自评报告.xlsx b/doc/自评表/实践资源-软件开发项目的个人自评报告.xlsx new file mode 100644 index 0000000..90b4983 Binary files /dev/null and b/doc/自评表/实践资源-软件开发项目的个人自评报告.xlsx differ diff --git a/doc/自评表/实践资源-软件开发项目的团队自评报告.xlsx b/doc/自评表/实践资源-软件开发项目的团队自评报告.xlsx new file mode 100644 index 0000000..d468d24 Binary files /dev/null and b/doc/自评表/实践资源-软件开发项目的团队自评报告.xlsx differ diff --git a/doc/集成电路平台开发汇报2023年6月3日第二次验收汇报定稿.pptx b/doc/集成电路平台开发汇报2023年6月3日第二次验收汇报定稿.pptx deleted file mode 100644 index b2e8a92..0000000 Binary files a/doc/集成电路平台开发汇报2023年6月3日第二次验收汇报定稿.pptx and /dev/null differ diff --git a/doc/验收汇报PPT/VLSI前端开发工具集成化平台验收汇报.pptx b/doc/验收汇报PPT/VLSI前端开发工具集成化平台验收汇报.pptx new file mode 100644 index 0000000..a00df3b Binary files /dev/null and b/doc/验收汇报PPT/VLSI前端开发工具集成化平台验收汇报.pptx differ diff --git a/model/VLSI前端开发工具集成化平台软件需求模型(6月20日).vsdx b/model/VLSI前端开发工具集成化平台软件需求模型(6月20日).vsdx deleted file mode 100644 index b397017..0000000 Binary files a/model/VLSI前端开发工具集成化平台软件需求模型(6月20日).vsdx and /dev/null differ diff --git a/src/UWE_projectCode/RTL分析代码/cv32e40p_controller.sv b/src/UWE_projectCode/RTL分析代码/cv32e40p_controller.sv deleted file mode 100644 index 4c3295c..0000000 --- a/src/UWE_projectCode/RTL分析代码/cv32e40p_controller.sv +++ /dev/null @@ -1,1589 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this 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. - -//////////////////////////////////////////////////////////////////////////////// -// Engineer: Matthias Baer - baermatt@student.ethz.ch // -// // -// Additional contributions by: // -// Igor Loi - igor.loi@unibo.it // -// Andreas Traber - atraber@student.ethz.ch // -// Sven Stucki - svstucki@student.ethz.ch // -// Michael Gautschi - gautschi@iis.ee.ethz.ch // -// Davide Schiavone - pschiavo@iis.ee.ethz.ch // -// Robert Balas - balasr@iis.ee.ethz.ch // -// Andrea Bettati - andrea.bettati@studenti.unipr.it // -// // -// Design Name: Main controller // -// Project Name: RI5CY // -// Language: SystemVerilog // -// // -// Description: Main CPU controller of the processor // -// // -//////////////////////////////////////////////////////////////////////////////// - -module cv32e40p_controller import cv32e40p_pkg::*; -#( - parameter PULP_CLUSTER = 0, - parameter PULP_XPULP = 1 -) -( - input logic clk, // Gated clock - input logic clk_ungated_i, // Ungated clock - input logic rst_n, - - input logic fetch_enable_i, // Start the decoding - output logic ctrl_busy_o, // Core is busy processing instructions - output logic is_decoding_o, // Core is in decoding state - input logic is_fetch_failed_i, - - // decoder related signals - output logic deassert_we_o, // deassert write enable for next instruction - - input logic illegal_insn_i, // decoder encountered an invalid instruction - input logic ecall_insn_i, // decoder encountered an ecall instruction - input logic mret_insn_i, // decoder encountered an mret instruction - input logic uret_insn_i, // decoder encountered an uret instruction - - input logic dret_insn_i, // decoder encountered an dret instruction - - input logic mret_dec_i, - input logic uret_dec_i, - input logic dret_dec_i, - - input logic wfi_i, // decoder wants to execute a WFI - input logic ebrk_insn_i, // decoder encountered an ebreak instruction - input logic fencei_insn_i, // decoder encountered an fence.i instruction - input logic csr_status_i, // decoder encountered an csr status instruction - - output logic hwlp_mask_o, // prevent writes on the hwloop instructions in case interrupt are taken - - // from IF/ID pipeline - input logic instr_valid_i, // instruction coming from IF/ID pipeline is valid - - // from prefetcher - output logic instr_req_o, // Start fetching instructions - - // to prefetcher - output logic pc_set_o, // jump to address set by pc_mux - output logic [3:0] pc_mux_o, // Selector in the Fetch stage to select the rigth PC (normal, jump ...) - output logic [2:0] exc_pc_mux_o, // Selects target PC for exception - output logic [1:0] trap_addr_mux_o, // Selects trap address base - - // HWLoop signls - input logic [31:0] pc_id_i, - input logic is_compressed_i, - - // from hwloop_regs - input logic [1:0] [31:0] hwlp_start_addr_i, - input logic [1:0] [31:0] hwlp_end_addr_i, - input logic [1:0] [31:0] hwlp_counter_i, - - // to hwloop_regs - output logic [1:0] hwlp_dec_cnt_o, - - output logic hwlp_jump_o, - output logic [31:0] hwlp_targ_addr_o, - - // LSU - input logic data_req_ex_i, // data memory access is currently performed in EX stage - input logic data_we_ex_i, - input logic data_misaligned_i, - input logic data_load_event_i, - input logic data_err_i, - output logic data_err_ack_o, - - // from ALU - input logic mult_multicycle_i, // multiplier is taken multiple cycles and uses op c as storage - - // APU dependency checks - input logic apu_en_i, - input logic apu_read_dep_i, - input logic apu_write_dep_i, - - output logic apu_stall_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 - input logic [1:0] ctrl_transfer_insn_in_dec_i, // jump is being calculated in ALU - - // Interrupt Controller Signals - input logic irq_req_ctrl_i, - input logic irq_sec_ctrl_i, - input logic [4:0] irq_id_ctrl_i, - input logic irq_wu_ctrl_i, - input PrivLvl_t current_priv_lvl_i, - - output logic irq_ack_o, - output logic [4:0] irq_id_o, - - output logic [4:0] exc_cause_o, - - // Debug Signal - output logic debug_mode_o, - output logic [2:0] debug_cause_o, - output logic debug_csr_save_o, - input logic debug_req_i, - input logic debug_single_step_i, - input logic debug_ebreakm_i, - input logic debug_ebreaku_i, - input logic trigger_match_i, - output logic debug_p_elw_no_sleep_o, - output logic debug_wfi_no_sleep_o, - output logic debug_havereset_o, - output logic debug_running_o, - output logic debug_halted_o, - - // Wakeup Signal - output logic wake_from_sleep_o, - - output logic csr_save_if_o, - output logic csr_save_id_o, - output logic csr_save_ex_o, - output logic [5:0] csr_cause_o, - output logic csr_irq_sec_o, - output logic csr_restore_mret_id_o, - output logic csr_restore_uret_id_o, - - output logic csr_restore_dret_id_o, - - output logic csr_save_cause_o, - - - // Regfile target - input logic regfile_we_id_i, // currently decoded we enable - input logic [5:0] regfile_alu_waddr_id_i, // currently decoded target address - - // Forwarding signals from regfile - input logic regfile_we_ex_i, // FW: write enable from EX stage - input logic [5:0] regfile_waddr_ex_i, // FW: write address from EX stage - input logic regfile_we_wb_i, // FW: write enable from WB stage - input logic regfile_alu_we_fw_i, // FW: ALU/MUL write enable from EX stage - - // forwarding signals - output logic [1:0] operand_a_fw_mux_sel_o, // regfile ra data selector form ID stage - output logic [1:0] operand_b_fw_mux_sel_o, // regfile rb data selector form ID stage - output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage - - // forwarding detection signals - input logic reg_d_ex_is_reg_a_i, - input logic reg_d_ex_is_reg_b_i, - input logic reg_d_ex_is_reg_c_i, - input logic reg_d_wb_is_reg_a_i, - input logic reg_d_wb_is_reg_b_i, - input logic reg_d_wb_is_reg_c_i, - input logic reg_d_alu_is_reg_a_i, - input logic reg_d_alu_is_reg_b_i, - input logic reg_d_alu_is_reg_c_i, - - // stall signals - output logic halt_if_o, - output logic halt_id_o, - - output logic misaligned_stall_o, - output logic jr_stall_o, - output logic load_stall_o, - - input logic id_ready_i, // ID stage is ready - input logic id_valid_i, // ID stage is valid - - input logic ex_valid_i, // EX stage is done - - input logic wb_ready_i, // WB stage is ready - - // Performance Counters - output logic perf_pipeline_stall_o // stall due to elw extra cycles -); - - // FSM state encoding - ctrl_state_e ctrl_fsm_cs, ctrl_fsm_ns; - - // Debug state - debug_state_e debug_fsm_cs, debug_fsm_ns; - - logic jump_done, jump_done_q, jump_in_dec, branch_in_id_dec, branch_in_id; - - logic data_err_q; - - logic debug_mode_q, debug_mode_n; - logic ebrk_force_debug_mode; - logic is_hwlp_illegal, is_hwlp_body; - logic illegal_insn_q, illegal_insn_n; - logic debug_req_entry_q, debug_req_entry_n; - logic debug_force_wakeup_q, debug_force_wakeup_n; - - logic hwlp_end0_eq_pc; - logic hwlp_end1_eq_pc; - logic hwlp_counter0_gt_1; - logic hwlp_counter1_gt_1; - logic hwlp_end0_eq_pc_plus4; - logic hwlp_end1_eq_pc_plus4; - logic hwlp_start0_leq_pc; - logic hwlp_start1_leq_pc; - logic hwlp_end0_geq_pc; - logic hwlp_end1_geq_pc; - // Auxiliary signals to make hwlp_jump_o last only one cycle (converting it into a pulse) - logic hwlp_end_4_id_d, hwlp_end_4_id_q; - - logic debug_req_q; - logic debug_req_pending; - - // qualify wfi vs nosleep locally - logic wfi_active; - - - //////////////////////////////////////////////////////////////////////////////////////////// - // ____ ___ ____ _____ ____ ___ _ _ _____ ____ ___ _ _ _____ ____ // - // / ___/ _ \| _ \| ____| / ___/ _ \| \ | |_ _| _ \ / _ \| | | | | ____| _ \ // - // | | | | | | |_) | _| | | | | | | \| | | | | |_) | | | | | | | | _| | |_) | // - // | |__| |_| | _ <| |___ | |__| |_| | |\ | | | | _ <| |_| | |___| |___| |___| _ < // - // \____\___/|_| \_\_____| \____\___/|_| \_| |_| |_| \_\\___/|_____|_____|_____|_| \_\ // - // // - //////////////////////////////////////////////////////////////////////////////////////////// - - always_comb - begin - // Default values - - instr_req_o = 1'b1; - - data_err_ack_o = 1'b0; - - csr_save_if_o = 1'b0; - csr_save_id_o = 1'b0; - csr_save_ex_o = 1'b0; - csr_restore_mret_id_o = 1'b0; - csr_restore_uret_id_o = 1'b0; - - csr_restore_dret_id_o = 1'b0; - - csr_save_cause_o = 1'b0; - - exc_cause_o = '0; - exc_pc_mux_o = EXC_PC_IRQ; - trap_addr_mux_o = TRAP_MACHINE; - - csr_cause_o = '0; - csr_irq_sec_o = 1'b0; - - pc_mux_o = PC_BOOT; - pc_set_o = 1'b0; - jump_done = jump_done_q; - - ctrl_fsm_ns = ctrl_fsm_cs; - - ctrl_busy_o = 1'b1; - - halt_if_o = 1'b0; - halt_id_o = 1'b0; - is_decoding_o = 1'b0; - irq_ack_o = 1'b0; - irq_id_o = 5'b0; - - jump_in_dec = ctrl_transfer_insn_in_dec_i == BRANCH_JALR || ctrl_transfer_insn_in_dec_i == BRANCH_JAL; - - branch_in_id = ctrl_transfer_insn_in_id_i == BRANCH_COND; - branch_in_id_dec = ctrl_transfer_insn_in_dec_i == BRANCH_COND; - - ebrk_force_debug_mode = (debug_ebreakm_i && current_priv_lvl_i == PRIV_LVL_M) || - (debug_ebreaku_i && current_priv_lvl_i == PRIV_LVL_U); - debug_csr_save_o = 1'b0; - debug_cause_o = DBG_CAUSE_EBREAK; - debug_mode_n = debug_mode_q; - - illegal_insn_n = illegal_insn_q; - // a trap towards the debug unit is generated when one of the - // following conditions are true: - // - ebreak instruction encountered - // - single-stepping mode enabled - // - illegal instruction exception and IIE bit is set - // - IRQ and INTE bit is set and no exception is currently running - // - Debuger requests halt - - debug_req_entry_n = debug_req_entry_q; - - debug_force_wakeup_n = debug_force_wakeup_q; - - perf_pipeline_stall_o = 1'b0; - - hwlp_mask_o = 1'b0; - - is_hwlp_illegal = 1'b0; - - hwlp_dec_cnt_o = '0; - hwlp_end_4_id_d = 1'b0; - - // When the controller tells to hwlp-jump, the prefetcher does not always jump immediately, - // but the aligner immediately modifies pc_id to HWLP_BEGIN. This condition on hwlp_targ_addr_o - // 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]; - - unique case (ctrl_fsm_cs) - // We were just reset, wait for fetch_enable - RESET: - begin - is_decoding_o = 1'b0; - instr_req_o = 1'b0; - if (fetch_enable_i == 1'b1) - begin - ctrl_fsm_ns = BOOT_SET; - end - end - - // copy boot address to instr fetch address - BOOT_SET: - begin - is_decoding_o = 1'b0; - instr_req_o = 1'b1; - pc_mux_o = PC_BOOT; - pc_set_o = 1'b1; - if (debug_req_pending) begin - ctrl_fsm_ns = DBG_TAKEN_IF; - debug_force_wakeup_n = 1'b1; - end else begin - ctrl_fsm_ns = FIRST_FETCH; - end - end - - WAIT_SLEEP: - begin - is_decoding_o = 1'b0; - ctrl_busy_o = 1'b0; - instr_req_o = 1'b0; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = SLEEP; - end - - // instruction in if_stage is already valid - SLEEP: - begin - // we begin execution when an - // interrupt has arrived - is_decoding_o = 1'b0; - instr_req_o = 1'b0; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - // normal execution flow - // in debug mode or single step mode we leave immediately (wfi=nop) - if (wake_from_sleep_o) begin - if (debug_req_pending) begin - ctrl_fsm_ns = DBG_TAKEN_IF; - debug_force_wakeup_n = 1'b1; - end else begin - ctrl_fsm_ns = FIRST_FETCH; - end - end else begin - ctrl_busy_o = 1'b0; - end - end - - FIRST_FETCH: - begin - is_decoding_o = 1'b0; - - // ID stage is always ready - ctrl_fsm_ns = DECODE; - - // handle interrupts - if (irq_req_ctrl_i && ~(debug_req_pending || debug_mode_q)) begin - // This assumes that the pipeline is always flushed before - // going to sleep. - // Debug mode takes precedence over irq (see DECODE:) - - // Taken IRQ - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - pc_set_o = 1'b1; - pc_mux_o = PC_EXCEPTION; - exc_pc_mux_o = EXC_PC_IRQ; - exc_cause_o = irq_id_ctrl_i; - csr_irq_sec_o = irq_sec_ctrl_i; - - // IRQ interface - irq_ack_o = 1'b1; - irq_id_o = irq_id_ctrl_i; - - if (irq_sec_ctrl_i) - trap_addr_mux_o = TRAP_MACHINE; - else - trap_addr_mux_o = current_priv_lvl_i == PRIV_LVL_U ? TRAP_USER : TRAP_MACHINE; - - csr_save_cause_o = 1'b1; - csr_cause_o = {1'b1,irq_id_ctrl_i}; - csr_save_if_o = 1'b1; - end - end - - DECODE: - begin - - if (branch_taken_ex_i) - begin //taken branch - // there is a branch in the EX stage that is taken - - is_decoding_o = 1'b0; - - pc_mux_o = PC_BRANCH; - pc_set_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) - - end //taken branch - - else if (data_err_i) - begin //data error - // the current LW or SW have been blocked by the PMP - - is_decoding_o = 1'b0; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - csr_save_ex_o = 1'b1; - csr_save_cause_o = 1'b1; - data_err_ack_o = 1'b1; - //no jump in this stage as we have to wait one cycle to go to Machine Mode - - csr_cause_o = {1'b0, data_we_ex_i ? EXC_CAUSE_STORE_FAULT : EXC_CAUSE_LOAD_FAULT}; - ctrl_fsm_ns = FLUSH_WB; - - end //data error - - else if (is_fetch_failed_i) - begin - - // the current instruction has been blocked by the PMP - - is_decoding_o = 1'b0; - halt_id_o = 1'b1; - halt_if_o = 1'b1; - csr_save_if_o = 1'b1; - csr_save_cause_o = !debug_mode_q; - - //no jump in this stage as we have to wait one cycle to go to Machine Mode - - csr_cause_o = {1'b0, EXC_CAUSE_INSTR_FAULT}; - ctrl_fsm_ns = FLUSH_WB; - - - end - // decode and execute instructions only if the current conditional - // branch in the EX stage is either not taken, or there is no - // conditional branch in the EX stage - else if (instr_valid_i) //valid block - begin: blk_decode_level1 // now analyze the current instruction in the ID stage - - is_decoding_o = 1'b1; - illegal_insn_n = 1'b0; - - if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) - begin - //Serving the debug - halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = DBG_FLUSH; - debug_req_entry_n = 1'b1; - end - else if (irq_req_ctrl_i && ~debug_mode_q) - begin - // Taken IRQ - hwlp_mask_o = PULP_XPULP ? 1'b1 : 1'b0; - - is_decoding_o = 1'b0; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - pc_set_o = 1'b1; - pc_mux_o = PC_EXCEPTION; - exc_pc_mux_o = EXC_PC_IRQ; - exc_cause_o = irq_id_ctrl_i; - csr_irq_sec_o = irq_sec_ctrl_i; - - // IRQ interface - irq_ack_o = 1'b1; - irq_id_o = irq_id_ctrl_i; - - if (irq_sec_ctrl_i) - trap_addr_mux_o = TRAP_MACHINE; - else - trap_addr_mux_o = current_priv_lvl_i == PRIV_LVL_U ? TRAP_USER : TRAP_MACHINE; - - csr_save_cause_o = 1'b1; - csr_cause_o = {1'b1,irq_id_ctrl_i}; - csr_save_id_o = 1'b1; - end - else - begin - - is_hwlp_illegal = is_hwlp_body & (jump_in_dec || branch_in_id_dec || mret_insn_i || uret_insn_i || dret_insn_i || is_compressed_i || fencei_insn_i || wfi_active); - - if(illegal_insn_i || is_hwlp_illegal) begin - - halt_if_o = 1'b1; - halt_id_o = 1'b0; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; - illegal_insn_n = 1'b1; - - end else begin - - //decoding block - unique case (1'b1) - - jump_in_dec: begin - // handle unconditional jumps - // we can jump directly since we know the address already - // we don't need to worry about conditional branches here as they - // will be evaluated in the EX stage - pc_mux_o = PC_JUMP; - // if there is a jr stall, wait for it to be gone - if ((~jr_stall_o) && (~jump_done_q)) begin - pc_set_o = 1'b1; - jump_done = 1'b1; - end - end - - ebrk_insn_i: begin - halt_if_o = 1'b1; - halt_id_o = 1'b0; - - if (debug_mode_q) - // we got back to the park loop in the debug rom - ctrl_fsm_ns = DBG_FLUSH; - - else if (ebrk_force_debug_mode) begin - // debug module commands us to enter debug mode anyway - ctrl_fsm_ns = DBG_FLUSH; - end else begin - // otherwise just a normal ebreak exception - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; - end - - end - - wfi_active: begin - halt_if_o = 1'b1; - halt_id_o = 1'b0; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; - end - - ecall_insn_i: begin - halt_if_o = 1'b1; - halt_id_o = 1'b0; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; - end - - fencei_insn_i: begin - halt_if_o = 1'b1; - halt_id_o = 1'b0; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; - end - - mret_insn_i | uret_insn_i | dret_insn_i: begin - halt_if_o = 1'b1; - halt_id_o = 1'b0; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; - end - - csr_status_i: begin - halt_if_o = 1'b1; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; - end - - data_load_event_i: begin - ctrl_fsm_ns = id_ready_i ? ELW_EXE : DECODE; - halt_if_o = 1'b1; - end - - default: begin - - if(is_hwlp_body) begin - //we are at the inside of an HWloop, thus change state - - //We stay here in case we returned from the second last instruction, otherwise the next cycle - //in DECODE_HWLOOP we miss to jump, we jump at PC_END. - //This way looses a cycle but it's a corner case of returning from exceptions or interrupts - - ctrl_fsm_ns = hwlp_end0_eq_pc_plus4 || hwlp_end1_eq_pc_plus4 ? DECODE : DECODE_HWLOOP; - - // we can be at the end of HWloop due to a return from interrupt or ecall or ebreak or exceptions - if(hwlp_end0_eq_pc && hwlp_counter0_gt_1) begin - pc_mux_o = PC_HWLOOP; - if (~jump_done_q) begin - pc_set_o = 1'b1; - // Keep the instruction and the related address in the Aligner if - // ID is stalled during a jump - jump_done = 1'b1; - hwlp_dec_cnt_o[0] = 1'b1; - end - end - if(hwlp_end1_eq_pc && hwlp_counter1_gt_1) begin - pc_mux_o = PC_HWLOOP; - if (~jump_done_q) begin - pc_set_o = 1'b1; - // Keep the instruction and the related address in the Aligner if - // ID is stalled during a jump - jump_done = 1'b1; - hwlp_dec_cnt_o[1] = 1'b1; - end - end - end - end - - endcase // unique case (1'b1) - end - - if (debug_single_step_i & ~debug_mode_q) begin - // prevent any more instructions from executing - halt_if_o = 1'b1; - - // we don't handle dret here because its should be illegal - // anyway in this context - - // illegal, ecall, ebrk and xrettransition to later to a DBG - // state since we need the return address which is - // determined later - - if (id_ready_i) begin - // make sure the current instruction has been executed - unique case(1'b1) - - illegal_insn_i | ecall_insn_i: - begin - ctrl_fsm_ns = FLUSH_EX; - end - - (~ebrk_force_debug_mode & ebrk_insn_i): - begin - ctrl_fsm_ns = FLUSH_EX; - end - - mret_insn_i | uret_insn_i: - begin - ctrl_fsm_ns = FLUSH_EX; - end - - branch_in_id: - begin - ctrl_fsm_ns = DBG_WAIT_BRANCH; - end - - default: - // regular instruction or ebrk force debug - ctrl_fsm_ns = DBG_FLUSH; - endcase // unique case (1'b1) - end - end - - end // else: !if (irq_req_ctrl_i && ~debug_mode_q) - - end //valid block - else begin - is_decoding_o = 1'b0; - perf_pipeline_stall_o = data_load_event_i; - end - end - - DECODE_HWLOOP: - begin - if (PULP_XPULP) begin - if (instr_valid_i) // valid block - begin // now analyze the current instruction in the ID stage - - is_decoding_o = 1'b1; - - if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) - begin - //Serving the debug - halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = DBG_FLUSH; - debug_req_entry_n = 1'b1; - end - else if (irq_req_ctrl_i && ~debug_mode_q) - begin - // Taken IRQ - hwlp_mask_o = PULP_XPULP ? 1'b1 : 1'b0; - - is_decoding_o = 1'b0; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - pc_set_o = 1'b1; - pc_mux_o = PC_EXCEPTION; - exc_pc_mux_o = EXC_PC_IRQ; - exc_cause_o = irq_id_ctrl_i; - csr_irq_sec_o = irq_sec_ctrl_i; - - // IRQ interface - irq_ack_o = 1'b1; - irq_id_o = irq_id_ctrl_i; - - if (irq_sec_ctrl_i) - trap_addr_mux_o = TRAP_MACHINE; - else - trap_addr_mux_o = current_priv_lvl_i == PRIV_LVL_U ? TRAP_USER : TRAP_MACHINE; - - csr_save_cause_o = 1'b1; - csr_cause_o = {1'b1,irq_id_ctrl_i}; - csr_save_id_o = 1'b1; - - ctrl_fsm_ns = DECODE; - end - else - begin - - is_hwlp_illegal = (jump_in_dec || branch_in_id_dec || mret_insn_i || uret_insn_i || dret_insn_i || is_compressed_i || fencei_insn_i || wfi_active); - - if(illegal_insn_i || is_hwlp_illegal) begin - - halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = FLUSH_EX; - illegal_insn_n = 1'b1; - - end else begin - - //decoding block - unique case (1'b1) - - ebrk_insn_i: begin - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - if (debug_mode_q) - // we got back to the park loop in the debug rom - ctrl_fsm_ns = DBG_FLUSH; - - else if (ebrk_force_debug_mode) - // debug module commands us to enter debug mode anyway - ctrl_fsm_ns = DBG_FLUSH; - - else begin - // otherwise just a normal ebreak exception - ctrl_fsm_ns = FLUSH_EX; - end - - end - - ecall_insn_i: begin - halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = FLUSH_EX; - end - - csr_status_i: begin - halt_if_o = 1'b1; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; - end - - data_load_event_i: begin - ctrl_fsm_ns = id_ready_i ? ELW_EXE : DECODE_HWLOOP; - halt_if_o = 1'b1; - end - - default: begin - - // we can be at the end of HWloop due to a return from interrupt or ecall or ebreak or exceptions - if(hwlp_end1_eq_pc_plus4) begin - if(hwlp_counter1_gt_1) begin - hwlp_end_4_id_d = 1'b1; - hwlp_targ_addr_o = hwlp_start_addr_i[1]; - ctrl_fsm_ns = DECODE_HWLOOP; - end else - ctrl_fsm_ns = is_hwlp_body ? DECODE_HWLOOP : DECODE; - end - - if(hwlp_end0_eq_pc_plus4) begin - if(hwlp_counter0_gt_1) begin - hwlp_end_4_id_d = 1'b1; - hwlp_targ_addr_o = hwlp_start_addr_i[0]; - ctrl_fsm_ns = DECODE_HWLOOP; - end else - ctrl_fsm_ns = is_hwlp_body ? DECODE_HWLOOP : DECODE; - end - - hwlp_dec_cnt_o[0] = hwlp_end0_eq_pc; - hwlp_dec_cnt_o[1] = hwlp_end1_eq_pc; - - end - endcase // unique case (1'b1) - end // else: !if(illegal_insn_i) - - if (debug_single_step_i & ~debug_mode_q) begin - // prevent any more instructions from executing - halt_if_o = 1'b1; - - // we don't handle dret here because its should be illegal - // anyway in this context - - // illegal, ecall, ebrk and xrettransition to later to a DBG - // state since we need the return address which is - // determined later - - if (id_ready_i) begin - // make sure the current instruction has been executed - unique case(1'b1) - - illegal_insn_i | ecall_insn_i: - begin - ctrl_fsm_ns = FLUSH_EX; - end - - (~ebrk_force_debug_mode & ebrk_insn_i): - begin - ctrl_fsm_ns = FLUSH_EX; - end - - mret_insn_i | uret_insn_i: - begin - ctrl_fsm_ns = FLUSH_EX; - end - - branch_in_id: - begin - ctrl_fsm_ns = DBG_WAIT_BRANCH; - end - - default: - // regular instruction or ebrk force debug - ctrl_fsm_ns = DBG_FLUSH; - endcase // unique case (1'b1) - end - end // if (debug_single_step_i & ~debug_mode_q) - - end // else: !if (irq_req_ctrl_i && ~debug_mode_q) - - end // block: blk_decode_level1 : valid block - else begin - is_decoding_o = 1'b0; - perf_pipeline_stall_o = data_load_event_i; - end - end - end - - // flush the pipeline, insert NOP into EX stage - FLUSH_EX: - begin - is_decoding_o = 1'b0; - - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - if (data_err_i) - begin //data error - // the current LW or SW have been blocked by the PMP - csr_save_ex_o = 1'b1; - csr_save_cause_o = 1'b1; - data_err_ack_o = 1'b1; - //no jump in this stage as we have to wait one cycle to go to Machine Mode - csr_cause_o = {1'b0, data_we_ex_i ? EXC_CAUSE_STORE_FAULT : EXC_CAUSE_LOAD_FAULT}; - ctrl_fsm_ns = FLUSH_WB; - //putting illegal to 0 as if it was 1, the core is going to jump to the exception of the EX stage, - //so the illegal was never executed - illegal_insn_n = 1'b0; - end //data erro - else if (ex_valid_i) begin - //check done to prevent data harzard in the CSR registers - ctrl_fsm_ns = FLUSH_WB; - - if(illegal_insn_q) begin - csr_save_id_o = 1'b1; - csr_save_cause_o = !debug_mode_q; - csr_cause_o = {1'b0, EXC_CAUSE_ILLEGAL_INSN}; - end else begin - unique case (1'b1) - ebrk_insn_i: begin - csr_save_id_o = 1'b1; - csr_save_cause_o = 1'b1; - csr_cause_o = {1'b0, EXC_CAUSE_BREAKPOINT}; - end - ecall_insn_i: begin - csr_save_id_o = 1'b1; - csr_save_cause_o = !debug_mode_q; - csr_cause_o = {1'b0, current_priv_lvl_i == PRIV_LVL_U ? EXC_CAUSE_ECALL_UMODE : EXC_CAUSE_ECALL_MMODE}; - end - default:; - endcase // unique case (1'b1) - end - - end - end - - IRQ_FLUSH_ELW: - begin - if (PULP_CLUSTER == 1'b1) begin - is_decoding_o = 1'b0; - - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - ctrl_fsm_ns = DECODE; - - perf_pipeline_stall_o = data_load_event_i; - - if (irq_req_ctrl_i && ~(debug_req_pending || debug_mode_q)) begin - // Taken IRQ - is_decoding_o = 1'b0; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - pc_set_o = 1'b1; - pc_mux_o = PC_EXCEPTION; - exc_pc_mux_o = EXC_PC_IRQ; - exc_cause_o = irq_id_ctrl_i; - csr_irq_sec_o = irq_sec_ctrl_i; - - // IRQ interface - irq_ack_o = 1'b1; - irq_id_o = irq_id_ctrl_i; - - if (irq_sec_ctrl_i) - trap_addr_mux_o = TRAP_MACHINE; - else - trap_addr_mux_o = current_priv_lvl_i == PRIV_LVL_U ? TRAP_USER : TRAP_MACHINE; - - csr_save_cause_o = 1'b1; - csr_cause_o = {1'b1,irq_id_ctrl_i}; - csr_save_id_o = 1'b1; - end - end - end - - ELW_EXE: - begin - if (PULP_CLUSTER == 1'b1) begin - is_decoding_o = 1'b0; - - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - //if we are here, a elw is executing now in the EX stage - //or if an interrupt has been received - //the ID stage contains the PC_ID of the elw, therefore halt_id is set to invalid the instruction - //If an interrupt occurs, we replay the ELW - //No needs to check irq_int_req_i since in the EX stage there is only the elw, no CSR pendings - if(id_ready_i) - ctrl_fsm_ns = ((debug_req_pending || trigger_match_i) & ~debug_mode_q) ? DBG_FLUSH : IRQ_FLUSH_ELW; - // if from the ELW EXE we go to IRQ_FLUSH_ELW, it is assumed that if there was an IRQ req together with the grant and IE was valid, then - // there must be no hazard due to xIE - else - ctrl_fsm_ns = ELW_EXE; - - perf_pipeline_stall_o = data_load_event_i; - end - end - - // flush the pipeline, insert NOP into EX and WB stage - FLUSH_WB: - begin - is_decoding_o = 1'b0; - - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - ctrl_fsm_ns = DECODE; - - if(data_err_q) begin - //PMP data_error - pc_mux_o = PC_EXCEPTION; - pc_set_o = 1'b1; - trap_addr_mux_o = TRAP_MACHINE; - //little hack during testing - exc_pc_mux_o = EXC_PC_EXCEPTION; - exc_cause_o = data_we_ex_i ? EXC_CAUSE_LOAD_FAULT : EXC_CAUSE_STORE_FAULT; - - end - else if (is_fetch_failed_i) begin - //instruction fetch error - pc_mux_o = PC_EXCEPTION; - pc_set_o = 1'b1; - trap_addr_mux_o = TRAP_MACHINE; - exc_pc_mux_o = debug_mode_q ? EXC_PC_DBE : EXC_PC_EXCEPTION; - exc_cause_o = EXC_CAUSE_INSTR_FAULT; - - end - else begin - if(illegal_insn_q) begin - //exceptions - pc_mux_o = PC_EXCEPTION; - pc_set_o = 1'b1; - trap_addr_mux_o = TRAP_MACHINE; - exc_pc_mux_o = debug_mode_q ? EXC_PC_DBE : EXC_PC_EXCEPTION; - illegal_insn_n = 1'b0; - if (debug_single_step_i && ~debug_mode_q) - ctrl_fsm_ns = DBG_TAKEN_IF; - end else begin - unique case(1'b1) - ebrk_insn_i: begin - //ebreak - pc_mux_o = PC_EXCEPTION; - pc_set_o = 1'b1; - trap_addr_mux_o = TRAP_MACHINE; - exc_pc_mux_o = EXC_PC_EXCEPTION; - - if (debug_single_step_i && ~debug_mode_q) - ctrl_fsm_ns = DBG_TAKEN_IF; - end - ecall_insn_i: begin - //ecall - pc_mux_o = PC_EXCEPTION; - pc_set_o = 1'b1; - trap_addr_mux_o = TRAP_MACHINE; - exc_pc_mux_o = debug_mode_q ? EXC_PC_DBE : EXC_PC_EXCEPTION; - - if (debug_single_step_i && ~debug_mode_q) - ctrl_fsm_ns = DBG_TAKEN_IF; - end - - mret_insn_i: begin - csr_restore_mret_id_o = !debug_mode_q; - ctrl_fsm_ns = XRET_JUMP; - end - uret_insn_i: begin - csr_restore_uret_id_o = !debug_mode_q; - ctrl_fsm_ns = XRET_JUMP; - end - dret_insn_i: begin - csr_restore_dret_id_o = 1'b1; - ctrl_fsm_ns = XRET_JUMP; - end - - csr_status_i: begin - - if(hwlp_end0_eq_pc && hwlp_counter0_gt_1) begin - pc_mux_o = PC_HWLOOP; - pc_set_o = 1'b1; - hwlp_dec_cnt_o[0] = 1'b1; - end - if(hwlp_end1_eq_pc && hwlp_counter1_gt_1) begin - pc_mux_o = PC_HWLOOP; - pc_set_o = 1'b1; - hwlp_dec_cnt_o[1] = 1'b1; - end - end - - wfi_i: begin - if ( debug_req_pending) begin - ctrl_fsm_ns = DBG_TAKEN_IF; - debug_force_wakeup_n = 1'b1; - end else begin - ctrl_fsm_ns = WAIT_SLEEP; - end - end - fencei_insn_i: begin - // we just jump to instruction after the fence.i since that - // forces the instruction cache to refetch - pc_mux_o = PC_FENCEI; - pc_set_o = 1'b1; - end - default:; - endcase - end - end - - end - - XRET_JUMP: - begin - is_decoding_o = 1'b0; - ctrl_fsm_ns = DECODE; - unique case(1'b1) - mret_dec_i: begin - //mret - pc_mux_o = debug_mode_q ? PC_EXCEPTION : PC_MRET; - pc_set_o = 1'b1; - exc_pc_mux_o = EXC_PC_DBE; // only used if in debug_mode - end - uret_dec_i: begin - //uret - pc_mux_o = debug_mode_q ? PC_EXCEPTION : PC_URET; - pc_set_o = 1'b1; - exc_pc_mux_o = EXC_PC_DBE; // only used if in debug_mode - end - dret_dec_i: begin - //dret - // this case is only reachable while in debug_mode - pc_mux_o = PC_DRET; - pc_set_o = 1'b1; - debug_mode_n = 1'b0; - end - default:; - endcase - - if (debug_single_step_i && ~debug_mode_q) begin - ctrl_fsm_ns = DBG_TAKEN_IF; - end - end - - // a branch was in ID when trying to go to debug rom. Wait until we can - // determine branch target address (for saving into dpc) before proceeding - DBG_WAIT_BRANCH: - begin - is_decoding_o = 1'b0; - halt_if_o = 1'b1; - - if (branch_taken_ex_i) begin - // there is a branch in the EX stage that is taken - pc_mux_o = PC_BRANCH; - pc_set_o = 1'b1; - end - - ctrl_fsm_ns = DBG_FLUSH; - end - - // We enter this state when we encounter - // 1. ebreak during debug mode - // 2. trigger match - // 3. ebreak with forced entry into debug mode (ebreakm or ebreaku set). - // 4. halt request during decode - // Regular ebreak's go through FLUSH_EX and FLUSH_WB. - // For 1. we don't update dcsr and dpc while for 2., 3., & 4. we do - // dpc is set to the address of ebreak and trigger match - // not to the next instruction's (which is why we save the pc in id). - DBG_TAKEN_ID: - begin - is_decoding_o = 1'b0; - pc_set_o = 1'b1; - pc_mux_o = PC_EXCEPTION; - exc_pc_mux_o = EXC_PC_DBD; - // If not in debug mode then save cause and dpc csrs - // else it was an ebreak in debug mode, so don't update csrs - if (~debug_mode_q) begin - csr_save_cause_o = 1'b1; - csr_save_id_o = 1'b1; - debug_csr_save_o = 1'b1; - if (trigger_match_i) - debug_cause_o = DBG_CAUSE_TRIGGER; // pri 4 (highest) - else if (ebrk_force_debug_mode & ebrk_insn_i) - debug_cause_o = DBG_CAUSE_EBREAK; // pri 3 - else if (debug_req_entry_q) - debug_cause_o = DBG_CAUSE_HALTREQ;// pri 2 and 1 - - end - debug_req_entry_n = 1'b0; - ctrl_fsm_ns = DECODE; - debug_mode_n = 1'b1; - end - - // We enter this state for single stepping - // DPC is set the next instruction to be executed/fetched - DBG_TAKEN_IF: - begin - is_decoding_o = 1'b0; - pc_set_o = 1'b1; - pc_mux_o = PC_EXCEPTION; - exc_pc_mux_o = EXC_PC_DBD; - csr_save_cause_o = 1'b1; - debug_csr_save_o = 1'b1; - 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 - csr_save_if_o = 1'b1; - ctrl_fsm_ns = DECODE; - debug_mode_n = 1'b1; - debug_force_wakeup_n = 1'b0; - end - - - DBG_FLUSH: - begin - is_decoding_o = 1'b0; - - halt_if_o = 1'b1; - halt_id_o = 1'b1; - - perf_pipeline_stall_o = data_load_event_i; - - if (data_err_i) - begin //data error - // the current LW or SW have been blocked by the PMP - csr_save_ex_o = 1'b1; - csr_save_cause_o = 1'b1; - data_err_ack_o = 1'b1; - //no jump in this stage as we have to wait one cycle to go to Machine Mode - csr_cause_o = {1'b0, data_we_ex_i ? EXC_CAUSE_STORE_FAULT : EXC_CAUSE_LOAD_FAULT}; - ctrl_fsm_ns = FLUSH_WB; - end //data error - else begin - if(debug_mode_q | - trigger_match_i | - (ebrk_force_debug_mode & ebrk_insn_i) | - data_load_event_i | - debug_req_entry_q ) - begin - ctrl_fsm_ns = DBG_TAKEN_ID; - end else - begin - // else must be debug_single_step_i - ctrl_fsm_ns = DBG_TAKEN_IF; - end - end - end - // Debug end - - default: begin - is_decoding_o = 1'b0; - instr_req_o = 1'b0; - ctrl_fsm_ns = RESET; - end - endcase - end - - - -generate - if(PULP_XPULP) begin : gen_hwlp - ////////////////////////////////////////////////////////////////////////////// - // Convert hwlp_jump_o to a pulse - ////////////////////////////////////////////////////////////////////////////// - - // hwlp_jump_o should last one cycle only, as the prefetcher - // reacts immediately. If it last more cycles, the prefetcher - // goes on requesting HWLP_BEGIN more than one time (wrong!). - // This signal is not controlled by id_ready because otherwise, - // in case of stall, the jump would happen at the end of the stall. - - // Make hwlp_jump_o last only one cycle - assign hwlp_jump_o = (hwlp_end_4_id_d && !hwlp_end_4_id_q) ? 1'b1 : 1'b0; - - always_ff @(posedge clk or negedge rst_n) begin - if(!rst_n) begin - hwlp_end_4_id_q <= 1'b0; - end else begin - hwlp_end_4_id_q <= hwlp_end_4_id_d; - end - end - - assign hwlp_end0_eq_pc = hwlp_end_addr_i[0] == pc_id_i; - assign hwlp_end1_eq_pc = hwlp_end_addr_i[1] == pc_id_i; - assign hwlp_counter0_gt_1 = hwlp_counter_i[0] > 1; - assign hwlp_counter1_gt_1 = hwlp_counter_i[1] > 1; - assign hwlp_end0_eq_pc_plus4 = hwlp_end_addr_i[0] == pc_id_i + 4; - assign hwlp_end1_eq_pc_plus4 = hwlp_end_addr_i[1] == pc_id_i + 4; - assign hwlp_start0_leq_pc = hwlp_start_addr_i[0] <= pc_id_i; - assign hwlp_start1_leq_pc = hwlp_start_addr_i[1] <= pc_id_i; - assign hwlp_end0_geq_pc = hwlp_end_addr_i[0] >= pc_id_i; - assign hwlp_end1_geq_pc = hwlp_end_addr_i[1] >= pc_id_i; - assign is_hwlp_body = ((hwlp_start0_leq_pc && hwlp_end0_geq_pc) && hwlp_counter0_gt_1) || ((hwlp_start1_leq_pc && hwlp_end1_geq_pc) && hwlp_counter1_gt_1); - - end else begin : gen_no_hwlp - - assign hwlp_jump_o = 1'b0; - assign hwlp_end_4_id_q = 1'b0; - assign hwlp_end0_eq_pc = 1'b0; - assign hwlp_end1_eq_pc = 1'b0; - assign hwlp_counter0_gt_1 = 1'b0; - assign hwlp_counter1_gt_1 = 1'b0; - assign hwlp_end0_eq_pc_plus4 = 1'b0; - assign hwlp_end1_eq_pc_plus4 = 1'b0; - assign hwlp_start0_leq_pc = 1'b0; - assign hwlp_start1_leq_pc = 1'b0; - assign hwlp_end0_geq_pc = 1'b0; - assign hwlp_end1_geq_pc = 1'b0; - assign is_hwlp_body = 1'b0; - - end - -endgenerate - - ///////////////////////////////////////////////////////////// - // ____ _ _ _ ____ _ _ // - // / ___|| |_ __ _| | | / ___|___ _ __ | |_ _ __ ___ | | // - // \___ \| __/ _` | | | | | / _ \| '_ \| __| '__/ _ \| | // - // ___) | || (_| | | | | |__| (_) | | | | |_| | | (_) | | // - // |____/ \__\__,_|_|_| \____\___/|_| |_|\__|_| \___/|_| // - // // - ///////////////////////////////////////////////////////////// - always_comb - begin - load_stall_o = 1'b0; - deassert_we_o = 1'b0; - - // deassert WE when the core is not decoding instructions - if (~is_decoding_o) - deassert_we_o = 1'b1; - - // deassert WE in case of illegal instruction - if (illegal_insn_i) - deassert_we_o = 1'b1; - - // Stall because of load operation - if ( - ( (data_req_ex_i == 1'b1) && (regfile_we_ex_i == 1'b1) || - (wb_ready_i == 1'b0) && (regfile_we_wb_i == 1'b1) - ) && - ( (reg_d_ex_is_reg_a_i == 1'b1) || (reg_d_ex_is_reg_b_i == 1'b1) || (reg_d_ex_is_reg_c_i == 1'b1) || - (is_decoding_o && (regfile_we_id_i && !data_misaligned_i) && (regfile_waddr_ex_i == regfile_alu_waddr_id_i)) ) - ) - begin - deassert_we_o = 1'b1; - load_stall_o = 1'b1; - end - - // Stall because of jr path - // - always stall if a result is to be forwarded to the PC - // we don't care about in which state the ctrl_fsm is as we deassert_we - // anyway when we are not in DECODE - if ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && - (((regfile_we_wb_i == 1'b1) && (reg_d_wb_is_reg_a_i == 1'b1)) || - ((regfile_we_ex_i == 1'b1) && (reg_d_ex_is_reg_a_i == 1'b1)) || - ((regfile_alu_we_fw_i == 1'b1) && (reg_d_alu_is_reg_a_i == 1'b1))) ) - begin - jr_stall_o = 1'b1; - deassert_we_o = 1'b1; - end - else - begin - jr_stall_o = 1'b0; - end - end - - - // stall because of misaligned data access - assign misaligned_stall_o = data_misaligned_i; - - // APU dependency stalls (data hazards) - assign apu_stall_o = apu_read_dep_i | (apu_write_dep_i & ~apu_en_i); - - // Forwarding control unit - always_comb - begin - // default assignements - operand_a_fw_mux_sel_o = SEL_REGFILE; - operand_b_fw_mux_sel_o = SEL_REGFILE; - operand_c_fw_mux_sel_o = SEL_REGFILE; - - // Forwarding WB -> ID - if (regfile_we_wb_i == 1'b1) - begin - if (reg_d_wb_is_reg_a_i == 1'b1) - operand_a_fw_mux_sel_o = SEL_FW_WB; - if (reg_d_wb_is_reg_b_i == 1'b1) - operand_b_fw_mux_sel_o = SEL_FW_WB; - if (reg_d_wb_is_reg_c_i == 1'b1) - operand_c_fw_mux_sel_o = SEL_FW_WB; - end - - // Forwarding EX -> ID - if (regfile_alu_we_fw_i == 1'b1) - begin - if (reg_d_alu_is_reg_a_i == 1'b1) - operand_a_fw_mux_sel_o = SEL_FW_EX; - if (reg_d_alu_is_reg_b_i == 1'b1) - operand_b_fw_mux_sel_o = SEL_FW_EX; - if (reg_d_alu_is_reg_c_i == 1'b1) - operand_c_fw_mux_sel_o = SEL_FW_EX; - end - - // for misaligned memory accesses - if (data_misaligned_i) - begin - operand_a_fw_mux_sel_o = SEL_FW_EX; - operand_b_fw_mux_sel_o = SEL_REGFILE; - end else if (mult_multicycle_i) begin - operand_c_fw_mux_sel_o = SEL_FW_EX; - end - end - - // update registers - always_ff @(posedge clk , negedge rst_n) - begin : UPDATE_REGS - if ( rst_n == 1'b0 ) - begin - ctrl_fsm_cs <= RESET; - jump_done_q <= 1'b0; - data_err_q <= 1'b0; - - debug_mode_q <= 1'b0; - illegal_insn_q <= 1'b0; - - debug_req_entry_q <= 1'b0; - debug_force_wakeup_q <= 1'b0; - end - else - begin - ctrl_fsm_cs <= ctrl_fsm_ns; - - // clear when id is valid (no instruction incoming) - jump_done_q <= jump_done & (~id_ready_i); - - data_err_q <= data_err_i; - - debug_mode_q <= debug_mode_n; - - illegal_insn_q <= illegal_insn_n; - - debug_req_entry_q <= debug_req_entry_n; - debug_force_wakeup_q <= debug_force_wakeup_n; - end - end - - // wakeup from sleep conditions - assign wake_from_sleep_o = irq_wu_ctrl_i || debug_req_pending || debug_mode_q; - - // debug mode - assign debug_mode_o = debug_mode_q; - assign debug_req_pending = debug_req_i || debug_req_q; - - // Do not let p.elw cause core_sleep_o during debug - assign debug_p_elw_no_sleep_o = debug_mode_q || debug_req_q || debug_single_step_i || trigger_match_i; - - // Do not let WFI cause core_sleep_o (but treat as NOP): - // - // - During debug - // - For PULP Cluster (only p.elw can trigger sleep) - - assign debug_wfi_no_sleep_o = debug_mode_q || debug_req_pending || debug_single_step_i || trigger_match_i || PULP_CLUSTER; - - // 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) - always_ff @(posedge clk_ungated_i, negedge rst_n) - if ( !rst_n ) - debug_req_q <= 1'b0; - else - if( debug_req_i ) - debug_req_q <= 1'b1; - else if( debug_mode_q ) - debug_req_q <= 1'b0; - - // Debug state FSM - always_ff @(posedge clk , negedge rst_n) - begin - if ( rst_n == 1'b0 ) - begin - debug_fsm_cs <= HAVERESET; - end - else - begin - debug_fsm_cs <= debug_fsm_ns; - end - end - - always_comb - begin - debug_fsm_ns = debug_fsm_cs; - - case (debug_fsm_cs) - HAVERESET: - begin - if (debug_mode_n || (ctrl_fsm_ns == FIRST_FETCH)) begin - if (debug_mode_n) begin - debug_fsm_ns = HALTED; - end else begin - debug_fsm_ns = RUNNING; - end - end - end - - RUNNING: - begin - if (debug_mode_n) begin - debug_fsm_ns = HALTED; - end - end - - HALTED: - begin - if (!debug_mode_n) begin - debug_fsm_ns = RUNNING; - end - end - - default: begin - debug_fsm_ns = HAVERESET; - end - endcase - end - - assign debug_havereset_o = debug_fsm_cs[HAVERESET_INDEX]; - assign debug_running_o = debug_fsm_cs[RUNNING_INDEX]; - assign debug_halted_o = debug_fsm_cs[HALTED_INDEX]; - - //---------------------------------------------------------------------------- - // Assertions - //---------------------------------------------------------------------------- - -`ifdef CV32E40P_ASSERT_ON - - // make sure that taken branches do not happen back-to-back, as this is not - // possible without branch prediction in the IF stage - assert property ( - @(posedge clk) (branch_taken_ex_i) |=> (~branch_taken_ex_i) ) else $warning("Two branches back-to-back are taken"); - - // ELW_EXE and IRQ_FLUSH_ELW states are only used for PULP_CLUSTER = 1 - property p_pulp_cluster_only_states; - @(posedge clk) (1'b1) |-> ( !((PULP_CLUSTER == 1'b0) && ((ctrl_fsm_cs == ELW_EXE) || (ctrl_fsm_cs == IRQ_FLUSH_ELW))) ); - endproperty - - a_pulp_cluster_only_states : assert property(p_pulp_cluster_only_states); - - // WAIT_SLEEP and SLEEP states are never used for PULP_CLUSTER = 1 - property p_pulp_cluster_excluded_states; - @(posedge clk) (1'b1) |-> ( !((PULP_CLUSTER == 1'b1) && ((ctrl_fsm_cs == SLEEP) || (ctrl_fsm_cs == WAIT_SLEEP))) ); - endproperty - - a_pulp_cluster_excluded_states : assert property(p_pulp_cluster_excluded_states); - - generate - if (PULP_XPULP) begin : gen_pulp_xpulp_assertions - - // HWLoop 0 and 1 having target address constraints - property p_hwlp_same_target_address; - @(posedge clk) (hwlp_counter_i[1] > 1 && hwlp_counter_i[0] > 1) |-> ( hwlp_end_addr_i[1] >= hwlp_end_addr_i[0] + 8 ); - endproperty - - a_hwlp_same_target_address : assert property(p_hwlp_same_target_address) else $warning("%t, HWLoops target address do not respect constraints", $time); - - end else begin : gen_no_pulp_xpulp_assertions - - property p_no_hwlp; - @(posedge clk) (1'b1) |-> ((pc_mux_o != PC_HWLOOP) && (ctrl_fsm_cs != DECODE_HWLOOP) && - (hwlp_mask_o == 1'b0) && (is_hwlp_illegal == 'b0) && (is_hwlp_body == 'b0) && - (hwlp_start_addr_i == 'b0) && (hwlp_end_addr_i == 'b0) && (hwlp_counter_i[1] == 32'b0) && (hwlp_counter_i[0] == 32'b0) && - (hwlp_dec_cnt_o == 2'b0) && (hwlp_jump_o == 1'b0) && (hwlp_targ_addr_o == 32'b0) && - (hwlp_end0_eq_pc == 1'b0) && (hwlp_end1_eq_pc == 1'b0) && (hwlp_counter0_gt_1 == 1'b0) && (hwlp_counter1_gt_1 == 1'b0) && - (hwlp_end0_eq_pc_plus4 == 1'b0) && (hwlp_end1_eq_pc_plus4 == 1'b0) && (hwlp_start0_leq_pc == 0) && (hwlp_start1_leq_pc == 0) && - (hwlp_end0_geq_pc == 1'b0) && (hwlp_end1_geq_pc == 1'b0) && (hwlp_end_4_id_d == 1'b0) && (hwlp_end_4_id_q == 1'b0)); - endproperty - - a_no_hwlp : assert property(p_no_hwlp); - - end - 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 - a_dbg_flush : assert property (@(posedge clk) disable iff (!rst_n) (ctrl_fsm_cs==DBG_FLUSH) |-> (ctrl_fsm_ns!=DBG_FLUSH) ); - - // Ensure that debug state outputs are one-hot - a_debug_state_onehot : assert property (@(posedge clk) $onehot({debug_havereset_o, debug_running_o, debug_halted_o})); - - // Ensure that debug_halted_o equals debug_mode_q - a_debug_halted_equals_debug_mode : assert property (@(posedge clk) disable iff (!rst_n) (1'b1) |-> (debug_mode_q == debug_halted_o)); - - // Ensure ID always ready in FIRST_FETCH state - a_first_fetch_id_ready : assert property (@(posedge clk) disable iff (!rst_n) (ctrl_fsm_cs == FIRST_FETCH) |-> (id_ready_i == 1'b1)); - - // Ensure that the only way to get to DBG_TAKEN_IF from DBG_FLUSH is if debug_single_step_i is asserted - a_dbg_flush_to_taken_if : assert property (@(posedge clk) disable iff (!rst_n) (ctrl_fsm_cs == DBG_FLUSH) && (ctrl_fsm_ns == DBG_TAKEN_IF) |-> debug_single_step_i); - -`endif - -endmodule // cv32e40p_controller diff --git a/src/UWE_projectCode/RTL分析代码/cv32e40p_cs_registers.sv b/src/UWE_projectCode/RTL分析代码/cv32e40p_cs_registers.sv deleted file mode 100644 index a46aab1..0000000 --- a/src/UWE_projectCode/RTL分析代码/cv32e40p_cs_registers.sv +++ /dev/null @@ -1,1587 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this 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. - -//////////////////////////////////////////////////////////////////////////////// -// Engineer: Sven Stucki - svstucki@student.ethz.ch // -// // -// Additional contributions by: // -// Andreas Traber - atraber@iis.ee.ethz.ch // -// Michael Gautschi - gautschi@iis.ee.ethz.ch // -// Davide Schiavone - pschiavo@iis.ee.ethz.ch // -// Andrea Bettati - andrea.bettati@studenti.unipr.it // -// // -// Design Name: Control and Status Registers // -// Project Name: RI5CY // -// Language: SystemVerilog // -// // -// Description: Control and Status Registers (CSRs) loosely following the // -// RiscV draft priviledged instruction set spec (v1.9) // -// Added Floating point support // -// // -//////////////////////////////////////////////////////////////////////////////// - -module cv32e40p_cs_registers - import cv32e40p_pkg::*; -#( - parameter N_HWLP = 2, - parameter N_HWLP_BITS = $clog2(N_HWLP), - parameter APU = 0, - parameter A_EXTENSION = 0, - parameter FPU = 0, - parameter PULP_SECURE = 0, - parameter USE_PMP = 0, - parameter N_PMP_ENTRIES = 16, - parameter NUM_MHPMCOUNTERS = 1, - parameter PULP_XPULP = 0, - parameter PULP_CLUSTER = 0, - parameter DEBUG_TRIGGER_EN = 1 -) ( - // Clock and Reset - input logic clk, - input logic rst_n, - - // Hart ID - input logic [31:0] hart_id_i, - output logic [23:0] mtvec_o, - output logic [23:0] utvec_o, - output logic [ 1:0] mtvec_mode_o, - output logic [ 1:0] utvec_mode_o, - - // Used for mtvec address - input logic [31:0] mtvec_addr_i, - input logic csr_mtvec_init_i, - - // Interface to registers (SRAM like) - input csr_num_e csr_addr_i, - input logic [31:0] csr_wdata_i, - input csr_opcode_e csr_op_i, - output logic [31:0] csr_rdata_o, - - output logic [ 2:0] frm_o, - input logic [C_FFLAG-1:0] fflags_i, - input logic fflags_we_i, - - // Interrupts - output logic [31:0] mie_bypass_o, - input logic [31:0] mip_i, - output logic m_irq_enable_o, - output logic u_irq_enable_o, - - //csr_irq_sec_i is always 0 if PULP_SECURE is zero - input logic csr_irq_sec_i, - output logic sec_lvl_o, - output logic [31:0] mepc_o, - output logic [31:0] uepc_o, - //mcounteren_o is always 0 if PULP_SECURE is zero - output logic [31:0] mcounteren_o, - - // debug - input logic debug_mode_i, - input logic [ 2:0] debug_cause_i, - input logic debug_csr_save_i, - output logic [31:0] depc_o, - output logic debug_single_step_o, - output logic debug_ebreakm_o, - output logic debug_ebreaku_o, - output logic trigger_match_o, - - - output logic [N_PMP_ENTRIES-1:0][31:0] pmp_addr_o, - output logic [N_PMP_ENTRIES-1:0][ 7:0] pmp_cfg_o, - - output PrivLvl_t priv_lvl_o, - - input logic [31:0] pc_if_i, - input logic [31:0] pc_id_i, - input logic [31:0] pc_ex_i, - - input logic csr_save_if_i, - input logic csr_save_id_i, - input logic csr_save_ex_i, - - input logic csr_restore_mret_i, - input logic csr_restore_uret_i, - - input logic csr_restore_dret_i, - //coming from controller - input logic [ 5:0] csr_cause_i, - //coming from controller - input logic csr_save_cause_i, - // Hardware loops - input logic [N_HWLP-1:0][31:0] hwlp_start_i, - input logic [N_HWLP-1:0][31:0] hwlp_end_i, - input logic [N_HWLP-1:0][31:0] hwlp_cnt_i, - - output logic [ 31:0] hwlp_data_o, - output logic [N_HWLP_BITS-1:0] hwlp_regid_o, - output logic [ 2:0] hwlp_we_o, - - // Performance Counters - input logic mhpmevent_minstret_i, - input logic mhpmevent_load_i, - input logic mhpmevent_store_i, - input logic mhpmevent_jump_i, // Jump instruction retired (j, jr, jal, jalr) - input logic mhpmevent_branch_i, // Branch instruction retired (beq, bne, etc.) - input logic mhpmevent_branch_taken_i, // Branch instruction taken - input logic mhpmevent_compressed_i, - input logic mhpmevent_jr_stall_i, - input logic mhpmevent_imiss_i, - input logic mhpmevent_ld_stall_i, - input logic mhpmevent_pipe_stall_i, - input logic apu_typeconflict_i, - input logic apu_contention_i, - input logic apu_dep_i, - input logic apu_wb_i -); - - localparam NUM_HPM_EVENTS = 16; - - localparam MTVEC_MODE = 2'b01; - - localparam MAX_N_PMP_ENTRIES = 16; - localparam MAX_N_PMP_CFG = 4; - localparam N_PMP_CFG = N_PMP_ENTRIES % 4 == 0 ? N_PMP_ENTRIES / 4 : N_PMP_ENTRIES / 4 + 1; - - localparam MSTATUS_UIE_BIT = 0; - localparam MSTATUS_SIE_BIT = 1; - localparam MSTATUS_MIE_BIT = 3; - localparam MSTATUS_UPIE_BIT = 4; - localparam MSTATUS_SPIE_BIT = 5; - localparam MSTATUS_MPIE_BIT = 7; - localparam MSTATUS_SPP_BIT = 8; - localparam MSTATUS_MPP_BIT_HIGH = 12; - localparam MSTATUS_MPP_BIT_LOW = 11; - localparam MSTATUS_MPRV_BIT = 17; - - // misa - localparam logic [1:0] MXL = 2'd1; // M-XLEN: XLEN in M-Mode for RV32 - localparam logic [31:0] MISA_VALUE = (32'(A_EXTENSION) << 0) // A - Atomic Instructions extension - | (1 << 2) // C - Compressed extension - | (0 << 3) // D - Double precision floating-point extension - | (0 << 4) // E - RV32E base ISA - | (32'(FPU) << 5) // F - Single precision floating-point extension - | (1 << 8) // I - RV32I/64I/128I base ISA - | (1 << 12) // M - Integer Multiply/Divide extension - | (0 << 13) // N - User level interrupts supported - | (0 << 18) // S - Supervisor mode implemented - | (32'(PULP_SECURE) << 20) // U - User mode implemented - | (32'(PULP_XPULP || PULP_CLUSTER) << 23) // X - Non-standard extensions present - | (32'(MXL) << 30); // M-XLEN - - localparam MHPMCOUNTER_WIDTH = 64; - - // This local parameter when set to 1 makes the Perf Counters not compliant with RISC-V - // as it does not implement mcycle and minstret - // but only HPMCOUNTERs (depending on NUM_MHPMCOUNTERS) - localparam PULP_PERF_COUNTERS = 0; - - typedef struct packed { - logic uie; - // logic sie; - unimplemented, hardwired to '0 - // logic hie; - unimplemented, hardwired to '0 - logic mie; - logic upie; - // logic spie; - unimplemented, hardwired to '0 - // logic hpie; - unimplemented, hardwired to '0 - logic mpie; - // logic spp; - unimplemented, hardwired to '0 - // logic[1:0] hpp; - unimplemented, hardwired to '0 - PrivLvl_t mpp; - logic mprv; - } Status_t; - - typedef struct packed { - logic [31:28] xdebugver; - logic [27:16] zero2; - logic ebreakm; - logic zero1; - logic ebreaks; - logic ebreaku; - logic stepie; - logic stopcount; - logic stoptime; - logic [8:6] cause; - logic zero0; - logic mprven; - logic nmip; - logic step; - PrivLvl_t prv; - } Dcsr_t; - - typedef struct packed { - logic [MAX_N_PMP_ENTRIES-1:0][31:0] pmpaddr; - logic [MAX_N_PMP_CFG-1:0][31:0] pmpcfg_packed; - logic [MAX_N_PMP_ENTRIES-1:0][7:0] pmpcfg; - } Pmp_t; - - // CSR update logic - logic [31:0] csr_wdata_int; - logic [31:0] csr_rdata_int; - logic csr_we_int; - logic [C_RM-1:0] frm_q, frm_n; - logic [C_FFLAG-1:0] fflags_q, fflags_n; - - // Interrupt control signals - logic [31:0] mepc_q, mepc_n; - logic [31:0] uepc_q, uepc_n; - // Trigger - logic [31:0] tmatch_control_rdata; - logic [31:0] tmatch_value_rdata; - logic [15:0] tinfo_types; - // Debug - Dcsr_t dcsr_q, dcsr_n; - logic [31:0] depc_q, depc_n; - logic [31:0] dscratch0_q, dscratch0_n; - logic [31:0] dscratch1_q, dscratch1_n; - logic [31:0] mscratch_q, mscratch_n; - - logic [31:0] exception_pc; - Status_t mstatus_q, mstatus_n; - logic [5:0] mcause_q, mcause_n; - logic [5:0] ucause_q, ucause_n; - //not implemented yet - logic [23:0] mtvec_n, mtvec_q; - logic [23:0] utvec_n, utvec_q; - logic [1:0] mtvec_mode_n, mtvec_mode_q; - logic [1:0] utvec_mode_n, utvec_mode_q; - - logic [31:0] mip; // Bits are masked according to IRQ_MASK - logic [31:0] mie_q, mie_n; // Bits are masked according to IRQ_MASK - - logic [31:0] csr_mie_wdata; - logic csr_mie_we; - - logic is_irq; - PrivLvl_t priv_lvl_n, priv_lvl_q; - Pmp_t pmp_reg_q, pmp_reg_n; - //clock gating for pmp regs - logic [MAX_N_PMP_ENTRIES-1:0] pmpaddr_we; - logic [MAX_N_PMP_ENTRIES-1:0] pmpcfg_we; - - // Performance Counter Signals - logic [ 31:0][MHPMCOUNTER_WIDTH-1:0] mhpmcounter_q; // performance counters - logic [31:0][31:0] mhpmevent_q, mhpmevent_n; // event enable - logic [31:0] mcounteren_q, mcounteren_n; // user mode counter enable - logic [31:0] mcountinhibit_q, mcountinhibit_n; // performance counter enable - logic [NUM_HPM_EVENTS-1:0] hpm_events; // events for performance counters - logic [31:0][MHPMCOUNTER_WIDTH-1:0] mhpmcounter_increment; // increment of mhpmcounter_q - logic [31:0] mhpmcounter_write_lower; // write 32 lower bits of mhpmcounter_q - logic [31:0] mhpmcounter_write_upper; // write 32 upper bits mhpmcounter_q - logic [31:0] mhpmcounter_write_increment; // write increment of mhpmcounter_q - - assign is_irq = csr_cause_i[5]; - - // mip CSR - assign mip = mip_i; - - // mie_n is used instead of mie_q such that a CSR write to the MIE register can - // affect the instruction immediately following it. - - // MIE CSR operation logic - always_comb begin - csr_mie_wdata = csr_wdata_i; - csr_mie_we = 1'b1; - - case (csr_op_i) - CSR_OP_WRITE: csr_mie_wdata = csr_wdata_i; - CSR_OP_SET: csr_mie_wdata = csr_wdata_i | mie_q; - CSR_OP_CLEAR: csr_mie_wdata = (~csr_wdata_i) & mie_q; - CSR_OP_READ: begin - csr_mie_wdata = csr_wdata_i; - csr_mie_we = 1'b0; - end - endcase - end - - assign mie_bypass_o = ((csr_addr_i == CSR_MIE) && csr_mie_we) ? csr_mie_wdata & IRQ_MASK : mie_q; - - //////////////////////////////////////////// - // ____ ____ ____ ____ // - // / ___/ ___|| _ \ | _ \ ___ __ _ // - // | | \___ \| |_) | | |_) / _ \/ _` | // - // | |___ ___) | _ < | _ < __/ (_| | // - // \____|____/|_| \_\ |_| \_\___|\__, | // - // |___/ // - //////////////////////////////////////////// - - // NOTE!!!: Any new CSR register added in this file must also be - // added to the valid CSR register list cv32e40p_decoder.v - - genvar j; - - - if (PULP_SECURE == 1) begin : gen_pulp_secure_read_logic - // read logic - always_comb begin - case (csr_addr_i) - // fcsr: Floating-Point Control and Status Register (frm + fflags). - CSR_FFLAGS: csr_rdata_int = (FPU == 1) ? {27'b0, fflags_q} : '0; - CSR_FRM: csr_rdata_int = (FPU == 1) ? {29'b0, frm_q} : '0; - CSR_FCSR: csr_rdata_int = (FPU == 1) ? {24'b0, frm_q, fflags_q} : '0; - - // mstatus - CSR_MSTATUS: - csr_rdata_int = { - 14'b0, - mstatus_q.mprv, - 4'b0, - mstatus_q.mpp, - 3'b0, - mstatus_q.mpie, - 2'h0, - mstatus_q.upie, - mstatus_q.mie, - 2'h0, - mstatus_q.uie - }; - - // misa: machine isa register - CSR_MISA: csr_rdata_int = MISA_VALUE; - - // mie: machine interrupt enable - CSR_MIE: begin - csr_rdata_int = mie_q; - end - - // mtvec: machine trap-handler base address - CSR_MTVEC: csr_rdata_int = {mtvec_q, 6'h0, mtvec_mode_q}; - // mscratch: machine scratch - CSR_MSCRATCH: csr_rdata_int = mscratch_q; - // mepc: exception program counter - CSR_MEPC: csr_rdata_int = mepc_q; - // mcause: exception cause - CSR_MCAUSE: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]}; - // mip: interrupt pending - CSR_MIP: begin - csr_rdata_int = mip; - end - - // mhartid: unique hardware thread id - CSR_MHARTID: csr_rdata_int = hart_id_i; - - // mvendorid: Machine Vendor ID - CSR_MVENDORID: csr_rdata_int = {MVENDORID_BANK, MVENDORID_OFFSET}; - - // marchid: Machine Architecture ID - CSR_MARCHID: csr_rdata_int = MARCHID; - - // unimplemented, read 0 CSRs - CSR_MIMPID, CSR_MTVAL: csr_rdata_int = 'b0; - - // mcounteren: Machine Counter-Enable - CSR_MCOUNTEREN: csr_rdata_int = mcounteren_q; - - CSR_TSELECT, CSR_TDATA3, CSR_MCONTEXT, CSR_SCONTEXT: csr_rdata_int = 'b0; // Always read 0 - CSR_TDATA1: csr_rdata_int = tmatch_control_rdata; - CSR_TDATA2: csr_rdata_int = tmatch_value_rdata; - CSR_TINFO: csr_rdata_int = tinfo_types; - - CSR_DCSR: csr_rdata_int = dcsr_q; // - CSR_DPC: csr_rdata_int = depc_q; - CSR_DSCRATCH0: csr_rdata_int = dscratch0_q; // - CSR_DSCRATCH1: csr_rdata_int = dscratch1_q; // - - // Hardware Performance Monitor - CSR_MCYCLE, - CSR_MINSTRET, - CSR_MHPMCOUNTER3, - CSR_MHPMCOUNTER4, CSR_MHPMCOUNTER5, CSR_MHPMCOUNTER6, CSR_MHPMCOUNTER7, - CSR_MHPMCOUNTER8, CSR_MHPMCOUNTER9, CSR_MHPMCOUNTER10, CSR_MHPMCOUNTER11, - CSR_MHPMCOUNTER12, CSR_MHPMCOUNTER13, CSR_MHPMCOUNTER14, CSR_MHPMCOUNTER15, - CSR_MHPMCOUNTER16, CSR_MHPMCOUNTER17, CSR_MHPMCOUNTER18, CSR_MHPMCOUNTER19, - CSR_MHPMCOUNTER20, CSR_MHPMCOUNTER21, CSR_MHPMCOUNTER22, CSR_MHPMCOUNTER23, - CSR_MHPMCOUNTER24, CSR_MHPMCOUNTER25, CSR_MHPMCOUNTER26, CSR_MHPMCOUNTER27, - CSR_MHPMCOUNTER28, CSR_MHPMCOUNTER29, CSR_MHPMCOUNTER30, CSR_MHPMCOUNTER31, - CSR_CYCLE, - CSR_INSTRET, - CSR_HPMCOUNTER3, - CSR_HPMCOUNTER4, CSR_HPMCOUNTER5, CSR_HPMCOUNTER6, CSR_HPMCOUNTER7, - CSR_HPMCOUNTER8, CSR_HPMCOUNTER9, CSR_HPMCOUNTER10, CSR_HPMCOUNTER11, - CSR_HPMCOUNTER12, CSR_HPMCOUNTER13, CSR_HPMCOUNTER14, CSR_HPMCOUNTER15, - CSR_HPMCOUNTER16, CSR_HPMCOUNTER17, CSR_HPMCOUNTER18, CSR_HPMCOUNTER19, - CSR_HPMCOUNTER20, CSR_HPMCOUNTER21, CSR_HPMCOUNTER22, CSR_HPMCOUNTER23, - CSR_HPMCOUNTER24, CSR_HPMCOUNTER25, CSR_HPMCOUNTER26, CSR_HPMCOUNTER27, - CSR_HPMCOUNTER28, CSR_HPMCOUNTER29, CSR_HPMCOUNTER30, CSR_HPMCOUNTER31: - csr_rdata_int = mhpmcounter_q[csr_addr_i[4:0]][31:0]; - - CSR_MCYCLEH, - CSR_MINSTRETH, - CSR_MHPMCOUNTER3H, - CSR_MHPMCOUNTER4H, CSR_MHPMCOUNTER5H, CSR_MHPMCOUNTER6H, CSR_MHPMCOUNTER7H, - CSR_MHPMCOUNTER8H, CSR_MHPMCOUNTER9H, CSR_MHPMCOUNTER10H, CSR_MHPMCOUNTER11H, - CSR_MHPMCOUNTER12H, CSR_MHPMCOUNTER13H, CSR_MHPMCOUNTER14H, CSR_MHPMCOUNTER15H, - CSR_MHPMCOUNTER16H, CSR_MHPMCOUNTER17H, CSR_MHPMCOUNTER18H, CSR_MHPMCOUNTER19H, - CSR_MHPMCOUNTER20H, CSR_MHPMCOUNTER21H, CSR_MHPMCOUNTER22H, CSR_MHPMCOUNTER23H, - CSR_MHPMCOUNTER24H, CSR_MHPMCOUNTER25H, CSR_MHPMCOUNTER26H, CSR_MHPMCOUNTER27H, - CSR_MHPMCOUNTER28H, CSR_MHPMCOUNTER29H, CSR_MHPMCOUNTER30H, CSR_MHPMCOUNTER31H, - CSR_CYCLEH, - CSR_INSTRETH, - CSR_HPMCOUNTER3H, - CSR_HPMCOUNTER4H, CSR_HPMCOUNTER5H, CSR_HPMCOUNTER6H, CSR_HPMCOUNTER7H, - CSR_HPMCOUNTER8H, CSR_HPMCOUNTER9H, CSR_HPMCOUNTER10H, CSR_HPMCOUNTER11H, - CSR_HPMCOUNTER12H, CSR_HPMCOUNTER13H, CSR_HPMCOUNTER14H, CSR_HPMCOUNTER15H, - CSR_HPMCOUNTER16H, CSR_HPMCOUNTER17H, CSR_HPMCOUNTER18H, CSR_HPMCOUNTER19H, - CSR_HPMCOUNTER20H, CSR_HPMCOUNTER21H, CSR_HPMCOUNTER22H, CSR_HPMCOUNTER23H, - CSR_HPMCOUNTER24H, CSR_HPMCOUNTER25H, CSR_HPMCOUNTER26H, CSR_HPMCOUNTER27H, - CSR_HPMCOUNTER28H, CSR_HPMCOUNTER29H, CSR_HPMCOUNTER30H, CSR_HPMCOUNTER31H: - csr_rdata_int = mhpmcounter_q[csr_addr_i[4:0]][63:32]; - - CSR_MCOUNTINHIBIT: csr_rdata_int = mcountinhibit_q; - - CSR_MHPMEVENT3, - CSR_MHPMEVENT4, CSR_MHPMEVENT5, CSR_MHPMEVENT6, CSR_MHPMEVENT7, - CSR_MHPMEVENT8, CSR_MHPMEVENT9, CSR_MHPMEVENT10, CSR_MHPMEVENT11, - CSR_MHPMEVENT12, CSR_MHPMEVENT13, CSR_MHPMEVENT14, CSR_MHPMEVENT15, - CSR_MHPMEVENT16, CSR_MHPMEVENT17, CSR_MHPMEVENT18, CSR_MHPMEVENT19, - CSR_MHPMEVENT20, CSR_MHPMEVENT21, CSR_MHPMEVENT22, CSR_MHPMEVENT23, - CSR_MHPMEVENT24, CSR_MHPMEVENT25, CSR_MHPMEVENT26, CSR_MHPMEVENT27, - CSR_MHPMEVENT28, CSR_MHPMEVENT29, CSR_MHPMEVENT30, CSR_MHPMEVENT31: - csr_rdata_int = mhpmevent_q[csr_addr_i[4:0]]; - - // hardware loops (not official) - CSR_LPSTART0: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_start_i[0]; - CSR_LPEND0: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_end_i[0]; - CSR_LPCOUNT0: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_cnt_i[0]; - CSR_LPSTART1: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_start_i[1]; - CSR_LPEND1: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_end_i[1]; - CSR_LPCOUNT1: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_cnt_i[1]; - - // PMP config registers - CSR_PMPCFG0: csr_rdata_int = USE_PMP ? pmp_reg_q.pmpcfg_packed[0] : '0; - CSR_PMPCFG1: csr_rdata_int = USE_PMP ? pmp_reg_q.pmpcfg_packed[1] : '0; - CSR_PMPCFG2: csr_rdata_int = USE_PMP ? pmp_reg_q.pmpcfg_packed[2] : '0; - CSR_PMPCFG3: csr_rdata_int = USE_PMP ? pmp_reg_q.pmpcfg_packed[3] : '0; - - CSR_PMPADDR0, CSR_PMPADDR1, CSR_PMPADDR2, CSR_PMPADDR3, - CSR_PMPADDR4, CSR_PMPADDR5, CSR_PMPADDR6, CSR_PMPADDR7, - CSR_PMPADDR8, CSR_PMPADDR9, CSR_PMPADDR10, CSR_PMPADDR11, - CSR_PMPADDR12, CSR_PMPADDR13, CSR_PMPADDR14, CSR_PMPADDR15 : - csr_rdata_int = USE_PMP ? pmp_reg_q.pmpaddr[csr_addr_i[3:0]] : '0; - - /* USER CSR */ - // ustatus - CSR_USTATUS: csr_rdata_int = {27'b0, mstatus_q.upie, 3'h0, mstatus_q.uie}; - // utvec: user trap-handler base address - CSR_UTVEC: csr_rdata_int = {utvec_q, 6'h0, utvec_mode_q}; - // duplicated mhartid: unique hardware thread id (not official) - CSR_UHARTID: csr_rdata_int = !PULP_XPULP ? 'b0 : hart_id_i; - // uepc: exception program counter - CSR_UEPC: csr_rdata_int = uepc_q; - // ucause: exception cause - CSR_UCAUSE: csr_rdata_int = {ucause_q[5], 26'h0, ucause_q[4:0]}; - - // current priv level (not official) - CSR_PRIVLV: csr_rdata_int = !PULP_XPULP ? 'b0 : {30'h0, priv_lvl_q}; - - default: csr_rdata_int = '0; - endcase - end - end else begin : gen_no_pulp_secure_read_logic // PULP_SECURE == 0 - // read logic - always_comb begin - - case (csr_addr_i) - // fcsr: Floating-Point Control and Status Register (frm + fflags). - CSR_FFLAGS: csr_rdata_int = (FPU == 1) ? {27'b0, fflags_q} : '0; - CSR_FRM: csr_rdata_int = (FPU == 1) ? {29'b0, frm_q} : '0; - CSR_FCSR: csr_rdata_int = (FPU == 1) ? {24'b0, frm_q, fflags_q} : '0; - // mstatus: always M-mode, contains IE bit - CSR_MSTATUS: - csr_rdata_int = { - 14'b0, - mstatus_q.mprv, - 4'b0, - mstatus_q.mpp, - 3'b0, - mstatus_q.mpie, - 2'h0, - mstatus_q.upie, - mstatus_q.mie, - 2'h0, - mstatus_q.uie - }; - // misa: machine isa register - CSR_MISA: csr_rdata_int = MISA_VALUE; - // mie: machine interrupt enable - CSR_MIE: begin - csr_rdata_int = mie_q; - end - - // mtvec: machine trap-handler base address - CSR_MTVEC: csr_rdata_int = {mtvec_q, 6'h0, mtvec_mode_q}; - // mscratch: machine scratch - CSR_MSCRATCH: csr_rdata_int = mscratch_q; - // mepc: exception program counter - CSR_MEPC: csr_rdata_int = mepc_q; - // mcause: exception cause - CSR_MCAUSE: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]}; - // mip: interrupt pending - CSR_MIP: begin - csr_rdata_int = mip; - end - // mhartid: unique hardware thread id - CSR_MHARTID: csr_rdata_int = hart_id_i; - - // mvendorid: Machine Vendor ID - CSR_MVENDORID: csr_rdata_int = {MVENDORID_BANK, MVENDORID_OFFSET}; - - // marchid: Machine Architecture ID - CSR_MARCHID: csr_rdata_int = MARCHID; - - // unimplemented, read 0 CSRs - CSR_MIMPID, CSR_MTVAL: csr_rdata_int = 'b0; - - CSR_TSELECT, CSR_TDATA3, CSR_MCONTEXT, CSR_SCONTEXT: csr_rdata_int = 'b0; // Always read 0 - CSR_TDATA1: csr_rdata_int = tmatch_control_rdata; - CSR_TDATA2: csr_rdata_int = tmatch_value_rdata; - CSR_TINFO: csr_rdata_int = tinfo_types; - - CSR_DCSR: csr_rdata_int = dcsr_q; // - CSR_DPC: csr_rdata_int = depc_q; - CSR_DSCRATCH0: csr_rdata_int = dscratch0_q; // - CSR_DSCRATCH1: csr_rdata_int = dscratch1_q; // - - // Hardware Performance Monitor - CSR_MCYCLE, - CSR_MINSTRET, - CSR_MHPMCOUNTER3, - CSR_MHPMCOUNTER4, CSR_MHPMCOUNTER5, CSR_MHPMCOUNTER6, CSR_MHPMCOUNTER7, - CSR_MHPMCOUNTER8, CSR_MHPMCOUNTER9, CSR_MHPMCOUNTER10, CSR_MHPMCOUNTER11, - CSR_MHPMCOUNTER12, CSR_MHPMCOUNTER13, CSR_MHPMCOUNTER14, CSR_MHPMCOUNTER15, - CSR_MHPMCOUNTER16, CSR_MHPMCOUNTER17, CSR_MHPMCOUNTER18, CSR_MHPMCOUNTER19, - CSR_MHPMCOUNTER20, CSR_MHPMCOUNTER21, CSR_MHPMCOUNTER22, CSR_MHPMCOUNTER23, - CSR_MHPMCOUNTER24, CSR_MHPMCOUNTER25, CSR_MHPMCOUNTER26, CSR_MHPMCOUNTER27, - CSR_MHPMCOUNTER28, CSR_MHPMCOUNTER29, CSR_MHPMCOUNTER30, CSR_MHPMCOUNTER31, - CSR_CYCLE, - CSR_INSTRET, - CSR_HPMCOUNTER3, - CSR_HPMCOUNTER4, CSR_HPMCOUNTER5, CSR_HPMCOUNTER6, CSR_HPMCOUNTER7, - CSR_HPMCOUNTER8, CSR_HPMCOUNTER9, CSR_HPMCOUNTER10, CSR_HPMCOUNTER11, - CSR_HPMCOUNTER12, CSR_HPMCOUNTER13, CSR_HPMCOUNTER14, CSR_HPMCOUNTER15, - CSR_HPMCOUNTER16, CSR_HPMCOUNTER17, CSR_HPMCOUNTER18, CSR_HPMCOUNTER19, - CSR_HPMCOUNTER20, CSR_HPMCOUNTER21, CSR_HPMCOUNTER22, CSR_HPMCOUNTER23, - CSR_HPMCOUNTER24, CSR_HPMCOUNTER25, CSR_HPMCOUNTER26, CSR_HPMCOUNTER27, - CSR_HPMCOUNTER28, CSR_HPMCOUNTER29, CSR_HPMCOUNTER30, CSR_HPMCOUNTER31: - csr_rdata_int = mhpmcounter_q[csr_addr_i[4:0]][31:0]; - - CSR_MCYCLEH, - CSR_MINSTRETH, - CSR_MHPMCOUNTER3H, - CSR_MHPMCOUNTER4H, CSR_MHPMCOUNTER5H, CSR_MHPMCOUNTER6H, CSR_MHPMCOUNTER7H, - CSR_MHPMCOUNTER8H, CSR_MHPMCOUNTER9H, CSR_MHPMCOUNTER10H, CSR_MHPMCOUNTER11H, - CSR_MHPMCOUNTER12H, CSR_MHPMCOUNTER13H, CSR_MHPMCOUNTER14H, CSR_MHPMCOUNTER15H, - CSR_MHPMCOUNTER16H, CSR_MHPMCOUNTER17H, CSR_MHPMCOUNTER18H, CSR_MHPMCOUNTER19H, - CSR_MHPMCOUNTER20H, CSR_MHPMCOUNTER21H, CSR_MHPMCOUNTER22H, CSR_MHPMCOUNTER23H, - CSR_MHPMCOUNTER24H, CSR_MHPMCOUNTER25H, CSR_MHPMCOUNTER26H, CSR_MHPMCOUNTER27H, - CSR_MHPMCOUNTER28H, CSR_MHPMCOUNTER29H, CSR_MHPMCOUNTER30H, CSR_MHPMCOUNTER31H, - CSR_CYCLEH, - CSR_INSTRETH, - CSR_HPMCOUNTER3H, - CSR_HPMCOUNTER4H, CSR_HPMCOUNTER5H, CSR_HPMCOUNTER6H, CSR_HPMCOUNTER7H, - CSR_HPMCOUNTER8H, CSR_HPMCOUNTER9H, CSR_HPMCOUNTER10H, CSR_HPMCOUNTER11H, - CSR_HPMCOUNTER12H, CSR_HPMCOUNTER13H, CSR_HPMCOUNTER14H, CSR_HPMCOUNTER15H, - CSR_HPMCOUNTER16H, CSR_HPMCOUNTER17H, CSR_HPMCOUNTER18H, CSR_HPMCOUNTER19H, - CSR_HPMCOUNTER20H, CSR_HPMCOUNTER21H, CSR_HPMCOUNTER22H, CSR_HPMCOUNTER23H, - CSR_HPMCOUNTER24H, CSR_HPMCOUNTER25H, CSR_HPMCOUNTER26H, CSR_HPMCOUNTER27H, - CSR_HPMCOUNTER28H, CSR_HPMCOUNTER29H, CSR_HPMCOUNTER30H, CSR_HPMCOUNTER31H: - csr_rdata_int = (MHPMCOUNTER_WIDTH == 64) ? mhpmcounter_q[csr_addr_i[4:0]][63:32] : '0; - - CSR_MCOUNTINHIBIT: csr_rdata_int = mcountinhibit_q; - - CSR_MHPMEVENT3, - CSR_MHPMEVENT4, CSR_MHPMEVENT5, CSR_MHPMEVENT6, CSR_MHPMEVENT7, - CSR_MHPMEVENT8, CSR_MHPMEVENT9, CSR_MHPMEVENT10, CSR_MHPMEVENT11, - CSR_MHPMEVENT12, CSR_MHPMEVENT13, CSR_MHPMEVENT14, CSR_MHPMEVENT15, - CSR_MHPMEVENT16, CSR_MHPMEVENT17, CSR_MHPMEVENT18, CSR_MHPMEVENT19, - CSR_MHPMEVENT20, CSR_MHPMEVENT21, CSR_MHPMEVENT22, CSR_MHPMEVENT23, - CSR_MHPMEVENT24, CSR_MHPMEVENT25, CSR_MHPMEVENT26, CSR_MHPMEVENT27, - CSR_MHPMEVENT28, CSR_MHPMEVENT29, CSR_MHPMEVENT30, CSR_MHPMEVENT31: - csr_rdata_int = mhpmevent_q[csr_addr_i[4:0]]; - - // hardware loops (not official) - CSR_LPSTART0: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_start_i[0]; - CSR_LPEND0: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_end_i[0]; - CSR_LPCOUNT0: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_cnt_i[0]; - CSR_LPSTART1: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_start_i[1]; - CSR_LPEND1: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_end_i[1]; - CSR_LPCOUNT1: csr_rdata_int = !PULP_XPULP ? 'b0 : hwlp_cnt_i[1]; - - /* USER CSR */ - // dublicated mhartid: unique hardware thread id (not official) - CSR_UHARTID: csr_rdata_int = !PULP_XPULP ? 'b0 : hart_id_i; - // current priv level (not official) - CSR_PRIVLV: csr_rdata_int = !PULP_XPULP ? 'b0 : {30'h0, priv_lvl_q}; - default: csr_rdata_int = '0; - endcase - end - end //PULP_SECURE - - if (PULP_SECURE == 1) begin : gen_pulp_secure_write_logic - // write logic - always_comb begin - fflags_n = fflags_q; - frm_n = frm_q; - mscratch_n = mscratch_q; - mepc_n = mepc_q; - uepc_n = uepc_q; - depc_n = depc_q; - dcsr_n = dcsr_q; - dscratch0_n = dscratch0_q; - dscratch1_n = dscratch1_q; - - mstatus_n = mstatus_q; - mcause_n = mcause_q; - ucause_n = ucause_q; - hwlp_we_o = '0; - hwlp_regid_o = '0; - exception_pc = pc_id_i; - priv_lvl_n = priv_lvl_q; - mtvec_n = csr_mtvec_init_i ? mtvec_addr_i[31:8] : mtvec_q; - utvec_n = utvec_q; - mtvec_mode_n = mtvec_mode_q; - utvec_mode_n = utvec_mode_q; - pmp_reg_n.pmpaddr = pmp_reg_q.pmpaddr; - pmp_reg_n.pmpcfg_packed = pmp_reg_q.pmpcfg_packed; - pmpaddr_we = '0; - pmpcfg_we = '0; - - mie_n = mie_q; - - if (FPU == 1) if (fflags_we_i) fflags_n = fflags_i | fflags_q; - - case (csr_addr_i) - // fcsr: Floating-Point Control and Status Register (frm, fflags, fprec). - CSR_FFLAGS: if (csr_we_int) fflags_n = (FPU == 1) ? csr_wdata_int[C_FFLAG-1:0] : '0; - CSR_FRM: if (csr_we_int) frm_n = (FPU == 1) ? csr_wdata_int[C_RM-1:0] : '0; - CSR_FCSR: - if (csr_we_int) begin - fflags_n = (FPU == 1) ? csr_wdata_int[C_FFLAG-1:0] : '0; - frm_n = (FPU == 1) ? csr_wdata_int[C_RM+C_FFLAG-1:C_FFLAG] : '0; - end - - // mstatus: IE bit - CSR_MSTATUS: - if (csr_we_int) begin - mstatus_n = '{ - uie: csr_wdata_int[MSTATUS_UIE_BIT], - mie: csr_wdata_int[MSTATUS_MIE_BIT], - upie: csr_wdata_int[MSTATUS_UPIE_BIT], - mpie: csr_wdata_int[MSTATUS_MPIE_BIT], - mpp: PrivLvl_t'(csr_wdata_int[MSTATUS_MPP_BIT_HIGH:MSTATUS_MPP_BIT_LOW]), - mprv: csr_wdata_int[MSTATUS_MPRV_BIT] - }; - end - // mie: machine interrupt enable - CSR_MIE: - if (csr_we_int) begin - mie_n = csr_wdata_int & IRQ_MASK; - end - // mtvec: machine trap-handler base address - CSR_MTVEC: - if (csr_we_int) begin - mtvec_n = csr_wdata_int[31:8]; - mtvec_mode_n = {1'b0, csr_wdata_int[0]}; // Only direct and vectored mode are supported - end - // mscratch: machine scratch - CSR_MSCRATCH: - if (csr_we_int) begin - mscratch_n = csr_wdata_int; - end - // mepc: exception program counter - CSR_MEPC: - if (csr_we_int) begin - mepc_n = csr_wdata_int & ~32'b1; // force 16-bit alignment - end - // mcause - CSR_MCAUSE: if (csr_we_int) mcause_n = {csr_wdata_int[31], csr_wdata_int[4:0]}; - - // Debug - CSR_DCSR: - if (csr_we_int) begin - // Following are read-only and never assigned here (dcsr_q value is used): - // - // - xdebugver - // - cause - // - nmip - - dcsr_n.ebreakm = csr_wdata_int[15]; - dcsr_n.ebreaks = 1'b0; // ebreaks (implemented as WARL) - dcsr_n.ebreaku = csr_wdata_int[12]; - dcsr_n.stepie = csr_wdata_int[11]; // stepie - dcsr_n.stopcount = 1'b0; // stopcount - dcsr_n.stoptime = 1'b0; // stoptime - dcsr_n.mprven = 1'b0; // mprven - dcsr_n.step = csr_wdata_int[2]; - dcsr_n.prv = (PrivLvl_t'(csr_wdata_int[1:0]) == PRIV_LVL_M) ? PRIV_LVL_M : PRIV_LVL_U; // prv (implemented as WARL) - end - - CSR_DPC: - if (csr_we_int) begin - depc_n = csr_wdata_int & ~32'b1; // force 16-bit alignment - end - - CSR_DSCRATCH0: - if (csr_we_int) begin - dscratch0_n = csr_wdata_int; - end - - CSR_DSCRATCH1: - if (csr_we_int) begin - dscratch1_n = csr_wdata_int; - end - - // hardware loops - CSR_LPSTART0: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b001; - hwlp_regid_o = 1'b0; - end - CSR_LPEND0: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b010; - hwlp_regid_o = 1'b0; - end - CSR_LPCOUNT0: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b100; - hwlp_regid_o = 1'b0; - end - CSR_LPSTART1: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b001; - hwlp_regid_o = 1'b1; - end - CSR_LPEND1: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b010; - hwlp_regid_o = 1'b1; - end - CSR_LPCOUNT1: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b100; - hwlp_regid_o = 1'b1; - end - - // PMP config registers - CSR_PMPCFG0: - if (csr_we_int) begin - pmp_reg_n.pmpcfg_packed[0] = csr_wdata_int; - pmpcfg_we[3:0] = 4'b1111; - end - CSR_PMPCFG1: - if (csr_we_int) begin - pmp_reg_n.pmpcfg_packed[1] = csr_wdata_int; - pmpcfg_we[7:4] = 4'b1111; - end - CSR_PMPCFG2: - if (csr_we_int) begin - pmp_reg_n.pmpcfg_packed[2] = csr_wdata_int; - pmpcfg_we[11:8] = 4'b1111; - end - CSR_PMPCFG3: - if (csr_we_int) begin - pmp_reg_n.pmpcfg_packed[3] = csr_wdata_int; - pmpcfg_we[15:12] = 4'b1111; - end - - CSR_PMPADDR0, CSR_PMPADDR1, CSR_PMPADDR2, CSR_PMPADDR3, - CSR_PMPADDR4, CSR_PMPADDR5, CSR_PMPADDR6, CSR_PMPADDR7, - CSR_PMPADDR8, CSR_PMPADDR9, CSR_PMPADDR10, CSR_PMPADDR11, - CSR_PMPADDR12, CSR_PMPADDR13, CSR_PMPADDR14, CSR_PMPADDR15 : - if (csr_we_int) begin - pmp_reg_n.pmpaddr[csr_addr_i[3:0]] = csr_wdata_int; - pmpaddr_we[csr_addr_i[3:0]] = 1'b1; - end - - - /* USER CSR */ - // ucause: exception cause - CSR_USTATUS: - if (csr_we_int) begin - mstatus_n = '{ - uie: csr_wdata_int[MSTATUS_UIE_BIT], - mie: mstatus_q.mie, - upie: csr_wdata_int[MSTATUS_UPIE_BIT], - mpie: mstatus_q.mpie, - mpp: mstatus_q.mpp, - mprv: mstatus_q.mprv - }; - end - // utvec: user trap-handler base address - CSR_UTVEC: - if (csr_we_int) begin - utvec_n = csr_wdata_int[31:8]; - utvec_mode_n = {1'b0, csr_wdata_int[0]}; // Only direct and vectored mode are supported - end - // uepc: exception program counter - CSR_UEPC: - if (csr_we_int) begin - uepc_n = csr_wdata_int; - end - // ucause: exception cause - CSR_UCAUSE: if (csr_we_int) ucause_n = {csr_wdata_int[31], csr_wdata_int[4:0]}; - endcase - - // exception controller gets priority over other writes - unique case (1'b1) - - csr_save_cause_i: begin - - unique case (1'b1) - csr_save_if_i: exception_pc = pc_if_i; - csr_save_id_i: exception_pc = pc_id_i; - csr_save_ex_i: exception_pc = pc_ex_i; - default: ; - endcase - - unique case (priv_lvl_q) - - PRIV_LVL_U: begin - if (~is_irq) begin - //Exceptions, Ecall U --> M - priv_lvl_n = PRIV_LVL_M; - mstatus_n.mpie = mstatus_q.uie; - mstatus_n.mie = 1'b0; - mstatus_n.mpp = PRIV_LVL_U; - if (debug_csr_save_i) depc_n = exception_pc; - else mepc_n = exception_pc; - mcause_n = csr_cause_i; - - end else begin - if (~csr_irq_sec_i) begin - //U --> U - priv_lvl_n = PRIV_LVL_U; - mstatus_n.upie = mstatus_q.uie; - mstatus_n.uie = 1'b0; - if (debug_csr_save_i) depc_n = exception_pc; - else uepc_n = exception_pc; - ucause_n = csr_cause_i; - - end else begin - //U --> M - priv_lvl_n = PRIV_LVL_M; - mstatus_n.mpie = mstatus_q.uie; - mstatus_n.mie = 1'b0; - mstatus_n.mpp = PRIV_LVL_U; - if (debug_csr_save_i) depc_n = exception_pc; - else mepc_n = exception_pc; - mcause_n = csr_cause_i; - end - end - end //PRIV_LVL_U - - PRIV_LVL_M: begin - if (debug_csr_save_i) begin - // all interrupts are masked, don't update cause, epc, tval dpc - // and mpstatus - dcsr_n.prv = PRIV_LVL_M; - dcsr_n.cause = debug_cause_i; - depc_n = exception_pc; - end else begin - //Exceptions or Interrupts from PRIV_LVL_M always do M --> M - priv_lvl_n = PRIV_LVL_M; - mstatus_n.mpie = mstatus_q.mie; - mstatus_n.mie = 1'b0; - mstatus_n.mpp = PRIV_LVL_M; - mepc_n = exception_pc; - mcause_n = csr_cause_i; - end - end //PRIV_LVL_M - default: ; - - endcase - - end //csr_save_cause_i - - csr_restore_uret_i: begin //URET - //mstatus_q.upp is implicitly 0, i.e PRIV_LVL_U - mstatus_n.uie = mstatus_q.upie; - priv_lvl_n = PRIV_LVL_U; - mstatus_n.upie = 1'b1; - end //csr_restore_uret_i - - csr_restore_mret_i: begin //MRET - unique case (mstatus_q.mpp) - PRIV_LVL_U: begin - mstatus_n.uie = mstatus_q.mpie; - priv_lvl_n = PRIV_LVL_U; - mstatus_n.mpie = 1'b1; - mstatus_n.mpp = PRIV_LVL_U; - end - PRIV_LVL_M: begin - mstatus_n.mie = mstatus_q.mpie; - priv_lvl_n = PRIV_LVL_M; - mstatus_n.mpie = 1'b1; - mstatus_n.mpp = PRIV_LVL_U; - end - default: ; - endcase - end //csr_restore_mret_i - - - csr_restore_dret_i: begin //DRET - // Restore to the recorded privilege level - priv_lvl_n = dcsr_q.prv; - - end //csr_restore_dret_i - - default: ; - endcase - end - end else begin : gen_no_pulp_secure_write_logic //PULP_SECURE == 0 - // write logic - always_comb begin - fflags_n = fflags_q; - frm_n = frm_q; - mscratch_n = mscratch_q; - mepc_n = mepc_q; - uepc_n = 'b0; // Not used if PULP_SECURE == 0 - depc_n = depc_q; - dcsr_n = dcsr_q; - dscratch0_n = dscratch0_q; - dscratch1_n = dscratch1_q; - - mstatus_n = mstatus_q; - mcause_n = mcause_q; - ucause_n = '0; // Not used if PULP_SECURE == 0 - hwlp_we_o = '0; - hwlp_regid_o = '0; - exception_pc = pc_id_i; - priv_lvl_n = priv_lvl_q; - mtvec_n = csr_mtvec_init_i ? mtvec_addr_i[31:8] : mtvec_q; - utvec_n = '0; // Not used if PULP_SECURE == 0 - pmp_reg_n.pmpaddr = '0; // Not used if PULP_SECURE == 0 - pmp_reg_n.pmpcfg_packed = '0; // Not used if PULP_SECURE == 0 - pmp_reg_n.pmpcfg = '0; // Not used if PULP_SECURE == 0 - pmpaddr_we = '0; - pmpcfg_we = '0; - - mie_n = mie_q; - mtvec_mode_n = mtvec_mode_q; - utvec_mode_n = '0; // Not used if PULP_SECURE == 0 - - if (FPU == 1) if (fflags_we_i) fflags_n = fflags_i | fflags_q; - - case (csr_addr_i) - // fcsr: Floating-Point Control and Status Register (frm, fflags, fprec). - CSR_FFLAGS: if (csr_we_int) fflags_n = (FPU == 1) ? csr_wdata_int[C_FFLAG-1:0] : '0; - CSR_FRM: if (csr_we_int) frm_n = (FPU == 1) ? csr_wdata_int[C_RM-1:0] : '0; - CSR_FCSR: - if (csr_we_int) begin - fflags_n = (FPU == 1) ? csr_wdata_int[C_FFLAG-1:0] : '0; - frm_n = (FPU == 1) ? csr_wdata_int[C_RM+C_FFLAG-1:C_FFLAG] : '0; - end - - // mstatus: IE bit - CSR_MSTATUS: - if (csr_we_int) begin - mstatus_n = '{ - uie: csr_wdata_int[MSTATUS_UIE_BIT], - mie: csr_wdata_int[MSTATUS_MIE_BIT], - upie: csr_wdata_int[MSTATUS_UPIE_BIT], - mpie: csr_wdata_int[MSTATUS_MPIE_BIT], - mpp: PrivLvl_t'(csr_wdata_int[MSTATUS_MPP_BIT_HIGH:MSTATUS_MPP_BIT_LOW]), - mprv: csr_wdata_int[MSTATUS_MPRV_BIT] - }; - end - // mie: machine interrupt enable - CSR_MIE: - if (csr_we_int) begin - mie_n = csr_wdata_int & IRQ_MASK; - end - // mtvec: machine trap-handler base address - CSR_MTVEC: - if (csr_we_int) begin - mtvec_n = csr_wdata_int[31:8]; - mtvec_mode_n = {1'b0, csr_wdata_int[0]}; // Only direct and vectored mode are supported - end - // mscratch: machine scratch - CSR_MSCRATCH: - if (csr_we_int) begin - mscratch_n = csr_wdata_int; - end - // mepc: exception program counter - CSR_MEPC: - if (csr_we_int) begin - mepc_n = csr_wdata_int & ~32'b1; // force 16-bit alignment - end - // mcause - CSR_MCAUSE: if (csr_we_int) mcause_n = {csr_wdata_int[31], csr_wdata_int[4:0]}; - - CSR_DCSR: - if (csr_we_int) begin - // Following are read-only and never assigned here (dcsr_q value is used): - // - // - xdebugver - // - cause - // - nmip - - dcsr_n.ebreakm = csr_wdata_int[15]; - dcsr_n.ebreaks = 1'b0; // ebreaks (implemented as WARL) - dcsr_n.ebreaku = 1'b0; // ebreaku (implemented as WARL) - dcsr_n.stepie = csr_wdata_int[11]; // stepie - dcsr_n.stopcount = 1'b0; // stopcount - dcsr_n.stoptime = 1'b0; // stoptime - dcsr_n.mprven = 1'b0; // mprven - dcsr_n.step = csr_wdata_int[2]; - dcsr_n.prv = PRIV_LVL_M; // prv (implemendted as WARL) - end - - CSR_DPC: - if (csr_we_int) begin - depc_n = csr_wdata_int & ~32'b1; // force 16-bit alignment - end - - CSR_DSCRATCH0: - if (csr_we_int) begin - dscratch0_n = csr_wdata_int; - end - - CSR_DSCRATCH1: - if (csr_we_int) begin - dscratch1_n = csr_wdata_int; - end - - // hardware loops - CSR_LPSTART0: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b001; - hwlp_regid_o = 1'b0; - end - CSR_LPEND0: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b010; - hwlp_regid_o = 1'b0; - end - CSR_LPCOUNT0: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b100; - hwlp_regid_o = 1'b0; - end - CSR_LPSTART1: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b001; - hwlp_regid_o = 1'b1; - end - CSR_LPEND1: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b010; - hwlp_regid_o = 1'b1; - end - CSR_LPCOUNT1: - if (PULP_XPULP && csr_we_int) begin - hwlp_we_o = 3'b100; - hwlp_regid_o = 1'b1; - end - endcase - - // exception controller gets priority over other writes - unique case (1'b1) - - csr_save_cause_i: begin - unique case (1'b1) - csr_save_if_i: exception_pc = pc_if_i; - csr_save_id_i: exception_pc = pc_id_i; - csr_save_ex_i: exception_pc = pc_ex_i; - default: ; - endcase - - if (debug_csr_save_i) begin - // all interrupts are masked, don't update cause, epc, tval dpc and - // mpstatus - dcsr_n.prv = PRIV_LVL_M; - dcsr_n.cause = debug_cause_i; - depc_n = exception_pc; - end else begin - priv_lvl_n = PRIV_LVL_M; - mstatus_n.mpie = mstatus_q.mie; - mstatus_n.mie = 1'b0; - mstatus_n.mpp = PRIV_LVL_M; - mepc_n = exception_pc; - mcause_n = csr_cause_i; - end - end //csr_save_cause_i - - csr_restore_mret_i: begin //MRET - mstatus_n.mie = mstatus_q.mpie; - priv_lvl_n = PRIV_LVL_M; - mstatus_n.mpie = 1'b1; - mstatus_n.mpp = PRIV_LVL_M; - end //csr_restore_mret_i - - csr_restore_dret_i: begin //DRET - // Restore to the recorded privilege level - priv_lvl_n = dcsr_q.prv; - end //csr_restore_dret_i - - default: ; - endcase - end - end //PULP_SECURE - - assign hwlp_data_o = (PULP_XPULP) ? csr_wdata_int : '0; - - // CSR operation logic - always_comb begin - csr_wdata_int = csr_wdata_i; - csr_we_int = 1'b1; - - case (csr_op_i) - CSR_OP_WRITE: csr_wdata_int = csr_wdata_i; - CSR_OP_SET: csr_wdata_int = csr_wdata_i | csr_rdata_o; - CSR_OP_CLEAR: csr_wdata_int = (~csr_wdata_i) & csr_rdata_o; - - CSR_OP_READ: begin - csr_wdata_int = csr_wdata_i; - csr_we_int = 1'b0; - end - endcase - end - - assign csr_rdata_o = csr_rdata_int; - - // directly output some registers - assign m_irq_enable_o = mstatus_q.mie && !(dcsr_q.step && !dcsr_q.stepie); - assign u_irq_enable_o = mstatus_q.uie && !(dcsr_q.step && !dcsr_q.stepie); - assign priv_lvl_o = priv_lvl_q; - assign sec_lvl_o = priv_lvl_q[0]; - assign frm_o = (FPU == 1) ? frm_q : '0; - - assign mtvec_o = mtvec_q; - assign utvec_o = utvec_q; - assign mtvec_mode_o = mtvec_mode_q; - assign utvec_mode_o = utvec_mode_q; - - assign mepc_o = mepc_q; - assign uepc_o = uepc_q; - - assign mcounteren_o = PULP_SECURE ? mcounteren_q : '0; - - assign depc_o = depc_q; - - assign pmp_addr_o = pmp_reg_q.pmpaddr; - assign pmp_cfg_o = pmp_reg_q.pmpcfg; - - assign debug_single_step_o = dcsr_q.step; - assign debug_ebreakm_o = dcsr_q.ebreakm; - assign debug_ebreaku_o = dcsr_q.ebreaku; - - generate - if (PULP_SECURE == 1) begin : gen_pmp_user - - for (j = 0; j < N_PMP_ENTRIES; j++) begin : CS_PMP_CFG - assign pmp_reg_n.pmpcfg[j] = pmp_reg_n.pmpcfg_packed[j/4][8*((j%4)+1)-1:8*(j%4)]; - assign pmp_reg_q.pmpcfg_packed[j/4][8*((j%4)+1)-1:8*(j%4)] = pmp_reg_q.pmpcfg[j]; - end - - for (j = 0; j < N_PMP_ENTRIES; j++) begin : CS_PMP_REGS_FF - always_ff @(posedge clk, negedge rst_n) begin - if (rst_n == 1'b0) begin - pmp_reg_q.pmpcfg[j] <= '0; - pmp_reg_q.pmpaddr[j] <= '0; - end else begin - if (pmpcfg_we[j]) pmp_reg_q.pmpcfg[j] <= USE_PMP ? pmp_reg_n.pmpcfg[j] : '0; - if (pmpaddr_we[j]) pmp_reg_q.pmpaddr[j] <= USE_PMP ? pmp_reg_n.pmpaddr[j] : '0; - end - end - end //CS_PMP_REGS_FF - - always_ff @(posedge clk, negedge rst_n) begin - if (rst_n == 1'b0) begin - uepc_q <= '0; - ucause_q <= '0; - utvec_q <= '0; - utvec_mode_q <= MTVEC_MODE; - priv_lvl_q <= PRIV_LVL_M; - end else begin - uepc_q <= uepc_n; - ucause_q <= ucause_n; - utvec_q <= utvec_n; - utvec_mode_q <= utvec_mode_n; - priv_lvl_q <= priv_lvl_n; - end - end - end else begin : gen_no_pmp_user - assign pmp_reg_q = '0; - assign uepc_q = '0; - assign ucause_q = '0; - assign utvec_q = '0; - assign utvec_mode_q = '0; - assign priv_lvl_q = PRIV_LVL_M; - end - endgenerate - - // actual registers - always_ff @(posedge clk, negedge rst_n) begin - if (rst_n == 1'b0) begin - frm_q <= '0; - fflags_q <= '0; - mstatus_q <= '{ - uie: 1'b0, - mie: 1'b0, - upie: 1'b0, - mpie: 1'b0, - mpp: PRIV_LVL_M, - mprv: 1'b0 - }; - mepc_q <= '0; - mcause_q <= '0; - - depc_q <= '0; - dcsr_q <= '{ - xdebugver: XDEBUGVER_STD, - cause: DBG_CAUSE_NONE, // 3'h0 - prv: PRIV_LVL_M, - default: '0 - }; - dscratch0_q <= '0; - dscratch1_q <= '0; - mscratch_q <= '0; - mie_q <= '0; - mtvec_q <= '0; - mtvec_mode_q <= MTVEC_MODE; - end else begin - // update CSRs - if (FPU == 1) begin - frm_q <= frm_n; - fflags_q <= fflags_n; - end else begin - frm_q <= 'b0; - fflags_q <= 'b0; - end - if (PULP_SECURE == 1) begin - mstatus_q <= mstatus_n; - end else begin - mstatus_q <= '{ - uie: 1'b0, - mie: mstatus_n.mie, - upie: 1'b0, - mpie: mstatus_n.mpie, - mpp: PRIV_LVL_M, - mprv: 1'b0 - }; - end - mepc_q <= mepc_n; - mcause_q <= mcause_n; - depc_q <= depc_n; - dcsr_q <= dcsr_n; - dscratch0_q <= dscratch0_n; - dscratch1_q <= dscratch1_n; - mscratch_q <= mscratch_n; - mie_q <= mie_n; - mtvec_q <= mtvec_n; - mtvec_mode_q <= mtvec_mode_n; - end - end - //////////////////////////////////////////////////////////////////////// - // ____ _ _____ _ // - // | _ \ ___| |__ _ _ __ _ |_ _| __(_) __ _ __ _ ___ _ __ // - // | | | |/ _ \ '_ \| | | |/ _` | | || '__| |/ _` |/ _` |/ _ \ '__| // - // | |_| | __/ |_) | |_| | (_| | | || | | | (_| | (_| | __/ | // - // |____/ \___|_.__/ \__,_|\__, | |_||_| |_|\__, |\__, |\___|_| // - // |___/ |___/ |___/ // - //////////////////////////////////////////////////////////////////////// - - if (DEBUG_TRIGGER_EN) begin : gen_trigger_regs - // Register values - logic tmatch_control_exec_q; - logic [31:0] tmatch_value_q; - // Write enables - logic tmatch_control_we; - logic tmatch_value_we; - - // Write select - assign tmatch_control_we = csr_we_int & debug_mode_i & (csr_addr_i == CSR_TDATA1); - assign tmatch_value_we = csr_we_int & debug_mode_i & (csr_addr_i == CSR_TDATA2); - - - // Registers - always_ff @(posedge clk or negedge rst_n) begin - if (!rst_n) begin - tmatch_control_exec_q <= 'b0; - tmatch_value_q <= 'b0; - end else begin - if (tmatch_control_we) tmatch_control_exec_q <= csr_wdata_int[2]; - if (tmatch_value_we) tmatch_value_q <= csr_wdata_int[31:0]; - end - end - - // All supported trigger types - assign tinfo_types = 1 << TTYPE_MCONTROL; - - // Assign read data - // TDATA0 - only support simple address matching - assign tmatch_control_rdata = { - TTYPE_MCONTROL, // type : address/data match - 1'b1, // dmode : access from D mode only - 6'h00, // maskmax : exact match only - 1'b0, // hit : not supported - 1'b0, // select : address match only - 1'b0, // timing : match before execution - 2'b00, // sizelo : match any access - 4'h1, // action : enter debug mode - 1'b0, // chain : not supported - 4'h0, // match : simple match - 1'b1, // m : match in m-mode - 1'b0, // 0 : zero - 1'b0, // s : not supported - PULP_SECURE == 1, // u : match in u-mode - tmatch_control_exec_q, // execute : match instruction address - 1'b0, // store : not supported - 1'b0 - }; // load : not supported - - // TDATA1 - address match value only - assign tmatch_value_rdata = tmatch_value_q; - - // Breakpoint matching - // We match against the next address, as the breakpoint must be taken before execution - assign trigger_match_o = tmatch_control_exec_q & (pc_id_i[31:0] == tmatch_value_q[31:0]); - - end else begin : gen_no_trigger_regs - assign tinfo_types = 'b0; - assign tmatch_control_rdata = 'b0; - assign tmatch_value_rdata = 'b0; - assign trigger_match_o = 'b0; - end - - ///////////////////////////////////////////////////////////////// - // ____ __ ____ _ // - // | _ \ ___ _ __ / _| / ___|___ _ _ _ __ | |_ ___ _ __ // - // | |_) / _ \ '__| |_ | | / _ \| | | | '_ \| __/ _ \ '__| // - // | __/ __/ | | _| | |__| (_) | |_| | | | | || __/ | // - // |_| \___|_| |_|(_) \____\___/ \__,_|_| |_|\__\___|_| // - // // - ///////////////////////////////////////////////////////////////// - - // ------------------------ - // Events to count - assign hpm_events[0] = 1'b1; // cycle counter - assign hpm_events[1] = mhpmevent_minstret_i; // instruction counter - assign hpm_events[2] = mhpmevent_ld_stall_i; // nr of load use hazards - assign hpm_events[3] = mhpmevent_jr_stall_i; // nr of jump register hazards - assign hpm_events[4] = mhpmevent_imiss_i; // cycles waiting for instruction fetches, excluding jumps and branches - assign hpm_events[5] = mhpmevent_load_i; // nr of loads - assign hpm_events[6] = mhpmevent_store_i; // nr of stores - assign hpm_events[7] = mhpmevent_jump_i; // nr of jumps (unconditional) - assign hpm_events[8] = mhpmevent_branch_i; // nr of branches (conditional) - assign hpm_events[9] = mhpmevent_branch_taken_i; // nr of taken branches (conditional) - assign hpm_events[10] = mhpmevent_compressed_i; // compressed instruction counter - assign hpm_events[11] = PULP_CLUSTER ? mhpmevent_pipe_stall_i : 1'b0; // extra cycles from ELW - assign hpm_events[12] = !APU ? 1'b0 : apu_typeconflict_i && !apu_dep_i; - assign hpm_events[13] = !APU ? 1'b0 : apu_contention_i; - assign hpm_events[14] = !APU ? 1'b0 : apu_dep_i && !apu_contention_i; - assign hpm_events[15] = !APU ? 1'b0 : apu_wb_i; - - // ------------------------ - // address decoder for performance counter registers - logic mcounteren_we; - logic mcountinhibit_we; - logic mhpmevent_we; - - assign mcounteren_we = csr_we_int & (csr_addr_i == CSR_MCOUNTEREN); - assign mcountinhibit_we = csr_we_int & (csr_addr_i == CSR_MCOUNTINHIBIT); - assign mhpmevent_we = csr_we_int & ( (csr_addr_i == CSR_MHPMEVENT3 )|| - (csr_addr_i == CSR_MHPMEVENT4 ) || - (csr_addr_i == CSR_MHPMEVENT5 ) || - (csr_addr_i == CSR_MHPMEVENT6 ) || - (csr_addr_i == CSR_MHPMEVENT7 ) || - (csr_addr_i == CSR_MHPMEVENT8 ) || - (csr_addr_i == CSR_MHPMEVENT9 ) || - (csr_addr_i == CSR_MHPMEVENT10 ) || - (csr_addr_i == CSR_MHPMEVENT11 ) || - (csr_addr_i == CSR_MHPMEVENT12 ) || - (csr_addr_i == CSR_MHPMEVENT13 ) || - (csr_addr_i == CSR_MHPMEVENT14 ) || - (csr_addr_i == CSR_MHPMEVENT15 ) || - (csr_addr_i == CSR_MHPMEVENT16 ) || - (csr_addr_i == CSR_MHPMEVENT17 ) || - (csr_addr_i == CSR_MHPMEVENT18 ) || - (csr_addr_i == CSR_MHPMEVENT19 ) || - (csr_addr_i == CSR_MHPMEVENT20 ) || - (csr_addr_i == CSR_MHPMEVENT21 ) || - (csr_addr_i == CSR_MHPMEVENT22 ) || - (csr_addr_i == CSR_MHPMEVENT23 ) || - (csr_addr_i == CSR_MHPMEVENT24 ) || - (csr_addr_i == CSR_MHPMEVENT25 ) || - (csr_addr_i == CSR_MHPMEVENT26 ) || - (csr_addr_i == CSR_MHPMEVENT27 ) || - (csr_addr_i == CSR_MHPMEVENT28 ) || - (csr_addr_i == CSR_MHPMEVENT29 ) || - (csr_addr_i == CSR_MHPMEVENT30 ) || - (csr_addr_i == CSR_MHPMEVENT31 ) ); - - // ------------------------ - // Increment value for performance counters - genvar incr_gidx; - generate - for (incr_gidx = 0; incr_gidx < 32; incr_gidx++) begin : gen_mhpmcounter_increment - assign mhpmcounter_increment[incr_gidx] = mhpmcounter_q[incr_gidx] + 1; - end - endgenerate - - // ------------------------ - // next value for performance counters and control registers - always_comb begin - mcounteren_n = mcounteren_q; - mcountinhibit_n = mcountinhibit_q; - mhpmevent_n = mhpmevent_q; - - // User Mode Enable - if (PULP_SECURE && mcounteren_we) mcounteren_n = csr_wdata_int; - - // Inhibit Control - if (mcountinhibit_we) mcountinhibit_n = csr_wdata_int; - - // Event Control - if (mhpmevent_we) mhpmevent_n[csr_addr_i[4:0]] = csr_wdata_int; - end - - genvar wcnt_gidx; - generate - for (wcnt_gidx = 0; wcnt_gidx < 32; wcnt_gidx++) begin : gen_mhpmcounter_write - - // Write lower counter bits - assign mhpmcounter_write_lower[wcnt_gidx] = csr_we_int && (csr_addr_i == (CSR_MCYCLE + wcnt_gidx)); - - // Write upper counter bits - assign mhpmcounter_write_upper[wcnt_gidx] = !mhpmcounter_write_lower[wcnt_gidx] && - csr_we_int && (csr_addr_i == (CSR_MCYCLEH + wcnt_gidx)) && (MHPMCOUNTER_WIDTH == 64); - - // Increment counter - if (!PULP_PERF_COUNTERS) begin : gen_no_pulp_perf_counters - if (wcnt_gidx == 0) begin : gen_mhpmcounter_mcycle - // mcycle = mhpmcounter[0] : count every cycle (if not inhibited) - assign mhpmcounter_write_increment[wcnt_gidx] = !mhpmcounter_write_lower[wcnt_gidx] && - !mhpmcounter_write_upper[wcnt_gidx] && - !mcountinhibit_q[wcnt_gidx]; - end else if (wcnt_gidx == 2) begin : gen_mhpmcounter_minstret - // minstret = mhpmcounter[2] : count every retired instruction (if not inhibited) - assign mhpmcounter_write_increment[wcnt_gidx] = !mhpmcounter_write_lower[wcnt_gidx] && - !mhpmcounter_write_upper[wcnt_gidx] && - !mcountinhibit_q[wcnt_gidx] && - hpm_events[1]; - end else if( (wcnt_gidx>2) && (wcnt_gidx<(NUM_MHPMCOUNTERS+3))) begin : gen_mhpmcounter - // add +1 if any event is enabled and active - assign mhpmcounter_write_increment[wcnt_gidx] = !mhpmcounter_write_lower[wcnt_gidx] && - !mhpmcounter_write_upper[wcnt_gidx] && - !mcountinhibit_q[wcnt_gidx] && - |(hpm_events & mhpmevent_q[wcnt_gidx][NUM_HPM_EVENTS-1:0]); - end else begin : gen_mhpmcounter_not_implemented - assign mhpmcounter_write_increment[wcnt_gidx] = 1'b0; - end - end else begin : gen_pulp_perf_counters - // PULP PERF COUNTERS share all events in one register (not compliant with RISC-V) - assign mhpmcounter_write_increment[wcnt_gidx] = !mhpmcounter_write_lower[wcnt_gidx] && - !mhpmcounter_write_upper[wcnt_gidx] && - !mcountinhibit_q[wcnt_gidx] && - |(hpm_events & mhpmevent_q[wcnt_gidx][NUM_HPM_EVENTS-1:0]); - end - end - endgenerate - - // ------------------------ - // HPM Registers - // Counter Registers: mhpcounter_q[] - genvar cnt_gidx; - generate - for (cnt_gidx = 0; cnt_gidx < 32; cnt_gidx++) begin : gen_mhpmcounter - // mcyclce is located at index 0 - // there is no counter at index 1 - // minstret is located at index 2 - // Programable HPM counters start at index 3 - if ((cnt_gidx == 1) || (cnt_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented - assign mhpmcounter_q[cnt_gidx] = 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) begin - mhpmcounter_q[cnt_gidx] <= 'b0; - end else begin - if (PULP_PERF_COUNTERS && (cnt_gidx == 2 || cnt_gidx == 0)) begin - mhpmcounter_q[cnt_gidx] <= 'b0; - end else begin - if (mhpmcounter_write_lower[cnt_gidx]) begin - mhpmcounter_q[cnt_gidx][31:0] <= csr_wdata_int; - end else if (mhpmcounter_write_upper[cnt_gidx]) begin - mhpmcounter_q[cnt_gidx][63:32] <= csr_wdata_int; - end else if (mhpmcounter_write_increment[cnt_gidx]) begin - mhpmcounter_q[cnt_gidx] <= mhpmcounter_increment[cnt_gidx]; - end - end - end - end - end - endgenerate - - // Event Register: mhpevent_q[] - genvar evt_gidx; - generate - for (evt_gidx = 0; evt_gidx < 32; evt_gidx++) begin : gen_mhpmevent - // programable HPM events start at index3 - if ((evt_gidx < 3) || (evt_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented - assign mhpmevent_q[evt_gidx] = 'b0; - end else begin : gen_implemented - if (NUM_HPM_EVENTS < 32) begin : gen_tie_off - assign mhpmevent_q[evt_gidx][31:NUM_HPM_EVENTS] = 'b0; - end - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mhpmevent_q[evt_gidx][NUM_HPM_EVENTS-1:0] <= 'b0; - else - mhpmevent_q[evt_gidx][NUM_HPM_EVENTS-1:0] <= mhpmevent_n[evt_gidx][NUM_HPM_EVENTS-1:0]; - end - end - endgenerate - - // Enable Regsiter: mcounteren_q - genvar en_gidx; - generate - for (en_gidx = 0; en_gidx < 32; en_gidx++) begin : gen_mcounteren - if( (PULP_SECURE == 0) || - (en_gidx == 1) || - (en_gidx >= (NUM_MHPMCOUNTERS+3) ) ) - begin : gen_non_implemented - assign mcounteren_q[en_gidx] = 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mcounteren_q[en_gidx] <= 'b0; // default disable - else mcounteren_q[en_gidx] <= mcounteren_n[en_gidx]; - end - end - endgenerate - - // Inhibit Regsiter: mcountinhibit_q - // Note: implemented counters are disabled out of reset to save power - genvar inh_gidx; - generate - for (inh_gidx = 0; inh_gidx < 32; inh_gidx++) begin : gen_mcountinhibit - if ((inh_gidx == 1) || (inh_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented - assign mcountinhibit_q[inh_gidx] = 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mcountinhibit_q[inh_gidx] <= 'b1; // default disable - else mcountinhibit_q[inh_gidx] <= mcountinhibit_n[inh_gidx]; - end - end - endgenerate - -`ifdef CV32E40P_ASSERT_ON - - //---------------------------------------------------------------------------- - // Assertions - //---------------------------------------------------------------------------- - - // Check that mie_bypass_o equals mie_n - a_mie_bypass : - assert property (@(posedge clk) disable iff (!rst_n) (1'b1) |-> (mie_bypass_o == mie_n)); - -`endif - -endmodule - diff --git a/src/UWE_projectCode/RTL分析代码/cv32e40p_decoder.sv b/src/UWE_projectCode/RTL分析代码/cv32e40p_decoder.sv deleted file mode 100644 index 9987f7e..0000000 --- a/src/UWE_projectCode/RTL分析代码/cv32e40p_decoder.sv +++ /dev/null @@ -1,3048 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this 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. - -//////////////////////////////////////////////////////////////////////////////// -// Engineer Andreas Traber - atraber@iis.ee.ethz.ch // -// // -// Additional contributions by: // -// Matthias Baer - baermatt@student.ethz.ch // -// Igor Loi - igor.loi@unibo.it // -// Sven Stucki - svstucki@student.ethz.ch // -// Davide Schiavone - pschiavo@iis.ee.ethz.ch // -// // -// Design Name: Decoder // -// Project Name: RI5CY // -// Language: SystemVerilog // -// // -// Description: Decoder // -// // -//////////////////////////////////////////////////////////////////////////////// - -module cv32e40p_decoder import cv32e40p_pkg::*; import cv32e40p_apu_core_pkg::*; import cv32e40p_fpu_pkg::*; -#( - parameter PULP_XPULP = 1, // PULP ISA Extension (including PULP specific CSRs and hardware loop, excluding p.elw) - parameter PULP_CLUSTER = 0, - parameter A_EXTENSION = 0, - parameter FPU = 0, - parameter PULP_ZFINX = 0, - parameter PULP_SECURE = 0, - parameter USE_PMP = 0, - parameter APU_WOP_CPU = 6, - parameter DEBUG_TRIGGER_EN = 1 -) -( - // singals running to/from controller - input logic deassert_we_i, // deassert we, we are stalled or not active - - output logic illegal_insn_o, // illegal instruction encountered - output logic ebrk_insn_o, // trap instruction encountered - - output logic mret_insn_o, // return from exception instruction encountered (M) - output logic uret_insn_o, // return from exception instruction encountered (S) - output logic dret_insn_o, // return from debug (M) - - output logic mret_dec_o, // return from exception instruction encountered (M) without deassert - output logic uret_dec_o, // return from exception instruction encountered (S) without deassert - output logic dret_dec_o, // return from debug (M) without deassert - - output logic ecall_insn_o, // environment call (syscall) instruction encountered - output logic wfi_o , // pipeline flush is requested - - output logic fencei_insn_o, // fence.i instruction - - output logic rega_used_o, // rs1 is used by current instruction - output logic regb_used_o, // rs2 is used by current instruction - output logic regc_used_o, // rs3 is used by current instruction - - output logic reg_fp_a_o, // fp reg a is used - output logic reg_fp_b_o, // fp reg b is used - output logic reg_fp_c_o, // fp reg c is used - output logic reg_fp_d_o, // fp reg d is used - - output logic [ 0:0] bmask_a_mux_o, // bit manipulation mask a mux - output logic [ 1:0] bmask_b_mux_o, // bit manipulation mask b mux - output logic alu_bmask_a_mux_sel_o, // bit manipulation mask a mux (reg or imm) - output logic alu_bmask_b_mux_sel_o, // bit manipulation mask b mux (reg or imm) - - // from IF/ID pipeline - input logic [31:0] instr_rdata_i, // instruction read from instr memory/cache - input logic illegal_c_insn_i, // compressed instruction decode failed - - // ALU signals - output logic alu_en_o, // ALU enable - output alu_opcode_e alu_operator_o, // ALU operation selection - output logic [2:0] alu_op_a_mux_sel_o, // operand a selection: reg value, PC, immediate or zero - output logic [2:0] alu_op_b_mux_sel_o, // operand b selection: reg value or immediate - output logic [1:0] alu_op_c_mux_sel_o, // operand c selection: reg value or jump target - output logic [1:0] alu_vec_mode_o, // selects between 32 bit, 16 bit and 8 bit vectorial modes - output logic scalar_replication_o, // scalar replication enable - output logic scalar_replication_c_o, // scalar replication enable for operand C - output logic [0:0] imm_a_mux_sel_o, // immediate selection for operand a - output logic [3:0] imm_b_mux_sel_o, // immediate selection for operand b - output logic [1:0] regc_mux_o, // register c selection: S3, RD or 0 - output logic is_clpx_o, // whether the instruction is complex (pulpv3) or not - output logic is_subrot_o, - - // MUL related control signals - output mul_opcode_e mult_operator_o, // Multiplication operation selection - output logic mult_int_en_o, // perform integer multiplication - output logic mult_dot_en_o, // perform dot multiplication - output logic [0:0] mult_imm_mux_o, // Multiplication immediate mux selector - output logic mult_sel_subword_o, // Select subwords for 16x16 bit of multiplier - output logic [1:0] mult_signed_mode_o, // Multiplication in signed mode - output logic [1:0] mult_dot_signed_o, // Dot product in signed mode - - // FPU - input logic [C_RM-1:0] frm_i, // Rounding mode from float CSR - - output logic [cv32e40p_fpu_pkg::FP_FORMAT_BITS-1:0] fpu_dst_fmt_o, // fpu destination format - output logic [cv32e40p_fpu_pkg::FP_FORMAT_BITS-1:0] fpu_src_fmt_o, // fpu source format - output logic [cv32e40p_fpu_pkg::INT_FORMAT_BITS-1:0] fpu_int_fmt_o, // fpu integer format (for casts) - - // APU - output logic apu_en_o, - output logic [APU_WOP_CPU-1:0] apu_op_o, - output logic [1:0] apu_lat_o, - output logic [2:0] fp_rnd_mode_o, - - // register file related signals - output logic regfile_mem_we_o, // write enable for regfile - output logic regfile_alu_we_o, // write enable for 2nd regfile port - output logic regfile_alu_we_dec_o, // write enable for 2nd regfile port without deassert - output logic regfile_alu_waddr_sel_o, // Select register write address for ALU/MUL operations - - // CSR manipulation - output logic csr_access_o, // access to CSR - output logic csr_status_o, // access to xstatus CSR - output csr_opcode_e csr_op_o, // operation to perform on CSR - input PrivLvl_t current_priv_lvl_i, // The current privilege level - - // LD/ST unit signals - output logic data_req_o, // start transaction to data memory - output logic data_we_o, // data memory write enable - output logic prepost_useincr_o, // when not active bypass the alu result for address calculation - output logic [1:0] data_type_o, // data type on data memory: byte, half word or word - output logic [1:0] data_sign_extension_o, // sign extension on read data from data memory / NaN boxing - output logic [1:0] data_reg_offset_o, // offset in byte inside register for stores - output logic data_load_event_o, // data request is in the special event range - - // Atomic memory access - output logic [5:0] atop_o, - - // hwloop signals - output logic [2:0] hwlp_we_o, // write enable for hwloop regs - output logic hwlp_target_mux_sel_o, // selects immediate for hwloop target - output logic hwlp_start_mux_sel_o, // selects hwloop start address input - output logic hwlp_cnt_mux_sel_o, // selects hwloop counter input - - input logic debug_mode_i, // processor is in debug mode - input logic debug_wfi_no_sleep_i, // do not let WFI cause sleep - - // jump/branches - output logic [1:0] ctrl_transfer_insn_in_dec_o, // control transfer instruction without deassert - output logic [1:0] ctrl_transfer_insn_in_id_o, // control transfer instructio is decoded - output logic [1:0] ctrl_transfer_target_mux_sel_o, // jump target selection - - // HPM related control signals - input logic [31:0] mcounteren_i -); - - // write enable/request control - logic regfile_mem_we; - logic regfile_alu_we; - logic data_req; - logic [2:0] hwlp_we; - logic csr_illegal; - logic [1:0] ctrl_transfer_insn; - - csr_opcode_e csr_op; - - logic alu_en; - logic mult_int_en; - logic mult_dot_en; - logic apu_en; - - // this instruction needs floating-point rounding-mode verification - logic check_fprm; - - logic [cv32e40p_fpu_pkg::OP_BITS-1:0] fpu_op; // fpu operation - logic fpu_op_mod; // fpu operation modifier - logic fpu_vec_op; // fpu vectorial operation - // unittypes for latencies to help us decode for APU - enum logic[1:0] {ADDMUL, DIVSQRT, NONCOMP, CONV} fp_op_group; - - - ///////////////////////////////////////////// - // ____ _ // - // | _ \ ___ ___ ___ __| | ___ _ __ // - // | | | |/ _ \/ __/ _ \ / _` |/ _ \ '__| // - // | |_| | __/ (_| (_) | (_| | __/ | // - // |____/ \___|\___\___/ \__,_|\___|_| // - // // - ///////////////////////////////////////////// - - always_comb - begin - ctrl_transfer_insn = BRANCH_NONE; - ctrl_transfer_target_mux_sel_o = JT_JAL; - - alu_en = 1'b1; - alu_operator_o = ALU_SLTU; - alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; - alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; - alu_op_c_mux_sel_o = OP_C_REGC_OR_FWD; - alu_vec_mode_o = VEC_MODE32; - scalar_replication_o = 1'b0; - scalar_replication_c_o = 1'b0; - regc_mux_o = REGC_ZERO; - imm_a_mux_sel_o = IMMA_ZERO; - imm_b_mux_sel_o = IMMB_I; - - mult_operator_o = MUL_I; - mult_int_en = 1'b0; - mult_dot_en = 1'b0; - mult_imm_mux_o = MIMM_ZERO; - mult_signed_mode_o = 2'b00; - mult_sel_subword_o = 1'b0; - mult_dot_signed_o = 2'b00; - - apu_en = 1'b0; - apu_op_o = '0; - apu_lat_o = '0; - fp_rnd_mode_o = '0; - fpu_op = cv32e40p_fpu_pkg::SGNJ; - fpu_op_mod = 1'b0; - fpu_vec_op = 1'b0; - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP32; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP32; - fpu_int_fmt_o = cv32e40p_fpu_pkg::INT32; - check_fprm = 1'b0; - fp_op_group = ADDMUL; - - regfile_mem_we = 1'b0; - regfile_alu_we = 1'b0; - regfile_alu_waddr_sel_o = 1'b1; - - prepost_useincr_o = 1'b1; - - hwlp_we = 3'b0; - hwlp_target_mux_sel_o = 1'b0; - hwlp_start_mux_sel_o = 1'b0; - hwlp_cnt_mux_sel_o = 1'b0; - - csr_access_o = 1'b0; - csr_status_o = 1'b0; - csr_illegal = 1'b0; - csr_op = CSR_OP_READ; - mret_insn_o = 1'b0; - uret_insn_o = 1'b0; - - dret_insn_o = 1'b0; - - data_we_o = 1'b0; - data_type_o = 2'b00; - data_sign_extension_o = 2'b00; - data_reg_offset_o = 2'b00; - data_req = 1'b0; - data_load_event_o = 1'b0; - - atop_o = 6'b000000; - - illegal_insn_o = 1'b0; - ebrk_insn_o = 1'b0; - ecall_insn_o = 1'b0; - wfi_o = 1'b0; - - fencei_insn_o = 1'b0; - - rega_used_o = 1'b0; - regb_used_o = 1'b0; - regc_used_o = 1'b0; - reg_fp_a_o = 1'b0; - reg_fp_b_o = 1'b0; - reg_fp_c_o = 1'b0; - reg_fp_d_o = 1'b0; - - bmask_a_mux_o = BMASK_A_ZERO; - bmask_b_mux_o = BMASK_B_ZERO; - alu_bmask_a_mux_sel_o = BMASK_A_IMM; - alu_bmask_b_mux_sel_o = BMASK_B_IMM; - - is_clpx_o = 1'b0; - is_subrot_o = 1'b0; - - mret_dec_o = 1'b0; - uret_dec_o = 1'b0; - dret_dec_o = 1'b0; - - unique case (instr_rdata_i[6:0]) - - ////////////////////////////////////// - // _ _ _ __ __ ____ ____ // - // | | | | | \/ | _ \/ ___| // - // _ | | | | | |\/| | |_) \___ \ // - // | |_| | |_| | | | | __/ ___) | // - // \___/ \___/|_| |_|_| |____/ // - // // - ////////////////////////////////////// - - OPCODE_JAL: begin // Jump and Link - ctrl_transfer_target_mux_sel_o = JT_JAL; - ctrl_transfer_insn = BRANCH_JAL; - // Calculate and store PC+4 - alu_op_a_mux_sel_o = OP_A_CURRPC; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_PCINCR; - alu_operator_o = ALU_ADD; - regfile_alu_we = 1'b1; - // Calculate jump target (= PC + UJ imm) - end - - OPCODE_JALR: begin // Jump and Link Register - ctrl_transfer_target_mux_sel_o = JT_JALR; - ctrl_transfer_insn = BRANCH_JALR; - // Calculate and store PC+4 - alu_op_a_mux_sel_o = OP_A_CURRPC; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_PCINCR; - alu_operator_o = ALU_ADD; - regfile_alu_we = 1'b1; - // Calculate jump target (= RS1 + I imm) - rega_used_o = 1'b1; - - if (instr_rdata_i[14:12] != 3'b0) begin - ctrl_transfer_insn = BRANCH_NONE; - regfile_alu_we = 1'b0; - illegal_insn_o = 1'b1; - end - end - - OPCODE_BRANCH: begin // Branch - ctrl_transfer_target_mux_sel_o = JT_COND; - ctrl_transfer_insn = BRANCH_COND; - alu_op_c_mux_sel_o = OP_C_JT; - rega_used_o = 1'b1; - regb_used_o = 1'b1; - - unique case (instr_rdata_i[14:12]) - 3'b000: alu_operator_o = ALU_EQ; - 3'b001: alu_operator_o = ALU_NE; - 3'b100: alu_operator_o = ALU_LTS; - 3'b101: alu_operator_o = ALU_GES; - 3'b110: alu_operator_o = ALU_LTU; - 3'b111: alu_operator_o = ALU_GEU; - 3'b010: begin // p.beqimm - if (PULP_XPULP) begin - alu_operator_o = ALU_EQ; - regb_used_o = 1'b0; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_BI; - end else begin - illegal_insn_o = 1'b1; - end - end - 3'b011: begin // p.bneimm - if (PULP_XPULP) begin - alu_operator_o = ALU_NE; - regb_used_o = 1'b0; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_BI; - end else begin - illegal_insn_o = 1'b1; - end - end - endcase - end - - - ////////////////////////////////// - // _ ____ ______ _____ // - // | | | _ \ / / ___|_ _| // - // | | | | | |/ /\___ \ | | // - // | |___| |_| / / ___) || | // - // |_____|____/_/ |____/ |_| // - // // - ////////////////////////////////// - - OPCODE_STORE, - OPCODE_STORE_POST: begin - if (PULP_XPULP || (instr_rdata_i[6:0] == OPCODE_STORE)) begin - data_req = 1'b1; - data_we_o = 1'b1; - rega_used_o = 1'b1; - regb_used_o = 1'b1; - alu_operator_o = ALU_ADD; - // pass write data through ALU operand c - alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; - - // post-increment setup - if (instr_rdata_i[6:0] == OPCODE_STORE_POST) begin - prepost_useincr_o = 1'b0; - regfile_alu_waddr_sel_o = 1'b0; - regfile_alu_we = 1'b1; - end - - if (instr_rdata_i[14] == 1'b0) begin - // offset from immediate - imm_b_mux_sel_o = IMMB_S; - alu_op_b_mux_sel_o = OP_B_IMM; - end else begin - if (PULP_XPULP) begin - // offset from register - regc_used_o = 1'b1; - alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; - regc_mux_o = REGC_RD; - end else begin - illegal_insn_o = 1'b1; - end - end - - // store size - unique case (instr_rdata_i[13:12]) - 2'b00: data_type_o = 2'b10; // SB - 2'b01: data_type_o = 2'b01; // SH - 2'b10: data_type_o = 2'b00; // SW - default: begin - data_req = 1'b0; - data_we_o = 1'b0; - illegal_insn_o = 1'b1; - end - endcase - end else begin - illegal_insn_o = 1'b1; - end - end - - OPCODE_LOAD, - OPCODE_LOAD_POST: begin - if (PULP_XPULP || (instr_rdata_i[6:0] == OPCODE_LOAD)) begin - data_req = 1'b1; - regfile_mem_we = 1'b1; - rega_used_o = 1'b1; - data_type_o = 2'b00; - // offset from immediate - alu_operator_o = ALU_ADD; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_I; - - // post-increment setup - if (instr_rdata_i[6:0] == OPCODE_LOAD_POST) begin - prepost_useincr_o = 1'b0; - regfile_alu_waddr_sel_o = 1'b0; - regfile_alu_we = 1'b1; - end - - // sign/zero extension - data_sign_extension_o = {1'b0,~instr_rdata_i[14]}; - - // load size - unique case (instr_rdata_i[13:12]) - 2'b00: data_type_o = 2'b10; // LB - 2'b01: data_type_o = 2'b01; // LH - 2'b10: data_type_o = 2'b00; // LW - default: data_type_o = 2'b00; // illegal or reg-reg - endcase - - // reg-reg load (different encoding) - if (instr_rdata_i[14:12] == 3'b111) begin - if (PULP_XPULP) begin - // offset from RS2 - regb_used_o = 1'b1; - alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; - - // sign/zero extension - data_sign_extension_o = {1'b0, ~instr_rdata_i[30]}; - - // load size - unique case (instr_rdata_i[31:25]) - 7'b0000_000, - 7'b0100_000: data_type_o = 2'b10; // LB, LBU - 7'b0001_000, - 7'b0101_000: data_type_o = 2'b01; // LH, LHU - 7'b0010_000: data_type_o = 2'b00; // LW - default: begin - illegal_insn_o = 1'b1; - end - endcase - end else begin - illegal_insn_o = 1'b1; - end - end - - // special p.elw (event load) - if (instr_rdata_i[14:12] == 3'b110) begin - if (PULP_CLUSTER && (instr_rdata_i[6:0] == OPCODE_LOAD)) begin - data_load_event_o = 1'b1; - end else begin - // p.elw only valid for PULP_CLUSTER = 1; p.elw with post increment does not exist - illegal_insn_o = 1'b1; - end - end - - if (instr_rdata_i[14:12] == 3'b011) begin - // LD -> RV64 only - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - - OPCODE_AMO: begin - if (A_EXTENSION) begin : decode_amo - if (instr_rdata_i[14:12] == 3'b010) begin // RV32A Extension (word) - data_req = 1'b1; - data_type_o = 2'b00; - rega_used_o = 1'b1; - regb_used_o = 1'b1; - regfile_mem_we = 1'b1; - prepost_useincr_o = 1'b0; // only use alu_operand_a as address (not a+b) - alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; - - data_sign_extension_o = 1'b1; - - // Apply AMO instruction at `atop_o`. - atop_o = {1'b1, instr_rdata_i[31:27]}; - - unique case (instr_rdata_i[31:27]) - AMO_LR: begin - data_we_o = 1'b0; - end - AMO_SC, - AMO_SWAP, - AMO_ADD, - AMO_XOR, - AMO_AND, - AMO_OR, - AMO_MIN, - AMO_MAX, - AMO_MINU, - AMO_MAXU: begin - data_we_o = 1'b1; - alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; // pass write data through ALU operand c - end - default : illegal_insn_o = 1'b1; - endcase - end - else begin - illegal_insn_o = 1'b1; - end - end else begin : no_decode_amo - illegal_insn_o = 1'b1; - end - end - - - ////////////////////////// - // _ _ _ _ // - // / \ | | | | | | // - // / _ \ | | | | | | // - // / ___ \| |__| |_| | // - // /_/ \_\_____\___/ // - // // - ////////////////////////// - - OPCODE_LUI: begin // Load Upper Immediate - alu_op_a_mux_sel_o = OP_A_IMM; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_a_mux_sel_o = IMMA_ZERO; - imm_b_mux_sel_o = IMMB_U; - alu_operator_o = ALU_ADD; - regfile_alu_we = 1'b1; - end - - OPCODE_AUIPC: begin // Add Upper Immediate to PC - alu_op_a_mux_sel_o = OP_A_CURRPC; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_U; - alu_operator_o = ALU_ADD; - regfile_alu_we = 1'b1; - end - - OPCODE_OPIMM: begin // Register-Immediate ALU Operations - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_I; - regfile_alu_we = 1'b1; - rega_used_o = 1'b1; - - unique case (instr_rdata_i[14:12]) - 3'b000: alu_operator_o = ALU_ADD; // Add Immediate - 3'b010: alu_operator_o = ALU_SLTS; // Set to one if Lower Than Immediate - 3'b011: alu_operator_o = ALU_SLTU; // Set to one if Lower Than Immediate Unsigned - 3'b100: alu_operator_o = ALU_XOR; // Exclusive Or with Immediate - 3'b110: alu_operator_o = ALU_OR; // Or with Immediate - 3'b111: alu_operator_o = ALU_AND; // And with Immediate - - 3'b001: begin - alu_operator_o = ALU_SLL; // Shift Left Logical by Immediate - if (instr_rdata_i[31:25] != 7'b0) - illegal_insn_o = 1'b1; - end - - 3'b101: begin - if (instr_rdata_i[31:25] == 7'b0) - alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate - else if (instr_rdata_i[31:25] == 7'b010_0000) - alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate - else - illegal_insn_o = 1'b1; - end - - - endcase - end - - OPCODE_OP: begin // Register-Register ALU operation - - // PREFIX 11 - if (instr_rdata_i[31:30] == 2'b11) begin - if (PULP_XPULP) begin - ////////////////////////////// - // IMMEDIATE BIT-MANIPULATION - ////////////////////////////// - - regfile_alu_we = 1'b1; - rega_used_o = 1'b1; - - // bit-manipulation instructions - bmask_a_mux_o = BMASK_A_S3; - bmask_b_mux_o = BMASK_B_S2; - alu_op_b_mux_sel_o = OP_B_IMM; - - unique case (instr_rdata_i[14:12]) - 3'b000: begin - alu_operator_o = ALU_BEXT; - imm_b_mux_sel_o = IMMB_S2; - bmask_b_mux_o = BMASK_B_ZERO; - end - 3'b001: begin - alu_operator_o = ALU_BEXTU; - imm_b_mux_sel_o = IMMB_S2; - bmask_b_mux_o = BMASK_B_ZERO; - end - 3'b010: begin - alu_operator_o = ALU_BINS; - imm_b_mux_sel_o = IMMB_S2; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - end - 3'b011: begin - alu_operator_o = ALU_BCLR; - end - 3'b100: begin - alu_operator_o = ALU_BSET; - end - 3'b101: begin - alu_operator_o = ALU_BREV; - // Enable write back to RD - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - // Extract the source register on operand a - imm_b_mux_sel_o = IMMB_S2; - // Map the radix to bmask_a immediate - alu_bmask_a_mux_sel_o = BMASK_A_IMM; - if (instr_rdata_i[29:27] != 3'b0) begin - illegal_insn_o = 1'b1; - end - end - default: illegal_insn_o = 1'b1; - endcase - end else begin - illegal_insn_o = 1'b1; - end - end - - // PREFIX 10 - else if (instr_rdata_i[31:30] == 2'b10) begin - ////////////////////////////// - // REGISTER BIT-MANIPULATION - ////////////////////////////// - if (instr_rdata_i[29:25]==5'b00000) begin - if (PULP_XPULP) begin - regfile_alu_we = 1'b1; - rega_used_o = 1'b1; - - bmask_a_mux_o = BMASK_A_S3; - bmask_b_mux_o = BMASK_B_S2; - alu_op_b_mux_sel_o = OP_B_IMM; - - unique case (instr_rdata_i[14:12]) - 3'b000: begin - alu_operator_o = ALU_BEXT; - imm_b_mux_sel_o = IMMB_S2; - bmask_b_mux_o = BMASK_B_ZERO; - //register variant - alu_op_b_mux_sel_o = OP_B_BMASK; - alu_bmask_a_mux_sel_o = BMASK_A_REG; - regb_used_o = 1'b1; - end - 3'b001: begin - alu_operator_o = ALU_BEXTU; - imm_b_mux_sel_o = IMMB_S2; - bmask_b_mux_o = BMASK_B_ZERO; - //register variant - alu_op_b_mux_sel_o = OP_B_BMASK; - alu_bmask_a_mux_sel_o = BMASK_A_REG; - regb_used_o = 1'b1; - end - 3'b010: begin - alu_operator_o = ALU_BINS; - imm_b_mux_sel_o = IMMB_S2; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - //register variant - alu_op_b_mux_sel_o = OP_B_BMASK; - alu_bmask_a_mux_sel_o = BMASK_A_REG; - alu_bmask_b_mux_sel_o = BMASK_B_REG; - regb_used_o = 1'b1; - end - 3'b011: begin - alu_operator_o = ALU_BCLR; - //register variant - regb_used_o = 1'b1; - alu_bmask_a_mux_sel_o = BMASK_A_REG; - alu_bmask_b_mux_sel_o = BMASK_B_REG; - end - 3'b100: begin - alu_operator_o = ALU_BSET; - //register variant - regb_used_o = 1'b1; - alu_bmask_a_mux_sel_o = BMASK_A_REG; - alu_bmask_b_mux_sel_o = BMASK_B_REG; - end - default: illegal_insn_o = 1'b1; - endcase - end else begin - illegal_insn_o = 1'b1; - end - - /////////////////////// - // VECTORIAL FLOAT OPS - /////////////////////// - end else begin - // Vectorial FP not available in 'old' shared FPU - if (FPU==1 && C_XFVEC) begin - - // using APU instead of ALU - apu_en = 1'b1; - alu_en = 1'b0; - // by default, set all registers to FP registers and use 2 - rega_used_o = 1'b1; - regb_used_o = 1'b1; - if (PULP_ZFINX==0) begin - reg_fp_a_o = 1'b1; - reg_fp_b_o = 1'b1; - reg_fp_d_o = 1'b1; - end else begin - reg_fp_a_o = 1'b0; - reg_fp_b_o = 1'b0; - reg_fp_d_o = 1'b0; - end - fpu_vec_op = 1'b1; - // replication bit comes from instruction (can change for some ops) - scalar_replication_o = instr_rdata_i[14]; - // by default we need to verify rm is legal but assume it is for now - check_fprm = 1'b1; - fp_rnd_mode_o = frm_i; // all vectorial ops have rm from fcsr - - // Decode Formats - unique case (instr_rdata_i[13:12]) - // FP32 - 2'b00: begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP32; - alu_vec_mode_o = VEC_MODE32; - end - // FP16ALT - 2'b01: begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - alu_vec_mode_o = VEC_MODE16; - end - // FP16 - 2'b10: begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16; - alu_vec_mode_o = VEC_MODE16; - end - // FP8 - 2'b11: begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP8; - alu_vec_mode_o = VEC_MODE8; - end - endcase - - // By default, src=dst - fpu_src_fmt_o = fpu_dst_fmt_o; - - // decode vectorial FP instruction - unique case (instr_rdata_i[29:25]) inside - // vfadd.vfmt - Vectorial FP Addition - 5'b00001: begin - fpu_op = cv32e40p_fpu_pkg::ADD; - fp_op_group = ADDMUL; - // FPnew needs addition operands as operand B and C - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; - scalar_replication_o = 1'b0; - scalar_replication_c_o = instr_rdata_i[14]; - end - // vfsub.vfmt - Vectorial FP Subtraction - 5'b00010: begin - fpu_op = cv32e40p_fpu_pkg::ADD; - fpu_op_mod = 1'b1; - fp_op_group = ADDMUL; - // FPnew needs addition operands as operand B and C - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; - scalar_replication_o = 1'b0; - scalar_replication_c_o = instr_rdata_i[14]; - end - // vfmul.vfmt - Vectorial FP Multiplication - 5'b00011: begin - fpu_op = cv32e40p_fpu_pkg::MUL; - fp_op_group = ADDMUL; - end - // vfdiv.vfmt - Vectorial FP Division - 5'b00100: begin - fpu_op = cv32e40p_fpu_pkg::DIV; - fp_op_group = DIVSQRT; - end - // vfmin.vfmt - Vectorial FP Minimum - 5'b00101: begin - fpu_op = cv32e40p_fpu_pkg::MINMAX; - fp_rnd_mode_o = 3'b000; // min - fp_op_group = NONCOMP; - check_fprm = 1'b0; // instruction encoded in rm - end - // vfmax.vfmt - Vectorial FP Maximum - 5'b00110: begin - fpu_op = cv32e40p_fpu_pkg::MINMAX; - fp_rnd_mode_o = 3'b001; // max - fp_op_group = NONCOMP; - check_fprm = 1'b0; // instruction encoded in rm - end - // vfsqrt.vfmt - Vectorial FP Square Root - 5'b00111: begin - regb_used_o = 1'b0; - fpu_op = cv32e40p_fpu_pkg::SQRT; - fp_op_group = DIVSQRT; - // rs2 and R must be zero - if ((instr_rdata_i[24:20] != 5'b00000) || instr_rdata_i[14]) begin - illegal_insn_o = 1'b1; - end - end - // vfmac.vfmt - Vectorial FP Multiply-Accumulate - 5'b01000: begin - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; // third operand is rd - if (PULP_ZFINX==0) begin - reg_fp_c_o = 1'b1; - end else begin - reg_fp_c_o = 1'b0; - end - fpu_op = cv32e40p_fpu_pkg::FMADD; - fp_op_group = ADDMUL; - end - // vfmre.vfmt - Vectorial FP Multiply-Reduce - 5'b01001: begin - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; // third operand is rd - if (PULP_ZFINX==0) begin - reg_fp_c_o = 1'b1; - end else begin - reg_fp_c_o = 1'b0; - end - fpu_op = cv32e40p_fpu_pkg::FMADD; - fpu_op_mod = 1'b1; - fp_op_group = ADDMUL; - end - // Moves, Conversions, Classifications - 5'b01100: begin - regb_used_o = 1'b0; - scalar_replication_o = 1'b0; - // Decode Operation in rs2 - unique case (instr_rdata_i[24:20]) inside - // vfmv.{x.vfmt/vfmt.x} - Vectorial FP Reg <-> GP Reg Moves - 5'b00000: begin - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; // set rs2 = rs1 so we can map FMV to SGNJ in the unit - fpu_op = cv32e40p_fpu_pkg::SGNJ; - fp_rnd_mode_o = 3'b011; // passthrough without checking nan-box - fp_op_group = NONCOMP; - check_fprm = 1'b0; - // GP reg to FP reg - if (instr_rdata_i[14]) begin - reg_fp_a_o = 1'b0; // go from integer regfile - fpu_op_mod = 1'b0; // nan-box result - end - // FP reg to GP reg - else begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op_mod = 1'b1; // sign-extend result - end - end - // vfclass.vfmt - Vectorial FP Classifications - 5'b00001: begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::CLASSIFY; - fp_rnd_mode_o = 3'b000; - fp_op_group = NONCOMP; - check_fprm = 1'b0; - // R must not be set - if (instr_rdata_i[14]) illegal_insn_o = 1'b1; - end - // vfcvt.{x.vfmt/vfmt.x} - Vectorial FP <-> Int Conversions - 5'b0001?: begin - fp_op_group = CONV; - fpu_op_mod = instr_rdata_i[14]; // signed/unsigned switch - // Integer width matches FP width - unique case (instr_rdata_i[13:12]) - // FP32 - 2'b00 : fpu_int_fmt_o = cv32e40p_fpu_pkg::INT32; - // FP16[ALT] - 2'b01, - 2'b10: fpu_int_fmt_o = cv32e40p_fpu_pkg::INT16; - // FP8 - 2'b11: fpu_int_fmt_o = cv32e40p_fpu_pkg::INT8; - endcase - // Int to FP conversion - if (instr_rdata_i[20]) begin - reg_fp_a_o = 1'b0; // go from integer regfile - fpu_op = cv32e40p_fpu_pkg::I2F; - end - // FP to Int conversion - else begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::F2I; - end - end - // vfcvt.vfmt.vfmt - Vectorial FP <-> FP Conversions - 5'b001??: begin - fpu_op = cv32e40p_fpu_pkg::F2F; - fp_op_group = CONV; - // check source format - unique case (instr_rdata_i[21:20]) - // Only process instruction if corresponding extension is active (static) - 2'b00: begin - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP32; - if (~C_RVF) illegal_insn_o = 1'b1; - end - 2'b01: begin - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - if (~C_XF16ALT) illegal_insn_o = 1'b1; - end - 2'b10: begin - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16; - if (~C_XF16) illegal_insn_o = 1'b1; - end - 2'b11: begin - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP8; - if (~C_XF8) illegal_insn_o = 1'b1; - end - endcase - // R must not be set - if (instr_rdata_i[14]) illegal_insn_o = 1'b1; - end - // others - default : illegal_insn_o = 1'b1; - endcase - end - // vfsgnj.vfmt - Vectorial FP Sign Injection - 5'b01101: begin - fpu_op = cv32e40p_fpu_pkg::SGNJ; - fp_rnd_mode_o = 3'b000; // sgnj - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vfsgnjn.vfmt - Vectorial FP Negated Sign Injection - 5'b01110: begin - fpu_op = cv32e40p_fpu_pkg::SGNJ; - fp_rnd_mode_o = 3'b001; // sgnjn - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vfsgnjx.vfmt - Vectorial FP Xored Sign Injection - 5'b01111: begin - fpu_op = cv32e40p_fpu_pkg::SGNJ; - fp_rnd_mode_o = 3'b010; // sgnjx - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vfeq.vfmt - Vectorial FP Equals - 5'b10000: begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::CMP; - fp_rnd_mode_o = 3'b010; // eq - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vfne.vfmt - Vectorial FP Not Equals - 5'b10001: begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::CMP; - fpu_op_mod = 1'b1; // invert output - fp_rnd_mode_o = 3'b010; // eq - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vflt.vfmt - Vectorial FP Less Than - 5'b10010: begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::CMP; - fp_rnd_mode_o = 3'b001; // lt - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vfge.vfmt - Vectorial FP Greater Than or Equals - 5'b10011: begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::CMP; - fpu_op_mod = 1'b1; // invert output - fp_rnd_mode_o = 3'b001; // lt - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vfle.vfmt - Vectorial FP Less Than or Equals - 5'b10100: begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::CMP; - fp_rnd_mode_o = 3'b000; // le - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vfgt.vfmt - Vectorial FP Greater Than - 5'b10101: begin - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::CMP; - fpu_op_mod = 1'b1; // invert output - fp_rnd_mode_o = 3'b000; // le - fp_op_group = NONCOMP; - check_fprm = 1'b0; - end - // vfcpk{a-d}.vfmt.s/d - 5'b110??: begin - // vfcpk{{a/c}/{b/d}} selection in R bit - fpu_op_mod = instr_rdata_i[14]; - fp_op_group = CONV; - scalar_replication_o = 1'b0; - - if (instr_rdata_i[25]) fpu_op = cv32e40p_fpu_pkg::CPKCD; // vfcpk{c/d} - else fpu_op = cv32e40p_fpu_pkg::CPKAB; // vfcpk{a/b} - - // vfcpk{a-d}.vfmt.d - from double - if (instr_rdata_i[26]) begin - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP64; - if (~C_RVD) illegal_insn_o = 1'b1; - end - // vfcpk{a-d}.vfmt.s - else begin - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP32; - if (~C_RVF) illegal_insn_o = 1'b1; - end - // Resolve legal vfcpk / format combinations (mostly static) - if (fpu_op == cv32e40p_fpu_pkg::CPKCD) begin // vfcpk{c/d} not possible unless FP8 and FLEN>=64 - if (~C_XF8 || ~C_RVD) illegal_insn_o = 1'b1; - end else begin - if (instr_rdata_i[14]) begin // vfcpkb - // vfcpkb not possible for FP32 - if (fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP32) illegal_insn_o = 1'b1; - // vfcpkb not possible for FP16[ALT] if not RVD - if (~C_RVD && (fpu_dst_fmt_o != cv32e40p_fpu_pkg::FP8)) illegal_insn_o = 1'b1; - end - end - end - // Rest are illegal instructions - default: begin - illegal_insn_o = 1'b1; - end - endcase - - // check enabled formats (static) - // need RVD for F vectors - if ((~C_RVF || ~C_RVD) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP32) illegal_insn_o = 1'b1; - // need RVF for F16 vectors - if ((~C_XF16 || ~C_RVF) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP16) illegal_insn_o = 1'b1; - // need RVF for F16 vectors - if ((~C_XF16ALT || ~C_RVF) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP16ALT) begin - illegal_insn_o = 1'b1; - end - // need F16 for F8 vectors - if ((~C_XF8 || (~C_XF16 && ~C_XF16ALT)) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP8) begin - illegal_insn_o = 1'b1; - end - - // check rounding mode - if (check_fprm) begin - unique case (frm_i) inside - [3'b000:3'b100] : ; //legal rounding modes - default : illegal_insn_o = 1'b1; - endcase - end - - // Set latencies for FPnew from config. The C_LAT constants contain the number - // of pipeline registers. the APU takes the following values: - // 1 = single cycle (no latency), 2 = one pipestage, 3 = two or more pipestages - case (fp_op_group) - // ADDMUL has format dependent latency - ADDMUL : begin - unique case (fpu_dst_fmt_o) - cv32e40p_fpu_pkg::FP32 : apu_lat_o = (C_LAT_FP32<2) ? C_LAT_FP32+1 : 2'h3; - cv32e40p_fpu_pkg::FP16 : apu_lat_o = (C_LAT_FP16<2) ? C_LAT_FP16+1 : 2'h3; - cv32e40p_fpu_pkg::FP16ALT : apu_lat_o = (C_LAT_FP16ALT<2) ? C_LAT_FP16ALT+1 : 2'h3; - cv32e40p_fpu_pkg::FP8 : apu_lat_o = (C_LAT_FP8<2) ? C_LAT_FP8+1 : 2'h3; - default : ; - endcase - end - // DIVSQRT is iterative and takes more than 2 cycles - DIVSQRT : apu_lat_o = 2'h3; - // NONCOMP uses the same latency for all formats - NONCOMP : apu_lat_o = (C_LAT_NONCOMP<2) ? C_LAT_NONCOMP+1 : 2'h3; - // CONV uses the same latency for all formats - CONV : apu_lat_o = (C_LAT_CONV<2) ? C_LAT_CONV+1 : 2'h3; - endcase - - // Set FPnew OP and OPMOD as the APU op - apu_op_o = {fpu_vec_op, fpu_op_mod, fpu_op}; - end - // FPU!=1 or no Vectors or old shared unit - else begin - illegal_insn_o = 1'b1; - end - end // Vectorial Float Ops - - end // prefix 10 - - // PREFIX 00/01 - else begin - // non bit-manipulation instructions - regfile_alu_we = 1'b1; - rega_used_o = 1'b1; - - if (~instr_rdata_i[28]) regb_used_o = 1'b1; - - unique case ({instr_rdata_i[30:25], instr_rdata_i[14:12]}) - // RV32I ALU operations - {6'b00_0000, 3'b000}: alu_operator_o = ALU_ADD; // Add - {6'b10_0000, 3'b000}: alu_operator_o = ALU_SUB; // Sub - {6'b00_0000, 3'b010}: alu_operator_o = ALU_SLTS; // Set Lower Than - {6'b00_0000, 3'b011}: alu_operator_o = ALU_SLTU; // Set Lower Than Unsigned - {6'b00_0000, 3'b100}: alu_operator_o = ALU_XOR; // Xor - {6'b00_0000, 3'b110}: alu_operator_o = ALU_OR; // Or - {6'b00_0000, 3'b111}: alu_operator_o = ALU_AND; // And - {6'b00_0000, 3'b001}: alu_operator_o = ALU_SLL; // Shift Left Logical - {6'b00_0000, 3'b101}: alu_operator_o = ALU_SRL; // Shift Right Logical - {6'b10_0000, 3'b101}: alu_operator_o = ALU_SRA; // Shift Right Arithmetic - - // supported RV32M instructions - {6'b00_0001, 3'b000}: begin // mul - alu_en = 1'b0; - mult_int_en = 1'b1; - mult_operator_o = MUL_MAC32; - regc_mux_o = REGC_ZERO; - end - {6'b00_0001, 3'b001}: begin // mulh - alu_en = 1'b0; - regc_used_o = 1'b1; - regc_mux_o = REGC_ZERO; - mult_signed_mode_o = 2'b11; - mult_int_en = 1'b1; - mult_operator_o = MUL_H; - end - {6'b00_0001, 3'b010}: begin // mulhsu - alu_en = 1'b0; - regc_used_o = 1'b1; - regc_mux_o = REGC_ZERO; - mult_signed_mode_o = 2'b01; - mult_int_en = 1'b1; - mult_operator_o = MUL_H; - end - {6'b00_0001, 3'b011}: begin // mulhu - alu_en = 1'b0; - regc_used_o = 1'b1; - regc_mux_o = REGC_ZERO; - mult_signed_mode_o = 2'b00; - mult_int_en = 1'b1; - mult_operator_o = MUL_H; - end - {6'b00_0001, 3'b100}: begin // div - alu_op_a_mux_sel_o = OP_A_REGB_OR_FWD; - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - regb_used_o = 1'b1; - alu_operator_o = ALU_DIV; - end - {6'b00_0001, 3'b101}: begin // divu - alu_op_a_mux_sel_o = OP_A_REGB_OR_FWD; - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - regb_used_o = 1'b1; - alu_operator_o = ALU_DIVU; - end - {6'b00_0001, 3'b110}: begin // rem - alu_op_a_mux_sel_o = OP_A_REGB_OR_FWD; - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - regb_used_o = 1'b1; - alu_operator_o = ALU_REM; - end - {6'b00_0001, 3'b111}: begin // remu - alu_op_a_mux_sel_o = OP_A_REGB_OR_FWD; - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - regb_used_o = 1'b1; - alu_operator_o = ALU_REMU; - end - - // PULP specific instructions - {6'b10_0001, 3'b000}: begin // p.mac - if (PULP_XPULP) begin - alu_en = 1'b0; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - mult_int_en = 1'b1; - mult_operator_o = MUL_MAC32; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b10_0001, 3'b001}: begin // p.msu - if (PULP_XPULP) begin - alu_en = 1'b0; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - mult_int_en = 1'b1; - mult_operator_o = MUL_MSU32; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_0010, 3'b010}: begin // Set Lower Equal Than - p.slet - if (PULP_XPULP) begin - alu_operator_o = ALU_SLETS; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_0010, 3'b011}: begin // Set Lower Equal Than Unsigned; p.sletu - if (PULP_XPULP) begin - alu_operator_o = ALU_SLETU; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_0010, 3'b100}: begin // Min - p.min - if (PULP_XPULP) begin - alu_operator_o = ALU_MIN; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_0010, 3'b101}: begin // Min Unsigned - p.minu - if (PULP_XPULP) begin - alu_operator_o = ALU_MINU; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_0010, 3'b110}: begin // Max - p.max - if (PULP_XPULP) begin - alu_operator_o = ALU_MAX; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_0010, 3'b111}: begin // Max Unsigned - p.maxu - if (PULP_XPULP) begin - alu_operator_o = ALU_MAXU; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_0100, 3'b101}: begin // Rotate Right - p.ror - if (PULP_XPULP) begin - alu_operator_o = ALU_ROR; - end else begin - illegal_insn_o = 1'b1; - end - end - - // PULP specific instructions using only one source register - - {6'b00_1000, 3'b000}: begin // Find First 1 - p.ff1 - if (PULP_XPULP) begin - alu_operator_o = ALU_FF1; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1000, 3'b001}: begin // Find Last 1 - p.fl1 - if (PULP_XPULP) begin - alu_operator_o = ALU_FL1; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1000, 3'b010}: begin // Count Leading Bits - p.clb - if (PULP_XPULP) begin - alu_operator_o = ALU_CLB; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1000, 3'b011}: begin // Count set bits (popcount) - p.cnt - if (PULP_XPULP) begin - alu_operator_o = ALU_CNT; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1000, 3'b100}: begin // Sign-extend Halfword - p.exths - if (PULP_XPULP) begin - alu_operator_o = ALU_EXTS; - alu_vec_mode_o = VEC_MODE16; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1000, 3'b101}: begin // Zero-extend Halfword - p.exthz - if (PULP_XPULP) begin - alu_operator_o = ALU_EXT; - alu_vec_mode_o = VEC_MODE16; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1000, 3'b110}: begin // Sign-extend Byte - p.extbs - if (PULP_XPULP) begin - alu_operator_o = ALU_EXTS; - alu_vec_mode_o = VEC_MODE8; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1000, 3'b111}: begin // Zero-extend Byte - p.extbz - if (PULP_XPULP) begin - alu_operator_o = ALU_EXT; - alu_vec_mode_o = VEC_MODE8; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_0010, 3'b000}: begin // p.abs - if (PULP_XPULP) begin - alu_operator_o = ALU_ABS; - if (instr_rdata_i[24:20] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1010, 3'b001}: begin // p.clip - if (PULP_XPULP) begin - alu_operator_o = ALU_CLIP; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_CLIP; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1010, 3'b010}: begin // p.clipu - if (PULP_XPULP) begin - alu_operator_o = ALU_CLIPU; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_CLIP; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1010, 3'b101}: begin // p.clipr - if (PULP_XPULP) begin - alu_operator_o = ALU_CLIP; - regb_used_o = 1'b1; - end else begin - illegal_insn_o = 1'b1; - end - end - {6'b00_1010, 3'b110}: begin // p.clipur - if (PULP_XPULP) begin - alu_operator_o = ALU_CLIPU; - regb_used_o = 1'b1; - end else begin - illegal_insn_o = 1'b1; - end - end - - default: begin - illegal_insn_o = 1'b1; - end - endcase - end - end - - //////////////////////////// - // ______ _____ _ _ // - // | ____| __ \| | | | // - // | |__ | |__) | | | | // - // | __| | ___/| | | | // - // | | | | | |__| | // - // |_| |_| \____/ // - // // - //////////////////////////// - - // floating point arithmetic - OPCODE_OP_FP: begin - if (FPU==1) begin - - // using APU instead of ALU - apu_en = 1'b1; - alu_en = 1'b0; - // by default, set all registers to FP registers and use 2 - rega_used_o = 1'b1; - regb_used_o = 1'b1; - if (PULP_ZFINX==0) begin - reg_fp_a_o = 1'b1; - reg_fp_b_o = 1'b1; - reg_fp_d_o = 1'b1; - end else begin - reg_fp_a_o = 1'b0; - reg_fp_b_o = 1'b0; - reg_fp_d_o = 1'b0; - end - // by default we need to verify rm is legal but assume it is for now - check_fprm = 1'b1; - fp_rnd_mode_o = instr_rdata_i[14:12]; - - // Decode Formats (preliminary, can change for some ops) - unique case (instr_rdata_i[26:25]) - // FP32 - 2'b00: fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP32; - // FP64 - 2'b01: fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP64; - // FP16 or FP16ALT - 2'b10: begin - // FP16alt encoded in rm field - if (instr_rdata_i[14:12]==3'b101) fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - // this can still change to FP16ALT - else fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16; - end - // FP8 - 2'b11: fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP8; - endcase - - // By default, src=dst - fpu_src_fmt_o = fpu_dst_fmt_o; - - // decode FP instruction - unique case (instr_rdata_i[31:27]) - // fadd.fmt - FP Addition - 5'b00000: begin - fpu_op = cv32e40p_fpu_pkg::ADD; - fp_op_group = ADDMUL; - apu_op_o = 2'b0; - apu_lat_o = (PIPE_REG_ADDSUB==1) ? 2'h2 : 2'h1; - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; - end - // fsub.fmt - FP Subtraction - 5'b00001: begin - fpu_op = cv32e40p_fpu_pkg::ADD; - fpu_op_mod = 1'b1; - fp_op_group = ADDMUL; - apu_op_o = 2'b1; - apu_lat_o = (PIPE_REG_ADDSUB==1) ? 2'h2 : 2'h1; - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; - end - // fmul.fmt - FP Multiplication - 5'b00010: begin - fpu_op = cv32e40p_fpu_pkg::MUL; - fp_op_group = ADDMUL; - apu_lat_o = (PIPE_REG_MULT==1) ? 2'h2 : 2'h1; - end - // fdiv.fmt - FP Division - 5'b00011: begin - fpu_op = cv32e40p_fpu_pkg::DIV; - fp_op_group = DIVSQRT; - apu_lat_o = 2'h3; - end - // fsqrt.fmt - FP Square Root - 5'b01011: begin - regb_used_o = 1'b0; - fpu_op = cv32e40p_fpu_pkg::SQRT; - fp_op_group = DIVSQRT; - apu_op_o = 1'b1; - apu_lat_o = 2'h3; - // rs2 must be zero - if (instr_rdata_i[24:20] != 5'b00000) illegal_insn_o = 1'b1; - end - // fsgn{j[n]/jx}.fmt - FP Sign Injection - 5'b00100: begin - fpu_op = cv32e40p_fpu_pkg::SGNJ; - fp_op_group = NONCOMP; - check_fprm = 1'b0; // instruction encoded in rm, do the check here - if (C_XF16ALT) begin // FP16ALT instructions encoded in rm separately (static) - if (!(instr_rdata_i[14:12] inside {[3'b000:3'b010], [3'b100:3'b110]})) begin - illegal_insn_o = 1'b1; - end - // FP16ALT uses special encoding here - if (instr_rdata_i[14]) begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - end else begin - fp_rnd_mode_o = {1'b0, instr_rdata_i[13:12]}; - end - end else begin - if (!(instr_rdata_i[14:12] inside {[3'b000:3'b010]})) illegal_insn_o = 1'b1; - end - end - // fmin/fmax.fmt - FP Minimum / Maximum - 5'b00101: begin - fpu_op = cv32e40p_fpu_pkg::MINMAX; - fp_op_group = NONCOMP; - check_fprm = 1'b0; // instruction encoded in rm, do the check here - if (C_XF16ALT) begin // FP16ALT instructions encoded in rm separately (static) - if (!(instr_rdata_i[14:12] inside {[3'b000:3'b001], [3'b100:3'b101]})) begin - illegal_insn_o = 1'b1; - end - // FP16ALT uses special encoding here - if (instr_rdata_i[14]) begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - end else begin - fp_rnd_mode_o = {1'b0, instr_rdata_i[13:12]}; - end - end else begin - if (!(instr_rdata_i[14:12] inside {[3'b000:3'b001]})) illegal_insn_o = 1'b1; - end - end - // fcvt.fmt.fmt - FP to FP Conversion - 5'b01000: begin - regb_used_o = 1'b0; - fpu_op = cv32e40p_fpu_pkg::F2F; - fp_op_group = CONV; - // bits [22:20] used, other bits must be 0 - if (instr_rdata_i[24:23]) illegal_insn_o = 1'b1; - // check source format - unique case (instr_rdata_i[22:20]) - // Only process instruction if corresponding extension is active (static) - 3'b000: begin - if (~C_RVF) illegal_insn_o = 1'b1; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP32; - end - 3'b001: begin - if (~C_RVD) illegal_insn_o = 1'b1; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP64; - end - 3'b010: begin - if (~C_XF16) illegal_insn_o = 1'b1; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16; - end - 3'b110: begin - if (~C_XF16ALT) illegal_insn_o = 1'b1; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - end - 3'b011: begin - if (~C_XF8) illegal_insn_o = 1'b1; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP8; - end - default: illegal_insn_o = 1'b1; - endcase - end - // fmulex.s.fmt - FP Expanding Multiplication to FP32 - 5'b01001: begin - fpu_op = cv32e40p_fpu_pkg::MUL; - fp_op_group = ADDMUL; - apu_lat_o = (PIPE_REG_MULT==1) ? 2'h2 : 2'h1; - // set dst format to FP32 - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP32; - end - // fmacex.s.fmt - FP Expanding Multipy-Accumulate to FP32 - 5'b01010: begin - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; // third operand is rd - if (PULP_ZFINX==0) begin - reg_fp_c_o = 1'b1; - end else begin - reg_fp_c_o = 1'b0; - end - fpu_op = cv32e40p_fpu_pkg::FMADD; - fp_op_group = ADDMUL; - apu_lat_o = (PIPE_REG_MULT==1) ? 2'h2 : 2'h1; - // set dst format to FP32 - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP32; - end - // feq/flt/fle.fmt - FP Comparisons - 5'b10100: begin - fpu_op = cv32e40p_fpu_pkg::CMP; - fp_op_group = NONCOMP; - reg_fp_d_o = 1'b0; // go to integer regfile - check_fprm = 1'b0; // instruction encoded in rm, do the check here - if (C_XF16ALT) begin // FP16ALT instructions encoded in rm separately (static) - if (!(instr_rdata_i[14:12] inside {[3'b000:3'b010], [3'b100:3'b110]})) begin - illegal_insn_o = 1'b1; - end - // FP16ALT uses special encoding here - if (instr_rdata_i[14]) begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - end else begin - fp_rnd_mode_o = {1'b0, instr_rdata_i[13:12]}; - end - end else begin - if (!(instr_rdata_i[14:12] inside {[3'b000:3'b010]})) illegal_insn_o = 1'b1; - end - end - // fcvt.ifmt.fmt - FP to Int Conversion - 5'b11000: begin - regb_used_o = 1'b0; - reg_fp_d_o = 1'b0; // go to integer regfile - fpu_op = cv32e40p_fpu_pkg::F2I; - fp_op_group = CONV; - fpu_op_mod = instr_rdata_i[20]; // signed/unsigned switch - apu_op_o = 2'b1; - apu_lat_o = (PIPE_REG_CAST==1) ? 2'h2 : 2'h1; - - unique case (instr_rdata_i[26:25]) //fix for casting to different formats other than FP32 - 2'b00: begin - if (~C_RVF) illegal_insn_o = 1; - else fpu_src_fmt_o = cv32e40p_fpu_pkg::FP32; - end - 2'b01: begin - if (~C_RVD) illegal_insn_o = 1; - else fpu_src_fmt_o = cv32e40p_fpu_pkg::FP64; - end - 2'b10: begin - if (instr_rdata_i[14:12] == 3'b101) begin - if (~C_XF16ALT) illegal_insn_o = 1; - else fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - end else if (~C_XF16) begin - illegal_insn_o = 1; - end else begin - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16; - end - end - 2'b11: begin - if (~C_XF8) illegal_insn_o = 1; - else fpu_src_fmt_o = cv32e40p_fpu_pkg::FP8; - end - endcase // unique case (instr_rdata_i[26:25]) - // bits [21:20] used, other bits must be 0 - if (instr_rdata_i[24:21]) illegal_insn_o = 1'b1; // in RV32, no casts to L allowed. - end - // fcvt.fmt.ifmt - Int to FP Conversion - 5'b11010: begin - regb_used_o = 1'b0; - reg_fp_a_o = 1'b0; // go from integer regfile - fpu_op = cv32e40p_fpu_pkg::I2F; - fp_op_group = CONV; - fpu_op_mod = instr_rdata_i[20]; // signed/unsigned switch - apu_op_o = 2'b0; - apu_lat_o = (PIPE_REG_CAST==1) ? 2'h2 : 2'h1; - // bits [21:20] used, other bits must be 0 - if (instr_rdata_i[24:21]) illegal_insn_o = 1'b1; // in RV32, no casts to L allowed. - end - // move and class - 5'b11100: begin - regb_used_o = 1'b0; - reg_fp_d_o = 1'b0; // go to integer regfile - fp_op_group = NONCOMP; - check_fprm = 1'b0; // instruction encoded in rm, do the check here - // fmv.x.fmt - FPR to GPR Move - if (instr_rdata_i[14:12] == 3'b000 || (C_XF16ALT && instr_rdata_i[14:12] == 3'b100)) begin - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; // set rs2 = rs1 so we can map FMV to SGNJ in the unit - fpu_op = cv32e40p_fpu_pkg::SGNJ; // mapped to SGNJ-passthrough since no recoding - fpu_op_mod = 1'b1; // sign-extend result - fp_rnd_mode_o = 3'b011; // passthrough without checking nan-box - // FP16ALT uses special encoding here - if (instr_rdata_i[14]) begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - end - // fclass.fmt - FP Classify - end else if (instr_rdata_i[14:12] == 3'b001 || (C_XF16ALT && instr_rdata_i[14:12] == 3'b101)) begin - fpu_op = cv32e40p_fpu_pkg::CLASSIFY; - fp_rnd_mode_o = 3'b000; - // FP16ALT uses special encoding here - if (instr_rdata_i[14]) begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - end - end else begin - illegal_insn_o = 1'b1; - end - // rs2 must be zero - if (instr_rdata_i[24:20]) illegal_insn_o = 1'b1; - end - // fmv.fmt.x - GPR to FPR Move - 5'b11110: begin - regb_used_o = 1'b0; - reg_fp_a_o = 1'b0; // go from integer regfile - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; // set rs2 = rs1 so we can map FMV to SGNJ in the unit - fpu_op = cv32e40p_fpu_pkg::SGNJ; // mapped to SGNJ-passthrough since no recoding - fpu_op_mod = 1'b0; // nan-box result - fp_op_group = NONCOMP; - fp_rnd_mode_o = 3'b011; // passthrough without checking nan-box - check_fprm = 1'b0; // instruction encoded in rm, do the check here - if (instr_rdata_i[14:12] == 3'b000 || (C_XF16ALT && instr_rdata_i[14:12] == 3'b100)) begin - // FP16ALT uses special encoding here - if (instr_rdata_i[14]) begin - fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - fpu_src_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - end - end else begin - illegal_insn_o = 1'b1; - end - // rs2 must be zero - if (instr_rdata_i[24:20] != 5'b00000) illegal_insn_o = 1'b1; - end - // Rest are illegal instructions - default: begin - illegal_insn_o = 1'b1; - end - endcase - - // check enabled formats (static) - if (~C_RVF && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP32) illegal_insn_o = 1'b1; - if ((~C_RVD) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP64) illegal_insn_o = 1'b1; - if ((~C_XF16) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP16) illegal_insn_o = 1'b1; - if ((~C_XF16ALT) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP16ALT) begin - illegal_insn_o = 1'b1; - end - if ((~C_XF8) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP8) illegal_insn_o = 1'b1; - - // check rounding mode - if (check_fprm) begin - unique case (instr_rdata_i[14:12]) inside - [3'b000:3'b100]: ; //legal rounding modes - 3'b101: begin // Alternative Half-Precsision encded as fmt=10 and rm=101 - if (~C_XF16ALT || fpu_dst_fmt_o != cv32e40p_fpu_pkg::FP16ALT) illegal_insn_o = 1'b1; - // actual rounding mode from frm csr - unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes - default : illegal_insn_o = 1'b1; - endcase - end - 3'b111: begin - // rounding mode from frm csr - unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes - default : illegal_insn_o = 1'b1; - endcase - end - default : illegal_insn_o = 1'b1; - endcase - end - - // Set latencies for FPnew from config. The C_LAT constants contain the number - // of pipeline registers. the APU takes the following values: - // 1 = single cycle (no latency), 2 = one pipestage, 3 = two or more pipestages - case (fp_op_group) - // ADDMUL has format dependent latency - ADDMUL : begin - unique case (fpu_dst_fmt_o) - cv32e40p_fpu_pkg::FP32 : apu_lat_o = (C_LAT_FP32<2) ? C_LAT_FP32+1 : 2'h3; - cv32e40p_fpu_pkg::FP64 : apu_lat_o = (C_LAT_FP64<2) ? C_LAT_FP64+1 : 2'h3; - cv32e40p_fpu_pkg::FP16 : apu_lat_o = (C_LAT_FP16<2) ? C_LAT_FP16+1 : 2'h3; - cv32e40p_fpu_pkg::FP16ALT : apu_lat_o = (C_LAT_FP16ALT<2) ? C_LAT_FP16ALT+1 : 2'h3; - cv32e40p_fpu_pkg::FP8 : apu_lat_o = (C_LAT_FP8<2) ? C_LAT_FP8+1 : 2'h3; - default : ; - endcase - end - // DIVSQRT is iterative and takes more than 2 cycles - DIVSQRT : apu_lat_o = 2'h3; - // NONCOMP uses the same latency for all formats - NONCOMP : apu_lat_o = (C_LAT_NONCOMP<2) ? C_LAT_NONCOMP+1 : 2'h3; - // CONV uses the same latency for all formats - CONV : apu_lat_o = (C_LAT_CONV<2) ? C_LAT_CONV+1 : 2'h3; - endcase - - // Set FPnew OP and OPMOD as the APU op - apu_op_o = {fpu_vec_op, fpu_op_mod, fpu_op}; - - end - // FPU!=1 - else - illegal_insn_o = 1'b1; - end - - // floating point fused arithmetic - OPCODE_OP_FMADD, - OPCODE_OP_FMSUB, - OPCODE_OP_FNMSUB, - OPCODE_OP_FNMADD : begin - if (FPU==1) begin - // using APU instead of ALU - apu_en = 1'b1; - alu_en = 1'b0; - apu_lat_o = (PIPE_REG_MAC>1) ? 2'h3 : 2'h2; - // all registers are FP registers and use three - rega_used_o = 1'b1; - regb_used_o = 1'b1; - regc_used_o = 1'b1; - regc_mux_o = REGC_S4; - if (PULP_ZFINX==0) begin - reg_fp_a_o = 1'b1; - reg_fp_b_o = 1'b1; - reg_fp_c_o = 1'b1; - reg_fp_d_o = 1'b1; - end else begin - reg_fp_a_o = 1'b0; - reg_fp_b_o = 1'b0; - reg_fp_c_o = 1'b0; - reg_fp_d_o = 1'b0; - end - fp_rnd_mode_o = instr_rdata_i[14:12]; - - // Decode Formats - unique case (instr_rdata_i[26:25]) - // FP32 - 2'b00 : fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP32; - // FP64 - 2'b01 : fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP64; - // FP16 or FP16ALT - 2'b10 : begin - // FP16alt encoded in rm field - if (instr_rdata_i[14:12]==3'b101) fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16ALT; - else fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP16; - end - // FP8 - 2'b11 : fpu_dst_fmt_o = cv32e40p_fpu_pkg::FP8; - endcase - - // By default, src=dst - fpu_src_fmt_o = fpu_dst_fmt_o; - - // decode FP intstruction - unique case (instr_rdata_i[6:0]) - // fmadd.fmt - FP Fused multiply-add - OPCODE_OP_FMADD : begin - fpu_op = cv32e40p_fpu_pkg::FMADD; - apu_op_o = 2'b00; - end - // fmsub.fmt - FP Fused multiply-subtract - OPCODE_OP_FMSUB : begin - fpu_op = cv32e40p_fpu_pkg::FMADD; - fpu_op_mod = 1'b1; - apu_op_o = 2'b01; - end - // fnmsub.fmt - FP Negated fused multiply-subtract - OPCODE_OP_FNMSUB : begin - fpu_op = cv32e40p_fpu_pkg::FNMSUB; - apu_op_o = 2'b10; - end - // fnmadd.fmt - FP Negated fused multiply-add - OPCODE_OP_FNMADD : begin - fpu_op = cv32e40p_fpu_pkg::FNMSUB; - fpu_op_mod = 1'b1; - apu_op_o = 2'b11; - end - endcase - - // check enabled formats (static) - if (~C_RVF && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP32) illegal_insn_o = 1'b1; - if ((~C_RVD) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP64) illegal_insn_o = 1'b1; - if ((~C_XF16) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP16) illegal_insn_o = 1'b1; - if ((~C_XF16ALT) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP16ALT) begin - illegal_insn_o = 1'b1; - end - if ((~C_XF8) && fpu_dst_fmt_o == cv32e40p_fpu_pkg::FP8) illegal_insn_o = 1'b1; - - // check rounding mode - unique case (instr_rdata_i[14:12]) inside - [3'b000:3'b100]: ; //legal rounding modes - 3'b101: begin // Alternative Half-Precsision encded as fmt=10 and rm=101 - if (~C_XF16ALT || fpu_dst_fmt_o != cv32e40p_fpu_pkg::FP16ALT) illegal_insn_o = 1'b1; - // actual rounding mode from frm csr - unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes - default : illegal_insn_o = 1'b1; - endcase - end - 3'b111: begin - // rounding mode from frm csr - unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes - default : illegal_insn_o = 1'b1; - endcase - end - default : illegal_insn_o = 1'b1; - endcase - - // Set latencies for FPnew from config. The C_LAT constants contain the number - // of pipeline registers. the APU takes the following values: - // 1 = single cycle (no latency), 2 = one pipestage, 3 = two or more pipestages - // format dependent latency - unique case (fpu_dst_fmt_o) - cv32e40p_fpu_pkg::FP32 : apu_lat_o = (C_LAT_FP32<2) ? C_LAT_FP32+1 : 2'h3; - cv32e40p_fpu_pkg::FP64 : apu_lat_o = (C_LAT_FP64<2) ? C_LAT_FP64+1 : 2'h3; - cv32e40p_fpu_pkg::FP16 : apu_lat_o = (C_LAT_FP16<2) ? C_LAT_FP16+1 : 2'h3; - cv32e40p_fpu_pkg::FP16ALT : apu_lat_o = (C_LAT_FP16ALT<2) ? C_LAT_FP16ALT+1 : 2'h3; - cv32e40p_fpu_pkg::FP8 : apu_lat_o = (C_LAT_FP8<2) ? C_LAT_FP8+1 : 2'h3; - default : ; - endcase - - // Set FPnew OP and OPMOD as the APU op - apu_op_o = {fpu_vec_op, fpu_op_mod, fpu_op}; - end - // FPU!=1 - else begin - illegal_insn_o = 1'b1; - end - end - - OPCODE_STORE_FP: begin - if (FPU==1) begin - data_req = 1'b1; - data_we_o = 1'b1; - rega_used_o = 1'b1; - regb_used_o = 1'b1; - alu_operator_o = ALU_ADD; - if (PULP_ZFINX==0) begin - reg_fp_b_o = 1'b1; - end else begin - reg_fp_b_o = 1'b0; - end - - // offset from immediate - imm_b_mux_sel_o = IMMB_S; - alu_op_b_mux_sel_o = OP_B_IMM; - - // pass write data through ALU operand c - alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; - - // Decode data type - unique case (instr_rdata_i[14:12]) - // fsb - FP8 store - 3'b000 : if (C_XF8) data_type_o = 2'b10; - else illegal_insn_o = 1'b1; - // fsh - FP16 store - 3'b001 : if (C_XF16 | C_XF16ALT) data_type_o = 2'b01; - else illegal_insn_o = 1'b1; - // fsw - FP32 store - 3'b010 : if (C_RVF) data_type_o = 2'b00; - else illegal_insn_o = 1'b1; - // fsd - FP64 store - 3'b011 : if (C_RVD) data_type_o = 2'b00; // 64bit stores unsupported! - else illegal_insn_o = 1'b1; - default: illegal_insn_o = 1'b1; - endcase - - // sanitize memory bus signals for illegal instr (not sure if needed??) - if (illegal_insn_o) begin - data_req = 1'b0; - data_we_o = 1'b0; - end - end - // FPU!=1 - else - illegal_insn_o = 1'b1; - end - - OPCODE_LOAD_FP: begin - if (FPU==1) begin - data_req = 1'b1; - regfile_mem_we = 1'b1; - if (PULP_ZFINX==0) begin - reg_fp_d_o = 1'b1; - end else begin - reg_fp_d_o = 1'b0; - end - rega_used_o = 1'b1; - alu_operator_o = ALU_ADD; - - // offset from immediate - imm_b_mux_sel_o = IMMB_I; - alu_op_b_mux_sel_o = OP_B_IMM; - - // NaN boxing - data_sign_extension_o = 2'b10; - - // Decode data type - unique case (instr_rdata_i[14:12]) - // flb - FP8 load - 3'b000 : if (C_XF8) data_type_o = 2'b10; - else illegal_insn_o = 1'b1; - // flh - FP16 load - 3'b001 : if (C_XF16 | C_XF16ALT) data_type_o = 2'b01; - else illegal_insn_o = 1'b1; - // flw - FP32 load - 3'b010 : if (C_RVF) data_type_o = 2'b00; - else illegal_insn_o = 1'b1; - // fld - FP64 load - 3'b011 : if (C_RVD) data_type_o = 2'b00; // 64bit loads unsupported! - else illegal_insn_o = 1'b1; - default: illegal_insn_o = 1'b1; - endcase - end - // FPU!=1 - else - illegal_insn_o = 1'b1; - end - - OPCODE_PULP_OP: begin // PULP specific ALU instructions with three source operands - if (PULP_XPULP) begin - regfile_alu_we = 1'b1; - rega_used_o = 1'b1; - regb_used_o = 1'b1; - - case (instr_rdata_i[13:12]) - 2'b00: begin // multiply with subword selection - alu_en = 1'b0; - - mult_sel_subword_o = instr_rdata_i[30]; - mult_signed_mode_o = {2{instr_rdata_i[31]}}; - - mult_imm_mux_o = MIMM_S3; - regc_mux_o = REGC_ZERO; - mult_int_en = 1'b1; - - if (instr_rdata_i[14]) - mult_operator_o = MUL_IR; - else - mult_operator_o = MUL_I; - end - - 2'b01: begin // MAC with subword selection - alu_en = 1'b0; - - mult_sel_subword_o = instr_rdata_i[30]; - mult_signed_mode_o = {2{instr_rdata_i[31]}}; - - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - mult_imm_mux_o = MIMM_S3; - mult_int_en = 1'b1; - - if (instr_rdata_i[14]) - mult_operator_o = MUL_IR; - else - mult_operator_o = MUL_I; - end - - 2'b10: begin // add with normalization and rounding - // decide between using unsigned and rounding, and combinations - // thereof - case ({instr_rdata_i[31],instr_rdata_i[14]}) - 2'b00: alu_operator_o = ALU_ADD; - 2'b01: alu_operator_o = ALU_ADDR; - 2'b10: alu_operator_o = ALU_ADDU; - 2'b11: alu_operator_o = ALU_ADDUR; - endcase - - bmask_a_mux_o = BMASK_A_ZERO; - bmask_b_mux_o = BMASK_B_S3; - - if (instr_rdata_i[30]) begin - //register variant - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - alu_bmask_b_mux_sel_o = BMASK_B_REG; - alu_op_a_mux_sel_o = OP_A_REGC_OR_FWD; - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - if(instr_rdata_i[29:25] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end - - end - - 2'b11: begin // sub with normalization and rounding - // decide between using unsigned and rounding, and combinations - // thereof - case ({instr_rdata_i[31],instr_rdata_i[14]}) - 2'b00: alu_operator_o = ALU_SUB; - 2'b01: alu_operator_o = ALU_SUBR; - 2'b10: alu_operator_o = ALU_SUBU; - 2'b11: alu_operator_o = ALU_SUBUR; - endcase - - bmask_a_mux_o = BMASK_A_ZERO; - bmask_b_mux_o = BMASK_B_S3; - - if (instr_rdata_i[30]) begin - //register variant - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - alu_bmask_b_mux_sel_o = BMASK_B_REG; - alu_op_a_mux_sel_o = OP_A_REGC_OR_FWD; - alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; - if(instr_rdata_i[29:25] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end - - end - endcase - end else begin - illegal_insn_o = 1'b1; - end - end - - OPCODE_VECOP: begin - if (PULP_XPULP) begin - regfile_alu_we = 1'b1; - rega_used_o = 1'b1; - imm_b_mux_sel_o = IMMB_VS; - - // vector size - if (instr_rdata_i[12]) begin - alu_vec_mode_o = VEC_MODE8; - mult_operator_o = MUL_DOT8; - end else begin - alu_vec_mode_o = VEC_MODE16; - mult_operator_o = MUL_DOT16; - end - - // distinguish normal vector, sc and sci modes - if (instr_rdata_i[14]) begin - scalar_replication_o = 1'b1; - - if (instr_rdata_i[13]) begin - // immediate scalar replication, .sci - alu_op_b_mux_sel_o = OP_B_IMM; - end else begin - // register scalar replication, .sc - regb_used_o = 1'b1; - end - end else begin - // normal register use - regb_used_o = 1'b1; - end - - // now decode the instruction - unique case (instr_rdata_i[31:26]) - 6'b00000_0: begin // cv.add - alu_operator_o = ALU_ADD; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00001_0: begin // cv.sub - alu_operator_o = ALU_SUB; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00010_0: begin // cv.avg - alu_operator_o = ALU_ADD; - imm_b_mux_sel_o = IMMB_VS; - bmask_b_mux_o = BMASK_B_ONE; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00011_0: begin // cv.avgu - alu_operator_o = ALU_ADDU; - imm_b_mux_sel_o = IMMB_VU; - bmask_b_mux_o = BMASK_B_ONE; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00100_0: begin // cv.min - alu_operator_o = ALU_MIN; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00101_0: begin // cv.minu - alu_operator_o = ALU_MINU; - imm_b_mux_sel_o = IMMB_VU; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00110_0: begin // cv.max - alu_operator_o = ALU_MAX; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00111_0: begin // cv.maxu - alu_operator_o = ALU_MAXU; - imm_b_mux_sel_o = IMMB_VU; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01000_0: begin // cv.srl - alu_operator_o = ALU_SRL; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01001_0: begin // cv.sra - alu_operator_o = ALU_SRA; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01010_0: begin // cv.sll - alu_operator_o = ALU_SLL; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01011_0: begin // cv.or - alu_operator_o = ALU_OR; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01100_0: begin // cv.xor - alu_operator_o = ALU_XOR; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01101_0: begin // cv.and - alu_operator_o = ALU_AND; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01110_0: begin // cv.abs - alu_operator_o = ALU_ABS; - imm_b_mux_sel_o = IMMB_VS; - if (!(instr_rdata_i[14:12] == 3'b000 || instr_rdata_i[14:12] == 3'b001)) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[25:20] != 6'b000000) begin - illegal_insn_o = 1'b1; - end - end - 6'b11000_0: begin // cv.shuffle, cv.shuffleI0 - alu_operator_o = ALU_SHUF; - imm_b_mux_sel_o = IMMB_SHUF; - regb_used_o = 1'b1; - scalar_replication_o = 1'b0; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011 || instr_rdata_i[14:12] == 3'b100 - || instr_rdata_i[14:12] == 3'b101) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b11101_0, - 6'b11110_0, - 6'b11111_0: begin // cv.shuffleI1 cv.shuffleI2 cv.shuffleI3 - alu_operator_o = ALU_SHUF; - imm_b_mux_sel_o = IMMB_SHUF; - regb_used_o = 1'b1; - scalar_replication_o = 1'b0; - if (instr_rdata_i[14:12] != 3'b111) begin - illegal_insn_o = 1'b1; - end - end - 6'b11001_0: begin // cv.shuffle2 - alu_operator_o = ALU_SHUF2; - regb_used_o = 1'b1; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - scalar_replication_o = 1'b0; - if (!(instr_rdata_i[14:12] == 3'b000 || instr_rdata_i[14:12] == 3'b001)) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[25] != 1'b0) begin - illegal_insn_o = 1'b1; - end - end - 6'b11010_0: begin // cv.pack - alu_operator_o = instr_rdata_i[25] ? ALU_PCKHI : ALU_PCKLO; - regb_used_o = 1'b1; - if (instr_rdata_i[14:12] != 3'b000) begin - illegal_insn_o = 1'b1; - end - end - 6'b11011_0: begin // cv.packhi - alu_operator_o = ALU_PCKHI; - regb_used_o = 1'b1; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - if (instr_rdata_i[14:12] != 3'b001) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[25] != 1'b0) begin - illegal_insn_o = 1'b1; - end - end - 6'b11100_0: begin // cv.packlo - alu_operator_o = ALU_PCKLO; - regb_used_o = 1'b1; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - if (instr_rdata_i[14:12] != 3'b001) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[25] != 1'b0) begin - illegal_insn_o = 1'b1; - end - end - 6'b01111_0: begin // cv.extract - alu_operator_o = ALU_EXTS; - if (!(instr_rdata_i[14:12] == 3'b110 || instr_rdata_i[14:12] == 3'b111)) begin - illegal_insn_o = 1'b1; - end - end - 6'b10010_0: begin // cv.extractu - alu_operator_o = ALU_EXT; - if (!(instr_rdata_i[14:12] == 3'b110 || instr_rdata_i[14:12] == 3'b111)) begin - illegal_insn_o = 1'b1; - end - end - 6'b10110_0: begin // cv.insert - alu_operator_o = ALU_INS; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; - if (!(instr_rdata_i[14:12] == 3'b110 || instr_rdata_i[14:12] == 3'b111)) begin - illegal_insn_o = 1'b1; - end - end - 6'b10000_0: begin // cv.dotup - alu_en = 1'b0; - mult_dot_en = 1'b1; - mult_dot_signed_o = 2'b00; - imm_b_mux_sel_o = IMMB_VU; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b10001_0: begin // cv.dotusp - alu_en = 1'b0; - mult_dot_en = 1'b1; - mult_dot_signed_o = 2'b01; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b10011_0: begin // cv.dotsp - alu_en = 1'b0; - mult_dot_en = 1'b1; - mult_dot_signed_o = 2'b11; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b10100_0: begin // cv.sdotup - alu_en = 1'b0; - mult_dot_en = 1'b1; - mult_dot_signed_o = 2'b00; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - imm_b_mux_sel_o = IMMB_VU; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b10101_0: begin // cv.sdotusp - alu_en = 1'b0; - mult_dot_en = 1'b1; - mult_dot_signed_o = 2'b01; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b10111_0: begin // cv.sdotsp - alu_en = 1'b0; - mult_dot_en = 1'b1; - mult_dot_signed_o = 2'b11; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - - /* COMPLEX INSTRUCTIONS */ - - 6'b01010_1: begin // cv.clpxmul.{r,i}.{/,div2,div4,div8} - alu_en = 1'b0; - mult_dot_en = 1'b1; - mult_dot_signed_o = 2'b11; - is_clpx_o = 1'b1; - regc_used_o = 1'b1; - regc_mux_o = REGC_RD; - scalar_replication_o = 1'b0; - alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; - regb_used_o = 1'b1; - illegal_insn_o = instr_rdata_i[12]; - end - - 6'b01101_1: begin // cv.subrotmj.{/,div2,div4,div8} - alu_operator_o = ALU_SUB; - is_clpx_o = 1'b1; - scalar_replication_o = 1'b0; - alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; - regb_used_o = 1'b1; - is_subrot_o = 1'b1; - if (instr_rdata_i[25] != 1'b0 || instr_rdata_i[12] != 1'b0) begin - illegal_insn_o = 1'b1; - end - end - - 6'b01011_1: begin // cv.cplxconj - alu_operator_o = ALU_ABS; - is_clpx_o = 1'b1; - scalar_replication_o = 1'b0; - regb_used_o = 1'b0; - if (instr_rdata_i[14:12] != 3'b000) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[25:20] != 6'b000000) begin - illegal_insn_o = 1'b1; - end - end - - 6'b01110_1: begin // cv.add.{div2,div4,div8} - alu_operator_o = ALU_ADD; - is_clpx_o = 1'b1; - scalar_replication_o = 1'b0; - alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; - regb_used_o = 1'b1; - if (!(instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b100 || instr_rdata_i[14:12] == 3'b110)) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[25] != 1'b0) begin - illegal_insn_o = 1'b1; - end - end - - 6'b01100_1: begin // cv.sub.{div2,div4,div8} - alu_operator_o = ALU_SUB; - is_clpx_o = 1'b1; - scalar_replication_o = 1'b0; - alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; - regb_used_o = 1'b1; - if (!(instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b100 || instr_rdata_i[14:12] == 3'b110)) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[25] != 1'b0) begin - illegal_insn_o = 1'b1; - end - end - - // comparisons, always have bit 26 set - 6'b00000_1: begin // cv.cmpeq - alu_operator_o = ALU_EQ; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00001_1: begin // cv.cmpne - alu_operator_o = ALU_NE; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00010_1: begin // cv.cmpgt - alu_operator_o = ALU_GTS; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00011_1: begin // cv.cmpge - alu_operator_o = ALU_GES; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00100_1: begin // cv.cmplt - alu_operator_o = ALU_LTS; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00101_1: begin // cv.cmple - alu_operator_o = ALU_LES; - imm_b_mux_sel_o = IMMB_VS; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00110_1: begin // cv.cmpgtu - alu_operator_o = ALU_GTU; - imm_b_mux_sel_o = IMMB_VU; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b00111_1: begin // cv.cmpgeu - alu_operator_o = ALU_GEU; - imm_b_mux_sel_o = IMMB_VU; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01000_1: begin // cv.cmpltu - alu_operator_o = ALU_LTU; - imm_b_mux_sel_o = IMMB_VU; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - 6'b01001_1: begin // cv.cmpleu - alu_operator_o = ALU_LEU; - imm_b_mux_sel_o = IMMB_VU; - if (instr_rdata_i[14:12] == 3'b010 || instr_rdata_i[14:12] == 3'b011) begin - illegal_insn_o = 1'b1; - end - if (instr_rdata_i[14:12] != 3'b110 && instr_rdata_i[14:12] != 3'b111 && instr_rdata_i[25] != 1'b0 ) begin - illegal_insn_o = 1'b1; - end - end - - default: illegal_insn_o = 1'b1; - endcase - end else begin - illegal_insn_o = 1'b1; - end - end - - //////////////////////////////////////////////// - // ____ ____ _____ ____ ___ _ _ // - // / ___|| _ \| ____/ ___|_ _| / \ | | // - // \___ \| |_) | _|| | | | / _ \ | | // - // ___) | __/| |__| |___ | | / ___ \| |___ // - // |____/|_| |_____\____|___/_/ \_\_____| // - // // - //////////////////////////////////////////////// - - OPCODE_FENCE: begin - unique case (instr_rdata_i[14:12]) - 3'b000: begin // FENCE (FENCE.I instead, a bit more conservative) - // flush pipeline - fencei_insn_o = 1'b1; - end - - 3'b001: begin // FENCE.I - // flush prefetch buffer, flush pipeline - fencei_insn_o = 1'b1; - end - - default: begin - illegal_insn_o = 1'b1; - end - endcase - end - - OPCODE_SYSTEM: begin - if (instr_rdata_i[14:12] == 3'b000) - begin - // non CSR related SYSTEM instructions - if ( {instr_rdata_i[19:15], instr_rdata_i[11:7]} == '0) - begin - unique case (instr_rdata_i[31:20]) - 12'h000: // ECALL - begin - // environment (system) call - ecall_insn_o = 1'b1; - end - - 12'h001: // ebreak - begin - // debugger trap - ebrk_insn_o = 1'b1; - end - - 12'h302: // mret - begin - illegal_insn_o = (PULP_SECURE) ? current_priv_lvl_i != PRIV_LVL_M : 1'b0; - mret_insn_o = ~illegal_insn_o; - mret_dec_o = 1'b1; - end - - 12'h002: // uret - begin - illegal_insn_o = (PULP_SECURE) ? 1'b0 : 1'b1; - uret_insn_o = ~illegal_insn_o; - uret_dec_o = 1'b1; - end - - 12'h7b2: // dret - begin - illegal_insn_o = !debug_mode_i; - dret_insn_o = debug_mode_i; - dret_dec_o = 1'b1; - end - - 12'h105: // wfi - begin - wfi_o = 1'b1; - if (debug_wfi_no_sleep_i) begin - // Treat as NOP (do not cause sleep mode entry) - // Using decoding similar to ADDI, but without register reads/writes, i.e. - // keep regfile_alu_we = 0, rega_used_o = 0 - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMMB_I; - alu_operator_o = ALU_ADD; - end - end - - default: - begin - illegal_insn_o = 1'b1; - end - endcase - end else illegal_insn_o = 1'b1; - end - else - begin - // instruction to read/modify CSR - csr_access_o = 1'b1; - regfile_alu_we = 1'b1; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_a_mux_sel_o = IMMA_Z; - imm_b_mux_sel_o = IMMB_I; // CSR address is encoded in I imm - - if (instr_rdata_i[14] == 1'b1) begin - // rs1 field is used as immediate - alu_op_a_mux_sel_o = OP_A_IMM; - end else begin - rega_used_o = 1'b1; - alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; - end - - // instr_rdata_i[19:14] = rs or immediate value - // if set or clear with rs==x0 or imm==0, - // then do not perform a write action - unique case (instr_rdata_i[13:12]) - 2'b01: csr_op = CSR_OP_WRITE; - 2'b10: csr_op = instr_rdata_i[19:15] == 5'b0 ? CSR_OP_READ : CSR_OP_SET; - 2'b11: csr_op = instr_rdata_i[19:15] == 5'b0 ? CSR_OP_READ : CSR_OP_CLEAR; - default: csr_illegal = 1'b1; - endcase - - if (instr_rdata_i[29:28] > current_priv_lvl_i) begin - // No access to higher privilege CSR - csr_illegal = 1'b1; - end - - // Determine if CSR access is illegal - case (instr_rdata_i[31:20]) - // Floating point - CSR_FFLAGS, - CSR_FRM, - CSR_FCSR : - if(!FPU) csr_illegal = 1'b1; - - // Writes to read only CSRs results in illegal instruction - CSR_MVENDORID, - CSR_MARCHID, - CSR_MIMPID, - CSR_MHARTID : - if(csr_op != CSR_OP_READ) csr_illegal = 1'b1; - - // These are valid CSR registers - CSR_MSTATUS, - CSR_MEPC, - CSR_MTVEC, - CSR_MCAUSE : - // Not illegal, but treat as status CSR for side effect handling - csr_status_o = 1'b1; - - // These are valid CSR registers - CSR_MISA, - CSR_MIE, - CSR_MSCRATCH, - CSR_MTVAL, - CSR_MIP : - ; // do nothing, not illegal - - // Hardware Performance Monitor - CSR_MCYCLE, - CSR_MINSTRET, - CSR_MHPMCOUNTER3, - CSR_MHPMCOUNTER4, CSR_MHPMCOUNTER5, CSR_MHPMCOUNTER6, CSR_MHPMCOUNTER7, - CSR_MHPMCOUNTER8, CSR_MHPMCOUNTER9, CSR_MHPMCOUNTER10, CSR_MHPMCOUNTER11, - CSR_MHPMCOUNTER12, CSR_MHPMCOUNTER13, CSR_MHPMCOUNTER14, CSR_MHPMCOUNTER15, - CSR_MHPMCOUNTER16, CSR_MHPMCOUNTER17, CSR_MHPMCOUNTER18, CSR_MHPMCOUNTER19, - CSR_MHPMCOUNTER20, CSR_MHPMCOUNTER21, CSR_MHPMCOUNTER22, CSR_MHPMCOUNTER23, - CSR_MHPMCOUNTER24, CSR_MHPMCOUNTER25, CSR_MHPMCOUNTER26, CSR_MHPMCOUNTER27, - CSR_MHPMCOUNTER28, CSR_MHPMCOUNTER29, CSR_MHPMCOUNTER30, CSR_MHPMCOUNTER31, - CSR_MCYCLEH, - CSR_MINSTRETH, - CSR_MHPMCOUNTER3H, - CSR_MHPMCOUNTER4H, CSR_MHPMCOUNTER5H, CSR_MHPMCOUNTER6H, CSR_MHPMCOUNTER7H, - CSR_MHPMCOUNTER8H, CSR_MHPMCOUNTER9H, CSR_MHPMCOUNTER10H, CSR_MHPMCOUNTER11H, - CSR_MHPMCOUNTER12H, CSR_MHPMCOUNTER13H, CSR_MHPMCOUNTER14H, CSR_MHPMCOUNTER15H, - CSR_MHPMCOUNTER16H, CSR_MHPMCOUNTER17H, CSR_MHPMCOUNTER18H, CSR_MHPMCOUNTER19H, - CSR_MHPMCOUNTER20H, CSR_MHPMCOUNTER21H, CSR_MHPMCOUNTER22H, CSR_MHPMCOUNTER23H, - CSR_MHPMCOUNTER24H, CSR_MHPMCOUNTER25H, CSR_MHPMCOUNTER26H, CSR_MHPMCOUNTER27H, - CSR_MHPMCOUNTER28H, CSR_MHPMCOUNTER29H, CSR_MHPMCOUNTER30H, CSR_MHPMCOUNTER31H, - CSR_MCOUNTINHIBIT, - CSR_MHPMEVENT3, - CSR_MHPMEVENT4, CSR_MHPMEVENT5, CSR_MHPMEVENT6, CSR_MHPMEVENT7, - CSR_MHPMEVENT8, CSR_MHPMEVENT9, CSR_MHPMEVENT10, CSR_MHPMEVENT11, - CSR_MHPMEVENT12, CSR_MHPMEVENT13, CSR_MHPMEVENT14, CSR_MHPMEVENT15, - CSR_MHPMEVENT16, CSR_MHPMEVENT17, CSR_MHPMEVENT18, CSR_MHPMEVENT19, - CSR_MHPMEVENT20, CSR_MHPMEVENT21, CSR_MHPMEVENT22, CSR_MHPMEVENT23, - CSR_MHPMEVENT24, CSR_MHPMEVENT25, CSR_MHPMEVENT26, CSR_MHPMEVENT27, - CSR_MHPMEVENT28, CSR_MHPMEVENT29, CSR_MHPMEVENT30, CSR_MHPMEVENT31 : - // Not illegal, but treat as status CSR to get accurate counts - csr_status_o = 1'b1; - - // Hardware Performance Monitor (unprivileged read-only mirror CSRs) - CSR_CYCLE, - CSR_INSTRET, - CSR_HPMCOUNTER3, - CSR_HPMCOUNTER4, CSR_HPMCOUNTER5, CSR_HPMCOUNTER6, CSR_HPMCOUNTER7, - CSR_HPMCOUNTER8, CSR_HPMCOUNTER9, CSR_HPMCOUNTER10, CSR_HPMCOUNTER11, - CSR_HPMCOUNTER12, CSR_HPMCOUNTER13, CSR_HPMCOUNTER14, CSR_HPMCOUNTER15, - CSR_HPMCOUNTER16, CSR_HPMCOUNTER17, CSR_HPMCOUNTER18, CSR_HPMCOUNTER19, - CSR_HPMCOUNTER20, CSR_HPMCOUNTER21, CSR_HPMCOUNTER22, CSR_HPMCOUNTER23, - CSR_HPMCOUNTER24, CSR_HPMCOUNTER25, CSR_HPMCOUNTER26, CSR_HPMCOUNTER27, - CSR_HPMCOUNTER28, CSR_HPMCOUNTER29, CSR_HPMCOUNTER30, CSR_HPMCOUNTER31, - CSR_CYCLEH, - CSR_INSTRETH, - CSR_HPMCOUNTER3H, - CSR_HPMCOUNTER4H, CSR_HPMCOUNTER5H, CSR_HPMCOUNTER6H, CSR_HPMCOUNTER7H, - CSR_HPMCOUNTER8H, CSR_HPMCOUNTER9H, CSR_HPMCOUNTER10H, CSR_HPMCOUNTER11H, - CSR_HPMCOUNTER12H, CSR_HPMCOUNTER13H, CSR_HPMCOUNTER14H, CSR_HPMCOUNTER15H, - CSR_HPMCOUNTER16H, CSR_HPMCOUNTER17H, CSR_HPMCOUNTER18H, CSR_HPMCOUNTER19H, - CSR_HPMCOUNTER20H, CSR_HPMCOUNTER21H, CSR_HPMCOUNTER22H, CSR_HPMCOUNTER23H, - CSR_HPMCOUNTER24H, CSR_HPMCOUNTER25H, CSR_HPMCOUNTER26H, CSR_HPMCOUNTER27H, - CSR_HPMCOUNTER28H, CSR_HPMCOUNTER29H, CSR_HPMCOUNTER30H, CSR_HPMCOUNTER31H : - // Read-only and readable from user mode only if the bit of mcounteren is set - if((csr_op != CSR_OP_READ) || (PULP_SECURE && (current_priv_lvl_i != PRIV_LVL_M) && !mcounteren_i[instr_rdata_i[24:20]])) begin - csr_illegal = 1'b1; - end else begin - csr_status_o = 1'b1; - end - - // This register only exists in user mode - CSR_MCOUNTEREN : - if(!PULP_SECURE) begin - csr_illegal = 1'b1; - end else begin - csr_status_o = 1'b1; - end - - // Debug register access - CSR_DCSR, - CSR_DPC, - CSR_DSCRATCH0, - CSR_DSCRATCH1 : - if(!debug_mode_i) begin - csr_illegal = 1'b1; - end else begin - csr_status_o = 1'b1; - end - - // Debug Trigger register access - CSR_TSELECT, - CSR_TDATA1, - CSR_TDATA2, - CSR_TDATA3, - CSR_TINFO, - CSR_MCONTEXT, - CSR_SCONTEXT : - if(DEBUG_TRIGGER_EN != 1) - csr_illegal = 1'b1; - - // Hardware Loop register, UHARTID access - CSR_LPSTART0, - CSR_LPEND0, - CSR_LPCOUNT0, - CSR_LPSTART1, - CSR_LPEND1, - CSR_LPCOUNT1, - CSR_UHARTID : - if(!PULP_XPULP) csr_illegal = 1'b1; - - // PRIVLV access - CSR_PRIVLV : - if(!PULP_XPULP) begin - csr_illegal = 1'b1; - end else begin - csr_status_o = 1'b1; - end - - // PMP register access - CSR_PMPCFG0, - CSR_PMPCFG1, - CSR_PMPCFG2, - CSR_PMPCFG3, - CSR_PMPADDR0, - CSR_PMPADDR1, - CSR_PMPADDR2, - CSR_PMPADDR3, - CSR_PMPADDR4, - CSR_PMPADDR5, - CSR_PMPADDR6, - CSR_PMPADDR7, - CSR_PMPADDR8, - CSR_PMPADDR9, - CSR_PMPADDR10, - CSR_PMPADDR11, - CSR_PMPADDR12, - CSR_PMPADDR13, - CSR_PMPADDR14, - CSR_PMPADDR15 : - if(!USE_PMP) csr_illegal = 1'b1; - - // User register access - CSR_USTATUS, - CSR_UEPC, - CSR_UTVEC, - CSR_UCAUSE : - if (!PULP_SECURE) begin - csr_illegal = 1'b1; - end else begin - csr_status_o = 1'b1; - end - - default : csr_illegal = 1'b1; - - endcase // case (instr_rdata_i[31:20]) - - illegal_insn_o = csr_illegal; - - end - - end - - - /////////////////////////////////////////////// - // _ ___ ___ ___ ___ ____ // - // | | | \ \ / / | / _ \ / _ \| _ \ // - // | |_| |\ \ /\ / /| | | | | | | | | |_) | // - // | _ | \ V V / | |__| |_| | |_| | __/ // - // |_| |_| \_/\_/ |_____\___/ \___/|_| // - // // - /////////////////////////////////////////////// - - OPCODE_HWLOOP: begin - if(PULP_XPULP) begin : HWLOOP_FEATURE_ENABLED - hwlp_target_mux_sel_o = 1'b0; - - unique case (instr_rdata_i[14:12]) - 3'b000: begin - // lp.starti: set start address to PC + I-type immediate - hwlp_we[0] = 1'b1; - hwlp_start_mux_sel_o = 1'b0; - if(instr_rdata_i[19:15] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end - - 3'b001: begin - // lp.endi: set end address to PC + I-type immediate - hwlp_we[1] = 1'b1; - if(instr_rdata_i[19:15] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end - - 3'b010: begin - // lp.count: initialize counter from rs1 - hwlp_we[2] = 1'b1; - hwlp_cnt_mux_sel_o = 1'b1; - rega_used_o = 1'b1; - if(instr_rdata_i[31:20] != 12'b0) begin - illegal_insn_o = 1'b1; - end - end - - 3'b011: begin - // lp.counti: initialize counter from I-type immediate - hwlp_we[2] = 1'b1; - hwlp_cnt_mux_sel_o = 1'b0; - if(instr_rdata_i[19:15] != 5'b0) begin - illegal_insn_o = 1'b1; - end - end - - 3'b100: begin - // lp.setup: initialize counter from rs1, set start address to - // next instruction and end address to PC + I-type immediate - hwlp_we = 3'b111; - hwlp_start_mux_sel_o = 1'b1; - hwlp_cnt_mux_sel_o = 1'b1; - rega_used_o = 1'b1; - end - - 3'b101: begin - // lp.setupi: initialize counter from immediate, set start address to - // next instruction and end address to PC + I-type immediate - hwlp_we = 3'b111; - hwlp_target_mux_sel_o = 1'b1; - hwlp_start_mux_sel_o = 1'b1; - hwlp_cnt_mux_sel_o = 1'b0; - end - - default: begin - illegal_insn_o = 1'b1; - end - endcase // case (instr_rdata_i[14:12]) - - if(instr_rdata_i[11:8] != 4'b0) begin - illegal_insn_o = 1'b1; - end - - - - end else begin // block: HWLOOP_FEATURE_ENABLED - illegal_insn_o = 1'b1; - end - end // case: OPCODE_HWLOOP - - default: begin - illegal_insn_o = 1'b1; - end - endcase - - - // make sure invalid compressed instruction causes an exception - if (illegal_c_insn_i) begin - illegal_insn_o = 1'b1; - end - - end - - // deassert we signals (in case of stalls) - assign alu_en_o = (deassert_we_i) ? 1'b0 : alu_en; - assign apu_en_o = (deassert_we_i) ? 1'b0 : apu_en; - assign mult_int_en_o = (deassert_we_i) ? 1'b0 : mult_int_en; - assign mult_dot_en_o = (deassert_we_i) ? 1'b0 : mult_dot_en; - assign regfile_mem_we_o = (deassert_we_i) ? 1'b0 : regfile_mem_we; - assign regfile_alu_we_o = (deassert_we_i) ? 1'b0 : regfile_alu_we; - assign data_req_o = (deassert_we_i) ? 1'b0 : data_req; - assign hwlp_we_o = (deassert_we_i) ? 3'b0 : hwlp_we; - assign csr_op_o = (deassert_we_i) ? CSR_OP_READ : csr_op; - assign ctrl_transfer_insn_in_id_o = (deassert_we_i) ? BRANCH_NONE : ctrl_transfer_insn; - - assign ctrl_transfer_insn_in_dec_o = ctrl_transfer_insn; - assign regfile_alu_we_dec_o = regfile_alu_we; - -endmodule // cv32e40p_decoder diff --git a/src/UWE_projectCode/finddialog查找搜索代码/UWE_file.pro b/src/UWE_projectCode/finddialog查找搜索代码/UWE_file.pro deleted file mode 100644 index e73f5e1..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/UWE_file.pro +++ /dev/null @@ -1,26 +0,0 @@ -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -# You can make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -SOURCES += \ - finddialog.cpp \ - main.cpp \ - mainwindow.cpp - -HEADERS += \ - finddialog.h \ - mainwindow.h - -FORMS += \ - mainwindow.ui - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target diff --git a/src/UWE_projectCode/finddialog查找搜索代码/UWE_file.pro.user b/src/UWE_projectCode/finddialog查找搜索代码/UWE_file.pro.user deleted file mode 100644 index 1ec1387..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/UWE_file.pro.user +++ /dev/null @@ -1,427 +0,0 @@ - - - - - - EnvironmentId - {9ae9cba5-5ab5-4831-839f-36c967a0caed} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 80 - true - true - 1 - false - true - false - 0 - true - true - 0 - 8 - true - false - 1 - true - true - true - *.md, *.MD, Makefile - false - true - - - - ProjectExplorer.Project.PluginSettings - - - true - false - true - true - true - true - - - 0 - true - - -fno-delayed-template-parsing - - true - Builtin.BuildSystem - - true - true - Builtin.DefaultTidyAndClazy - 4 - - - - true - - - true - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop Qt 5.12.12 MinGW 32-bit - Desktop Qt 5.12.12 MinGW 32-bit - qt.qt5.51212.win32_mingw73_kit - 0 - 0 - 0 - - 0 - E:\QTUWE\UWEproject\build-UWE_file-Desktop_Qt_5_12_12_MinGW_32_bit-Debug - E:/QTUWE/UWEproject/build-UWE_file-Desktop_Qt_5_12_12_MinGW_32_bit-Debug - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Debug - Qt4ProjectManager.Qt4BuildConfiguration - 2 - - - E:\QTUWE\UWEproject\build-UWE_file-Desktop_Qt_5_12_12_MinGW_32_bit-Release - E:/QTUWE/UWEproject/build-UWE_file-Desktop_Qt_5_12_12_MinGW_32_bit-Release - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Release - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - - - 0 - E:\QTUWE\UWEproject\build-UWE_file-Desktop_Qt_5_12_12_MinGW_32_bit-Profile - E:/QTUWE/UWEproject/build-UWE_file-Desktop_Qt_5_12_12_MinGW_32_bit-Profile - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Profile - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - 0 - - 3 - - - 0 - Deploy - Deploy - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - true - - 2 - - Qt4ProjectManager.Qt4RunConfiguration:E:/QTUWE/UWEproject/UWE_file/UWE_file.pro - E:/QTUWE/UWEproject/UWE_file/UWE_file.pro - false - false - true - false - false - E:/QTUWE/UWEproject/build-UWE_file-Desktop_Qt_5_12_12_MinGW_32_bit-Debug - - 1 - - - - ProjectExplorer.Project.Target.1 - - Desktop - Desktop Qt 5.12.12 MinGW 64-bit - Desktop Qt 5.12.12 MinGW 64-bit - qt.qt5.51212.win64_mingw73_kit - 0 - 0 - 0 - - 0 - E:\QTUWE\UWEproject\build-UWE_file-Desktop_Qt_5_12_12_MinGW_64_bit-Debug - E:/QTUWE/UWEproject/build-UWE_file-Desktop_Qt_5_12_12_MinGW_64_bit-Debug - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Debug - Qt4ProjectManager.Qt4BuildConfiguration - 2 - - - E:\QTUWE\UWEproject\build-UWE_file-Desktop_Qt_5_12_12_MinGW_64_bit-Release - E:/QTUWE/UWEproject/build-UWE_file-Desktop_Qt_5_12_12_MinGW_64_bit-Release - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Release - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - - - 0 - E:\QTUWE\UWEproject\build-UWE_file-Desktop_Qt_5_12_12_MinGW_64_bit-Profile - E:/QTUWE/UWEproject/build-UWE_file-Desktop_Qt_5_12_12_MinGW_64_bit-Profile - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Profile - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - 0 - - 3 - - - 0 - Deploy - Deploy - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - true - - 2 - - ProjectExplorer.CustomExecutableRunConfiguration - - false - false - false - false - - 1 - - - - ProjectExplorer.Project.TargetCount - 2 - - - ProjectExplorer.Project.Updater.FileVersion - 22 - - - Version - 22 - - diff --git a/src/UWE_projectCode/finddialog查找搜索代码/finddialog.cpp b/src/UWE_projectCode/finddialog查找搜索代码/finddialog.cpp deleted file mode 100644 index c488191..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/finddialog.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "finddialog.h" -#include "mainwindow.h" -#include -#include -#include -#include -#include -#include -#include -FindDialog::FindDialog(QWidget *parent, QPlainTextEdit* pText) - : QDialog(parent, Qt::WindowCloseButtonHint | Qt::Drawer) -{ - initControl(); - connectSlot(); - setLayout(&m_layout); - setWindowTitle("Find"); - setPlainTextEdit(pText); -} - -void FindDialog::initControl() -{ - m_findLbl.setText("Find What:"); - m_findBtn.setText("Find Next"); - m_closeBtn.setText("Close"); - m_matchChkBx.setText("Match Case"); - m_backwardBtn.setText("Backward"); - m_forwardBtn.setText("Forward"); - m_forwardBtn.setChecked(true); - m_radioGrpBx.setTitle("Direction"); - - m_hbLayout.addWidget(&m_forwardBtn); - m_hbLayout.addWidget(&m_backwardBtn); - - m_radioGrpBx.setLayout(&m_hbLayout); - - m_layout.setSpacing(10); - m_layout.addWidget(&m_findLbl, 0, 0); - m_layout.addWidget(&m_findEdit, 0, 1); - m_layout.addWidget(&m_findBtn, 0, 2); - m_layout.addWidget(&m_matchChkBx, 1, 0); - m_layout.addWidget(&m_radioGrpBx, 1, 1); - m_layout.addWidget(&m_closeBtn, 1, 2); - -} - -void FindDialog::connectSlot() -{ - connect(&m_findBtn, SIGNAL(clicked()), this, SLOT(onFindClicked())); - connect(&m_closeBtn, SIGNAL(clicked()), this, SLOT(onCloseClicked())); -} - -void FindDialog::setPlainTextEdit(QPlainTextEdit* pText) -{ - m_pText = pText; -} - -QPlainTextEdit* FindDialog::getPlainTextEdit() -{ - return m_pText; -} - -bool FindDialog::event(QEvent* evt) -{ - if( evt->type() == QEvent::Close ) - { - hide(); - - return true; - } - - return QDialog::event(evt); -} - -void FindDialog::onFindClicked() -{ - QString target = m_findEdit.text(); - - if( (m_pText != NULL) && (target != "") ) - { - QString text = m_pText->toPlainText(); - QTextCursor c = m_pText->textCursor(); - int index = -1; - if( m_forwardBtn.isChecked() ) - { - index = text.indexOf(target, c.position(), m_matchChkBx.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive); - - if( index >= 0 ) - { - c.setPosition(index); - c.setPosition(index + target.length(), QTextCursor::KeepAnchor); - m_pText->setTextCursor(c); - QTextCharFormat highlight; - highlight.setBackground(Qt::red); - c.mergeCharFormat(highlight); - m_pText->mergeCurrentCharFormat(highlight); - } - } - - if( m_backwardBtn.isChecked() ) - { - index = text.lastIndexOf(target, c.position() - text.length() - 1, m_matchChkBx.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive); - - if( index >= 0 ) - { - c.setPosition(index + target.length()); - c.setPosition(index, QTextCursor::KeepAnchor); - - m_pText->setTextCursor(c); - QTextCharFormat highlight; - highlight.setBackground(Qt::red); - c.mergeCharFormat(highlight); - m_pText->mergeCurrentCharFormat(highlight); - } - } - - if( index < 0 ) - { - QMessageBox msg(this); - - msg.setWindowTitle("Find"); - msg.setText("Can not find \"" + target + "\" any more..."); - msg.setIcon(QMessageBox::Information); - msg.setStandardButtons(QMessageBox::Ok); - - msg.exec(); - } - } -} - - - -void FindDialog::onCloseClicked() -{ - close(); -} diff --git a/src/UWE_projectCode/finddialog查找搜索代码/finddialog.h b/src/UWE_projectCode/finddialog查找搜索代码/finddialog.h deleted file mode 100644 index 393866f..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/finddialog.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _FINDDIALOG_H_ -#define _FINDDIALOG_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class FindDialog : public QDialog -{ - Q_OBJECT - -protected: - QGroupBox m_radioGrpBx; - - QGridLayout m_layout; - QHBoxLayout m_hbLayout; - - QLabel m_findLbl; - QLineEdit m_findEdit; - QPushButton m_findBtn; - QPushButton m_closeBtn; - QCheckBox m_matchChkBx; - QRadioButton m_forwardBtn; - QRadioButton m_backwardBtn; - - QPointer m_pText; // FindDialog 聚合使用 QPlainTextEdit - QSharedPointer m_pFindDlg; - QTextCharFormat m_format; - void initControl(); - void connectSlot(); - -protected slots: - void onFindClicked(); - void onCloseClicked(); -public: - explicit FindDialog(QWidget* parent = 0, QPlainTextEdit* pText = 0); - void setPlainTextEdit(QPlainTextEdit* pText); - void highlightText(QPlainTextEdit* pText); - QPlainTextEdit* getPlainTextEdit(); - bool event(QEvent* evt); -}; - - - -#endif // _FINDDIALOG_H_ diff --git a/src/UWE_projectCode/finddialog查找搜索代码/main.cpp b/src/UWE_projectCode/finddialog查找搜索代码/main.cpp deleted file mode 100644 index fd3e533..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/main.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "mainwindow.h" - -#include - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindow w; - w.show(); - return a.exec(); -} diff --git a/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.cpp b/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.cpp deleted file mode 100644 index 79fdef1..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" -#include //QFileDialog类是Qt提供的一个用于指定操作文件的对话框小部件,使用前要先导入 -#include //弹出对话框 -#include //调试 -#include -#include -#include "finddialog.h" -MainWindow::MainWindow(QWidget *parent): - QMainWindow(parent), - ui(new Ui::MainWindow) -{ - ui->setupUi(this); - connect(ui->actionFind,SIGNAL(triggered()),this,SLOT(onFindClicked())); - connect(ui->newAction,&QAction::triggered,this,&MainWindow::newActionSlot);//创建链接,newAcion发出取地址信号(newAction),triggered 单击信号,this类mainwindow窗口处理信号 - //mainwindow.h创建槽函数 - //newActionSlot创建链接 - connect(ui->openAction,&QAction::triggered,this,&MainWindow::openActionSlot);//打开文件的槽点链接 - connect(ui->saveAction,&QAction::triggered,this,&MainWindow::saveActionSlot); - connect(ui->changeAction,&QAction::triggered,this,&MainWindow::changeActionSlot); - m_pFindDlg = QSharedPointer(new FindDialog(this, &plainTextEdit)); - m_format.setBackground(Qt::yellow); - m_format.setForeground(Qt::red); -} -MainWindow::~MainWindow() -{ - delete ui; -} -void MainWindow::on_actionFind_clicked() -{ - QPlainTextEdit* pText = ui->plainTextEdit; - FindDialog dlg(this,pText); - dlg.exec(); -} -void MainWindow::newActionSlot() -{ - ui->textEdit->clear(); - this->setWindowTitle("新建文本文档.txt"); - //ctrl+R运行 - //实现新建文本文档功能 - //之后仿照实现openAction(打开文件)等功能,添加槽函数 -} -void MainWindow::openActionSlot() -{ - //getOpenFileName和getOpenFileNames一个是获取单个文件路径,另一个是多个文件 - - //获取单个文件的本地或者网络路径 - //QUrl getOpenFileUrl(QWidget *parent = Q_NULLPTR, const QString &caption = QString(), const QUrl &dir = QUrl(), const QString &filter = QString(), QString *selectedFilter = Q_NULLPTR, Options options = Options(), const QStringList &supportedSchemes = QStringList()) - - //获取多个文件的本地或者网络路径 - //QList getOpenFileUrls(QWidget *parent = Q_NULLPTR, const QString &caption = QString(), const QUrl &dir = QUrl(), const QString &filter = QString(), QString *selectedFilter = Q_NULLPTR, Options options = Options(), const QStringList &supportedSchemes = QStringList()) - - QString fileName=QFileDialog::getOpenFileName(this,"选择一个文件", - QCoreApplication::applicationFilePath(), - "images(*.png *jpeg *bmp);;text files(*.txt *.doc *.docx);;video files(*.avi *.mp4 *.wmv);;*.cpp;;All files(*.*)");//静态函数用以返回用户当前选择的目录,(&dir默认打开文件目录,需要获取路径,Linux可以直接输入,window需要用QCoreApplication::applicationFilePath()获取) - if (fileName.isEmpty()) - { - QMessageBox::warning(this,"警告","请选择一个文件"); - } - else - { - //返回文件路径 - //qDebug()<textEdit->setText(QString(ba));//toPlainText获取string文本 - file.close(); - } -} -void MainWindow::saveActionSlot() -{ - QString fileName=QFileDialog::getSaveFileName(this,"选择一个文件",QCoreApplication::applicationFilePath()); - if(fileName.isEmpty()) - { - QMessageBox::warning(this,"警告","请选择一个文件"); - } - else - { - QFile file(fileName); - file.open(QIODevice::WriteOnly); - //ui->textEdit->toPlainText();//获取打开文件的内容 String格式 - QByteArray ba;//进行格式转换,变成字节格式 - ba.append(ui->textEdit->toPlainText()); - file.write(ba); - file.close(); - } -} -//事件:鼠标点击,键盘点击在客户端都叫做事件,通过捕捉事件来实现一些响应,事件被封装成QEvent类 -void MainWindow::changeActionSlot(){ - -} -void MainWindow::keyPressEvent(QKeyEvent *k) -{ - if(k->modifiers()==Qt::ControlModifier&&k->key()==Qt::Key_S)//modifiers()表示按键的附加信息 - { - saveActionSlot(); - } - if(k->modifiers()==Qt::ControlModifier&&k->key()==Qt::Key_F){ - on_actionFind_clicked(); - } -} -void MainWindow::mousePressEvent(QMouseEvent *m) -{ - //QPoint类被用于获取位置 - QPoint pt=m->pos(); - qDebug()<button()==Qt::LeftButton) - { - qDebug()<<"左键被按下"; - } - else if(m->button()==Qt::RightButton) - { - qDebug()<<"右键被按下"; - } -} diff --git a/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.h b/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.h deleted file mode 100644 index c8c9ff9..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include -#include //QFileDialog类是Qt提供的一个用于指定操作文件的对话框小部件,使用前要先导入 -#include -#include -#include -#include -//头文件用来写 类的声明 (包括类的成员的声明和方法声明)、函数原型、#define 常数等 -//必须按照以下格式来写 -/* -#ifndef MYCLASS_H -#define MYCLASS_H - -// code here - -#endif*/ -//源文件主要写实现头文件中已经声明的那些函数的具体代码。需要注意的是,开头必须#include一下实现的头文件,以及要用到的头文件 -QT_BEGIN_NAMESPACE -namespace Ui { class MainWindow; } -QT_END_NAMESPACE - -class MainWindow : public QMainWindow -{ - Q_OBJECT - - -public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - void keyPressEvent(QKeyEvent *k); - void mousePressEvent(QMouseEvent *m); - -private slots://创建槽函数 slot插槽 - void newActionSlot();//新建文件的槽点 创建之后进入mainwindow.cpp继续处理信息编辑 - void openActionSlot();//打开文件的槽点 - void saveActionSlot(); - void changeActionSlot(); - void on_actionFind_clicked(); - -private: - Ui::MainWindow *ui; - QPlainTextEdit plainTextEdit; // mainEditor为文本编辑框对象 - QSharedPointer m_pFindDlg; // MainWindow 组合使用 FindDialog 和 QPlainTextEdit - QTextCharFormat m_format; -}; -#endif // MAINWINDOW_H !!!必须要有的东西 diff --git a/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.ui b/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.ui deleted file mode 100644 index 98ecc89..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.ui +++ /dev/null @@ -1,109 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 800 - 600 - - - - MainWindow - - - - - - - - - - - - - PushButton - - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; font-style:italic; text-decoration: underline; vertical-align:sub;">sdasdasda</span></p></body></html> - - - - - - - - - 0 - 0 - 800 - 26 - - - - - 文件(&F) - - - - - - - - - 编译(&E) - - - - - 构建(&B) - - - - - 修改(C) - - - - - - - - - - - 新建(&N) - - - - - 打开(&O) - - - - - 另存为(&S) - - - - - 修改(C) - - - - - - diff --git a/src/UWE_projectCode/finddialog查找搜索代码/widget.cpp b/src/UWE_projectCode/finddialog查找搜索代码/widget.cpp deleted file mode 100644 index 6f751ff..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/widget.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "widget.h" -#include -#include - -Widget::Widget(QWidget *parent) - : QWidget(parent), m_button(this), m_edit(this), m_label(this) -{ - m_label.move(10, 10); - m_label.resize(150, 25); - m_label.setText("Test"); - - m_edit.move(10, 45); - m_edit.resize(150, 25); - - m_button.move(10, 80); - m_button.resize(150, 25); - m_button.setText("Test"); - - connect(&m_button, SIGNAL(clicked()), this, SLOT(onButtonClicked())); - connect(&m_edit, SIGNAL(textEdited(const QString&)), this, SLOT(onTextChange(const QString&))); - - QPalette p = m_button.palette(); // 获取m_button的调色板 - - p.setColor(QPalette::Active, QPalette::ButtonText, Qt::red); // 设置激活时,按钮文本为红色 - p.setColor(QPalette::Inactive, QPalette::ButtonText, Qt::red); // 设置非激活时,按钮文本为红色 - - m_button.setPalette(p); // 给m_button设置调色板 - - p = m_edit.palette(); - - p.setColor(QPalette::Active, QPalette::Highlight, Qt::red); // 高亮背景为红色 - p.setColor(QPalette::Active, QPalette::HighlightedText, Qt::white); // 高亮文本为白色 - - p.setColor(QPalette::Inactive, QPalette::Highlight, Qt::yellow); // 高亮背景为黄色 - p.setColor(QPalette::Inactive, QPalette::HighlightedText, Qt::green); // 高亮文本为白色 - - m_edit.setPalette(p); -} - -// 点击按钮更改m_label的调色板方案 -void Widget::onButtonClicked() -{ - QPalette p = m_label.palette(); - - p.setColor(QPalette::Active, QPalette::WindowText, Qt::green); - p.setColor(QPalette::Inactive, QPalette::WindowText, Qt::green); - - m_label.setPalette(p); -} - -void Widget::onTextChange(const QString&) -{ - if(m_edit.text().count() > 6) - { - m_edit.selectAll(); - QMessageBox::information(this, "tip", "字符超出限制", QMessageBox::Ok); - } -} - -Widget::~Widget() -{ - -} diff --git a/src/UWE_projectCode/finddialog查找搜索代码/widget.h b/src/UWE_projectCode/finddialog查找搜索代码/widget.h deleted file mode 100644 index b1406f6..0000000 --- a/src/UWE_projectCode/finddialog查找搜索代码/widget.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef WIDGET_H -#define WIDGET_H - -#include -#include -#include -#include - -class Widget : public QWidget -{ - Q_OBJECT - - QPushButton m_button; - QLineEdit m_edit; - QLabel m_label; -protected slots: - void onButtonClicked(); - void onTextChange(const QString&); -public: - Widget(QWidget *parent = 0); - ~Widget(); -}; - -#endif // WIDGET_H diff --git a/src/UWE_projectCode/前后端信息交互引用库/changelog.txt b/src/UWE_projectCode/前后端信息交互引用库/changelog.txt deleted file mode 100644 index 47f712e..0000000 --- a/src/UWE_projectCode/前后端信息交互引用库/changelog.txt +++ /dev/null @@ -1,714 +0,0 @@ -Version 1.10.x --------------- -* Bug - * slider: The step size is ignored for negative values. fixed. - * mobile: The animation does not work on some browsers. fixed. - * form: The 'dirty' property does not work with check and radio components. fixed. - * drawer: The 'onBeforeCollapse' event doesn't fire while collapsing it. fixed. -* Improvement - * compatible with strict mode. - * textbox: Add 'show' and 'hide' methods. - * textbox: Add 'setEditable' method. - * textbox: Add 'autoSize' property. - * form: Add 'focusOnValidate' property. - * menu: Add 'navItems' and 'findItems' methods. -* New Plugins - * radiogroup: A set of radio buttons, where no more than one of the buttons can be checked at a time. - * checkgroup: A set of checkbox components, where one or more options can be checked at a time. - -Version 1.10.0 --------------- -* Bug - * layout: The icon on the collapsed panel is overlaped by title. fixed. - * propertygrid: The css style of the row expander will affact that in the detailview. fixed. - * combogrid: The 'getValues' method returns incorrect values sometimes. fixed. - * datebox: The 'initValue' method can't apply a new value. fixed. -* Improvement - * datagrid: The 'sorter' function on the column accepts the entire row as the sorting parameters. - * datagrid: Add 'hformatter' and 'hstyler' properties for the colomns. - * datebox: Add 'getDate' and 'setDate' methods. - * pagination: Add 'onBeforeSelectPage' event. - * combo: Prevent from conflicting with svg. - * window: Add 'fixed' property. - * timepicker: Add 'hour24' property. - * layout: Add 'stopCollapsing' method. - * messager: Add 'tip' method. -* New Plugins - * drawer: Allow the user to anchor to the left or right edge of the screen. - -Version 1.9.0 -------------- -* Bug - * datagrid: Slow scrolling with mousewheel on frozen columns. fixed. - * datagrid: The 'rowStyler' function is called on empty row. fixed. - * linkbutton: Calling 'disable' method still can submit the form. fixed. - * combotree: The 'onBeforeSelect' event fires twice while selecting a node. fixed. - * combotreegrid: The 'onSelect' event fires twice while selecting a row. fixed. -* Improvement - * checkbox: Add 'readonly' property. - * radiobutton: Add 'readonly' property. - * Compatible with jQuery 3.x. -* New Plugins - * timepicker: Allow the user to choose time on a clock. - -Version 1.8.0 -------------- -* Bug - * treegrid: The 'pageNumber' can't be initialized with the specified value. fixed. - * checkbox: The disabled checkbox has no disabled label. fixed. -* Improvement - * switchbutton: Add the 'label','labelAlign','labelPosition','labelWidth' properties. - * switchbutton: Accept 'tabindex' attribute to get focus when the user press TAB key. - * form: The 'onChange' event is available for all the form component. - * calendar: The 'Date' property is available to support the hijri date. - * textbox: The floating label is available. - -Version 1.7.0 -------------- -* Bug - * sidemenu: The tooltip has a wrong position when the 'floatMenuPosition' is set to 'left'. fixed. - * datagrid: The horizontal scrollbar has a wrong state when the 'showHeader' is set to true. fixed. - * combo: The initialized value will trigger the form's 'onChange' event when the 'multiple' is set to true. fixed. - * panel: The horizontal panel doesn't work normally when 'noheader' property is set to true. fixed. - * pagination: The extended buttons may lose in IE when rebuild the component. fixed. -* Improvement - * tree: Add 'findBy' method to find a node by any fields. - * tree: The 'find' method is enhanced to find a node easily. - * combo: Add 'panelValign' property. - * datagrid: The sorting parameters will be ignored when the 'remoteSort' is set to false. - * timespinner: Add 'hour12' property to display in 12 hour format. - -Version 1.6.0 -------------- -* Bug - * maskedbox: The component does not accept numeric keypad. fixed. - * combogrid: When selecting multiple records, the datagrid will scroll to the last checked record. fixed. -* Improvement - * Compatible with jQuery 3.x. - * tabs: The 'toolPosition' property can accept 'top' and 'bottom' values. - * textbox: The textbox label has the animating feature when focus or blur on it. - * tooltip: Add 'valign' property. - * tree: The node class can be initialized by setting the 'nodeCls' in the data. -* New Plugins - * sidemenu: The sidemenu is created from accordion and tree plugins. It builds a collapsible menu with some categories. - * radiobutton: This plugin provides a round interface to select one option from a number of options. - * checkbox: This plugin allows a user to select a value from a small set of options. - -Version 1.5.5 -------------- -* Bug - * tabs: The selecting history has wrong order when the title contains complex elements. fixed. - * combo: The drop-down panel may not be hidden if a bigger 'delay' value is set. fixed. - * layout: The expanding panel does not collapse when move mouse quickly away from it. fixed. - * tagbox: The tagbox and the label don't stay in the same line. fixed. -* Improvement - * combo: The 'blur' event handler is attached to the 'inputEvents' property. - * numberbox: The 'cloneFrom' method is available. - * slider: The 'step' property can be set with a floating number. - * menu: The 'findItem' method allows the user to find menu item by any parameters. - * menubutton: Add 'showEvent' and 'hideEvent' properties. -* New Plugins - * maskedbox: The maskedbox enforces its structure as the user types. - -Version 1.5.4 -------------- -* Bug - * combotreegrid: The 'onChange' event does not fire when entering values on the inputing box. fixed. - * combobox: Clicking on the drop-down panel will jump to the bottom of body on win10 IE11. fixed. - * datebox: Clicking on the 'Today' button doesn't trigger the 'onSelect' event. fixed. - * propertygrid: The 'getChanges' method doesn't work after editing the only one row. fixed. -* Improvement - * combo: Add the 'panelEvents' property. - * combo: Attach the default 'mousedown' event handler. - * combobox: The 'setValues' method can be called to initialize the displaying text. - * combotreegrid: Press ENTER key to select the highlighted rows. - * panel: Improve the resizing performance. - * filebox: The 'files' method allows the user to get the selected file list. - * searchbox: Improvent the 'selectName' method. - -Version 1.5.3 -------------- -* Bug - * combobox: The 'iconCls' property can not be parsed from the