diff --git a/doc/“VLSI”前端开发工具集成化平台-软件设计规格说明书.doc b/doc/VLSI前端开发工具集成化平台-软件设计规格说明书需完善.doc
similarity index 100%
rename from doc/“VLSI”前端开发工具集成化平台-软件设计规格说明书.doc
rename to doc/VLSI前端开发工具集成化平台-软件设计规格说明书需完善.doc
diff --git a/doc/VLSI前端开发工具集成化平台构思与描述缺现有资料.docx b/doc/VLSI前端开发工具集成化平台构思与描述缺现有资料.docx
new file mode 100644
index 0000000..1a34056
Binary files /dev/null and b/doc/VLSI前端开发工具集成化平台构思与描述缺现有资料.docx differ
diff --git a/doc/VLSI前端开发工具集成化平台软件需求规格说明书缺现有资料.docx b/doc/VLSI前端开发工具集成化平台软件需求规格说明书缺现有资料.docx
new file mode 100644
index 0000000..238a14f
Binary files /dev/null and b/doc/VLSI前端开发工具集成化平台软件需求规格说明书缺现有资料.docx differ
diff --git a/doc/集成电路平台开发汇报2023年6月3日第二次验收汇报定稿.pptx b/doc/集成电路平台开发汇报2023年6月3日第二次验收汇报定稿.pptx
new file mode 100644
index 0000000..b2e8a92
Binary files /dev/null and b/doc/集成电路平台开发汇报2023年6月3日第二次验收汇报定稿.pptx differ
diff --git a/model/VLSI前端开发工具集成化平台软件需求模型需完善.vsdx b/model/VLSI前端开发工具集成化平台软件需求模型需完善.vsdx
new file mode 100644
index 0000000..6d5170b
Binary files /dev/null and b/model/VLSI前端开发工具集成化平台软件需求模型需完善.vsdx differ
diff --git a/model/“VLSI”前端开发工具集成化平台-软件设计模型.vsdx b/model/“VLSI”前端开发工具集成化平台-软件设计模型.vsdx
deleted file mode 100644
index 46a28e2..0000000
Binary files a/model/“VLSI”前端开发工具集成化平台-软件设计模型.vsdx and /dev/null differ
diff --git a/src/UWE_projectCode/RTL分析代码/cv32e40p_controller.sv b/src/UWE_projectCode/RTL分析代码/cv32e40p_controller.sv
new file mode 100644
index 0000000..4c3295c
--- /dev/null
+++ b/src/UWE_projectCode/RTL分析代码/cv32e40p_controller.sv
@@ -0,0 +1,1589 @@
+// 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
new file mode 100644
index 0000000..a46aab1
--- /dev/null
+++ b/src/UWE_projectCode/RTL分析代码/cv32e40p_cs_registers.sv
@@ -0,0 +1,1587 @@
+// 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
new file mode 100644
index 0000000..9987f7e
--- /dev/null
+++ b/src/UWE_projectCode/RTL分析代码/cv32e40p_decoder.sv
@@ -0,0 +1,3048 @@
+// 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
new file mode 100644
index 0000000..e73f5e1
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/UWE_file.pro
@@ -0,0 +1,26 @@
+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
new file mode 100644
index 0000000..1ec1387
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/UWE_file.pro.user
@@ -0,0 +1,427 @@
+
+
+
+
+
+ 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
new file mode 100644
index 0000000..c488191
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/finddialog.cpp
@@ -0,0 +1,135 @@
+#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
new file mode 100644
index 0000000..393866f
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/finddialog.h
@@ -0,0 +1,53 @@
+#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
new file mode 100644
index 0000000..fd3e533
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/main.cpp
@@ -0,0 +1,11 @@
+#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
new file mode 100644
index 0000000..79fdef1
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.cpp
@@ -0,0 +1,116 @@
+#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
new file mode 100644
index 0000000..c8c9ff9
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.h
@@ -0,0 +1,49 @@
+#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
new file mode 100644
index 0000000..98ecc89
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/mainwindow.ui
@@ -0,0 +1,109 @@
+
+
+ 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>
+
+
+
+
+
+
+
+
+
+ 新建(&N)
+
+
+
+
+ 打开(&O)
+
+
+
+
+ 另存为(&S)
+
+
+
+
+ 修改(C)
+
+
+
+
+
+
diff --git a/src/UWE_projectCode/finddialog查找搜索代码/widget.cpp b/src/UWE_projectCode/finddialog查找搜索代码/widget.cpp
new file mode 100644
index 0000000..6f751ff
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/widget.cpp
@@ -0,0 +1,63 @@
+#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
new file mode 100644
index 0000000..b1406f6
--- /dev/null
+++ b/src/UWE_projectCode/finddialog查找搜索代码/widget.h
@@ -0,0 +1,24 @@
+#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/highlighter.cpp b/src/UWE_projectCode/highlighter.cpp
deleted file mode 100644
index 05f4e4a..0000000
--- a/src/UWE_projectCode/highlighter.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "highlighter.h"
-
-HighLighter::HighLighter(QTextDocument *parent) :
- QSyntaxHighlighter(parent)
-{
- HighlightRule num_rule;
- num_rule.pattern.setPattern("[0-9]{1,1}");
- num_rule.format.setForeground(QColor(144,238,144));
- highlightrules.append(num_rule);
-
- HighlightRule key_rule;
- key_rule.pattern.setPattern("\\b(char|string|int|float|double|bool|void|true|flase)\\b");
- key_rule.format.setForeground(QColor(30,144,255));
- highlightrules.append(key_rule);
-
- HighlightRule code_rule;
- code_rule.pattern.setPattern("\\b(if|while|for|else|break|return|switch|case)\\b");
- code_rule.format.setForeground(QColor(186,85,211));
- highlightrules.append(code_rule);
-}
-
-void HighLighter::highlightBlock(const QString &text)
-{
- for(const HighlightRule &rule : highlightrules){
- QRegExp expression(rule.pattern);
- int index = expression.indexIn(text);
- while(index>=0){
- int length = expression.matchedLength();
- setFormat(index,length,rule.format);
- index = expression.indexIn(text,index+length);}
- }
-}
diff --git a/src/UWE_projectCode/highlighter.h b/src/UWE_projectCode/highlighter.h
deleted file mode 100644
index 0e7802f..0000000
--- a/src/UWE_projectCode/highlighter.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef HIGHLIGHTER_H
-#define HIGHLIGHTER_H
-
-#include
-#include
-#include
-#include
-
-class HighLighter :public QSyntaxHighlighter{
- Q_OBJECT
-public:
- explicit HighLighter(QTextDocument *parent=0);
-protected:
- void highlightBlock(const QString &text);
-private:
- struct HighlightRule{
- QRegExp pattern;
- QTextCharFormat format;
- };
- QVector highlightrules;
-};
-#endif // HIGHLIGHTER_H
diff --git a/src/UWE_projectCode/mainwindow.cpp b/src/UWE_projectCode/mainwindow.cpp
deleted file mode 100644
index 86ef3f9..0000000
--- a/src/UWE_projectCode/mainwindow.cpp
+++ /dev/null
@@ -1,711 +0,0 @@
-#include "mainwindow.h"
-#include "ui_mainwindow.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "highlighter.h"
-using namespace std;
-
-// 是否启用QMainWindow自带的菜单栏
-//#define USE_DEFAULT_MENU_BAR
-MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
-{
- ui->setupUi(this);
- this->variate_map = new Variate_Map;
- //建立项目与主界面的联系
- this->work_project = new Work_Project;
- this->work_project->father = this;
-
- // 在右侧浮动窗口中添加report窗口
- dockWidget_report = new QDockWidget(tr("report"), this);
- dockWidget_report->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetClosable);
- dockWidget_report->setVisible(true);
- addDockWidget(Qt::RightDockWidgetArea, dockWidget_report);
- tabifyDockWidget(ui->dockWidget_src, dockWidget_report);
- ui->dockWidget_src->raise();
-
- // 在左侧浮动窗口中添加module窗口
- tabifyDockWidget(ui->dockWidget_file, ui->dockWidget_module);
- ui->dockWidget_file->raise();
-
- //指定菜单栏
-#ifdef USE_DEFAULT_MENU_BAR
- //添加菜单栏(此处添加为的为QMainWindow自带的菜单)
- pMenuBar = this->menuBar();
-#else
- //添加自定义菜单
- pMenuBar = new QMenuBar(this);
-#endif
-
- //定义菜单项
- //(&n)代表快捷方式,当窗口获得焦点时按alt+n即可打开“测试”菜单项
- pMenu1 = new QMenu("文件(&n)",this);
- pMenu2 = new QMenu("执行",this);
- pMenu3 = new QMenu("工具",this);
-
- //定义子菜单
- //(&s)为子菜单快捷键,当打开该菜单项后,按下‘s’键即可响应
- pAction_newproject = new QAction("新建项目(&s)",this);
- //新建一个带图标的菜单项,图标使用资源文件中的资源
- pAction_openproject = new QAction(QIcon(":/new/prefix1/resource/soccer_ball.ico"),"打开项目",this);
- pAction_save = new QAction("保存",this);
- pAction_syn = new QAction("run syn(&y)",this);
- pAction_parameter_config = new QAction("参数配置",this);
- pActionTest5 = new QAction("测试5(&M)",this);
- pActionTest6 = new QAction("测试6",this);
-
- //将菜单项添加到子菜单
- pMenu1->addAction(pAction_newproject);
- pMenu1->addAction(pAction_openproject);
- //在菜单项之间添加分割线
- pMenu1->addSeparator();
- pMenu1->addAction(pAction_save);
-
- pMenu2->addAction(pAction_parameter_config);
- pMenu2->addAction(pAction_syn);
-
-
- pMenu3->addAction(pActionTest5);
- pMenu3->addAction(pActionTest6);
-
- //将子菜单添加到菜单栏
- pMenuBar->addMenu(pMenu1);
- pMenuBar->addMenu(pMenu2);
- pMenuBar->addMenu(pMenu3);
-
- // 终端窗口
- ui->pushButton_run_cmd->setFocus();
- ui->pushButton_run_cmd->setShortcut(Qt::Key_Return);
-
- m_process_bash = new QProcess;
- m_process_bash->start("bash");
- m_process_bash->waitForStarted();
- m_process_bash->write("cd / \n");
-
-
- // 设置module列表
- this->model_module = new QStandardItemModel;
- model_module->setHorizontalHeaderLabels(QStringList()<<"module name"<<"state");
- this->ui->treeView_module->setModel(model_module);
- this->ui->treeView_module->setColumnWidth(0, 200);
- this->ui->treeView_module->setColumnWidth(1, 50);
-
- QMenu *menu_module = new QMenu(this);
- QAction *pAction_newmodule = new QAction("new module", this);
- QAction *pAction_delmodule = new QAction("delete module", this);
- menu_module->addAction(pAction_newmodule);
- menu_module->addAction(pAction_delmodule);
- ui->treeView_module->setContextMenuPolicy(Qt::CustomContextMenu);
-
- // 建立信号槽连接,处理module树形列表右键菜单事件
- connect(ui->treeView_module, &QTreeView::customContextMenuRequested, this, [=](const QPoint &pos) {
- // 显示右键菜单
- menu_module->popup(ui->treeView_module->viewport()->mapToGlobal(pos));
- });
- // new mdoule槽连接
- connect(pAction_newmodule, &QAction::triggered, this, &MainWindow::New_module);
-
-
-#ifndef USE_DEFAULT_MENU_BAR
- //当不使用QMainWindow自带的菜单栏时,必须要加上此行
- setMenuBar(pMenuBar);
-#endif
-
- //添加菜单响应函数
- connect(pAction_newproject, &QAction::triggered, this->work_project, &Work_Project::New_Project_1);
- connect(pAction_openproject,&QAction::triggered,this,&MainWindow::OpenProject);
- connect(pAction_parameter_config, &QAction::triggered, this, &MainWindow::Parameter_Config);
-
- connect(m_process_bash, &QProcess::readyReadStandardOutput, this, &MainWindow::readBashStandardOutputInfo);
- connect(m_process_bash, &QProcess::readyReadStandardError, this, &MainWindow::readBashStandardErrorInfo);
-
- //int Index = ui->tabWidget_src->currentIndex();
- //QTextEdit *editor = dynamic_cast(ui->tabWidget_src->currentWidget());
- //highlighter = new HighLighter(editor->document());
-// highlighter = new HighLighter(ui->tabWidget_src->currentWidget()->->document());
-}
-
-// 打开项目响应函数
-void MainWindow::OpenProject()
-{
- this->work_project->work_project_path = QFileDialog::getExistingDirectory(this, "打开项目", "/");
- chdir(work_project->work_project_path.toStdString().data());
- work_project->Get_Work_config();
-
- //设置树形文件列表
- this->model_file = new QFileSystemModel;
- this->model_file->setRootPath(this->work_project->work_project_path);
- this->ui->treeView_file->setModel(this->model_file);
- this->ui->treeView_file->setRootIndex(this->model_file->index(this->work_project->work_project_path));
- this->ui->treeView_file->setHeaderHidden(true);
- this->ui->treeView_file->setColumnHidden(1, true);
- this->ui->treeView_file->setColumnHidden(2, true);
- this->ui->treeView_file->setColumnHidden(3, true);
-
- connect(this->ui->treeView_file, &QTreeView::clicked, this, &MainWindow::TreeClicked);
-
- //终端进入工作项目
- string cmd_cd = "cd " + work_project->work_project_path.toStdString() + "\n pwd \n";
- this->m_process_bash->write(cmd_cd.data());
-}
-
-MainWindow::~MainWindow()
-{
- delete ui;
-}
-
-string get_current_date();
-// 参数配置响应函数
-void MainWindow::Parameter_Config()
-{
- this->variate_map->add_variate("TCLPATH", ".");
- this->variate_map->add_variate("DCWORK", "./dc.work");
- this->variate_map->add_variate("current_date", get_current_date());
- //this->variate_map->Generate_Config_File();
-
- this->ui->textEdit_cmd->append("Parameter config completed!\n");
-}
-
-// 新建项目1响应函数
-void Work_Project::New_Project_1()
-{
- QDialog *qdialog = new QDialog;
- qdialog->setWindowTitle("新建项目");
- qdialog->setFixedSize(800, 450);
-
- QHBoxLayout *layout = new QHBoxLayout(qdialog);
- QListWidget *listWidget = new QListWidget;
- listWidget->setMinimumWidth(150);
- listWidget->setFont(QFont("宋体",14));
- listWidget->addItem("Project1");
- listWidget->addItem("");
- QWidget *widget1 = new QWidget, *widget2 = new QWidget;
- widget1->setMaximumHeight(350); widget2->setMaximumHeight(350);
- QLabel *lab1 = new QLabel("创建项目流程主要包括导入项目路径、导入代码\n路径、选择顶层模块", widget1);
- lab1->setFont(QFont("宋体", 15));
- lab1->setWordWrap(true);
- lab1->adjustSize();
- lab1->setMinimumSize(500, 100);
- QLabel *lab2 = new QLabel("", widget2);
- QStackedLayout *stackedLayout = new QStackedLayout;
- stackedLayout->addWidget(widget1);
- stackedLayout->addWidget(widget2);
-
- layout->addWidget(listWidget, 2);
- layout->addLayout(stackedLayout, 3);
- qdialog->setLayout(layout);
-
- QPushButton *button_next = new QPushButton("下一步", qdialog);
- button_next->move(568, 400);
- QPushButton *button_cancel = new QPushButton("取消", qdialog);
- button_cancel->move(675, 400);
-
- QObject::connect(listWidget, &QListWidget::currentRowChanged, stackedLayout, &QStackedLayout::setCurrentIndex);
- QObject::connect(button_next, &QPushButton::clicked, qdialog, &QDialog::close);
- QObject::connect(button_next, &QPushButton::clicked, this, &Work_Project::New_Project_2);
- QObject::connect(button_cancel, &QPushButton::clicked, qdialog, &QDialog::close);
-
- qdialog->exec();
-}
-
-
-// 新建项目2响应函数(新建项目2对话框)
-void Work_Project::New_Project_2()
-{
- QDialog *qdialog = new QDialog;
- qdialog->setWindowTitle("新建项目");
- qdialog->setFixedSize(800,450);
-
- //添加表格布局
- QFormLayout* layout = new QFormLayout();
- layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
- edit_work_project_path = new QLineEdit();
- edit_work_project_name = new QLineEdit();
- layout->addRow("项目路径:", edit_work_project_path);
- layout->addRow("新建项目名称:", edit_work_project_name);
-
- // 选择路径按钮
- QPushButton *button_work_project_path = new QPushButton(edit_work_project_path);
- button_work_project_path->setText("......");
- button_work_project_path->setCursor(Qt::ArrowCursor);
- QWidgetAction* action = new QWidgetAction(edit_work_project_path);
- action->setDefaultWidget(button_work_project_path);
- edit_work_project_path->addAction(action, QLineEdit::TrailingPosition);
-
- // 将布局添加到对话框
- qdialog->setLayout(layout);
-
- // 操作按键
- QPushButton *button_next = new QPushButton("下一步", qdialog);
- button_next->move(568, 400);
- QPushButton *button_back = new QPushButton("上一步", qdialog);
- button_back->move(675, 400);
-
- // 按键响应信号槽函数
- connect(button_work_project_path, &QPushButton::clicked, this, &Work_Project::Work_Project_path_choose);
- connect(button_next, &QPushButton::clicked, qdialog, &QDialog::close);
- connect(button_next, &QPushButton::clicked, this, &Work_Project::New_Project_setup);
- QObject::connect(button_back, &QPushButton::clicked, qdialog, &QDialog::close);
- QObject::connect(button_back, &QPushButton::clicked, this, &Work_Project::New_Project_1);
-
- // 显示对话框
- qdialog->exec();
-}
-
-
-// 工作项目setup设置界面
-void Work_Project::New_Project_setup()
-{
- // 新建对话框
- QDialog *qdialog = new QDialog;
- qdialog->setWindowTitle("setup");
- qdialog->setFixedSize(800,490);
-
- // 新建输入框
- QFormLayout* layout = new QFormLayout();
- layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
- edit_designer = new QLineEdit(); layout->addRow("designer:", edit_designer);
- edit_company = new QLineEdit(); layout->addRow("company:", edit_company);
- edit_synthetic_library = new QLineEdit(); layout->addRow("synthetic_library:", edit_synthetic_library);
- edit_target_library = new QLineEdit(); layout->addRow("target_library:", edit_target_library);
- edit_link_library = new QLineEdit(); layout->addRow("link_library:", edit_link_library);
- edit_symbol_library=new QLineEdit(); layout->addRow("symbol_library:", edit_symbol_library);
- edit_cache_write=new QLineEdit(); layout->addRow("cache_write:", edit_cache_write);
- edit_cache_read=new QLineEdit(); layout->addRow("cache_read:", edit_cache_read);
- edit_my_lib_path=new QLineEdit(); layout->addRow("my_lib_path:", edit_my_lib_path);
- edit_search_path=new QLineEdit(); layout->addRow("search_path:", edit_search_path);
- edit_suppress_message=new QLineEdit(); layout->addRow("suppress_message:", edit_suppress_message);
- edit_define_design_lib=new QLineEdit(); layout->addRow("define_design_lib:", edit_define_design_lib);
- edit_view_script_submenu_items=new QLineEdit(); layout->addRow("view_script_submenu_items:", edit_view_script_submenu_items);
-
- // 将布局添加到对话框
- qdialog->setLayout(layout);
-
- // 操作按键
- QPushButton *button_next = new QPushButton("下一步", qdialog);
- button_next->move(568, 455);
- QPushButton *button_back = new QPushButton("上一步", qdialog);
- button_back->move(675, 455);
-
- // 按键响应信号槽函数
- connect(button_next, &QPushButton::clicked, qdialog, &QDialog::close);
- connect(button_next, &QPushButton::clicked, this, &Work_Project::Src_Project_Environment_set);
- QObject::connect(button_back, &QPushButton::clicked, qdialog, &QDialog::close);
- QObject::connect(button_back, &QPushButton::clicked, this, &Work_Project::New_Project_2);
-
- // 显示对话框
- qdialog->exec();
-}
-
-// 按钮选择工作项目路径响应函数
-void Work_Project::Work_Project_path_choose()
-{
- this->work_project_path = QFileDialog::getExistingDirectory(0, "选择目录", "/");
- edit_work_project_path->setText(work_project_path);
-}
-
-// 芯片环境设置响应函数
-void Work_Project::Src_Project_Environment_set()
-{
- work_project_name = edit_work_project_name->text();
- work_project_path = edit_work_project_path->text();
-
- QDialog *qdialog = new QDialog;
- qdialog->setWindowTitle("芯片项目环境设置");
- qdialog->setFixedSize(800, 450);
-
- //输入框及其按钮
- QFormLayout *layout = new QFormLayout;
- layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
- edit_src_project_path = new QLineEdit;
- edit_src_path = new QLineEdit;
-// edit_module_name = new QLineEdit;
- layout->addRow("芯片项目路径:", edit_src_project_path);
- layout->addRow("代码路径", edit_src_path);
-// layout->addRow("模块名称", edit_module_name);
-
- QPushButton *button_src_project_path = new QPushButton(edit_src_project_path);
- QPushButton *button_src_path = new QPushButton(edit_src_path);
- button_src_project_path->setText("..."); button_src_path->setText("...");
- button_src_project_path->setCursor(Qt::ArrowCursor); button_src_path->setCursor(Qt::ArrowCursor);
- QWidgetAction *action_Project_path = new QWidgetAction(edit_src_project_path), *action_src_path = new QWidgetAction(edit_src_path);
- action_Project_path->setDefaultWidget(button_src_project_path); action_src_path->setDefaultWidget(button_src_path);
- edit_src_project_path->addAction(action_Project_path, QLineEdit::TrailingPosition); edit_src_path->addAction(action_src_path, QLineEdit::TrailingPosition);
- qdialog->setLayout(layout);
-
- //单独按钮
- QPushButton *button_determine = new QPushButton("确定", qdialog), *button_back = new QPushButton("上一步", qdialog);
- button_determine->move(568, 400); button_back->move(675, 400);
-
- //按钮对应槽函数
- connect(button_src_project_path, &QPushButton::clicked, this, &Work_Project::Src_Project_path_choose);
- connect(button_src_path, &QPushButton::clicked, this, &Work_Project::Src_path_choose);
- connect(button_determine, &QPushButton::clicked, qdialog, &QDialog::close);
- connect(button_determine, &QPushButton::clicked, this, &Work_Project::Src_Prokect_Environment_set_Determine);
- connect(button_back, &QPushButton::clicked, qdialog, &QDialog::close);
- connect(button_back, &QPushButton::clicked, this, &Work_Project::New_Project_setup);
-
- qdialog->exec();
-}
-
-// 选择芯片项目路径响应函数
-void Work_Project::Src_Project_path_choose()
-{
- this->src_project_path = QFileDialog::getExistingDirectory(0, "选择目录", "/");
- edit_src_project_path->setText(src_project_path);
-}
-
-// 选择代码路径响应函数
-void Work_Project::Src_path_choose()
-{
- src_path = QFileDialog::getExistingDirectory(0, "选择目录", "/");
- edit_src_path->setText(src_path);
-}
-
-// 芯片项目环境配置确定响应函数
-void Work_Project::Src_Prokect_Environment_set_Determine()
-{
- src_project_path = edit_src_project_path->text();
- src_path = edit_src_path->text();
-// module_name = edit_module_name->text();
-
- // 生成工作项目对应文件夹
- string str_work_project_path = work_project_path.toStdString(), str_work_project_name = work_project_name.toStdString();
- chdir(str_work_project_path.data());
- mkdir(str_work_project_name.data(), 0755);
- str_work_project_path += '/' + str_work_project_name;
- chdir(str_work_project_path.data());
- work_project_path = QString::fromStdString(str_work_project_path);
- qDebug() << work_project_path;
-
- // 保存配置信息
- Generate_UWE_Work_config();
-
- // 设置树形文件列表
- this->father->model_file = new QFileSystemModel;
- this->father->model_file->setRootPath(work_project_path);
- this->father->ui->treeView_file->setModel(this->father->model_file);
- this->father->ui->treeView_file->setRootIndex(this->father->model_file->index(work_project_path));
- this->father->ui->treeView_file->setHeaderHidden(true);
- this->father->ui->treeView_file->setColumnHidden(1, true);
- this->father->ui->treeView_file->setColumnHidden(2, true);
- this->father->ui->treeView_file->setColumnHidden(3, true);
-
- connect(this->father->ui->treeView_file, &QTreeView::clicked, this->father, &MainWindow::TreeClicked);
-
- // 终端进入项目文件夹,链接src代码文件夹
- string ln_cmd = " ln -s " + this->src_path.toStdString() + ' ' + "./src"; ln_cmd += "\nln -s /home/UWE/zj/tmp/Scripts ./Scripts";
- string cmd_1 = "cd "+str_work_project_path+'\n' + "pwd\n" + ln_cmd+'\n';
- this->father->m_process_bash->write(cmd_1.data());
-
- // 生成执行所需tcl文件
- ofstream out1("ProjectPathSetting.tcl", ios::out);
- out1 << "set PROJECTPATH " << this->src_project_path.toStdString() << "\n" << "puts ${PROJECTPATH}";
- out1.close();
-// ofstream out2("setModuleName.tcl", ios::out);
-// out2 << "set Design " << this->module_name.toStdString() << "\n" << "puts ${Design}";
-// out2.close();
-
- // make Prepare的一系列操作
- string cmd_2 = "echo 'ProjectPathSetting.tcl is generated successfully!\n./src soft link is created.\nsetModuleName.tcl is created.'\n";
- string cmd_cp = "cp -r /home/UWE/zj/tmp/Template/* ./ \ntouch tmp.log \necho 'copy files in Template here.' \ncp -r /home/UWE/zj/tmp/Makefile ./ \n"
- "cp -r /home/UWE/zj/test_1/syn_main.tcl ./ \n";
- string cmd_flist = "filelistpath=`find ./src/ -maxdepth 1 -name '*flist*' -type f` \nfilelistname=${filelistpath#*src/} \necho '`include \"./\"' > ./dc.work/filelist.v \n";
- string cmd_incdir = "incdirlistpath=`find ./src/ -maxdepth 1 -name '*incdir*' -type f` \nincdirlistname=${incdirlistpath#*src/} \necho -f ./src/$incdirlistname \ > ./nc.work/sim_filelist.f \n";
- string cmd_nc = "echo '-f ./src/'$filelistname'' \ >> ./nc.work/sim_filelist.f \necho \" \" >> ./nc.work/sim_filelist.f \necho //Add simulation files bellow >> ./nc.work/sim_filelist.f \n";
- string cmd_mv = "mv ./spyglass.work/demo.prj ./spyglass.work/"; cmd_mv += this->module_name.toStdString(); cmd_mv += ".prj \n";
- cmd_mv += "mv ./spyglass.work/waiver/demo.awl ./spyglass.work/waiver/"+this->module_name.toStdString()+".awl\n";
- cmd_2 += cmd_cp + cmd_flist + cmd_incdir + cmd_nc + cmd_mv;
- //cout << cmd_2;
- this->father->m_process_bash->write(cmd_2.data());
-
- // 生成synopsys_dc.setup文件
- ofstream out_setup("synopsys_dc.setup", ios::out);
- out_setup << "set designer " << this->edit_designer->text().toStdString() << '\n';
- out_setup << "set company " << this->edit_company->text().toStdString() << '\n';
- out_setup << "set synthetic_library " << this->edit_synthetic_library->text().toStdString() << '\n';
- out_setup << "set target_library " << this->edit_target_library->text().toStdString() << '\n';
- out_setup << "set link_library " << this->edit_link_library->text().toStdString() << '\n';
- out_setup << "set symbol_library " << this->edit_symbol_library->text().toStdString() << '\n';
- out_setup << "set cache_write " << this->edit_cache_write->text().toStdString() << '\n';
- out_setup << "set cache_read $cache_write\n";
- out_setup << "set my_lib_path " << this->edit_my_lib_path->text().toStdString() << '\n';
- out_setup << "set search_path " << this->edit_search_path->text().toStdString() << '\n';
- out_setup << "suppress_message " << this->edit_suppress_message->text().toStdString() << '\n';
- out_setup << "define_design_lib DEFAULT -path " << this->edit_define_design_lib->text().toStdString() << '\n';
- out_setup << "set view_script_submenu_items " << this->edit_view_script_submenu_items->text().toStdString() << '\n';
- out_setup.close();
-}
-
-// 生成工作项目配置文件
-void Work_Project::Generate_UWE_Work_config()
-{
- ofstream out("UWE_work_config", ios::out);
- out << "work_project_path = " << work_project_path.toStdString() << endl;
- out << "work_project_name = " << work_project_name.toStdString() << endl;
- out << "src_project_path = " << src_project_path.toStdString() << endl;
- out << "src_path = " << src_path.toStdString() << endl;
- out << "module_name = " << module_name.toStdString() << endl;
- out.close();
-}
-
-// 根据配置文件获取工作项目配置
-void Work_Project::Get_Work_config()
-{
- ifstream in("UWE_work_config", ios::in);
- string str;
- in >> str >> str >> str;
- in >> str >> str >> str; work_project_name = QString::fromStdString(str);
- in >> str >> str >> str; src_project_path = QString::fromStdString(str);
- in >> str >> str >> str; src_path = QString::fromStdString(str);
- in >> str >> str >> str; module_name = QString::fromStdString(str);
- in.close();
-}
-
-// 获取当前系统时间
-string get_current_date()
-{
- time_t timeReal;
- time(&timeReal);
- timeReal = timeReal + 8*3600;
- tm* t = gmtime(&timeReal);
- string str = to_string(t->tm_year+1900) + '_' + to_string(t->tm_mon+1)+to_string(t->tm_mday) + '_' + to_string(t->tm_hour)+to_string(t->tm_min);
- return str;
-}
-
-// 点击树形文件列表展示文本内容
-void MainWindow::TreeClicked(const QModelIndex &index)
-{
- ui->dockWidget_src->show();
- QString context, file_name = model_file->fileName(index);
- QString path = model_file->filePath(index);
- for (int i = 0; i < ui->tabWidget_src->count(); ++i) {
- if (ui->tabWidget_src->tabText(i) == file_name) {
- ui->tabWidget_src->setCurrentIndex(i);
- ui->dockWidget_src->show();
- ui->dockWidget_src->raise();
- return;
- }
- }
-
- QFile file(path);
- file.open(QFile::ReadOnly | QFile::Text);
- context = file.readAll();
- file.close();
-
- if (!context.isEmpty()){
- QTextEdit *textEdit_src = new QTextEdit;
- textEdit_src->setText(context);
- textEdit_src->setFont(QFont("Consolas", 12));
-
- ui->tabWidget_src->addTab(textEdit_src, file_name);
- ui->tabWidget_src->setCurrentWidget(textEdit_src);
- }
- ui->dockWidget_src->raise();
-}
-
-// 终端输出内容响应函数
-void MainWindow::readBashStandardOutputInfo()
-{
- QByteArray cmdout = m_process_bash->readAllStandardOutput();
-
- // 综合完成响应函数
- if (cmdout.indexOf("Thank you...") != -1){
- qDebug() << "syn sucessfully!" << endl;
- QStandardItem *item = model_module->item(row_current_module_treeview, 1);
- item->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton));
- }
-
- if (!cmdout.isEmpty()){
- ui->textEdit_cmd->append(QString::fromLocal8Bit(cmdout));
- }
- QScrollBar *scroll = ui->textEdit_cmd->verticalScrollBar();
- scroll->setSliderPosition(scroll->maximum());
-}
-
-
-// 终端输出错误信息响应函数
-void MainWindow::readBashStandardErrorInfo()
-{
- QByteArray cmdout = m_process_bash->readAllStandardError();
- if (!cmdout.isEmpty()){
- ui->textEdit_cmd->append(QString::fromLocal8Bit(cmdout));
- }
- QScrollBar *scroll = ui->textEdit_cmd->verticalScrollBar();
- scroll->setSliderPosition(scroll->maximum());
-}
-
-// 字符串变量替换
-void MainWindow::String_Replace(string &str, string variate_key)
-{
- string variate_value = this->variate_map->get_value(variate_key);
- int variate_size = variate_key.size();
- while (str.find(variate_key) != string::npos)
- str = str.replace(str.find(variate_key), variate_size, variate_value);
-}
-
-// 生成配置文件
-void Variate_Map::Generate_Config_File()
-{
- ofstream out("parameter.tcl", ios::out);
- for (auto i : mapper)
- out << "set " << i.first << ' ' << i.second << endl;
- out.close();
-}
-
-// 保存参数配置
-void MainWindow::on_buttonBox_Save_accepted()
-{
- string FLOW_value = (ui->radioButton_FLOW_TRUE->isChecked()) ? "TRUE" : "FALSE";
- variate_map->add_variate("FLOW", FLOW_value);
- string LOADDDC_value = (ui->radioButton_LOADDDC_TRUE->isChecked()) ? "TRUE" : "FALSE";
- variate_map->add_variate("LOADDDC", LOADDDC_value);
- string CHECKCODE_value = (ui->radioButton_CHECKCODE_TRUE->isChecked()) ? "TRUE" : "FALSE";
- variate_map->add_variate("CHECKCODE", CHECKCODE_value);
- string DEBUGSDC_value = (ui->radioButton_DEBUGSDC_TRUE->isChecked()) ? "TRUE" : "FALSE";
- variate_map->add_variate("DEBUGSDC", DEBUGSDC_value);
-
- variate_map->Generate_Config_File();
- ui->textEdit_cmd->append("parameter.tcl has been generated sucessfully!\n");
-}
-
-// 运行综合按钮响应函数
-void MainWindow::on_pushButton_runsyn_clicked()
-{
- Parameter_Config();
-
- string syn_cmd = "dc_shell-t -f TCLPATH/syn_main.tcl | tee dc.log DCWORK/Logs/dc_current_date.log \nmake c_R0 \n";
- this->String_Replace(syn_cmd, "TCLPATH");
- this->String_Replace(syn_cmd, "DCWORK");
- this->String_Replace(syn_cmd, "current_date");
- cout << syn_cmd << endl;
- this->ui->textEdit_cmd->append("run syn \n");
- this->m_process_bash->write(syn_cmd.data());
-}
-
-// 代码窗口关闭响应函数
-void MainWindow::on_tabWidget_src_tabCloseRequested(int index)
-{
- QTextEdit *text_edit = qobject_cast(ui->tabWidget_src->widget(index));
- QString file_name = ui->tabWidget_src->tabText(index);
- QString file_path = model_file->rootPath() + "/" + file_name;
-
- if (text_edit) {
- // »ñÈ¡µ±Ç°Îı¾¿òÖеÄÄÚÈÝ
- QString curr_content = text_edit->toPlainText();
-
- // ¶ÁÈ¡ÔʼÎļþÄÚÈÝ
- QString orig_content;
- QFile file(file_path);
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- orig_content = file.readAll();
- file.close();
- }
-
- // Èç¹ûµ±Ç°ÄÚÈÝÓëÔʼÄÚÈݲ»Í¬£¬Ôò˵Ã÷ÎļþÒѱ»±à¼£¬ÐèÒª±£´æÐÞ¸Ä
- if (curr_content != orig_content) {
- if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
- QTextStream out(&file);
- out << curr_content;
- file.close();
- }
- }
- }
-
- // ½«±êǩҳ´Ó±êÇ©¿Ø¼þÖÐɾ³ý
- ui->tabWidget_src->removeTab(index);
-}
-
-// R0_check result按钮响应函数
-void MainWindow::on_pushButton_result_clicked()
-{
- ktextEdit = new KTextEdit(dockWidget_report);
- //获取result内容
- QString result_path = QDir::currentPath() + "/R0_check.result";
- QFile file(result_path);
- QString context;
- file.open(QFile::ReadOnly | QFile::Text);
- while (!file.atEnd()) {
- QByteArray line = file.readLine();
- QString str(line);
- context.append(str);
- }
- ktextEdit->SetText(context);
- //设置文本游标到文本头
- QTextCursor cursor = ktextEdit->textCursor();
- cursor.movePosition(QTextCursor::Start);
- ktextEdit->setTextCursor(cursor);
-
- dockWidget_report->setWidget(ktextEdit);
-
- dockWidget_report->raise();
-}
-
-//终端运行按钮响应函数
-void MainWindow::on_pushButton_run_cmd_clicked()
-{
- QString strCmd = ui->lineEdit->text();
- ui->textEdit_cmd->append("Linux:~$ " + strCmd);
- m_process_bash->write(ui->lineEdit->text().toLocal8Bit() + '\n');
- ui->lineEdit->clear();
-}
-
-// New nodule响应函数
-void MainWindow::New_module()
-{
- QDialog *qdialog = new QDialog;
- qdialog->setWindowTitle("module name");
- qdialog->setFixedSize(500, 50);
-
- //输入框及其按钮
- QFormLayout *layout = new QFormLayout;
- layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
- QLineEdit *edit_module_name = new QLineEdit;
- layout->addRow("module name:", edit_module_name);
-
- qdialog->setLayout(layout);
-
- //单独按钮
- QPushButton *button_determine = new QPushButton("确定", qdialog);
- button_determine->move(300, 100);
-
- //按钮对应槽函数
- connect(button_determine, &QPushButton::clicked, qdialog, &QDialog::close);
- connect(button_determine, &QPushButton::clicked, this, [=]{
- QList items;
- items.append(new QStandardItem(edit_module_name->text()));
-// childItem->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton));
- QStandardItem *Item_state = new QStandardItem();
- Item_state->setIcon(QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion));
- items.append(Item_state);
- model_module->appendRow(items);
- row_current_module_treeview++;
-
- this->work_project->module_name = edit_module_name->text();
- ofstream out2("setModuleName.tcl", ios::out);
- out2 << "set Design " << edit_module_name->text().toStdString() << "\n" << "puts ${Design}";
- out2.close();
- });
-
- qdialog->exec();
-}
diff --git a/src/UWE_projectCode/mainwindow.h b/src/UWE_projectCode/mainwindow.h
deleted file mode 100644
index f49a7a8..0000000
--- a/src/UWE_projectCode/mainwindow.h
+++ /dev/null
@@ -1,168 +0,0 @@
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include