cores-swerv-el2/design/dec/el2_dec_tlu_ctl.sv

2949 lines
154 KiB
Systemverilog
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: Apache-2.0
// Copyright 2020 Western Digital Corporation or it's affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//********************************************************************************
// el2_dec_tlu_ctl.sv
//
//
// Function: CSRs, Commit/WB, flushing, exceptions, interrupts
// Comments:
//
//********************************************************************************
module el2_dec_tlu_ctl
import el2_pkg::*;
#(
`include "el2_param.vh"
)
(
input logic clk,
input logic free_clk,
input logic free_l2clk,
input logic rst_l,
input logic scan_mode,
input logic [31:1] rst_vec, // reset vector, from core pins
input logic nmi_int, // nmi pin
input logic [31:1] nmi_vec, // nmi vector
input logic i_cpu_halt_req, // Asynchronous Halt request to CPU
input logic i_cpu_run_req, // Asynchronous Restart request to CPU
input logic lsu_fastint_stall_any, // needed by lsu for 2nd pass of dma with ecc correction, stall next cycle
// perf counter inputs
input logic ifu_pmu_instr_aligned, // aligned instructions
input logic ifu_pmu_fetch_stall, // fetch unit stalled
input logic ifu_pmu_ic_miss, // icache miss
input logic ifu_pmu_ic_hit, // icache hit
input logic ifu_pmu_bus_error, // Instruction side bus error
input logic ifu_pmu_bus_busy, // Instruction side bus busy
input logic ifu_pmu_bus_trxn, // Instruction side bus transaction
input logic dec_pmu_instr_decoded, // decoded instructions
input logic dec_pmu_decode_stall, // decode stall
input logic dec_pmu_presync_stall, // decode stall due to presync'd inst
input logic dec_pmu_postsync_stall,// decode stall due to postsync'd inst
input logic lsu_store_stall_any, // SB or WB is full, stall decode
input logic dma_dccm_stall_any, // DMA stall of lsu
input logic dma_iccm_stall_any, // DMA stall of ifu
input logic exu_pmu_i0_br_misp, // pipe 0 branch misp
input logic exu_pmu_i0_br_ataken, // pipe 0 branch actual taken
input logic exu_pmu_i0_pc4, // pipe 0 4 byte branch
input logic lsu_pmu_bus_trxn, // D side bus transaction
input logic lsu_pmu_bus_misaligned, // D side bus misaligned
input logic lsu_pmu_bus_error, // D side bus error
input logic lsu_pmu_bus_busy, // D side bus busy
input logic lsu_pmu_load_external_m, // D side bus load
input logic lsu_pmu_store_external_m, // D side bus store
input logic dma_pmu_dccm_read, // DMA DCCM read
input logic dma_pmu_dccm_write, // DMA DCCM write
input logic dma_pmu_any_read, // DMA read
input logic dma_pmu_any_write, // DMA write
input logic [31:1] lsu_fir_addr, // Fast int address
input logic [1:0] lsu_fir_error, // Fast int lookup error
input logic iccm_dma_sb_error, // I side dma single bit error
input el2_lsu_error_pkt_t lsu_error_pkt_r, // lsu precise exception/error packet
input logic lsu_single_ecc_error_incr, // LSU inc SB error counter
input logic dec_pause_state, // Pause counter not zero
input logic lsu_imprecise_error_store_any, // store bus error
input logic lsu_imprecise_error_load_any, // store bus error
input logic [31:0] lsu_imprecise_error_addr_any, // store bus error address
input logic dec_csr_wen_unq_d, // valid csr with write - for csr legal
input logic dec_csr_any_unq_d, // valid csr - for csr legal
input logic [11:0] dec_csr_rdaddr_d, // read address for csr
input logic dec_csr_wen_r, // csr write enable at wb
input logic [11:0] dec_csr_wraddr_r, // write address for csr
input logic [31:0] dec_csr_wrdata_r, // csr write data at wb
input logic dec_csr_stall_int_ff, // csr is mie/mstatus
input logic dec_tlu_i0_valid_r, // pipe 0 op at e4 is valid
input logic [31:1] exu_npc_r, // for NPC tracking
input logic [31:1] dec_tlu_i0_pc_r, // for PC/NPC tracking
input el2_trap_pkt_t dec_tlu_packet_r, // exceptions known at decode
input logic [31:0] dec_illegal_inst, // For mtval
input logic dec_i0_decode_d, // decode valid, used for clean icache diagnostics
// branch info from pipe0 for errors or counter updates
input logic [1:0] exu_i0_br_hist_r, // history
input logic exu_i0_br_error_r, // error
input logic exu_i0_br_start_error_r, // start error
input logic exu_i0_br_valid_r, // valid
input logic exu_i0_br_mp_r, // mispredict
input logic exu_i0_br_middle_r, // middle of bank
// branch info from pipe1 for errors or counter updates
input logic exu_i0_br_way_r, // way hit or repl
output logic dec_tlu_core_empty, // core is empty
// Debug start
output logic dec_dbg_cmd_done, // abstract command done
output logic dec_dbg_cmd_fail, // abstract command failed
output logic dec_tlu_dbg_halted, // Core is halted and ready for debug command
output logic dec_tlu_debug_mode, // Core is in debug mode
output logic dec_tlu_resume_ack, // Resume acknowledge
output logic dec_tlu_debug_stall, // stall decode while waiting on core to empty
output logic dec_tlu_flush_noredir_r , // Tell fetch to idle on this flush
output logic dec_tlu_mpc_halted_only, // Core is halted only due to MPC
output logic dec_tlu_flush_leak_one_r, // single step
output logic dec_tlu_flush_err_r, // iside perr/ecc rfpc. This is the D stage of the error
output logic dec_tlu_flush_extint, // fast ext int started
output logic [31:2] dec_tlu_meihap, // meihap for fast int
input logic dbg_halt_req, // DM requests a halt
input logic dbg_resume_req, // DM requests a resume
input logic ifu_miss_state_idle, // I-side miss buffer empty
input logic lsu_idle_any, // lsu is idle
input logic dec_div_active, // oop div is active
output el2_trigger_pkt_t [3:0] trigger_pkt_any, // trigger info for trigger blocks
input logic ifu_ic_error_start, // IC single bit error
input logic ifu_iccm_rd_ecc_single_err, // ICCM single bit error
input logic [70:0] ifu_ic_debug_rd_data, // diagnostic icache read data
input logic ifu_ic_debug_rd_data_valid, // diagnostic icache read data valid
output el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt, // packet of DICAWICS, DICAD0/1, DICAGO info for icache diagnostics
// Debug end
input logic [7:0] pic_claimid, // pic claimid for csr
input logic [3:0] pic_pl, // pic priv level for csr
input logic mhwakeup, // high priority external int, wakeup if halted
input logic mexintpend, // external interrupt pending
input logic timer_int, // timer interrupt pending
input logic soft_int, // software interrupt pending
output logic o_cpu_halt_status, // PMU interface, halted
output logic o_cpu_halt_ack, // halt req ack
output logic o_cpu_run_ack, // run req ack
output logic o_debug_mode_status, // Core to the PMU that core is in debug mode. When core is in debug mode, the PMU should refrain from sendng a halt or run request
input logic [31:4] core_id, // Core ID
// external MPC halt/run interface
input logic mpc_debug_halt_req, // Async halt request
input logic mpc_debug_run_req, // Async run request
input logic mpc_reset_run_req, // Run/halt after reset
output logic mpc_debug_halt_ack, // Halt ack
output logic mpc_debug_run_ack, // Run ack
output logic debug_brkpt_status, // debug breakpoint
output logic [3:0] dec_tlu_meicurpl, // to PIC
output logic [3:0] dec_tlu_meipt, // to PIC
output logic [31:0] dec_csr_rddata_d, // csr read data at wb
output logic dec_csr_legal_d, // csr indicates legal operation
output el2_br_tlu_pkt_t dec_tlu_br0_r_pkt, // branch pkt to bp
output logic dec_tlu_i0_kill_writeb_wb, // I0 is flushed, don't writeback any results to arch state
output logic dec_tlu_flush_lower_wb, // commit has a flush (exception, int, mispredict at e4)
output logic dec_tlu_i0_commit_cmt, // committed an instruction
output logic dec_tlu_i0_kill_writeb_r, // I0 is flushed, don't writeback any results to arch state
output logic dec_tlu_flush_lower_r, // commit has a flush (exception, int)
output logic [31:1] dec_tlu_flush_path_r, // flush pc
output logic dec_tlu_fence_i_r, // flush is a fence_i rfnpc, flush icache
output logic dec_tlu_wr_pause_r, // CSR write to pause reg is at R.
output logic dec_tlu_flush_pause_r, // Flush is due to pause
output logic dec_tlu_presync_d, // CSR read needs to be presync'd
output logic dec_tlu_postsync_d, // CSR needs to be presync'd
output logic [31:0] dec_tlu_mrac_ff, // CSR for memory region control
output logic dec_tlu_force_halt, // halt has been forced
output logic dec_tlu_perfcnt0, // toggles when pipe0 perf counter 0 has an event inc
output logic dec_tlu_perfcnt1, // toggles when pipe0 perf counter 1 has an event inc
output logic dec_tlu_perfcnt2, // toggles when pipe0 perf counter 2 has an event inc
output logic dec_tlu_perfcnt3, // toggles when pipe0 perf counter 3 has an event inc
output logic dec_tlu_i0_exc_valid_wb1, // pipe 0 exception valid
output logic dec_tlu_i0_valid_wb1, // pipe 0 valid
output logic dec_tlu_int_valid_wb1, // pipe 2 int valid
output logic [4:0] dec_tlu_exc_cause_wb1, // exception or int cause
output logic [31:0] dec_tlu_mtval_wb1, // MTVAL value
// feature disable from mfdc
output logic dec_tlu_external_ldfwd_disable, // disable external load forwarding
output logic dec_tlu_sideeffect_posted_disable, // disable posted stores to side-effect address
output logic dec_tlu_core_ecc_disable, // disable core ECC
output logic dec_tlu_bpred_disable, // disable branch prediction
output logic dec_tlu_wb_coalescing_disable, // disable writebuffer coalescing
output logic dec_tlu_pipelining_disable, // disable pipelining
output logic dec_tlu_trace_disable, // disable trace
output logic [2:0] dec_tlu_dma_qos_prty, // DMA QoS priority coming from MFDC [18:16]
// clock gating overrides from mcgc
output logic dec_tlu_misc_clk_override, // override misc clock domain gating
output logic dec_tlu_dec_clk_override, // override decode clock domain gating
output logic dec_tlu_ifu_clk_override, // override fetch clock domain gating
output logic dec_tlu_lsu_clk_override, // override load/store clock domain gating
output logic dec_tlu_bus_clk_override, // override bus clock domain gating
output logic dec_tlu_pic_clk_override, // override PIC clock domain gating
output logic dec_tlu_picio_clk_override,// override PICIO clock domain gating
output logic dec_tlu_dccm_clk_override, // override DCCM clock domain gating
output logic dec_tlu_icm_clk_override // override ICCM clock domain gating
);
logic clk_override, e4e5_int_clk, nmi_fir_type, nmi_lsu_load_type, nmi_lsu_store_type, nmi_int_detected_f, nmi_lsu_load_type_f,
nmi_lsu_store_type_f, allow_dbg_halt_csr_write, dbg_cmd_done_ns, i_cpu_run_req_d1_raw, debug_mode_status, lsu_single_ecc_error_r_d1,
sel_npc_r, sel_npc_resume, ce_int,
nmi_in_debug_mode, dpc_capture_npc, dpc_capture_pc, tdata_load, tdata_opcode, tdata_action, perfcnt_halted, tdata_chain,
tdata_kill_write;
logic reset_delayed, reset_detect, reset_detected;
logic wr_mstatus_r, wr_mtvec_r, wr_mcyclel_r, wr_mcycleh_r,
wr_minstretl_r, wr_minstreth_r, wr_mscratch_r, wr_mepc_r, wr_mcause_r, wr_mscause_r, wr_mtval_r,
wr_mrac_r, wr_meihap_r, wr_meicurpl_r, wr_meipt_r, wr_dcsr_r,
wr_dpc_r, wr_meicidpl_r, wr_meivt_r, wr_meicpct_r, wr_micect_r, wr_miccmect_r, wr_mfdht_r, wr_mfdhs_r,
wr_mdccmect_r,wr_mhpme3_r, wr_mhpme4_r, wr_mhpme5_r, wr_mhpme6_r;
logic wr_mpmc_r;
logic [1:1] mpmc_b_ns, mpmc, mpmc_b;
logic set_mie_pmu_fw_halt, fw_halted_ns, fw_halted;
logic wr_mcountinhibit_r;
logic [6:0] mcountinhibit;
logic wr_mtsel_r, wr_mtdata1_t0_r, wr_mtdata1_t1_r, wr_mtdata1_t2_r, wr_mtdata1_t3_r, wr_mtdata2_t0_r, wr_mtdata2_t1_r, wr_mtdata2_t2_r, wr_mtdata2_t3_r;
logic [31:0] mtdata2_t0, mtdata2_t1, mtdata2_t2, mtdata2_t3, mtdata2_tsel_out, mtdata1_tsel_out;
logic [9:0] mtdata1_t0_ns, mtdata1_t0, mtdata1_t1_ns, mtdata1_t1, mtdata1_t2_ns, mtdata1_t2, mtdata1_t3_ns, mtdata1_t3;
logic [9:0] tdata_wrdata_r;
logic [1:0] mtsel_ns, mtsel;
logic tlu_i0_kill_writeb_r;
logic [1:0] mstatus_ns, mstatus;
logic [1:0] mfdhs_ns, mfdhs;
logic [31:0] force_halt_ctr, force_halt_ctr_f;
logic force_halt;
logic [5:0] mfdht, mfdht_ns;
logic mstatus_mie_ns;
logic [30:0] mtvec_ns, mtvec;
logic [15:2] dcsr_ns, dcsr;
logic [5:0] mip_ns, mip;
logic [5:0] mie_ns, mie;
logic [31:0] mcyclel_ns, mcyclel;
logic [31:0] mcycleh_ns, mcycleh;
logic [31:0] minstretl_ns, minstretl;
logic [31:0] minstreth_ns, minstreth;
logic [31:0] micect_ns, micect, miccmect_ns, miccmect, mdccmect_ns, mdccmect;
logic [26:0] micect_inc, miccmect_inc, mdccmect_inc;
logic [31:0] mscratch;
logic [31:0] mhpmc3, mhpmc3_ns, mhpmc4, mhpmc4_ns, mhpmc5, mhpmc5_ns, mhpmc6, mhpmc6_ns;
logic [31:0] mhpmc3h, mhpmc3h_ns, mhpmc4h, mhpmc4h_ns, mhpmc5h, mhpmc5h_ns, mhpmc6h, mhpmc6h_ns;
logic [9:0] mhpme3, mhpme4, mhpme5, mhpme6;
logic [31:0] mrac;
logic [9:2] meihap;
logic [31:10] meivt;
logic [3:0] meicurpl_ns, meicurpl;
logic [3:0] meicidpl_ns, meicidpl;
logic [3:0] meipt_ns, meipt;
logic [31:0] mdseac;
logic mdseac_locked_ns, mdseac_locked_f, mdseac_en, nmi_lsu_detected;
logic [31:1] mepc_ns, mepc;
logic [31:1] dpc_ns, dpc;
logic [31:0] mcause_ns, mcause;
logic [3:0] mscause_ns, mscause, mscause_type;
logic [31:0] mtval_ns, mtval;
logic dec_pause_state_f, dec_tlu_wr_pause_r_d1, pause_expired_r, pause_expired_wb;
logic tlu_flush_lower_r, tlu_flush_lower_r_d1;
logic [31:1] tlu_flush_path_r, tlu_flush_path_r_d1;
logic i0_valid_wb;
logic tlu_i0_commit_cmt;
logic [31:1] vectored_path, interrupt_path;
logic [16:0] dicawics_ns, dicawics;
logic wr_dicawics_r, wr_dicad0_r, wr_dicad1_r, wr_dicad0h_r;
logic [31:0] dicad0_ns, dicad0, dicad0h_ns, dicad0h;
logic [6:0] dicad1_ns, dicad1_raw;
logic [31:0] dicad1;
logic ebreak_r, ebreak_to_debug_mode_r, ecall_r, illegal_r, mret_r, inst_acc_r, fence_i_r,
ic_perr_r, iccm_sbecc_r, ebreak_to_debug_mode_r_d1, kill_ebreak_count_r, inst_acc_second_r;
logic ce_int_ready, ext_int_ready, timer_int_ready, soft_int_ready, int_timer0_int_ready, int_timer1_int_ready, mhwakeup_ready,
take_ext_int, take_ce_int, take_timer_int, take_soft_int, take_int_timer0_int, take_int_timer1_int, take_nmi, take_nmi_r_d1, int_timer0_int_possible, int_timer1_int_possible;
logic i0_exception_valid_r, interrupt_valid_r, i0_exception_valid_r_d1, interrupt_valid_r_d1, exc_or_int_valid_r, exc_or_int_valid_r_d1, mdccme_ce_req, miccme_ce_req, mice_ce_req;
logic synchronous_flush_r;
logic [4:0] exc_cause_r, exc_cause_wb;
logic mcyclel_cout, mcyclel_cout_f, mcyclela_cout;
logic [31:0] mcyclel_inc;
logic [31:0] mcycleh_inc;
logic minstretl_cout, minstretl_cout_f, minstret_enable, minstretl_cout_ns, minstretl_couta;
logic [31:0] minstretl_inc, minstretl_read;
logic [31:0] minstreth_inc, minstreth_read;
logic [31:1] pc_r, pc_r_d1, npc_r, npc_r_d1;
logic valid_csr;
logic rfpc_i0_r;
logic lsu_i0_rfnpc_r;
logic dec_tlu_br0_error_r, dec_tlu_br0_start_error_r, dec_tlu_br0_v_r;
logic lsu_i0_exc_r, lsu_i0_exc_r_raw, lsu_exc_ma_r, lsu_exc_acc_r, lsu_exc_st_r,
lsu_exc_valid_r, lsu_exc_valid_r_raw, lsu_exc_valid_r_d1, lsu_i0_exc_r_d1, block_interrupts;
logic i0_trigger_eval_r;
logic request_debug_mode_r, request_debug_mode_r_d1, request_debug_mode_done, request_debug_mode_done_f;
logic take_halt, halt_taken, halt_taken_f, internal_dbg_halt_mode, dbg_tlu_halted_f, take_reset,
dbg_tlu_halted, core_empty, lsu_idle_any_f, ifu_miss_state_idle_f, resume_ack_ns,
debug_halt_req_f, debug_resume_req_f_raw, debug_resume_req_f, enter_debug_halt_req, dcsr_single_step_done, dcsr_single_step_done_f,
debug_halt_req_d1, debug_halt_req_ns, dcsr_single_step_running, dcsr_single_step_running_f, internal_dbg_halt_timers;
logic [3:0] i0_trigger_r, trigger_action, trigger_enabled,
i0_trigger_chain_masked_r;
logic i0_trigger_hit_r, i0_trigger_hit_raw_r, i0_trigger_action_r,
trigger_hit_r_d1,
mepc_trigger_hit_sel_pc_r;
logic [3:0] update_hit_bit_r, i0_iside_trigger_has_pri_r,i0trigger_qual_r, i0_lsu_trigger_has_pri_r;
logic cpu_halt_status, cpu_halt_ack, cpu_run_ack, ext_halt_pulse, i_cpu_halt_req_d1, i_cpu_run_req_d1;
logic inst_acc_r_raw, trigger_hit_dmode_r, trigger_hit_dmode_r_d1;
logic [9:0] mcgc, mcgc_ns, mcgc_int;
logic [18:0] mfdc;
logic i_cpu_halt_req_sync_qual, i_cpu_run_req_sync_qual, pmu_fw_halt_req_ns, pmu_fw_halt_req_f, int_timer_stalled,
fw_halt_req, enter_pmu_fw_halt_req, pmu_fw_tlu_halted, pmu_fw_tlu_halted_f, internal_pmu_fw_halt_mode,
internal_pmu_fw_halt_mode_f, int_timer0_int_hold, int_timer1_int_hold, int_timer0_int_hold_f, int_timer1_int_hold_f;
logic nmi_int_delayed, nmi_int_detected;
logic [3:0] trigger_execute, trigger_data, trigger_store;
logic dec_tlu_pmu_fw_halted;
logic mpc_run_state_ns, debug_brkpt_status_ns, mpc_debug_halt_ack_ns, mpc_debug_run_ack_ns, dbg_halt_state_ns, dbg_run_state_ns,
dbg_halt_state_f, mpc_debug_halt_req_sync_f, mpc_debug_run_req_sync_f, mpc_halt_state_f, mpc_halt_state_ns, mpc_run_state_f, debug_brkpt_status_f,
mpc_debug_halt_ack_f, mpc_debug_run_ack_f, dbg_run_state_f, mpc_debug_halt_req_sync_pulse,
mpc_debug_run_req_sync_pulse, debug_brkpt_valid, debug_halt_req, debug_resume_req, dec_tlu_mpc_halted_only_ns;
logic take_ext_int_start, ext_int_freeze, take_ext_int_start_d1, take_ext_int_start_d2,
take_ext_int_start_d3, ext_int_freeze_d1, csr_meicpct, ignore_ext_int_due_to_lsu_stall;
logic mcause_sel_nmi_store, mcause_sel_nmi_load, mcause_sel_nmi_ext, fast_int_meicpct;
logic [1:0] mcause_fir_error_type;
logic dbg_halt_req_held_ns, dbg_halt_req_held, dbg_halt_req_final;
logic iccm_repair_state_ns, iccm_repair_state_d1, iccm_repair_state_rfnpc;
// internal timer, isolated for size reasons
logic [31:0] dec_timer_rddata_d;
logic dec_timer_read_d, dec_timer_t0_pulse, dec_timer_t1_pulse;
logic csr_mitctl0;
logic csr_mitctl1;
logic csr_mitb0;
logic csr_mitb1;
logic csr_mitcnt0;
logic csr_mitcnt1;
logic nmi_int_sync, timer_int_sync, soft_int_sync, i_cpu_halt_req_sync, i_cpu_run_req_sync, mpc_debug_halt_req_sync, mpc_debug_run_req_sync, mpc_debug_halt_req_sync_raw;
logic csr_wr_clk;
logic e4e5_clk, e4_valid, e5_valid, e4e5_valid, internal_dbg_halt_mode_f, internal_dbg_halt_mode_f2;
logic lsu_pmu_load_external_r, lsu_pmu_store_external_r;
logic dec_tlu_flush_noredir_r_d1, dec_tlu_flush_pause_r_d1;
logic lsu_single_ecc_error_r;
logic [31:0] lsu_error_pkt_addr_r;
logic mcyclel_cout_in;
logic i0_valid_no_ebreak_ecall_r;
logic minstret_enable_f;
logic sel_exu_npc_r, sel_flush_npc_r, sel_hold_npc_r;
logic pc0_valid_r;
logic [15:0] mfdc_int, mfdc_ns;
logic [31:0] mrac_in;
logic [31:27] csr_sat;
logic [8:6] dcsr_cause;
logic enter_debug_halt_req_le, dcsr_cause_upgradeable;
logic icache_rd_valid, icache_wr_valid, icache_rd_valid_f, icache_wr_valid_f;
logic [3:0] mhpmc_inc_r, mhpmc_inc_r_d1;
logic [3:0][9:0] mhpme_vec;
logic mhpmc3_wr_en0, mhpmc3_wr_en1, mhpmc3_wr_en;
logic mhpmc4_wr_en0, mhpmc4_wr_en1, mhpmc4_wr_en;
logic mhpmc5_wr_en0, mhpmc5_wr_en1, mhpmc5_wr_en;
logic mhpmc6_wr_en0, mhpmc6_wr_en1, mhpmc6_wr_en;
logic mhpmc3h_wr_en0, mhpmc3h_wr_en;
logic mhpmc4h_wr_en0, mhpmc4h_wr_en;
logic mhpmc5h_wr_en0, mhpmc5h_wr_en;
logic mhpmc6h_wr_en0, mhpmc6h_wr_en;
logic [63:0] mhpmc3_incr, mhpmc4_incr, mhpmc5_incr, mhpmc6_incr;
logic perfcnt_halted_d1, zero_event_r;
logic [3:0] perfcnt_during_sleep;
logic [9:0] event_r;
el2_inst_pkt_t pmu_i0_itype_qual;
logic csr_mfdht;
logic csr_mfdhs;
logic csr_misa;
logic csr_mvendorid;
logic csr_marchid;
logic csr_mimpid;
logic csr_mhartid;
logic csr_mstatus;
logic csr_mtvec;
logic csr_mip;
logic csr_mie;
logic csr_mcyclel;
logic csr_mcycleh;
logic csr_minstretl;
logic csr_minstreth;
logic csr_mscratch;
logic csr_mepc;
logic csr_mcause;
logic csr_mscause;
logic csr_mtval;
logic csr_mrac;
logic csr_dmst;
logic csr_mdseac;
logic csr_meihap;
logic csr_meivt;
logic csr_meipt;
logic csr_meicurpl;
logic csr_meicidpl;
logic csr_dcsr;
logic csr_mcgc;
logic csr_mfdc;
logic csr_dpc;
logic csr_mtsel;
logic csr_mtdata1;
logic csr_mtdata2;
logic csr_mhpmc3;
logic csr_mhpmc4;
logic csr_mhpmc5;
logic csr_mhpmc6;
logic csr_mhpmc3h;
logic csr_mhpmc4h;
logic csr_mhpmc5h;
logic csr_mhpmc6h;
logic csr_mhpme3;
logic csr_mhpme4;
logic csr_mhpme5;
logic csr_mhpme6;
logic csr_mcountinhibit;
logic csr_mpmc;
logic csr_micect;
logic csr_miccmect;
logic csr_mdccmect;
logic csr_dicawics;
logic csr_dicad0h;
logic csr_dicad0;
logic csr_dicad1;
logic csr_dicago;
logic presync;
logic postsync;
logic legal;
logic dec_csr_wen_r_mod;
logic flush_clkvalid;
logic sel_fir_addr;
logic wr_mie_r;
logic mtval_capture_pc_r;
logic mtval_capture_pc_plus2_r;
logic mtval_capture_inst_r;
logic mtval_capture_lsu_r;
logic mtval_clear_r;
logic wr_mcgc_r;
logic wr_mfdc_r;
logic wr_mdeau_r;
logic trigger_hit_for_dscr_cause_r_d1;
logic conditionally_illegal;
logic [3:0] ifu_mscause ;
logic ifu_ic_error_start_f, ifu_iccm_rd_ecc_single_err_f;
el2_dec_timer_ctl #(.pt(pt)) int_timers(.*);
// end of internal timers
assign clk_override = dec_tlu_dec_clk_override;
// Async inputs to the core have to be sync'd to the core clock.
rvsyncss #(7) syncro_ff(.*,
.clk(free_clk),
.din ({nmi_int, timer_int, soft_int, i_cpu_halt_req, i_cpu_run_req, mpc_debug_halt_req, mpc_debug_run_req}),
.dout({nmi_int_sync, timer_int_sync, soft_int_sync, i_cpu_halt_req_sync, i_cpu_run_req_sync, mpc_debug_halt_req_sync_raw, mpc_debug_run_req_sync}));
// for CSRs that have inpipe writes only
rvoclkhdr csrwr_r_cgc ( .en(dec_csr_wen_r_mod | clk_override), .l1clk(csr_wr_clk), .* );
assign e4_valid = dec_tlu_i0_valid_r;
assign e4e5_valid = e4_valid | e5_valid;
assign flush_clkvalid = internal_dbg_halt_mode_f | i_cpu_run_req_d1 | interrupt_valid_r | interrupt_valid_r_d1 |
reset_delayed | pause_expired_r | pause_expired_wb | ic_perr_r | iccm_sbecc_r |
clk_override;
rvoclkhdr e4e5_cgc ( .en(e4e5_valid | clk_override), .l1clk(e4e5_clk), .* );
rvoclkhdr e4e5_int_cgc ( .en(e4e5_valid | flush_clkvalid), .l1clk(e4e5_int_clk), .* );
rvdffie #(11) freeff (.*, .clk(free_l2clk),
.din ({ifu_ic_error_start, ifu_iccm_rd_ecc_single_err, iccm_repair_state_ns, e4_valid, internal_dbg_halt_mode,
lsu_pmu_load_external_m, lsu_pmu_store_external_m, tlu_flush_lower_r, tlu_i0_kill_writeb_r,
internal_dbg_halt_mode_f, force_halt}),
.dout({ifu_ic_error_start_f, ifu_iccm_rd_ecc_single_err_f, iccm_repair_state_d1, e5_valid, internal_dbg_halt_mode_f,
lsu_pmu_load_external_r, lsu_pmu_store_external_r, tlu_flush_lower_r_d1, dec_tlu_i0_kill_writeb_wb,
internal_dbg_halt_mode_f2, dec_tlu_force_halt}));
assign dec_tlu_i0_kill_writeb_r = tlu_i0_kill_writeb_r;
assign nmi_int_detected = (nmi_int_sync & ~nmi_int_delayed) | nmi_lsu_detected | (nmi_int_detected_f & ~take_nmi_r_d1) | nmi_fir_type;
// if the first nmi is a lsu type, note it. If there's already an nmi pending, ignore. Simultaneous with FIR, drop.
assign nmi_lsu_load_type = (nmi_lsu_detected & lsu_imprecise_error_load_any & ~(nmi_int_detected_f & ~take_nmi_r_d1)) |
(nmi_lsu_load_type_f & ~take_nmi_r_d1);
assign nmi_lsu_store_type = (nmi_lsu_detected & lsu_imprecise_error_store_any & ~(nmi_int_detected_f & ~take_nmi_r_d1)) |
(nmi_lsu_store_type_f & ~take_nmi_r_d1);
assign nmi_fir_type = ~nmi_int_detected_f & take_ext_int_start_d3 & |lsu_fir_error[1:0];
// Filter subsequent bus errors after the first, until the lock on MDSEAC is cleared
assign nmi_lsu_detected = ~mdseac_locked_f & (lsu_imprecise_error_load_any | lsu_imprecise_error_store_any) & ~nmi_fir_type;
localparam MSTATUS_MIE = 0;
localparam MIP_MCEIP = 5;
localparam MIP_MITIP0 = 4;
localparam MIP_MITIP1 = 3;
localparam MIP_MEIP = 2;
localparam MIP_MTIP = 1;
localparam MIP_MSIP = 0;
localparam MIE_MCEIE = 5;
localparam MIE_MITIE0 = 4;
localparam MIE_MITIE1 = 3;
localparam MIE_MEIE = 2;
localparam MIE_MTIE = 1;
localparam MIE_MSIE = 0;
localparam DCSR_EBREAKM = 15;
localparam DCSR_STEPIE = 11;
localparam DCSR_STOPC = 10;
localparam DCSR_STEP = 2;
assign reset_delayed = reset_detect ^ reset_detected;
// ----------------------------------------------------------------------
// MPC halt
// - can interact with debugger halt and v-v
// fast ints in progress have priority
assign mpc_debug_halt_req_sync = mpc_debug_halt_req_sync_raw & ~ext_int_freeze_d1;
rvdffie #(16) mpvhalt_ff (.*, .clk(free_l2clk),
.din({1'b1, reset_detect,
nmi_int_sync, nmi_int_detected, nmi_lsu_load_type, nmi_lsu_store_type,
mpc_debug_halt_req_sync, mpc_debug_run_req_sync,
mpc_halt_state_ns, mpc_run_state_ns, debug_brkpt_status_ns,
mpc_debug_halt_ack_ns, mpc_debug_run_ack_ns,
dbg_halt_state_ns, dbg_run_state_ns,
dec_tlu_mpc_halted_only_ns}),
.dout({reset_detect, reset_detected,
nmi_int_delayed, nmi_int_detected_f, nmi_lsu_load_type_f, nmi_lsu_store_type_f,
mpc_debug_halt_req_sync_f, mpc_debug_run_req_sync_f,
mpc_halt_state_f, mpc_run_state_f, debug_brkpt_status_f,
mpc_debug_halt_ack_f, mpc_debug_run_ack_f,
dbg_halt_state_f, dbg_run_state_f,
dec_tlu_mpc_halted_only}));
// turn level sensitive requests into pulses
assign mpc_debug_halt_req_sync_pulse = mpc_debug_halt_req_sync & ~mpc_debug_halt_req_sync_f;
assign mpc_debug_run_req_sync_pulse = mpc_debug_run_req_sync & ~mpc_debug_run_req_sync_f;
// states
assign mpc_halt_state_ns = (mpc_halt_state_f | mpc_debug_halt_req_sync_pulse | (reset_delayed & ~mpc_reset_run_req)) & ~mpc_debug_run_req_sync;
assign mpc_run_state_ns = (mpc_run_state_f | (mpc_debug_run_req_sync_pulse & ~mpc_debug_run_ack_f)) & (internal_dbg_halt_mode_f & ~dcsr_single_step_running_f);
// note, MPC halt can allow the jtag debugger to just start sending commands. When that happens, set the interal debugger halt state to prevent
// MPC run from starting the core.
assign dbg_halt_state_ns = (dbg_halt_state_f | (dbg_halt_req_final | dcsr_single_step_done_f | trigger_hit_dmode_r_d1 | ebreak_to_debug_mode_r_d1)) & ~dbg_resume_req;
assign dbg_run_state_ns = (dbg_run_state_f | dbg_resume_req) & (internal_dbg_halt_mode_f & ~dcsr_single_step_running_f);
// tell dbg we are only MPC halted
assign dec_tlu_mpc_halted_only_ns = ~dbg_halt_state_f & mpc_halt_state_f;
// this asserts from detection of bkpt until after we leave debug mode
assign debug_brkpt_valid = ebreak_to_debug_mode_r_d1 | trigger_hit_dmode_r_d1;
assign debug_brkpt_status_ns = (debug_brkpt_valid | debug_brkpt_status_f) & (internal_dbg_halt_mode & ~dcsr_single_step_running_f);
// acks back to interface
assign mpc_debug_halt_ack_ns = mpc_halt_state_f & internal_dbg_halt_mode_f & mpc_debug_halt_req_sync & core_empty;
assign mpc_debug_run_ack_ns = (mpc_debug_run_req_sync & ~dbg_halt_state_ns & ~mpc_debug_halt_req_sync) | (mpc_debug_run_ack_f & mpc_debug_run_req_sync) ;
// Pins
assign mpc_debug_halt_ack = mpc_debug_halt_ack_f;
assign mpc_debug_run_ack = mpc_debug_run_ack_f;
assign debug_brkpt_status = debug_brkpt_status_f;
// DBG halt req is a pulse, fast ext int in progress has priority
assign dbg_halt_req_held_ns = (dbg_halt_req | dbg_halt_req_held) & ext_int_freeze_d1;
assign dbg_halt_req_final = (dbg_halt_req | dbg_halt_req_held) & ~ext_int_freeze_d1;
// combine MPC and DBG halt requests
assign debug_halt_req = (dbg_halt_req_final | mpc_debug_halt_req_sync | (reset_delayed & ~mpc_reset_run_req)) & ~internal_dbg_halt_mode_f & ~ext_int_freeze_d1;
assign debug_resume_req = ~debug_resume_req_f & // squash back to back resumes
((mpc_run_state_ns & ~dbg_halt_state_ns) | // MPC run req
(dbg_run_state_ns & ~mpc_halt_state_ns)); // dbg request is a pulse
// HALT
// dbg/pmu/fw requests halt, service as soon as lsu is not blocking interrupts
assign take_halt = (debug_halt_req_f | pmu_fw_halt_req_f) & ~synchronous_flush_r & ~mret_r & ~halt_taken_f & ~dec_tlu_flush_noredir_r_d1 & ~take_reset;
// hold after we take a halt, so we don't keep taking halts
assign halt_taken = (dec_tlu_flush_noredir_r_d1 & ~dec_tlu_flush_pause_r_d1 & ~take_ext_int_start_d1) | (halt_taken_f & ~dbg_tlu_halted_f & ~pmu_fw_tlu_halted_f & ~interrupt_valid_r_d1);
// After doing halt flush (RFNPC) wait until core is idle before asserting a particular halt mode
// It takes a cycle for mb_empty to assert after a fetch, take_halt covers that cycle
assign core_empty = force_halt |
(lsu_idle_any & lsu_idle_any_f & ifu_miss_state_idle & ifu_miss_state_idle_f & ~debug_halt_req & ~debug_halt_req_d1 & ~dec_div_active);
assign dec_tlu_core_empty = core_empty;
//--------------------------------------------------------------------------------
// Debug start
//
assign enter_debug_halt_req = (~internal_dbg_halt_mode_f & debug_halt_req) | dcsr_single_step_done_f | trigger_hit_dmode_r_d1 | ebreak_to_debug_mode_r_d1;
// dbg halt state active from request until non-step resume
assign internal_dbg_halt_mode = debug_halt_req_ns | (internal_dbg_halt_mode_f & ~(debug_resume_req_f & ~dcsr[DCSR_STEP]));
// dbg halt can access csrs as long as we are not stepping
assign allow_dbg_halt_csr_write = internal_dbg_halt_mode_f & ~dcsr_single_step_running_f;
// hold debug_halt_req_ns high until we enter debug halt
assign debug_halt_req_ns = enter_debug_halt_req | (debug_halt_req_f & ~dbg_tlu_halted);
assign dbg_tlu_halted = (debug_halt_req_f & core_empty & halt_taken) | (dbg_tlu_halted_f & ~debug_resume_req_f);
assign resume_ack_ns = (debug_resume_req_f & dbg_tlu_halted_f & dbg_run_state_ns);
assign dcsr_single_step_done = dec_tlu_i0_valid_r & ~dec_tlu_dbg_halted & dcsr[DCSR_STEP] & ~rfpc_i0_r;
assign dcsr_single_step_running = (debug_resume_req_f & dcsr[DCSR_STEP]) | (dcsr_single_step_running_f & ~dcsr_single_step_done_f);
assign dbg_cmd_done_ns = dec_tlu_i0_valid_r & dec_tlu_dbg_halted;
// used to hold off commits after an in-pipe debug mode request (triggers, DCSR)
assign request_debug_mode_r = (trigger_hit_dmode_r | ebreak_to_debug_mode_r) | (request_debug_mode_r_d1 & ~dec_tlu_flush_lower_wb);
assign request_debug_mode_done = (request_debug_mode_r_d1 | request_debug_mode_done_f) & ~dbg_tlu_halted_f;
rvdffie #(18) halt_ff (.*, .clk(free_l2clk),
.din({dec_tlu_flush_noredir_r, halt_taken, lsu_idle_any, ifu_miss_state_idle, dbg_tlu_halted,
resume_ack_ns, debug_halt_req_ns, debug_resume_req, trigger_hit_dmode_r,
dcsr_single_step_done, debug_halt_req, dec_tlu_wr_pause_r, dec_pause_state,
request_debug_mode_r, request_debug_mode_done, dcsr_single_step_running, dec_tlu_flush_pause_r,
dbg_halt_req_held_ns}),
.dout({dec_tlu_flush_noredir_r_d1, halt_taken_f, lsu_idle_any_f, ifu_miss_state_idle_f, dbg_tlu_halted_f,
dec_tlu_resume_ack , debug_halt_req_f, debug_resume_req_f_raw, trigger_hit_dmode_r_d1,
dcsr_single_step_done_f, debug_halt_req_d1, dec_tlu_wr_pause_r_d1, dec_pause_state_f,
request_debug_mode_r_d1, request_debug_mode_done_f, dcsr_single_step_running_f, dec_tlu_flush_pause_r_d1,
dbg_halt_req_held}));
// MPC run collides with DBG halt, fix it here
assign debug_resume_req_f = debug_resume_req_f_raw & ~dbg_halt_req;
assign dec_tlu_debug_stall = debug_halt_req_f;
assign dec_tlu_dbg_halted = dbg_tlu_halted_f;
assign dec_tlu_debug_mode = internal_dbg_halt_mode_f;
assign dec_tlu_pmu_fw_halted = pmu_fw_tlu_halted_f;
// kill fetch redirection on flush if going to halt, or if there's a fence during db-halt
assign dec_tlu_flush_noredir_r = take_halt | (fence_i_r & internal_dbg_halt_mode) | dec_tlu_flush_pause_r | (i0_trigger_hit_r & trigger_hit_dmode_r) | take_ext_int_start;
assign dec_tlu_flush_extint = take_ext_int_start;
// 1 cycle after writing the PAUSE counter, flush with noredir to idle F1-D.
assign dec_tlu_flush_pause_r = dec_tlu_wr_pause_r_d1 & ~interrupt_valid_r & ~take_ext_int_start;
// detect end of pause counter and rfpc
assign pause_expired_r = ~dec_pause_state & dec_pause_state_f & ~(ext_int_ready | ce_int_ready | timer_int_ready | soft_int_ready | int_timer0_int_hold_f | int_timer1_int_hold_f | nmi_int_detected | ext_int_freeze_d1) & ~interrupt_valid_r_d1 & ~debug_halt_req_f & ~pmu_fw_halt_req_f & ~halt_taken_f;
assign dec_tlu_flush_leak_one_r = dec_tlu_flush_lower_r & dcsr[DCSR_STEP] & (dec_tlu_resume_ack | dcsr_single_step_running) & ~dec_tlu_flush_noredir_r;
assign dec_tlu_flush_err_r = dec_tlu_flush_lower_r & (ic_perr_r | iccm_sbecc_r);
// If DM attempts to access an illegal CSR, send cmd_fail back
assign dec_dbg_cmd_done = dbg_cmd_done_ns;
assign dec_dbg_cmd_fail = illegal_r & dec_dbg_cmd_done;
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Triggers
//
localparam MTDATA1_DMODE = 9;
localparam MTDATA1_SEL = 7;
localparam MTDATA1_ACTION = 6;
localparam MTDATA1_CHAIN = 5;
localparam MTDATA1_MATCH = 4;
localparam MTDATA1_M_ENABLED = 3;
localparam MTDATA1_EXE = 2;
localparam MTDATA1_ST = 1;
localparam MTDATA1_LD = 0;
// Prioritize trigger hits with other exceptions.
//
// Trigger should have highest priority except:
// - trigger is an execute-data and there is an inst_access exception (lsu triggers won't fire, inst. is nop'd by decode)
// - trigger is a store-data and there is a lsu_acc_exc or lsu_ma_exc.
assign trigger_execute[3:0] = {mtdata1_t3[MTDATA1_EXE], mtdata1_t2[MTDATA1_EXE], mtdata1_t1[MTDATA1_EXE], mtdata1_t0[MTDATA1_EXE]};
assign trigger_data[3:0] = {mtdata1_t3[MTDATA1_SEL], mtdata1_t2[MTDATA1_SEL], mtdata1_t1[MTDATA1_SEL], mtdata1_t0[MTDATA1_SEL]};
assign trigger_store[3:0] = {mtdata1_t3[MTDATA1_ST], mtdata1_t2[MTDATA1_ST], mtdata1_t1[MTDATA1_ST], mtdata1_t0[MTDATA1_ST]};
// MSTATUS[MIE] needs to be on to take triggers unless the action is trigger to debug mode.
assign trigger_enabled[3:0] = {(mtdata1_t3[MTDATA1_ACTION] | mstatus[MSTATUS_MIE]) & mtdata1_t3[MTDATA1_M_ENABLED],
(mtdata1_t2[MTDATA1_ACTION] | mstatus[MSTATUS_MIE]) & mtdata1_t2[MTDATA1_M_ENABLED],
(mtdata1_t1[MTDATA1_ACTION] | mstatus[MSTATUS_MIE]) & mtdata1_t1[MTDATA1_M_ENABLED],
(mtdata1_t0[MTDATA1_ACTION] | mstatus[MSTATUS_MIE]) & mtdata1_t0[MTDATA1_M_ENABLED]};
// iside exceptions are always in i0
assign i0_iside_trigger_has_pri_r[3:0] = ~( (trigger_execute[3:0] & trigger_data[3:0] & {4{inst_acc_r_raw}}) | // exe-data with inst_acc
({4{exu_i0_br_error_r | exu_i0_br_start_error_r}})); // branch error in i0
// lsu excs have to line up with their respective triggers since the lsu op can be i0
assign i0_lsu_trigger_has_pri_r[3:0] = ~(trigger_store[3:0] & trigger_data[3:0] & {4{lsu_i0_exc_r_raw}});
// trigger hits have to be eval'd to cancel side effect lsu ops even though the pipe is already frozen
assign i0_trigger_eval_r = dec_tlu_i0_valid_r;
assign i0trigger_qual_r[3:0] = {4{i0_trigger_eval_r}} & dec_tlu_packet_r.i0trigger[3:0] & i0_iside_trigger_has_pri_r[3:0] & i0_lsu_trigger_has_pri_r[3:0] & trigger_enabled[3:0];
// Qual trigger hits
assign i0_trigger_r[3:0] = ~{4{dec_tlu_flush_lower_wb | dec_tlu_dbg_halted}} & i0trigger_qual_r[3:0];
// chaining can mask raw trigger info
assign i0_trigger_chain_masked_r[3:0] = {i0_trigger_r[3] & (~mtdata1_t2[MTDATA1_CHAIN] | i0_trigger_r[2]),
i0_trigger_r[2] & (~mtdata1_t2[MTDATA1_CHAIN] | i0_trigger_r[3]),
i0_trigger_r[1] & (~mtdata1_t0[MTDATA1_CHAIN] | i0_trigger_r[0]),
i0_trigger_r[0] & (~mtdata1_t0[MTDATA1_CHAIN] | i0_trigger_r[1])};
// This is the highest priority by this point.
assign i0_trigger_hit_raw_r = |i0_trigger_chain_masked_r[3:0];
assign i0_trigger_hit_r = i0_trigger_hit_raw_r;
// Actions include breakpoint, or dmode. Dmode is only possible if the DMODE bit is set.
// Otherwise, take a breakpoint.
assign trigger_action[3:0] = {mtdata1_t3[MTDATA1_ACTION] & mtdata1_t3[MTDATA1_DMODE],
mtdata1_t2[MTDATA1_ACTION] & mtdata1_t2[MTDATA1_DMODE] & ~mtdata1_t2[MTDATA1_CHAIN],
mtdata1_t1[MTDATA1_ACTION] & mtdata1_t1[MTDATA1_DMODE],
mtdata1_t0[MTDATA1_ACTION] & mtdata1_t0[MTDATA1_DMODE] & ~mtdata1_t0[MTDATA1_CHAIN]};
// this is needed to set the HIT bit in the triggers
assign update_hit_bit_r[3:0] = ({4{|i0_trigger_r[3:0] & ~rfpc_i0_r}} & {i0_trigger_chain_masked_r[3], i0_trigger_r[2], i0_trigger_chain_masked_r[1], i0_trigger_r[0]});
// action, 1 means dmode. Simultaneous triggers with at least 1 set for dmode force entire action to dmode.
assign i0_trigger_action_r = |(i0_trigger_chain_masked_r[3:0] & trigger_action[3:0]);
assign trigger_hit_dmode_r = (i0_trigger_hit_r & i0_trigger_action_r);
assign mepc_trigger_hit_sel_pc_r = i0_trigger_hit_r & ~trigger_hit_dmode_r;
//
// Debug end
//--------------------------------------------------------------------------------
//----------------------------------------------------------------------
//
// Commit
//
//----------------------------------------------------------------------
//--------------------------------------------------------------------------------
// External halt (not debug halt)
// - Fully interlocked handshake
// i_cpu_halt_req ____|--------------|_______________
// core_empty ---------------|___________
// o_cpu_halt_ack _________________|----|__________
// o_cpu_halt_status _______________|---------------------|_________
// i_cpu_run_req ______|----------|____
// o_cpu_run_ack ____________|------|________
//
// debug mode has priority, ignore PMU/FW halt/run while in debug mode
assign i_cpu_halt_req_sync_qual = i_cpu_halt_req_sync & ~dec_tlu_debug_mode & ~ext_int_freeze_d1;
assign i_cpu_run_req_sync_qual = i_cpu_run_req_sync & ~dec_tlu_debug_mode & pmu_fw_tlu_halted_f & ~ext_int_freeze_d1;
rvdffie #(10) exthaltff (.*, .clk(free_l2clk), .din({i_cpu_halt_req_sync_qual, i_cpu_run_req_sync_qual, cpu_halt_status,
cpu_halt_ack, cpu_run_ack, internal_pmu_fw_halt_mode,
pmu_fw_halt_req_ns, pmu_fw_tlu_halted,
int_timer0_int_hold, int_timer1_int_hold}),
.dout({i_cpu_halt_req_d1, i_cpu_run_req_d1_raw, o_cpu_halt_status,
o_cpu_halt_ack, o_cpu_run_ack, internal_pmu_fw_halt_mode_f,
pmu_fw_halt_req_f, pmu_fw_tlu_halted_f,
int_timer0_int_hold_f, int_timer1_int_hold_f}));
// only happens if we aren't in dgb_halt
assign ext_halt_pulse = i_cpu_halt_req_sync_qual & ~i_cpu_halt_req_d1;
assign enter_pmu_fw_halt_req = ext_halt_pulse | fw_halt_req;
assign pmu_fw_halt_req_ns = (enter_pmu_fw_halt_req | (pmu_fw_halt_req_f & ~pmu_fw_tlu_halted)) & ~debug_halt_req_f;
assign internal_pmu_fw_halt_mode = pmu_fw_halt_req_ns | (internal_pmu_fw_halt_mode_f & ~i_cpu_run_req_d1 & ~debug_halt_req_f);
// debug halt has priority
assign pmu_fw_tlu_halted = ((pmu_fw_halt_req_f & core_empty & halt_taken & ~enter_debug_halt_req) | (pmu_fw_tlu_halted_f & ~i_cpu_run_req_d1)) & ~debug_halt_req_f;
assign cpu_halt_ack = (i_cpu_halt_req_d1 & pmu_fw_tlu_halted_f) | (o_cpu_halt_ack & i_cpu_halt_req_sync);
assign cpu_halt_status = (pmu_fw_tlu_halted_f & ~i_cpu_run_req_d1) | (o_cpu_halt_status & ~i_cpu_run_req_d1 & ~internal_dbg_halt_mode_f);
assign cpu_run_ack = (~pmu_fw_tlu_halted_f & i_cpu_run_req_sync) | (o_cpu_halt_status & i_cpu_run_req_d1_raw) | (o_cpu_run_ack & i_cpu_run_req_sync);
assign debug_mode_status = internal_dbg_halt_mode_f;
assign o_debug_mode_status = debug_mode_status;
`ifdef RV_ASSERT_ON
assert_commit_while_halted: assert #0 (~(tlu_i0_commit_cmt & o_cpu_halt_status)) else $display("ERROR: Commiting while cpu_halt_status asserted!");
assert_flush_while_fastint: assert #0 (~((take_ext_int_start_d1 | take_ext_int_start_d2) & dec_tlu_flush_lower_r)) else $display("ERROR: TLU Flushing inside fast interrupt procedure!");
`endif
// high priority interrupts can wakeup from external halt, so can unmasked timer interrupts
assign i_cpu_run_req_d1 = i_cpu_run_req_d1_raw | ((nmi_int_detected | timer_int_ready | soft_int_ready | int_timer0_int_hold_f | int_timer1_int_hold_f | (mhwakeup & mhwakeup_ready)) & o_cpu_halt_status & ~i_cpu_halt_req_d1);
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
assign lsu_single_ecc_error_r = lsu_single_ecc_error_incr;
assign lsu_error_pkt_addr_r[31:0] = lsu_error_pkt_r.addr[31:0];
assign lsu_exc_valid_r_raw = lsu_error_pkt_r.exc_valid & ~dec_tlu_flush_lower_wb;
assign lsu_i0_exc_r_raw = lsu_error_pkt_r.exc_valid;
assign lsu_i0_exc_r = lsu_i0_exc_r_raw & lsu_exc_valid_r_raw & ~i0_trigger_hit_r & ~rfpc_i0_r;
assign lsu_exc_valid_r = lsu_i0_exc_r;
assign lsu_exc_ma_r = lsu_i0_exc_r & ~lsu_error_pkt_r.exc_type;
assign lsu_exc_acc_r = lsu_i0_exc_r & lsu_error_pkt_r.exc_type;
assign lsu_exc_st_r = lsu_i0_exc_r & lsu_error_pkt_r.inst_type;
// Single bit ECC errors on loads are RFNPC corrected, with the corrected data written to the GPR.
// LSU turns the load into a store and patches the data in the DCCM
assign lsu_i0_rfnpc_r = dec_tlu_i0_valid_r & ~i0_trigger_hit_r &
(~lsu_error_pkt_r.inst_type & lsu_error_pkt_r.single_ecc_error);
// Final commit valids
assign tlu_i0_commit_cmt = dec_tlu_i0_valid_r &
~rfpc_i0_r &
~lsu_i0_exc_r &
~inst_acc_r &
~dec_tlu_dbg_halted &
~request_debug_mode_r_d1 &
~i0_trigger_hit_r;
// unified place to manage the killing of arch state writebacks
assign tlu_i0_kill_writeb_r = rfpc_i0_r | lsu_i0_exc_r | inst_acc_r | (illegal_r & dec_tlu_dbg_halted) | i0_trigger_hit_r;
assign dec_tlu_i0_commit_cmt = tlu_i0_commit_cmt;
// refetch PC, microarch flush
// ic errors only in pipe0
assign rfpc_i0_r = ((dec_tlu_i0_valid_r & ~tlu_flush_lower_r_d1 & (exu_i0_br_error_r | exu_i0_br_start_error_r)) | // inst commit with rfpc
((ic_perr_r | iccm_sbecc_r) & ~ext_int_freeze_d1)) & // ic/iccm without inst commit
~i0_trigger_hit_r & // unless there's a trigger. Err signal to ic/iccm will assert anyway to clear the error.
~lsu_i0_rfnpc_r;
// From the indication of a iccm single bit error until the first commit or flush, maintain a repair state. In the repair state, rfnpc i0 commits.
assign iccm_repair_state_ns = iccm_sbecc_r | (iccm_repair_state_d1 & ~dec_tlu_flush_lower_r);
localparam MCPC = 12'h7c2;
// this is a flush of last resort, meaning only assert it if there is no other flush happening.
assign iccm_repair_state_rfnpc = tlu_i0_commit_cmt & iccm_repair_state_d1 &
~(ebreak_r | ecall_r | mret_r | take_reset | illegal_r | (dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCPC)));
if(pt.BTB_ENABLE==1) begin
// go ahead and repair the branch error on other flushes, doesn't have to be the rfpc flush
assign dec_tlu_br0_error_r = exu_i0_br_error_r & dec_tlu_i0_valid_r & ~tlu_flush_lower_r_d1;
assign dec_tlu_br0_start_error_r = exu_i0_br_start_error_r & dec_tlu_i0_valid_r & ~tlu_flush_lower_r_d1;
assign dec_tlu_br0_v_r = exu_i0_br_valid_r & dec_tlu_i0_valid_r & ~tlu_flush_lower_r_d1 & (~exu_i0_br_mp_r | ~exu_pmu_i0_br_ataken);
assign dec_tlu_br0_r_pkt.hist[1:0] = exu_i0_br_hist_r[1:0];
assign dec_tlu_br0_r_pkt.br_error = dec_tlu_br0_error_r;
assign dec_tlu_br0_r_pkt.br_start_error = dec_tlu_br0_start_error_r;
assign dec_tlu_br0_r_pkt.valid = dec_tlu_br0_v_r;
assign dec_tlu_br0_r_pkt.way = exu_i0_br_way_r;
assign dec_tlu_br0_r_pkt.middle = exu_i0_br_middle_r;
end // if (pt.BTB_ENABLE==1)
else begin
assign dec_tlu_br0_error_r = '0;
assign dec_tlu_br0_start_error_r = '0;
assign dec_tlu_br0_v_r = '0;
assign dec_tlu_br0_r_pkt = '0;
end // else: !if(pt.BTB_ENABLE==1)
// only expect these in pipe 0
assign ebreak_r = (dec_tlu_packet_r.pmu_i0_itype == EBREAK) & dec_tlu_i0_valid_r & ~i0_trigger_hit_r & ~dcsr[DCSR_EBREAKM] & ~rfpc_i0_r;
assign ecall_r = (dec_tlu_packet_r.pmu_i0_itype == ECALL) & dec_tlu_i0_valid_r & ~i0_trigger_hit_r & ~rfpc_i0_r;
assign illegal_r = ~dec_tlu_packet_r.legal & dec_tlu_i0_valid_r & ~i0_trigger_hit_r & ~rfpc_i0_r;
assign mret_r = (dec_tlu_packet_r.pmu_i0_itype == MRET) & dec_tlu_i0_valid_r & ~i0_trigger_hit_r & ~rfpc_i0_r;
// fence_i includes debug only fence_i's
assign fence_i_r = (dec_tlu_packet_r.fence_i & dec_tlu_i0_valid_r & ~i0_trigger_hit_r) & ~rfpc_i0_r;
assign ic_perr_r = ifu_ic_error_start_f & ~ext_int_freeze_d1 & (~internal_dbg_halt_mode_f | dcsr_single_step_running) & ~internal_pmu_fw_halt_mode_f;
assign iccm_sbecc_r = ifu_iccm_rd_ecc_single_err_f & ~ext_int_freeze_d1 & (~internal_dbg_halt_mode_f | dcsr_single_step_running) & ~internal_pmu_fw_halt_mode_f;
assign inst_acc_r_raw = dec_tlu_packet_r.icaf & dec_tlu_i0_valid_r;
assign inst_acc_r = inst_acc_r_raw & ~rfpc_i0_r & ~i0_trigger_hit_r;
assign inst_acc_second_r = dec_tlu_packet_r.icaf_second;
assign ebreak_to_debug_mode_r = (dec_tlu_packet_r.pmu_i0_itype == EBREAK) & dec_tlu_i0_valid_r & ~i0_trigger_hit_r & dcsr[DCSR_EBREAKM] & ~rfpc_i0_r;
rvdff #(1) exctype_wb_ff (.*, .clk(e4e5_clk),
.din (ebreak_to_debug_mode_r ),
.dout(ebreak_to_debug_mode_r_d1));
assign dec_tlu_fence_i_r = fence_i_r;
//
// Exceptions
//
// - MEPC <- PC
// - PC <- MTVEC, assert flush_lower
// - MCAUSE <- cause
// - MSCAUSE <- secondary cause
// - MTVAL <-
// - MPIE <- MIE
// - MIE <- 0
//
assign i0_exception_valid_r = (ebreak_r | ecall_r | illegal_r | inst_acc_r) & ~rfpc_i0_r & ~dec_tlu_dbg_halted;
// Cause:
//
// 0x2 : illegal
// 0x3 : breakpoint
// 0xb : Environment call M-mode
assign exc_cause_r[4:0] = ( ({5{take_ext_int}} & 5'h0b) |
({5{take_timer_int}} & 5'h07) |
({5{take_soft_int}} & 5'h03) |
({5{take_int_timer0_int}} & 5'h1d) |
({5{take_int_timer1_int}} & 5'h1c) |
({5{take_ce_int}} & 5'h1e) |
({5{illegal_r}} & 5'h02) |
({5{ecall_r}} & 5'h0b) |
({5{inst_acc_r}} & 5'h01) |
({5{ebreak_r | i0_trigger_hit_r}} & 5'h03) |
({5{lsu_exc_ma_r & ~lsu_exc_st_r}} & 5'h04) |
({5{lsu_exc_acc_r & ~lsu_exc_st_r}} & 5'h05) |
({5{lsu_exc_ma_r & lsu_exc_st_r}} & 5'h06) |
({5{lsu_exc_acc_r & lsu_exc_st_r}} & 5'h07)
) & ~{5{take_nmi}};
//
// Interrupts
//
// exceptions that are committed have already happened and will cause an int at E4 to wait a cycle
// or more if MSTATUS[MIE] is cleared.
//
// -in priority order, highest to lowest
// -single cycle window where a csr write to MIE/MSTATUS is at E4 when the other conditions for externals are met.
// Hold off externals for a cycle to make sure we are consistent with what was just written
assign mhwakeup_ready = ~dec_csr_stall_int_ff & mstatus_mie_ns & mip[MIP_MEIP] & mie_ns[MIE_MEIE];
assign ext_int_ready = ~dec_csr_stall_int_ff & mstatus_mie_ns & mip[MIP_MEIP] & mie_ns[MIE_MEIE] & ~ignore_ext_int_due_to_lsu_stall;
assign ce_int_ready = ~dec_csr_stall_int_ff & mstatus_mie_ns & mip[MIP_MCEIP] & mie_ns[MIE_MCEIE];
assign soft_int_ready = ~dec_csr_stall_int_ff & mstatus_mie_ns & mip[MIP_MSIP] & mie_ns[MIE_MSIE];
assign timer_int_ready = ~dec_csr_stall_int_ff & mstatus_mie_ns & mip[MIP_MTIP] & mie_ns[MIE_MTIE];
// MIP for internal timers pulses for 1 clock, resets the timer counter. Mip won't hold past the various stall conditions.
assign int_timer0_int_possible = mstatus_mie_ns & mie_ns[MIE_MITIE0];
assign int_timer0_int_ready = mip[MIP_MITIP0] & int_timer0_int_possible;
assign int_timer1_int_possible = mstatus_mie_ns & mie_ns[MIE_MITIE1];
assign int_timer1_int_ready = mip[MIP_MITIP1] & int_timer1_int_possible;
// Internal timers pulse and reset. If core is PMU/FW halted, the pulse will cause an exit from halt, but won't stick around
// Make it sticky, also for 1 cycle stall conditions.
assign int_timer_stalled = dec_csr_stall_int_ff | synchronous_flush_r | exc_or_int_valid_r_d1 | mret_r;
assign int_timer0_int_hold = (int_timer0_int_ready & (pmu_fw_tlu_halted_f | int_timer_stalled)) | (int_timer0_int_possible & int_timer0_int_hold_f & ~interrupt_valid_r & ~take_ext_int_start & ~internal_dbg_halt_mode_f);
assign int_timer1_int_hold = (int_timer1_int_ready & (pmu_fw_tlu_halted_f | int_timer_stalled)) | (int_timer1_int_possible & int_timer1_int_hold_f & ~interrupt_valid_r & ~take_ext_int_start & ~internal_dbg_halt_mode_f);
assign internal_dbg_halt_timers = internal_dbg_halt_mode_f & ~dcsr_single_step_running;
assign block_interrupts = ( (internal_dbg_halt_mode & (~dcsr_single_step_running | dec_tlu_i0_valid_r)) | // No ints in db-halt unless we are single stepping
internal_pmu_fw_halt_mode | i_cpu_halt_req_d1 |// No ints in PMU/FW halt. First we exit halt
take_nmi | // NMI is top priority
ebreak_to_debug_mode_r | // Heading to debug mode, hold off ints
synchronous_flush_r | // exception flush this cycle
exc_or_int_valid_r_d1 | // ext/int past cycle (need time for MIE to update)
mret_r | // mret in progress, for cases were ISR enables ints before mret
ext_int_freeze_d1 // Fast interrupt in progress (optional)
);
if (pt.FAST_INTERRUPT_REDIRECT) begin
assign take_ext_int_start = ext_int_ready & ~block_interrupts;
assign ext_int_freeze = take_ext_int_start | take_ext_int_start_d1 | take_ext_int_start_d2 | take_ext_int_start_d3;
assign take_ext_int = take_ext_int_start_d3 & ~|lsu_fir_error[1:0];
assign fast_int_meicpct = csr_meicpct & dec_csr_any_unq_d; // MEICPCT becomes illegal if fast ints are enabled
assign ignore_ext_int_due_to_lsu_stall = lsu_fastint_stall_any;
end
else begin
assign take_ext_int_start = 1'b0;
assign ext_int_freeze = 1'b0;
assign ext_int_freeze_d1 = 1'b0;
assign take_ext_int_start_d1 = 1'b0;
assign take_ext_int_start_d2 = 1'b0;
assign take_ext_int_start_d3 = 1'b0;
assign fast_int_meicpct = 1'b0;
assign ignore_ext_int_due_to_lsu_stall = 1'b0;
assign take_ext_int = ext_int_ready & ~block_interrupts;
end
assign take_ce_int = ce_int_ready & ~ext_int_ready & ~block_interrupts;
assign take_soft_int = soft_int_ready & ~ext_int_ready & ~ce_int_ready & ~block_interrupts;
assign take_timer_int = timer_int_ready & ~soft_int_ready & ~ext_int_ready & ~ce_int_ready & ~block_interrupts;
assign take_int_timer0_int = (int_timer0_int_ready | int_timer0_int_hold_f) & int_timer0_int_possible & ~dec_csr_stall_int_ff &
~timer_int_ready & ~soft_int_ready & ~ext_int_ready & ~ce_int_ready & ~block_interrupts;
assign take_int_timer1_int = (int_timer1_int_ready | int_timer1_int_hold_f) & int_timer1_int_possible & ~dec_csr_stall_int_ff &
~(int_timer0_int_ready | int_timer0_int_hold_f) & ~timer_int_ready & ~soft_int_ready & ~ext_int_ready & ~ce_int_ready & ~block_interrupts;
assign take_reset = reset_delayed & mpc_reset_run_req;
assign take_nmi = nmi_int_detected & ~internal_pmu_fw_halt_mode & (~internal_dbg_halt_mode | (dcsr_single_step_running_f & dcsr[DCSR_STEPIE] & ~dec_tlu_i0_valid_r & ~dcsr_single_step_done_f)) &
~synchronous_flush_r & ~mret_r & ~take_reset & ~ebreak_to_debug_mode_r & (~ext_int_freeze_d1 | (take_ext_int_start_d3 & |lsu_fir_error[1:0]));
assign interrupt_valid_r = take_ext_int | take_timer_int | take_soft_int | take_nmi | take_ce_int | take_int_timer0_int | take_int_timer1_int;
// Compute interrupt path:
// If vectored async is set in mtvec, flush path for interrupts is MTVEC + (4 * CAUSE);
assign vectored_path[31:1] = {mtvec[30:1], 1'b0} + {25'b0, exc_cause_r[4:0], 1'b0};
assign interrupt_path[31:1] = take_nmi ? nmi_vec[31:1] : ((mtvec[0] == 1'b1) ? vectored_path[31:1] : {mtvec[30:1], 1'b0});
assign sel_npc_r = lsu_i0_rfnpc_r | fence_i_r | iccm_repair_state_rfnpc | (i_cpu_run_req_d1 & ~interrupt_valid_r) | (rfpc_i0_r & ~dec_tlu_i0_valid_r);
assign sel_npc_resume = (i_cpu_run_req_d1 & pmu_fw_tlu_halted_f) | pause_expired_r;
assign sel_fir_addr = take_ext_int_start_d3 & ~|lsu_fir_error[1:0];
assign synchronous_flush_r = i0_exception_valid_r | // exception
rfpc_i0_r | // rfpc
lsu_exc_valid_r | // lsu exception in either pipe 0 or pipe 1
fence_i_r | // fence, a rfnpc
lsu_i0_rfnpc_r | // lsu dccm sb ecc
iccm_repair_state_rfnpc | // Iccm sb ecc
debug_resume_req_f | // resume from debug halt, fetch the dpc
sel_npc_resume | // resume from pmu/fw halt, or from pause and fetch the NPC
dec_tlu_wr_pause_r_d1 | // flush at start of pause
i0_trigger_hit_r; // trigger hit, ebreak or goto debug mode
assign tlu_flush_lower_r = interrupt_valid_r | mret_r | synchronous_flush_r | take_halt | take_reset | take_ext_int_start;
assign tlu_flush_path_r[31:1] = take_reset ? rst_vec[31:1] :
( ({31{sel_fir_addr}} & lsu_fir_addr[31:1]) |
({31{~take_nmi & sel_npc_r}} & npc_r[31:1]) |
({31{~take_nmi & rfpc_i0_r & dec_tlu_i0_valid_r & ~sel_npc_r}} & dec_tlu_i0_pc_r[31:1]) |
({31{interrupt_valid_r & ~sel_fir_addr}} & interrupt_path[31:1]) |
({31{(i0_exception_valid_r | lsu_exc_valid_r |
(i0_trigger_hit_r & ~trigger_hit_dmode_r)) & ~interrupt_valid_r & ~sel_fir_addr}} & {mtvec[30:1],1'b0}) |
({31{~take_nmi & mret_r}} & mepc[31:1]) |
({31{~take_nmi & debug_resume_req_f}} & dpc[31:1]) |
({31{~take_nmi & sel_npc_resume}} & npc_r_d1[31:1]) );
rvdffpcie #(31) flush_lower_ff (.*, .en(tlu_flush_lower_r),
.din({tlu_flush_path_r[31:1]}),
.dout({tlu_flush_path_r_d1[31:1]}));
assign dec_tlu_flush_lower_wb = tlu_flush_lower_r_d1;
assign dec_tlu_flush_lower_r = tlu_flush_lower_r;
assign dec_tlu_flush_path_r[31:1] = tlu_flush_path_r[31:1];
// this is used to capture mepc, etc.
assign exc_or_int_valid_r = lsu_exc_valid_r | i0_exception_valid_r | interrupt_valid_r | (i0_trigger_hit_r & ~trigger_hit_dmode_r);
rvdffie #(12) excinfo_wb_ff (.*,
.din({interrupt_valid_r, i0_exception_valid_r, exc_or_int_valid_r,
exc_cause_r[4:0], tlu_i0_commit_cmt & ~illegal_r, i0_trigger_hit_r,
take_nmi, pause_expired_r }),
.dout({interrupt_valid_r_d1, i0_exception_valid_r_d1, exc_or_int_valid_r_d1,
exc_cause_wb[4:0], i0_valid_wb, trigger_hit_r_d1,
take_nmi_r_d1, pause_expired_wb}));
//----------------------------------------------------------------------
//
// CSRs
//
//----------------------------------------------------------------------
// ----------------------------------------------------------------------
// MISA (RO)
// [31:30] XLEN - implementation width, 2'b01 - 32 bits
// [12] M - integer mul/div
// [8] I - RV32I
// [2] C - Compressed extension
localparam MISA = 12'h301;
// MVENDORID, MARCHID, MIMPID, MHARTID
localparam MVENDORID = 12'hf11;
localparam MARCHID = 12'hf12;
localparam MIMPID = 12'hf13;
localparam MHARTID = 12'hf14;
// ----------------------------------------------------------------------
// MSTATUS (RW)
// [12:11] MPP : Prior priv level, always 2'b11, not flopped
// [7] MPIE : Int enable previous [1]
// [3] MIE : Int enable [0]
localparam MSTATUS = 12'h300;
//When executing a MRET instruction, supposing MPP holds the value 3, MIE
//is set to MPIE; the privilege mode is changed to 3; MPIE is set to 1; and MPP is set to 3
assign dec_csr_wen_r_mod = dec_csr_wen_r & ~i0_trigger_hit_r & ~rfpc_i0_r;
assign wr_mstatus_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MSTATUS);
// set this even if we don't go to fwhalt due to debug halt. We committed the inst, so ...
assign set_mie_pmu_fw_halt = ~mpmc_b_ns[1] & fw_halt_req;
assign mstatus_ns[1:0] = ( ({2{~wr_mstatus_r & exc_or_int_valid_r}} & {mstatus[MSTATUS_MIE], 1'b0}) |
({2{ wr_mstatus_r & exc_or_int_valid_r}} & {dec_csr_wrdata_r[3], 1'b0}) |
({2{mret_r & ~exc_or_int_valid_r}} & {1'b1, mstatus[1]}) |
({2{set_mie_pmu_fw_halt}} & {mstatus[1], 1'b1}) |
({2{wr_mstatus_r & ~exc_or_int_valid_r}} & {dec_csr_wrdata_r[7], dec_csr_wrdata_r[3]}) |
({2{~wr_mstatus_r & ~exc_or_int_valid_r & ~mret_r & ~set_mie_pmu_fw_halt}} & mstatus[1:0]) );
// gate MIE if we are single stepping and DCSR[STEPIE] is off
assign mstatus_mie_ns = mstatus[MSTATUS_MIE] & (~dcsr_single_step_running_f | dcsr[DCSR_STEPIE]);
// ----------------------------------------------------------------------
// MTVEC (RW)
// [31:2] BASE : Trap vector base address
// [1] - Reserved, not implemented, reads zero
// [0] MODE : 0 = Direct, 1 = Asyncs are vectored to BASE + (4 * CAUSE)
localparam MTVEC = 12'h305;
assign wr_mtvec_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTVEC);
assign mtvec_ns[30:0] = {dec_csr_wrdata_r[31:2], dec_csr_wrdata_r[0]} ;
rvdffe #(31) mtvec_ff (.*, .en(wr_mtvec_r), .din(mtvec_ns[30:0]), .dout(mtvec[30:0]));
// ----------------------------------------------------------------------
// MIP (RW)
//
// [30] MCEIP : (RO) M-Mode Correctable Error interrupt pending
// [29] MITIP0 : (RO) M-Mode Internal Timer0 interrupt pending
// [28] MITIP1 : (RO) M-Mode Internal Timer1 interrupt pending
// [11] MEIP : (RO) M-Mode external interrupt pending
// [7] MTIP : (RO) M-Mode timer interrupt pending
// [3] MSIP : (RO) M-Mode software interrupt pending
localparam MIP = 12'h344;
assign ce_int = (mdccme_ce_req | miccme_ce_req | mice_ce_req);
assign mip_ns[5:0] = {ce_int, dec_timer_t0_pulse, dec_timer_t1_pulse, mexintpend, timer_int_sync, soft_int_sync};
// ----------------------------------------------------------------------
// MIE (RW)
// [30] MCEIE : (RO) M-Mode Correctable Error interrupt enable
// [29] MITIE0 : (RO) M-Mode Internal Timer0 interrupt enable
// [28] MITIE1 : (RO) M-Mode Internal Timer1 interrupt enable
// [11] MEIE : (RW) M-Mode external interrupt enable
// [7] MTIE : (RW) M-Mode timer interrupt enable
// [3] MSIE : (RW) M-Mode software interrupt enable
localparam MIE = 12'h304;
assign wr_mie_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MIE);
assign mie_ns[5:0] = wr_mie_r ? {dec_csr_wrdata_r[30:28], dec_csr_wrdata_r[11], dec_csr_wrdata_r[7], dec_csr_wrdata_r[3]} : mie[5:0];
rvdff #(6) mie_ff (.*, .clk(csr_wr_clk), .din(mie_ns[5:0]), .dout(mie[5:0]));
// ----------------------------------------------------------------------
// MCYCLEL (RW)
// [31:0] : Lower Cycle count
localparam MCYCLEL = 12'hb00;
assign kill_ebreak_count_r = ebreak_to_debug_mode_r & dcsr[DCSR_STOPC];
assign wr_mcyclel_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCYCLEL);
assign mcyclel_cout_in = ~(kill_ebreak_count_r | (dec_tlu_dbg_halted & dcsr[DCSR_STOPC]) | dec_tlu_pmu_fw_halted | mcountinhibit[0]);
// split for power
assign {mcyclela_cout, mcyclel_inc[7:0]} = mcyclel[7:0] + {7'b0, 1'b1};
assign {mcyclel_cout, mcyclel_inc[31:8]} = mcyclel[31:8] + {23'b0, mcyclela_cout};
assign mcyclel_ns[31:0] = wr_mcyclel_r ? dec_csr_wrdata_r[31:0] : mcyclel_inc[31:0];
rvdffe #(24) mcyclel_bff (.*, .clk(free_l2clk), .en(wr_mcyclel_r | (mcyclela_cout & mcyclel_cout_in)), .din(mcyclel_ns[31:8]), .dout(mcyclel[31:8]));
rvdffe #(8) mcyclel_aff (.*, .clk(free_l2clk), .en(wr_mcyclel_r | mcyclel_cout_in), .din(mcyclel_ns[7:0]), .dout(mcyclel[7:0]));
// ----------------------------------------------------------------------
// MCYCLEH (RW)
// [63:32] : Higher Cycle count
// Chained with mcyclel. Note: mcyclel overflow due to a mcycleh write gets ignored.
localparam MCYCLEH = 12'hb80;
assign wr_mcycleh_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCYCLEH);
assign mcycleh_inc[31:0] = mcycleh[31:0] + {31'b0, mcyclel_cout_f};
assign mcycleh_ns[31:0] = wr_mcycleh_r ? dec_csr_wrdata_r[31:0] : mcycleh_inc[31:0];
rvdffe #(32) mcycleh_ff (.*, .clk(free_l2clk), .en(wr_mcycleh_r | mcyclel_cout_f), .din(mcycleh_ns[31:0]), .dout(mcycleh[31:0]));
// ----------------------------------------------------------------------
// MINSTRETL (RW)
// [31:0] : Lower Instruction retired count
// From the spec "Some CSRs, such as the instructions retired counter, instret, may be modified as side effects
// of instruction execution. In these cases, if a CSR access instruction reads a CSR, it reads the
// value prior to the execution of the instruction. If a CSR access instruction writes a CSR, the
// update occurs after the execution of the instruction. In particular, a value written to instret by
// one instruction will be the value read by the following instruction (i.e., the increment of instret
// caused by the first instruction retiring happens before the write of the new value)."
localparam MINSTRETL = 12'hb02;
assign i0_valid_no_ebreak_ecall_r = dec_tlu_i0_valid_r & ~(ebreak_r | ecall_r | ebreak_to_debug_mode_r | illegal_r | mcountinhibit[2]);
assign wr_minstretl_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MINSTRETL);
assign {minstretl_couta, minstretl_inc[7:0]} = minstretl[7:0] + {7'b0,1'b1};
assign {minstretl_cout, minstretl_inc[31:8]} = minstretl[31:8] + {23'b0, minstretl_couta};
assign minstret_enable = (i0_valid_no_ebreak_ecall_r & tlu_i0_commit_cmt) | wr_minstretl_r;
assign minstretl_cout_ns = minstretl_cout & ~wr_minstreth_r & i0_valid_no_ebreak_ecall_r & ~dec_tlu_dbg_halted;
assign minstretl_ns[31:0] = wr_minstretl_r ? dec_csr_wrdata_r[31:0] : minstretl_inc[31:0];
rvdffe #(24) minstretl_bff (.*, .en(wr_minstretl_r | (minstretl_couta & minstret_enable)),
.din(minstretl_ns[31:8]), .dout(minstretl[31:8]));
rvdffe #(8) minstretl_aff (.*, .en(minstret_enable),
.din(minstretl_ns[7:0]), .dout(minstretl[7:0]));
assign minstretl_read[31:0] = minstretl[31:0];
// ----------------------------------------------------------------------
// MINSTRETH (RW)
// [63:32] : Higher Instret count
// Chained with minstretl. Note: minstretl overflow due to a minstreth write gets ignored.
localparam MINSTRETH = 12'hb82;
assign wr_minstreth_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MINSTRETH);
assign minstreth_inc[31:0] = minstreth[31:0] + {31'b0, minstretl_cout_f};
assign minstreth_ns[31:0] = wr_minstreth_r ? dec_csr_wrdata_r[31:0] : minstreth_inc[31:0];
rvdffe #(32) minstreth_ff (.*, .en((minstret_enable_f & minstretl_cout_f) | wr_minstreth_r), .din(minstreth_ns[31:0]), .dout(minstreth[31:0]));
assign minstreth_read[31:0] = minstreth_inc[31:0];
// ----------------------------------------------------------------------
// MSCRATCH (RW)
// [31:0] : Scratch register
localparam MSCRATCH = 12'h340;
assign wr_mscratch_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MSCRATCH);
rvdffe #(32) mscratch_ff (.*, .en(wr_mscratch_r), .din(dec_csr_wrdata_r[31:0]), .dout(mscratch[31:0]));
// ----------------------------------------------------------------------
// MEPC (RW)
// [31:1] : Exception PC
localparam MEPC = 12'h341;
// NPC
assign sel_exu_npc_r = ~dec_tlu_dbg_halted & ~tlu_flush_lower_r_d1 & dec_tlu_i0_valid_r;
assign sel_flush_npc_r = ~dec_tlu_dbg_halted & tlu_flush_lower_r_d1 & ~dec_tlu_flush_noredir_r_d1;
assign sel_hold_npc_r = ~sel_exu_npc_r & ~sel_flush_npc_r;
assign npc_r[31:1] = ( ({31{sel_exu_npc_r}} & exu_npc_r[31:1]) |
({31{~mpc_reset_run_req & reset_delayed}} & rst_vec[31:1]) | // init to reset vector for mpc halt on reset case
({31{(sel_flush_npc_r)}} & tlu_flush_path_r_d1[31:1]) |
({31{(sel_hold_npc_r)}} & npc_r_d1[31:1]) );
rvdffpcie #(31) npwbc_ff (.*, .en(sel_exu_npc_r | sel_flush_npc_r | reset_delayed), .din(npc_r[31:1]), .dout(npc_r_d1[31:1]));
// PC has to be captured for exceptions and interrupts. For MRET, we could execute it and then take an
// interrupt before the next instruction.
assign pc0_valid_r = ~dec_tlu_dbg_halted & dec_tlu_i0_valid_r;
assign pc_r[31:1] = ( ({31{ pc0_valid_r}} & dec_tlu_i0_pc_r[31:1]) |
({31{~pc0_valid_r}} & pc_r_d1[31:1]));
rvdffpcie #(31) pwbc_ff (.*, .en(pc0_valid_r), .din(pc_r[31:1]), .dout(pc_r_d1[31:1]));
assign wr_mepc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEPC);
assign mepc_ns[31:1] = ( ({31{i0_exception_valid_r | lsu_exc_valid_r | mepc_trigger_hit_sel_pc_r}} & pc_r[31:1]) |
({31{interrupt_valid_r}} & npc_r[31:1]) |
({31{wr_mepc_r & ~exc_or_int_valid_r}} & dec_csr_wrdata_r[31:1]) |
({31{~wr_mepc_r & ~exc_or_int_valid_r}} & mepc[31:1]) );
rvdffe #(31) mepc_ff (.*, .en(i0_exception_valid_r | lsu_exc_valid_r | mepc_trigger_hit_sel_pc_r | interrupt_valid_r | wr_mepc_r), .din(mepc_ns[31:1]), .dout(mepc[31:1]));
// ----------------------------------------------------------------------
// MCAUSE (RW)
// [31:0] : Exception Cause
localparam MCAUSE = 12'h342;
assign wr_mcause_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCAUSE);
assign mcause_sel_nmi_store = exc_or_int_valid_r & take_nmi & nmi_lsu_store_type;
assign mcause_sel_nmi_load = exc_or_int_valid_r & take_nmi & nmi_lsu_load_type;
assign mcause_sel_nmi_ext = exc_or_int_valid_r & take_nmi & take_ext_int_start_d3 & |lsu_fir_error[1:0] & ~nmi_int_detected_f;
// FIR value decoder
// 0 no error
// 1 uncorrectable ecc => f000_1000
// 2 dccm region access error => f000_1001
// 3 non dccm region access error => f000_1002
assign mcause_fir_error_type[1:0] = {&lsu_fir_error[1:0], lsu_fir_error[1] & ~lsu_fir_error[0]};
assign mcause_ns[31:0] = ( ({32{mcause_sel_nmi_store}} & {32'hf000_0000}) |
({32{mcause_sel_nmi_load}} & {32'hf000_0001}) |
({32{mcause_sel_nmi_ext}} & {28'hf000_100, 2'b0, mcause_fir_error_type[1:0]}) |
({32{exc_or_int_valid_r & ~take_nmi}} & {interrupt_valid_r, 26'b0, exc_cause_r[4:0]}) |
({32{wr_mcause_r & ~exc_or_int_valid_r}} & dec_csr_wrdata_r[31:0]) |
({32{~wr_mcause_r & ~exc_or_int_valid_r}} & mcause[31:0]) );
rvdffe #(32) mcause_ff (.*, .en(exc_or_int_valid_r | wr_mcause_r), .din(mcause_ns[31:0]), .dout(mcause[31:0]));
// ----------------------------------------------------------------------
// MSCAUSE (RW)
// [2:0] : Secondary exception Cause
localparam MSCAUSE = 12'h7ff;
assign wr_mscause_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MSCAUSE);
assign ifu_mscause[3:0] = (dec_tlu_packet_r.icaf_type[1:0] == 2'b00) ? 4'b1001 :
{2'b00 , dec_tlu_packet_r.icaf_type[1:0]} ;
assign mscause_type[3:0] = ( ({4{lsu_i0_exc_r}} & lsu_error_pkt_r.mscause[3:0]) |
({4{i0_trigger_hit_r}} & 4'b0001) |
({4{ebreak_r}} & 4'b0010) |
({4{inst_acc_r}} & ifu_mscause[3:0])
);
assign mscause_ns[3:0] = ( ({4{exc_or_int_valid_r}} & mscause_type[3:0]) |
({4{ wr_mscause_r & ~exc_or_int_valid_r}} & dec_csr_wrdata_r[3:0]) |
({4{~wr_mscause_r & ~exc_or_int_valid_r}} & mscause[3:0])
);
rvdff #(4) mscause_ff (.*, .clk(e4e5_int_clk), .din(mscause_ns[3:0]), .dout(mscause[3:0]));
// ----------------------------------------------------------------------
// MTVAL (RW)
// [31:0] : Exception address if relevant
localparam MTVAL = 12'h343;
assign wr_mtval_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTVAL);
assign mtval_capture_pc_r = exc_or_int_valid_r & (ebreak_r | (inst_acc_r & ~inst_acc_second_r) | mepc_trigger_hit_sel_pc_r) & ~take_nmi;
assign mtval_capture_pc_plus2_r = exc_or_int_valid_r & (inst_acc_r & inst_acc_second_r) & ~take_nmi;
assign mtval_capture_inst_r = exc_or_int_valid_r & illegal_r & ~take_nmi;
assign mtval_capture_lsu_r = exc_or_int_valid_r & lsu_exc_valid_r & ~take_nmi;
assign mtval_clear_r = exc_or_int_valid_r & ~mtval_capture_pc_r & ~mtval_capture_inst_r & ~mtval_capture_lsu_r & ~mepc_trigger_hit_sel_pc_r;
assign mtval_ns[31:0] = (({32{mtval_capture_pc_r}} & {pc_r[31:1], 1'b0}) |
({32{mtval_capture_pc_plus2_r}} & {pc_r[31:1] + 31'b1, 1'b0}) |
({32{mtval_capture_inst_r}} & dec_illegal_inst[31:0]) |
({32{mtval_capture_lsu_r}} & lsu_error_pkt_addr_r[31:0]) |
({32{wr_mtval_r & ~interrupt_valid_r}} & dec_csr_wrdata_r[31:0]) |
({32{~take_nmi & ~wr_mtval_r & ~mtval_capture_pc_r & ~mtval_capture_inst_r & ~mtval_clear_r & ~mtval_capture_lsu_r}} & mtval[31:0]) );
rvdffe #(32) mtval_ff (.*, .en(tlu_flush_lower_r | wr_mtval_r), .din(mtval_ns[31:0]), .dout(mtval[31:0]));
// ----------------------------------------------------------------------
// MCGC (RW) Clock gating control
// [31:10]: Reserved, reads 0x0
// [9] : picio_clk_override
// [7] : dec_clk_override
// [6] : Unused
// [5] : ifu_clk_override
// [4] : lsu_clk_override
// [3] : bus_clk_override
// [2] : pic_clk_override
// [1] : dccm_clk_override
// [0] : icm_clk_override
//
localparam MCGC = 12'h7f8;
assign wr_mcgc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCGC);
assign mcgc_ns[9:0] = wr_mcgc_r ? {~dec_csr_wrdata_r[9], dec_csr_wrdata_r[8:0]} : mcgc_int[9:0];
rvdffe #(10) mcgc_ff (.*, .en(wr_mcgc_r), .din(mcgc_ns[9:0]), .dout(mcgc_int[9:0]));
assign mcgc[9:0] = {~mcgc_int[9], mcgc_int[8:0]};
assign dec_tlu_picio_clk_override= mcgc[9];
assign dec_tlu_misc_clk_override = mcgc[8];
assign dec_tlu_dec_clk_override = mcgc[7];
//sign dec_tlu_exu_clk_override = mcgc[6];
assign dec_tlu_ifu_clk_override = mcgc[5];
assign dec_tlu_lsu_clk_override = mcgc[4];
assign dec_tlu_bus_clk_override = mcgc[3];
assign dec_tlu_pic_clk_override = mcgc[2];
assign dec_tlu_dccm_clk_override = mcgc[1];
assign dec_tlu_icm_clk_override = mcgc[0];
// ----------------------------------------------------------------------
// MFDC (RW) Feature Disable Control
// [31:19] : Reserved, reads 0x0
// [18:16] : DMA QoS Prty
// [15:13] : Reserved, reads 0x0
// [12] : Disable trace
// [11] : Disable external load forwarding
// [10] : Disable dual issue
// [9] : Disable pic multiple ints
// [8] : Disable core ecc
// [7] : Disable secondary alu?s
// [6] : Unused, 0x0
// [5] : Disable non-blocking loads/divides
// [4] : Disable fast divide
// [3] : Disable branch prediction and return stack
// [2] : Disable write buffer coalescing
// [1] : Disable load misses that bypass the write buffer
// [0] : Disable pipelining - Enable single instruction execution
//
localparam MFDC = 12'h7f9;
assign wr_mfdc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MFDC);
rvdffe #(16) mfdc_ff (.*, .en(wr_mfdc_r), .din({mfdc_ns[15:0]}), .dout(mfdc_int[15:0]));
// flip poweron value of bit 6 for AXI build
if(pt.BUILD_AXI4==1) begin : axi4
// flip poweron valid of bit 12
assign mfdc_ns[15:0] = {~dec_csr_wrdata_r[18:16], dec_csr_wrdata_r[12], dec_csr_wrdata_r[11:7], ~dec_csr_wrdata_r[6], dec_csr_wrdata_r[5:0]};
assign mfdc[18:0] = {~mfdc_int[15:13], 3'b0, mfdc_int[12], mfdc_int[11:7], ~mfdc_int[6], mfdc_int[5:0]};
end
else begin
// flip poweron valid of bit 12
assign mfdc_ns[15:0] = {~dec_csr_wrdata_r[18:16],dec_csr_wrdata_r[12:0]};
assign mfdc[18:0] = {~mfdc_int[15:13], 3'b0, mfdc_int[12:0]};
end
assign dec_tlu_dma_qos_prty[2:0] = mfdc[18:16];
assign dec_tlu_trace_disable = mfdc[12];
assign dec_tlu_external_ldfwd_disable = mfdc[11];
assign dec_tlu_core_ecc_disable = mfdc[8];
assign dec_tlu_sideeffect_posted_disable = mfdc[6];
assign dec_tlu_bpred_disable = mfdc[3];
assign dec_tlu_wb_coalescing_disable = mfdc[2];
assign dec_tlu_pipelining_disable = mfdc[0];
// ----------------------------------------------------------------------
// MCPC (RW) Pause counter
// [31:0] : Reads 0x0, decs in the wb register in decode_ctl
assign dec_tlu_wr_pause_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCPC) & ~interrupt_valid_r & ~take_ext_int_start;
// ----------------------------------------------------------------------
// MRAC (RW)
// [31:0] : Region Access Control Register, 16 regions, {side_effect, cachable} pairs
localparam MRAC = 12'h7c0;
assign wr_mrac_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MRAC);
// prevent pairs of 0x11, side_effect and cacheable
assign mrac_in[31:0] = {dec_csr_wrdata_r[31], dec_csr_wrdata_r[30] & ~dec_csr_wrdata_r[31],
dec_csr_wrdata_r[29], dec_csr_wrdata_r[28] & ~dec_csr_wrdata_r[29],
dec_csr_wrdata_r[27], dec_csr_wrdata_r[26] & ~dec_csr_wrdata_r[27],
dec_csr_wrdata_r[25], dec_csr_wrdata_r[24] & ~dec_csr_wrdata_r[25],
dec_csr_wrdata_r[23], dec_csr_wrdata_r[22] & ~dec_csr_wrdata_r[23],
dec_csr_wrdata_r[21], dec_csr_wrdata_r[20] & ~dec_csr_wrdata_r[21],
dec_csr_wrdata_r[19], dec_csr_wrdata_r[18] & ~dec_csr_wrdata_r[19],
dec_csr_wrdata_r[17], dec_csr_wrdata_r[16] & ~dec_csr_wrdata_r[17],
dec_csr_wrdata_r[15], dec_csr_wrdata_r[14] & ~dec_csr_wrdata_r[15],
dec_csr_wrdata_r[13], dec_csr_wrdata_r[12] & ~dec_csr_wrdata_r[13],
dec_csr_wrdata_r[11], dec_csr_wrdata_r[10] & ~dec_csr_wrdata_r[11],
dec_csr_wrdata_r[9], dec_csr_wrdata_r[8] & ~dec_csr_wrdata_r[9],
dec_csr_wrdata_r[7], dec_csr_wrdata_r[6] & ~dec_csr_wrdata_r[7],
dec_csr_wrdata_r[5], dec_csr_wrdata_r[4] & ~dec_csr_wrdata_r[5],
dec_csr_wrdata_r[3], dec_csr_wrdata_r[2] & ~dec_csr_wrdata_r[3],
dec_csr_wrdata_r[1], dec_csr_wrdata_r[0] & ~dec_csr_wrdata_r[1]};
rvdffe #(32) mrac_ff (.*, .en(wr_mrac_r), .din(mrac_in[31:0]), .dout(mrac[31:0]));
// drive to LSU/IFU
assign dec_tlu_mrac_ff[31:0] = mrac[31:0];
// ----------------------------------------------------------------------
// MDEAU (WAR0)
// [31:0] : Dbus Error Address Unlock register
//
localparam MDEAU = 12'hbc0;
assign wr_mdeau_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MDEAU);
// ----------------------------------------------------------------------
// MDSEAC (R)
// [31:0] : Dbus Store Error Address Capture register
//
localparam MDSEAC = 12'hfc0;
// only capture error bus if the MDSEAC reg is not locked
assign mdseac_locked_ns = mdseac_en | (mdseac_locked_f & ~wr_mdeau_r);
assign mdseac_en = (lsu_imprecise_error_store_any | lsu_imprecise_error_load_any) & ~nmi_int_detected_f & ~mdseac_locked_f;
rvdffe #(32) mdseac_ff (.*, .en(mdseac_en), .din(lsu_imprecise_error_addr_any[31:0]), .dout(mdseac[31:0]));
// ----------------------------------------------------------------------
// MPMC (R0W1)
// [0] : FW halt
// [1] : Set MSTATUS[MIE] on halt
localparam MPMC = 12'h7c6;
assign wr_mpmc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MPMC);
// allow the cycle of the dbg halt flush that contains the wr_mpmc_r to
// set the mstatus bit potentially, use delayed version of internal dbg halt.
assign fw_halt_req = wr_mpmc_r & dec_csr_wrdata_r[0] & ~internal_dbg_halt_mode_f2 & ~ext_int_freeze_d1;
assign fw_halted_ns = (fw_halt_req | fw_halted) & ~set_mie_pmu_fw_halt;
assign mpmc_b_ns[1] = wr_mpmc_r ? ~dec_csr_wrdata_r[1] : ~mpmc[1];
rvdff #(1) mpmc_ff (.*, .clk(csr_wr_clk), .din(mpmc_b_ns[1]), .dout(mpmc_b[1]));
assign mpmc[1] = ~mpmc_b[1];
// ----------------------------------------------------------------------
// MICECT (I-Cache error counter/threshold)
// [31:27] : Icache parity error threshold
// [26:0] : Icache parity error count
localparam MICECT = 12'h7f0;
assign csr_sat[31:27] = (dec_csr_wrdata_r[31:27] > 5'd26) ? 5'd26 : dec_csr_wrdata_r[31:27];
assign wr_micect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MICECT);
assign micect_inc[26:0] = micect[26:0] + {26'b0, ic_perr_r};
assign micect_ns = wr_micect_r ? {csr_sat[31:27], dec_csr_wrdata_r[26:0]} : {micect[31:27], micect_inc[26:0]};
rvdffe #(32) micect_ff (.*, .en(wr_micect_r | ic_perr_r), .din(micect_ns[31:0]), .dout(micect[31:0]));
assign mice_ce_req = |({32'hffffffff << micect[31:27]} & {5'b0, micect[26:0]});
// ----------------------------------------------------------------------
// MICCMECT (ICCM error counter/threshold)
// [31:27] : ICCM parity error threshold
// [26:0] : ICCM parity error count
localparam MICCMECT = 12'h7f1;
assign wr_miccmect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MICCMECT);
assign miccmect_inc[26:0] = miccmect[26:0] + {26'b0, iccm_sbecc_r | iccm_dma_sb_error};
assign miccmect_ns = wr_miccmect_r ? {csr_sat[31:27], dec_csr_wrdata_r[26:0]} : {miccmect[31:27], miccmect_inc[26:0]};
rvdffe #(32) miccmect_ff (.*, .clk(free_l2clk), .en(wr_miccmect_r | iccm_sbecc_r | iccm_dma_sb_error), .din(miccmect_ns[31:0]), .dout(miccmect[31:0]));
assign miccme_ce_req = |({32'hffffffff << miccmect[31:27]} & {5'b0, miccmect[26:0]});
// ----------------------------------------------------------------------
// MDCCMECT (DCCM error counter/threshold)
// [31:27] : DCCM parity error threshold
// [26:0] : DCCM parity error count
localparam MDCCMECT = 12'h7f2;
assign wr_mdccmect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MDCCMECT);
assign mdccmect_inc[26:0] = mdccmect[26:0] + {26'b0, lsu_single_ecc_error_r_d1};
assign mdccmect_ns = wr_mdccmect_r ? {csr_sat[31:27], dec_csr_wrdata_r[26:0]} : {mdccmect[31:27], mdccmect_inc[26:0]};
rvdffe #(32) mdccmect_ff (.*, .clk(free_l2clk), .en(wr_mdccmect_r | lsu_single_ecc_error_r_d1), .din(mdccmect_ns[31:0]), .dout(mdccmect[31:0]));
assign mdccme_ce_req = |({32'hffffffff << mdccmect[31:27]} & {5'b0, mdccmect[26:0]});
// ----------------------------------------------------------------------
// MFDHT (Force Debug Halt Threshold)
// [5:1] : Halt timeout threshold (power of 2)
// [0] : Halt timeout enabled
localparam MFDHT = 12'h7ce;
assign wr_mfdht_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MFDHT);
assign mfdht_ns[5:0] = wr_mfdht_r ? dec_csr_wrdata_r[5:0] : mfdht[5:0];
rvdffs #(6) mfdht_ff (.*, .clk(csr_wr_clk), .en(wr_mfdht_r), .din(mfdht_ns[5:0]), .dout(mfdht[5:0]));
// ----------------------------------------------------------------------
// MFDHS(RW)
// [1] : LSU operation pending when debug halt threshold reached
// [0] : IFU operation pending when debug halt threshold reached
localparam MFDHS = 12'h7cf;
assign wr_mfdhs_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MFDHS);
assign mfdhs_ns[1:0] = wr_mfdhs_r ? dec_csr_wrdata_r[1:0] : ((dbg_tlu_halted & ~dbg_tlu_halted_f) ? {~lsu_idle_any_f, ~ifu_miss_state_idle_f} : mfdhs[1:0]);
rvdffs #(2) mfdhs_ff (.*, .clk(free_clk), .en(wr_mfdhs_r | dbg_tlu_halted), .din(mfdhs_ns[1:0]), .dout(mfdhs[1:0]));
assign force_halt_ctr[31:0] = debug_halt_req_f ? (force_halt_ctr_f[31:0] + 32'b1) : (dbg_tlu_halted_f ? 32'b0 : force_halt_ctr_f[31:0]);
rvdffe #(32) forcehaltctr_ff (.*, .en(mfdht[0]), .din(force_halt_ctr[31:0]), .dout(force_halt_ctr_f[31:0]));
assign force_halt = mfdht[0] & |(force_halt_ctr_f[31:0] & (32'hffffffff << mfdht[5:1]));
// ----------------------------------------------------------------------
// MEIVT (External Interrupt Vector Table (R/W))
// [31:10]: Base address (R/W)
// [9:0] : Reserved, reads 0x0
localparam MEIVT = 12'hbc8;
assign wr_meivt_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEIVT);
rvdffe #(22) meivt_ff (.*, .en(wr_meivt_r), .din(dec_csr_wrdata_r[31:10]), .dout(meivt[31:10]));
// ----------------------------------------------------------------------
// MEIHAP (External Interrupt Handler Access Pointer (R))
// [31:10]: Base address (R/W)
// [9:2] : ClaimID (R)
// [1:0] : Reserved, 0x0
localparam MEIHAP = 12'hfc8;
assign wr_meihap_r = wr_meicpct_r;
rvdffe #(8) meihap_ff (.*, .en(wr_meihap_r), .din(pic_claimid[7:0]), .dout(meihap[9:2]));
assign dec_tlu_meihap[31:2] = {meivt[31:10], meihap[9:2]};
// ----------------------------------------------------------------------
// MEICURPL (R/W)
// [31:4] : Reserved (read 0x0)
// [3:0] : CURRPRI - Priority level of current interrupt service routine (R/W)
localparam MEICURPL = 12'hbcc;
assign wr_meicurpl_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEICURPL);
assign meicurpl_ns[3:0] = wr_meicurpl_r ? dec_csr_wrdata_r[3:0] : meicurpl[3:0];
rvdff #(4) meicurpl_ff (.*, .clk(csr_wr_clk), .din(meicurpl_ns[3:0]), .dout(meicurpl[3:0]));
// PIC needs this reg
assign dec_tlu_meicurpl[3:0] = meicurpl[3:0];
// ----------------------------------------------------------------------
// MEICIDPL (R/W)
// [31:4] : Reserved (read 0x0)
// [3:0] : External Interrupt Claim ID's Priority Level Register
localparam MEICIDPL = 12'hbcb;
assign wr_meicidpl_r = (dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEICIDPL)) | take_ext_int_start;
assign meicidpl_ns[3:0] = wr_meicpct_r ? pic_pl[3:0] : (wr_meicidpl_r ? dec_csr_wrdata_r[3:0] : meicidpl[3:0]);
// ----------------------------------------------------------------------
// MEICPCT (Capture CLAIMID in MEIHAP and PL in MEICIDPL
// [31:1] : Reserved (read 0x0)
// [0] : Capture (W1, Read 0)
localparam MEICPCT = 12'hbca;
assign wr_meicpct_r = (dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEICPCT)) | take_ext_int_start;
// ----------------------------------------------------------------------
// MEIPT (External Interrupt Priority Threshold)
// [31:4] : Reserved (read 0x0)
// [3:0] : PRITHRESH
localparam MEIPT = 12'hbc9;
assign wr_meipt_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEIPT);
assign meipt_ns[3:0] = wr_meipt_r ? dec_csr_wrdata_r[3:0] : meipt[3:0];
rvdff #(4) meipt_ff (.*, .clk(csr_wr_clk), .din(meipt_ns[3:0]), .dout(meipt[3:0]));
// to PIC
assign dec_tlu_meipt[3:0] = meipt[3:0];
// ----------------------------------------------------------------------
// DCSR (R/W) (Only accessible in debug mode)
// [31:28] : xdebugver (hard coded to 0x4) RO
// [27:16] : 0x0, reserved
// [15] : ebreakm
// [14] : 0x0, reserved
// [13] : ebreaks (0x0 for this core)
// [12] : ebreaku (0x0 for this core)
// [11] : stepie
// [10] : stopcount
// [9] : 0x0 //stoptime
// [8:6] : cause (RO)
// [5:4] : 0x0, reserved
// [3] : nmip
// [2] : step
// [1:0] : prv (0x3 for this core)
//
localparam DCSR = 12'h7b0;
// RV has clarified that 'priority 4' in the spec means top priority.
// 4. single step. 3. Debugger request. 2. Ebreak. 1. Trigger.
// RV debug spec indicates a cause priority change for trigger hits during single step.
assign trigger_hit_for_dscr_cause_r_d1 = trigger_hit_dmode_r_d1 | (trigger_hit_r_d1 & dcsr_single_step_done_f);
assign dcsr_cause[8:6] = ( ({3{dcsr_single_step_done_f & ~ebreak_to_debug_mode_r_d1 & ~trigger_hit_for_dscr_cause_r_d1 & ~debug_halt_req}} & 3'b100) |
({3{debug_halt_req & ~ebreak_to_debug_mode_r_d1 & ~trigger_hit_for_dscr_cause_r_d1}} & 3'b011) |
({3{ebreak_to_debug_mode_r_d1 & ~trigger_hit_for_dscr_cause_r_d1}} & 3'b001) |
({3{trigger_hit_for_dscr_cause_r_d1}} & 3'b010));
assign wr_dcsr_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DCSR);
// Multiple halt enter requests can happen before we are halted.
// We have to continue to upgrade based on dcsr_cause priority but we can't downgrade.
assign dcsr_cause_upgradeable = internal_dbg_halt_mode_f & (dcsr[8:6] == 3'b011);
assign enter_debug_halt_req_le = enter_debug_halt_req & (~dbg_tlu_halted | dcsr_cause_upgradeable);
assign nmi_in_debug_mode = nmi_int_detected_f & internal_dbg_halt_mode_f;
assign dcsr_ns[15:2] = enter_debug_halt_req_le ? {dcsr[15:9], dcsr_cause[8:6], dcsr[5:2]} :
(wr_dcsr_r ? {dec_csr_wrdata_r[15], 3'b0, dec_csr_wrdata_r[11:10], 1'b0, dcsr[8:6], 2'b00, nmi_in_debug_mode | dcsr[3], dec_csr_wrdata_r[2]} :
{dcsr[15:4], nmi_in_debug_mode, dcsr[2]});
rvdffe #(14) dcsr_ff (.*, .clk(free_l2clk), .en(enter_debug_halt_req_le | wr_dcsr_r | internal_dbg_halt_mode | take_nmi), .din(dcsr_ns[15:2]), .dout(dcsr[15:2]));
// ----------------------------------------------------------------------
// DPC (R/W) (Only accessible in debug mode)
// [31:0] : Debug PC
localparam DPC = 12'h7b1;
assign wr_dpc_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DPC);
assign dpc_capture_npc = dbg_tlu_halted & ~dbg_tlu_halted_f & ~request_debug_mode_done;
assign dpc_capture_pc = request_debug_mode_r;
assign dpc_ns[31:1] = ( ({31{~dpc_capture_pc & ~dpc_capture_npc & wr_dpc_r}} & dec_csr_wrdata_r[31:1]) |
({31{dpc_capture_pc}} & pc_r[31:1]) |
({31{~dpc_capture_pc & dpc_capture_npc}} & npc_r[31:1]) );
rvdffe #(31) dpc_ff (.*, .en(wr_dpc_r | dpc_capture_pc | dpc_capture_npc), .din(dpc_ns[31:1]), .dout(dpc[31:1]));
// ----------------------------------------------------------------------
// DICAWICS (R/W) (Only accessible in debug mode)
// [31:25] : Reserved
// [24] : Array select, 0 is data, 1 is tag
// [23:22] : Reserved
// [21:20] : Way select
// [19:17] : Reserved
// [16:3] : Index
// [2:0] : Reserved
localparam DICAWICS = 12'h7c8;
assign dicawics_ns[16:0] = {dec_csr_wrdata_r[24], dec_csr_wrdata_r[21:20], dec_csr_wrdata_r[16:3]};
assign wr_dicawics_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAWICS);
rvdffe #(17) dicawics_ff (.*, .en(wr_dicawics_r), .din(dicawics_ns[16:0]), .dout(dicawics[16:0]));
// ----------------------------------------------------------------------
// DICAD0 (R/W) (Only accessible in debug mode)
//
// If dicawics[array] is 0
// [31:0] : inst data
//
// If dicawics[array] is 1
// [31:16] : Tag
// [15:7] : Reserved
// [6:4] : LRU
// [3:1] : Reserved
// [0] : Valid
localparam DICAD0 = 12'h7c9;
assign dicad0_ns[31:0] = wr_dicad0_r ? dec_csr_wrdata_r[31:0] : ifu_ic_debug_rd_data[31:0];
assign wr_dicad0_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAD0);
rvdffe #(32) dicad0_ff (.*, .en(wr_dicad0_r | ifu_ic_debug_rd_data_valid), .din(dicad0_ns[31:0]), .dout(dicad0[31:0]));
// ----------------------------------------------------------------------
// DICAD0H (R/W) (Only accessible in debug mode)
//
// If dicawics[array] is 0
// [63:32] : inst data
//
localparam DICAD0H = 12'h7cc;
assign dicad0h_ns[31:0] = wr_dicad0h_r ? dec_csr_wrdata_r[31:0] : ifu_ic_debug_rd_data[63:32];
assign wr_dicad0h_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAD0H);
rvdffe #(32) dicad0h_ff (.*, .en(wr_dicad0h_r | ifu_ic_debug_rd_data_valid), .din(dicad0h_ns[31:0]), .dout(dicad0h[31:0]));
if (pt.ICACHE_ECC == 1) begin
// ----------------------------------------------------------------------
// DICAD1 (R/W) (Only accessible in debug mode)
// [6:0] : ECC
localparam DICAD1 = 12'h7ca;
assign dicad1_ns[6:0] = wr_dicad1_r ? dec_csr_wrdata_r[6:0] : ifu_ic_debug_rd_data[70:64];
assign wr_dicad1_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAD1);
rvdffe #(.WIDTH(7), .OVERRIDE(1)) dicad1_ff (.*, .en(wr_dicad1_r | ifu_ic_debug_rd_data_valid), .din(dicad1_ns[6:0]), .dout(dicad1_raw[6:0]));
assign dicad1[31:0] = {25'b0, dicad1_raw[6:0]};
end
else begin
// ----------------------------------------------------------------------
// DICAD1 (R/W) (Only accessible in debug mode)
// [3:0] : Parity
localparam DICAD1 = 12'h7ca;
assign dicad1_ns[3:0] = wr_dicad1_r ? dec_csr_wrdata_r[3:0] : ifu_ic_debug_rd_data[67:64];
assign wr_dicad1_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAD1);
rvdffs #(4) dicad1_ff (.*, .clk(free_clk), .en(wr_dicad1_r | ifu_ic_debug_rd_data_valid), .din(dicad1_ns[3:0]), .dout(dicad1_raw[3:0]));
assign dicad1[31:0] = {28'b0, dicad1_raw[3:0]};
end
// ----------------------------------------------------------------------
// DICAGO (R/W) (Only accessible in debug mode)
// [0] : Go
localparam DICAGO = 12'h7cb;
if (pt.ICACHE_ECC == 1)
assign dec_tlu_ic_diag_pkt.icache_wrdata[70:0] = { dicad1[6:0], dicad0h[31:0], dicad0[31:0]};
else
assign dec_tlu_ic_diag_pkt.icache_wrdata[70:0] = {3'b0, dicad1[3:0], dicad0h[31:0], dicad0[31:0]};
assign dec_tlu_ic_diag_pkt.icache_dicawics[16:0] = dicawics[16:0];
assign icache_rd_valid = allow_dbg_halt_csr_write & dec_csr_any_unq_d & dec_i0_decode_d & ~dec_csr_wen_unq_d & (dec_csr_rdaddr_d[11:0] == DICAGO);
assign icache_wr_valid = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAGO);
assign dec_tlu_ic_diag_pkt.icache_rd_valid = icache_rd_valid_f;
assign dec_tlu_ic_diag_pkt.icache_wr_valid = icache_wr_valid_f;
// ----------------------------------------------------------------------
// MTSEL (R/W)
// [1:0] : Trigger select : 00, 01, 10 are data/address triggers. 11 is inst count
localparam MTSEL = 12'h7a0;
assign wr_mtsel_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTSEL);
assign mtsel_ns[1:0] = wr_mtsel_r ? {dec_csr_wrdata_r[1:0]} : mtsel[1:0];
rvdff #(2) mtsel_ff (.*, .clk(csr_wr_clk), .din(mtsel_ns[1:0]), .dout(mtsel[1:0]));
// ----------------------------------------------------------------------
// MTDATA1 (R/W)
// [31:0] : Trigger Data 1
localparam MTDATA1 = 12'h7a1;
// for triggers 0, 1, 2 and 3 aka Match Control
// [31:28] : type, hard coded to 0x2
// [27] : dmode
// [26:21] : hard coded to 0x1f
// [20] : hit
// [19] : select (0 - address, 1 - data)
// [18] : timing, always 'before', reads 0x0
// [17:12] : action, bits [17:13] not implemented and reads 0x0
// [11] : chain
// [10:7] : match, bits [10:8] not implemented and reads 0x0
// [6] : M
// [5:3] : not implemented, reads 0x0
// [2] : execute
// [1] : store
// [0] : load
//
// decoder ring
// [27] : => 9
// [20] : => 8
// [19] : => 7
// [12] : => 6
// [11] : => 5
// [7] : => 4
// [6] : => 3
// [2] : => 2
// [1] : => 1
// [0] : => 0
// don't allow setting load-data.
assign tdata_load = dec_csr_wrdata_r[0] & ~dec_csr_wrdata_r[19];
// don't allow setting execute-data.
assign tdata_opcode = dec_csr_wrdata_r[2] & ~dec_csr_wrdata_r[19];
// don't allow clearing DMODE and action=1
assign tdata_action = (dec_csr_wrdata_r[27] & dbg_tlu_halted_f) & dec_csr_wrdata_r[12];
// Chain bit has conditions: WARL for triggers without chains. Force to zero if dmode is 0 but next trigger dmode is 1.
assign tdata_chain = mtsel[0] ? 1'b0 : // triggers 1 and 3 chain bit is always zero
mtsel[1] ? dec_csr_wrdata_r[11] & ~(mtdata1_t3[MTDATA1_DMODE] & ~dec_csr_wrdata_r[27]) : // trigger 2
dec_csr_wrdata_r[11] & ~(mtdata1_t1[MTDATA1_DMODE] & ~dec_csr_wrdata_r[27]); // trigger 0
// Kill mtdata1 write if dmode=1 but prior trigger has dmode=0/chain=1. Only applies to T1 and T3
assign tdata_kill_write = mtsel[1] ? dec_csr_wrdata_r[27] & (~mtdata1_t2[MTDATA1_DMODE] & mtdata1_t2[MTDATA1_CHAIN]) : // trigger 3
dec_csr_wrdata_r[27] & (~mtdata1_t0[MTDATA1_DMODE] & mtdata1_t0[MTDATA1_CHAIN]) ; // trigger 1
assign tdata_wrdata_r[9:0] = {dec_csr_wrdata_r[27] & dbg_tlu_halted_f,
dec_csr_wrdata_r[20:19],
tdata_action,
tdata_chain,
dec_csr_wrdata_r[7:6],
tdata_opcode,
dec_csr_wrdata_r[1],
tdata_load};
// If the DMODE bit is set, tdata1 can only be updated in debug_mode
assign wr_mtdata1_t0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA1) & (mtsel[1:0] == 2'b0) & (~mtdata1_t0[MTDATA1_DMODE] | dbg_tlu_halted_f);
assign mtdata1_t0_ns[9:0] = wr_mtdata1_t0_r ? tdata_wrdata_r[9:0] :
{mtdata1_t0[9], update_hit_bit_r[0] | mtdata1_t0[8], mtdata1_t0[7:0]};
assign wr_mtdata1_t1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA1) & (mtsel[1:0] == 2'b01) & (~mtdata1_t1[MTDATA1_DMODE] | dbg_tlu_halted_f) & ~tdata_kill_write;
assign mtdata1_t1_ns[9:0] = wr_mtdata1_t1_r ? tdata_wrdata_r[9:0] :
{mtdata1_t1[9], update_hit_bit_r[1] | mtdata1_t1[8], mtdata1_t1[7:0]};
assign wr_mtdata1_t2_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA1) & (mtsel[1:0] == 2'b10) & (~mtdata1_t2[MTDATA1_DMODE] | dbg_tlu_halted_f);
assign mtdata1_t2_ns[9:0] = wr_mtdata1_t2_r ? tdata_wrdata_r[9:0] :
{mtdata1_t2[9], update_hit_bit_r[2] | mtdata1_t2[8], mtdata1_t2[7:0]};
assign wr_mtdata1_t3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA1) & (mtsel[1:0] == 2'b11) & (~mtdata1_t3[MTDATA1_DMODE] | dbg_tlu_halted_f) & ~tdata_kill_write;
assign mtdata1_t3_ns[9:0] = wr_mtdata1_t3_r ? tdata_wrdata_r[9:0] :
{mtdata1_t3[9], update_hit_bit_r[3] | mtdata1_t3[8], mtdata1_t3[7:0]};
rvdffe #(10) mtdata1_t0_ff (.*, .en(trigger_enabled[0] | wr_mtdata1_t0_r), .din(mtdata1_t0_ns[9:0]), .dout(mtdata1_t0[9:0]));
rvdffe #(10) mtdata1_t1_ff (.*, .en(trigger_enabled[1] | wr_mtdata1_t1_r), .din(mtdata1_t1_ns[9:0]), .dout(mtdata1_t1[9:0]));
rvdffe #(10) mtdata1_t2_ff (.*, .en(trigger_enabled[2] | wr_mtdata1_t2_r), .din(mtdata1_t2_ns[9:0]), .dout(mtdata1_t2[9:0]));
rvdffe #(10) mtdata1_t3_ff (.*, .en(trigger_enabled[3] | wr_mtdata1_t3_r), .din(mtdata1_t3_ns[9:0]), .dout(mtdata1_t3[9:0]));
assign mtdata1_tsel_out[31:0] = ( ({32{(mtsel[1:0] == 2'b00)}} & {4'h2, mtdata1_t0[9], 6'b011111, mtdata1_t0[8:7], 6'b0, mtdata1_t0[6:5], 3'b0, mtdata1_t0[4:3], 3'b0, mtdata1_t0[2:0]}) |
({32{(mtsel[1:0] == 2'b01)}} & {4'h2, mtdata1_t1[9], 6'b011111, mtdata1_t1[8:7], 6'b0, mtdata1_t1[6:5], 3'b0, mtdata1_t1[4:3], 3'b0, mtdata1_t1[2:0]}) |
({32{(mtsel[1:0] == 2'b10)}} & {4'h2, mtdata1_t2[9], 6'b011111, mtdata1_t2[8:7], 6'b0, mtdata1_t2[6:5], 3'b0, mtdata1_t2[4:3], 3'b0, mtdata1_t2[2:0]}) |
({32{(mtsel[1:0] == 2'b11)}} & {4'h2, mtdata1_t3[9], 6'b011111, mtdata1_t3[8:7], 6'b0, mtdata1_t3[6:5], 3'b0, mtdata1_t3[4:3], 3'b0, mtdata1_t3[2:0]}));
assign trigger_pkt_any[0].select = mtdata1_t0[MTDATA1_SEL];
assign trigger_pkt_any[0].match = mtdata1_t0[MTDATA1_MATCH];
assign trigger_pkt_any[0].store = mtdata1_t0[MTDATA1_ST];
assign trigger_pkt_any[0].load = mtdata1_t0[MTDATA1_LD];
assign trigger_pkt_any[0].execute = mtdata1_t0[MTDATA1_EXE];
assign trigger_pkt_any[0].m = mtdata1_t0[MTDATA1_M_ENABLED];
assign trigger_pkt_any[1].select = mtdata1_t1[MTDATA1_SEL];
assign trigger_pkt_any[1].match = mtdata1_t1[MTDATA1_MATCH];
assign trigger_pkt_any[1].store = mtdata1_t1[MTDATA1_ST];
assign trigger_pkt_any[1].load = mtdata1_t1[MTDATA1_LD];
assign trigger_pkt_any[1].execute = mtdata1_t1[MTDATA1_EXE];
assign trigger_pkt_any[1].m = mtdata1_t1[MTDATA1_M_ENABLED];
assign trigger_pkt_any[2].select = mtdata1_t2[MTDATA1_SEL];
assign trigger_pkt_any[2].match = mtdata1_t2[MTDATA1_MATCH];
assign trigger_pkt_any[2].store = mtdata1_t2[MTDATA1_ST];
assign trigger_pkt_any[2].load = mtdata1_t2[MTDATA1_LD];
assign trigger_pkt_any[2].execute = mtdata1_t2[MTDATA1_EXE];
assign trigger_pkt_any[2].m = mtdata1_t2[MTDATA1_M_ENABLED];
assign trigger_pkt_any[3].select = mtdata1_t3[MTDATA1_SEL];
assign trigger_pkt_any[3].match = mtdata1_t3[MTDATA1_MATCH];
assign trigger_pkt_any[3].store = mtdata1_t3[MTDATA1_ST];
assign trigger_pkt_any[3].load = mtdata1_t3[MTDATA1_LD];
assign trigger_pkt_any[3].execute = mtdata1_t3[MTDATA1_EXE];
assign trigger_pkt_any[3].m = mtdata1_t3[MTDATA1_M_ENABLED];
// ----------------------------------------------------------------------
// MTDATA2 (R/W)
// [31:0] : Trigger Data 2
localparam MTDATA2 = 12'h7a2;
// If the DMODE bit is set, tdata2 can only be updated in debug_mode
assign wr_mtdata2_t0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA2) & (mtsel[1:0] == 2'b0) & (~mtdata1_t0[MTDATA1_DMODE] | dbg_tlu_halted_f);
assign wr_mtdata2_t1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA2) & (mtsel[1:0] == 2'b01) & (~mtdata1_t1[MTDATA1_DMODE] | dbg_tlu_halted_f);
assign wr_mtdata2_t2_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA2) & (mtsel[1:0] == 2'b10) & (~mtdata1_t2[MTDATA1_DMODE] | dbg_tlu_halted_f);
assign wr_mtdata2_t3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA2) & (mtsel[1:0] == 2'b11) & (~mtdata1_t3[MTDATA1_DMODE] | dbg_tlu_halted_f);
rvdffe #(32) mtdata2_t0_ff (.*, .en(wr_mtdata2_t0_r), .din(dec_csr_wrdata_r[31:0]), .dout(mtdata2_t0[31:0]));
rvdffe #(32) mtdata2_t1_ff (.*, .en(wr_mtdata2_t1_r), .din(dec_csr_wrdata_r[31:0]), .dout(mtdata2_t1[31:0]));
rvdffe #(32) mtdata2_t2_ff (.*, .en(wr_mtdata2_t2_r), .din(dec_csr_wrdata_r[31:0]), .dout(mtdata2_t2[31:0]));
rvdffe #(32) mtdata2_t3_ff (.*, .en(wr_mtdata2_t3_r), .din(dec_csr_wrdata_r[31:0]), .dout(mtdata2_t3[31:0]));
assign mtdata2_tsel_out[31:0] = ( ({32{(mtsel[1:0] == 2'b00)}} & mtdata2_t0[31:0]) |
({32{(mtsel[1:0] == 2'b01)}} & mtdata2_t1[31:0]) |
({32{(mtsel[1:0] == 2'b10)}} & mtdata2_t2[31:0]) |
({32{(mtsel[1:0] == 2'b11)}} & mtdata2_t3[31:0]));
assign trigger_pkt_any[0].tdata2[31:0] = mtdata2_t0[31:0];
assign trigger_pkt_any[1].tdata2[31:0] = mtdata2_t1[31:0];
assign trigger_pkt_any[2].tdata2[31:0] = mtdata2_t2[31:0];
assign trigger_pkt_any[3].tdata2[31:0] = mtdata2_t3[31:0];
//----------------------------------------------------------------------
// Performance Monitor Counters section starts
//----------------------------------------------------------------------
localparam MHPME_NOEVENT = 10'd0;
localparam MHPME_CLK_ACTIVE = 10'd1; // OOP - out of pipe
localparam MHPME_ICACHE_HIT = 10'd2; // OOP
localparam MHPME_ICACHE_MISS = 10'd3; // OOP
localparam MHPME_INST_COMMIT = 10'd4;
localparam MHPME_INST_COMMIT_16B = 10'd5;
localparam MHPME_INST_COMMIT_32B = 10'd6;
localparam MHPME_INST_ALIGNED = 10'd7; // OOP
localparam MHPME_INST_DECODED = 10'd8; // OOP
localparam MHPME_INST_MUL = 10'd9;
localparam MHPME_INST_DIV = 10'd10;
localparam MHPME_INST_LOAD = 10'd11;
localparam MHPME_INST_STORE = 10'd12;
localparam MHPME_INST_MALOAD = 10'd13;
localparam MHPME_INST_MASTORE = 10'd14;
localparam MHPME_INST_ALU = 10'd15;
localparam MHPME_INST_CSRREAD = 10'd16;
localparam MHPME_INST_CSRRW = 10'd17;
localparam MHPME_INST_CSRWRITE = 10'd18;
localparam MHPME_INST_EBREAK = 10'd19;
localparam MHPME_INST_ECALL = 10'd20;
localparam MHPME_INST_FENCE = 10'd21;
localparam MHPME_INST_FENCEI = 10'd22;
localparam MHPME_INST_MRET = 10'd23;
localparam MHPME_INST_BRANCH = 10'd24;
localparam MHPME_BRANCH_MP = 10'd25;
localparam MHPME_BRANCH_TAKEN = 10'd26;
localparam MHPME_BRANCH_NOTP = 10'd27;
localparam MHPME_FETCH_STALL = 10'd28; // OOP
localparam MHPME_DECODE_STALL = 10'd30; // OOP
localparam MHPME_POSTSYNC_STALL = 10'd31; // OOP
localparam MHPME_PRESYNC_STALL = 10'd32; // OOP
localparam MHPME_LSU_SB_WB_STALL = 10'd34; // OOP
localparam MHPME_DMA_DCCM_STALL = 10'd35; // OOP
localparam MHPME_DMA_ICCM_STALL = 10'd36; // OOP
localparam MHPME_EXC_TAKEN = 10'd37;
localparam MHPME_TIMER_INT_TAKEN = 10'd38;
localparam MHPME_EXT_INT_TAKEN = 10'd39;
localparam MHPME_FLUSH_LOWER = 10'd40;
localparam MHPME_BR_ERROR = 10'd41;
localparam MHPME_IBUS_TRANS = 10'd42; // OOP
localparam MHPME_DBUS_TRANS = 10'd43; // OOP
localparam MHPME_DBUS_MA_TRANS = 10'd44; // OOP
localparam MHPME_IBUS_ERROR = 10'd45; // OOP
localparam MHPME_DBUS_ERROR = 10'd46; // OOP
localparam MHPME_IBUS_STALL = 10'd47; // OOP
localparam MHPME_DBUS_STALL = 10'd48; // OOP
localparam MHPME_INT_DISABLED = 10'd49; // OOP
localparam MHPME_INT_STALLED = 10'd50; // OOP
localparam MHPME_INST_BITMANIP = 10'd54;
localparam MHPME_DBUS_LOAD = 10'd55;
localparam MHPME_DBUS_STORE = 10'd56;
// Counts even during sleep state
localparam MHPME_SLEEP_CYC = 10'd512; // OOP
localparam MHPME_DMA_READ_ALL = 10'd513; // OOP
localparam MHPME_DMA_WRITE_ALL = 10'd514; // OOP
localparam MHPME_DMA_READ_DCCM = 10'd515; // OOP
localparam MHPME_DMA_WRITE_DCCM = 10'd516; // OOP
// Pack the event selects into a vector for genvar
assign mhpme_vec[0][9:0] = mhpme3[9:0];
assign mhpme_vec[1][9:0] = mhpme4[9:0];
assign mhpme_vec[2][9:0] = mhpme5[9:0];
assign mhpme_vec[3][9:0] = mhpme6[9:0];
// only consider committed itypes
//logic [3:0] pmu_i0_itype_qual;
assign pmu_i0_itype_qual[3:0] = dec_tlu_packet_r.pmu_i0_itype[3:0] & {4{tlu_i0_commit_cmt}};
// Generate the muxed incs for all counters based on event type
for (genvar i=0 ; i < 4; i++) begin
assign mhpmc_inc_r[i] = {{~mcountinhibit[i+3]}} &
(
({1{(mhpme_vec[i][9:0] == MHPME_CLK_ACTIVE )}} & 1'b1) |
({1{(mhpme_vec[i][9:0] == MHPME_ICACHE_HIT )}} & {ifu_pmu_ic_hit}) |
({1{(mhpme_vec[i][9:0] == MHPME_ICACHE_MISS )}} & {ifu_pmu_ic_miss}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_COMMIT )}} & {tlu_i0_commit_cmt & ~illegal_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_COMMIT_16B )}} & {tlu_i0_commit_cmt & ~exu_pmu_i0_pc4 & ~illegal_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_COMMIT_32B )}} & {tlu_i0_commit_cmt & exu_pmu_i0_pc4 & ~illegal_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_ALIGNED )}} & ifu_pmu_instr_aligned) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_DECODED )}} & dec_pmu_instr_decoded) |
({1{(mhpme_vec[i][9:0] == MHPME_DECODE_STALL )}} & {dec_pmu_decode_stall}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_MUL )}} & {(pmu_i0_itype_qual == MUL)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_DIV )}} & {dec_tlu_packet_r.pmu_divide & tlu_i0_commit_cmt & ~illegal_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_LOAD )}} & {(pmu_i0_itype_qual == LOAD)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_STORE )}} & {(pmu_i0_itype_qual == STORE)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_MALOAD )}} & {(pmu_i0_itype_qual == LOAD)} &
{1{dec_tlu_packet_r.pmu_lsu_misaligned}}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_MASTORE )}} & {(pmu_i0_itype_qual == STORE)} &
{1{dec_tlu_packet_r.pmu_lsu_misaligned}}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_ALU )}} & {(pmu_i0_itype_qual == ALU)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_CSRREAD )}} & {(pmu_i0_itype_qual == CSRREAD)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_CSRWRITE )}} & {(pmu_i0_itype_qual == CSRWRITE)})|
({1{(mhpme_vec[i][9:0] == MHPME_INST_CSRRW )}} & {(pmu_i0_itype_qual == CSRRW)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_EBREAK )}} & {(pmu_i0_itype_qual == EBREAK)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_ECALL )}} & {(pmu_i0_itype_qual == ECALL)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_FENCE )}} & {(pmu_i0_itype_qual == FENCE)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_FENCEI )}} & {(pmu_i0_itype_qual == FENCEI)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_MRET )}} & {(pmu_i0_itype_qual == MRET)}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_BRANCH )}} & {
((pmu_i0_itype_qual == CONDBR) | (pmu_i0_itype_qual == JAL))}) |
({1{(mhpme_vec[i][9:0] == MHPME_BRANCH_MP )}} & {exu_pmu_i0_br_misp & tlu_i0_commit_cmt & ~illegal_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_BRANCH_TAKEN )}} & {exu_pmu_i0_br_ataken & tlu_i0_commit_cmt & ~illegal_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_BRANCH_NOTP )}} & {dec_tlu_packet_r.pmu_i0_br_unpred & tlu_i0_commit_cmt & ~illegal_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_FETCH_STALL )}} & { ifu_pmu_fetch_stall}) |
({1{(mhpme_vec[i][9:0] == MHPME_DECODE_STALL )}} & { dec_pmu_decode_stall}) |
({1{(mhpme_vec[i][9:0] == MHPME_POSTSYNC_STALL )}} & {dec_pmu_postsync_stall}) |
({1{(mhpme_vec[i][9:0] == MHPME_PRESYNC_STALL )}} & {dec_pmu_presync_stall}) |
({1{(mhpme_vec[i][9:0] == MHPME_LSU_SB_WB_STALL )}} & { lsu_store_stall_any}) |
({1{(mhpme_vec[i][9:0] == MHPME_DMA_DCCM_STALL )}} & { dma_dccm_stall_any}) |
({1{(mhpme_vec[i][9:0] == MHPME_DMA_ICCM_STALL )}} & { dma_iccm_stall_any}) |
({1{(mhpme_vec[i][9:0] == MHPME_EXC_TAKEN )}} & { (i0_exception_valid_r | i0_trigger_hit_r | lsu_exc_valid_r)}) |
({1{(mhpme_vec[i][9:0] == MHPME_TIMER_INT_TAKEN )}} & { take_timer_int | take_int_timer0_int | take_int_timer1_int}) |
({1{(mhpme_vec[i][9:0] == MHPME_EXT_INT_TAKEN )}} & { take_ext_int}) |
({1{(mhpme_vec[i][9:0] == MHPME_FLUSH_LOWER )}} & { tlu_flush_lower_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_BR_ERROR )}} & {(dec_tlu_br0_error_r | dec_tlu_br0_start_error_r) & rfpc_i0_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_IBUS_TRANS )}} & {ifu_pmu_bus_trxn}) |
({1{(mhpme_vec[i][9:0] == MHPME_DBUS_TRANS )}} & {lsu_pmu_bus_trxn}) |
({1{(mhpme_vec[i][9:0] == MHPME_DBUS_MA_TRANS )}} & {lsu_pmu_bus_misaligned}) |
({1{(mhpme_vec[i][9:0] == MHPME_IBUS_ERROR )}} & {ifu_pmu_bus_error}) |
({1{(mhpme_vec[i][9:0] == MHPME_DBUS_ERROR )}} & {lsu_pmu_bus_error}) |
({1{(mhpme_vec[i][9:0] == MHPME_IBUS_STALL )}} & {ifu_pmu_bus_busy}) |
({1{(mhpme_vec[i][9:0] == MHPME_DBUS_STALL )}} & {lsu_pmu_bus_busy}) |
({1{(mhpme_vec[i][9:0] == MHPME_INT_DISABLED )}} & {~mstatus[MSTATUS_MIE]}) |
({1{(mhpme_vec[i][9:0] == MHPME_INT_STALLED )}} & {~mstatus[MSTATUS_MIE] & |(mip[5:0] & mie[5:0])}) |
({1{(mhpme_vec[i][9:0] == MHPME_INST_BITMANIP )}} & {(pmu_i0_itype_qual == BITMANIPU)}) |
({1{(mhpme_vec[i][9:0] == MHPME_DBUS_LOAD )}} & {tlu_i0_commit_cmt & lsu_pmu_load_external_r & ~illegal_r}) |
({1{(mhpme_vec[i][9:0] == MHPME_DBUS_STORE )}} & {tlu_i0_commit_cmt & lsu_pmu_store_external_r & ~illegal_r}) |
// These count even during sleep
({1{(mhpme_vec[i][9:0] == MHPME_SLEEP_CYC )}} & {dec_tlu_pmu_fw_halted}) |
({1{(mhpme_vec[i][9:0] == MHPME_DMA_READ_ALL )}} & {dma_pmu_any_read}) |
({1{(mhpme_vec[i][9:0] == MHPME_DMA_WRITE_ALL )}} & {dma_pmu_any_write}) |
({1{(mhpme_vec[i][9:0] == MHPME_DMA_READ_DCCM )}} & {dma_pmu_dccm_read}) |
({1{(mhpme_vec[i][9:0] == MHPME_DMA_WRITE_DCCM )}} & {dma_pmu_dccm_write})
);
end
if(pt.FAST_INTERRUPT_REDIRECT)
rvdffie #(31) mstatus_ff (.*, .clk(free_l2clk),
.din({mdseac_locked_ns, lsu_single_ecc_error_r, lsu_exc_valid_r, lsu_i0_exc_r,
take_ext_int_start, take_ext_int_start_d1, take_ext_int_start_d2, ext_int_freeze,
mip_ns[5:0], mcyclel_cout & ~wr_mcycleh_r & mcyclel_cout_in,
minstret_enable, minstretl_cout_ns, fw_halted_ns,
meicidpl_ns[3:0], icache_rd_valid, icache_wr_valid, mhpmc_inc_r[3:0], perfcnt_halted,
mstatus_ns[1:0]}),
.dout({mdseac_locked_f, lsu_single_ecc_error_r_d1, lsu_exc_valid_r_d1, lsu_i0_exc_r_d1,
take_ext_int_start_d1, take_ext_int_start_d2, take_ext_int_start_d3, ext_int_freeze_d1,
mip[5:0], mcyclel_cout_f, minstret_enable_f, minstretl_cout_f,
fw_halted, meicidpl[3:0], icache_rd_valid_f, icache_wr_valid_f,
mhpmc_inc_r_d1[3:0], perfcnt_halted_d1,
mstatus[1:0]}));
else
rvdffie #(27) mstatus_ff (.*, .clk(free_l2clk),
.din({mdseac_locked_ns, lsu_single_ecc_error_r, lsu_exc_valid_r, lsu_i0_exc_r,
mip_ns[5:0], mcyclel_cout & ~wr_mcycleh_r & mcyclel_cout_in,
minstret_enable, minstretl_cout_ns, fw_halted_ns,
meicidpl_ns[3:0], icache_rd_valid, icache_wr_valid, mhpmc_inc_r[3:0], perfcnt_halted,
mstatus_ns[1:0]}),
.dout({mdseac_locked_f, lsu_single_ecc_error_r_d1, lsu_exc_valid_r_d1, lsu_i0_exc_r_d1,
mip[5:0], mcyclel_cout_f, minstret_enable_f, minstretl_cout_f,
fw_halted, meicidpl[3:0], icache_rd_valid_f, icache_wr_valid_f,
mhpmc_inc_r_d1[3:0], perfcnt_halted_d1,
mstatus[1:0]}));
assign perfcnt_halted = ((dec_tlu_dbg_halted & dcsr[DCSR_STOPC]) | dec_tlu_pmu_fw_halted);
assign perfcnt_during_sleep[3:0] = {4{~(dec_tlu_dbg_halted & dcsr[DCSR_STOPC])}} & {mhpme_vec[3][9],mhpme_vec[2][9],mhpme_vec[1][9],mhpme_vec[0][9]};
assign dec_tlu_perfcnt0 = mhpmc_inc_r_d1[0] & ~(perfcnt_halted_d1 & ~perfcnt_during_sleep[0]);
assign dec_tlu_perfcnt1 = mhpmc_inc_r_d1[1] & ~(perfcnt_halted_d1 & ~perfcnt_during_sleep[1]);
assign dec_tlu_perfcnt2 = mhpmc_inc_r_d1[2] & ~(perfcnt_halted_d1 & ~perfcnt_during_sleep[2]);
assign dec_tlu_perfcnt3 = mhpmc_inc_r_d1[3] & ~(perfcnt_halted_d1 & ~perfcnt_during_sleep[3]);
// ----------------------------------------------------------------------
// MHPMC3H(RW), MHPMC3(RW)
// [63:32][31:0] : Hardware Performance Monitor Counter 3
localparam MHPMC3 = 12'hB03;
localparam MHPMC3H = 12'hB83;
assign mhpmc3_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC3);
assign mhpmc3_wr_en1 = (~perfcnt_halted | perfcnt_during_sleep[0]) & (|(mhpmc_inc_r[0]));
assign mhpmc3_wr_en = mhpmc3_wr_en0 | mhpmc3_wr_en1;
assign mhpmc3_incr[63:0] = {mhpmc3h[31:0],mhpmc3[31:0]} + {63'b0, 1'b1};
assign mhpmc3_ns[31:0] = mhpmc3_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc3_incr[31:0];
rvdffe #(32) mhpmc3_ff (.*, .clk(free_l2clk), .en(mhpmc3_wr_en), .din(mhpmc3_ns[31:0]), .dout(mhpmc3[31:0]));
assign mhpmc3h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC3H);
assign mhpmc3h_wr_en = mhpmc3h_wr_en0 | mhpmc3_wr_en1;
assign mhpmc3h_ns[31:0] = mhpmc3h_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc3_incr[63:32];
rvdffe #(32) mhpmc3h_ff (.*, .clk(free_l2clk), .en(mhpmc3h_wr_en), .din(mhpmc3h_ns[31:0]), .dout(mhpmc3h[31:0]));
// ----------------------------------------------------------------------
// MHPMC4H(RW), MHPMC4(RW)
// [63:32][31:0] : Hardware Performance Monitor Counter 4
localparam MHPMC4 = 12'hB04;
localparam MHPMC4H = 12'hB84;
assign mhpmc4_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC4);
assign mhpmc4_wr_en1 = (~perfcnt_halted | perfcnt_during_sleep[1]) & (|(mhpmc_inc_r[1]));
assign mhpmc4_wr_en = mhpmc4_wr_en0 | mhpmc4_wr_en1;
assign mhpmc4_incr[63:0] = {mhpmc4h[31:0],mhpmc4[31:0]} + {63'b0,1'b1};
assign mhpmc4_ns[31:0] = mhpmc4_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc4_incr[31:0];
rvdffe #(32) mhpmc4_ff (.*, .clk(free_l2clk), .en(mhpmc4_wr_en), .din(mhpmc4_ns[31:0]), .dout(mhpmc4[31:0]));
assign mhpmc4h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC4H);
assign mhpmc4h_wr_en = mhpmc4h_wr_en0 | mhpmc4_wr_en1;
assign mhpmc4h_ns[31:0] = mhpmc4h_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc4_incr[63:32];
rvdffe #(32) mhpmc4h_ff (.*, .clk(free_l2clk), .en(mhpmc4h_wr_en), .din(mhpmc4h_ns[31:0]), .dout(mhpmc4h[31:0]));
// ----------------------------------------------------------------------
// MHPMC5H(RW), MHPMC5(RW)
// [63:32][31:0] : Hardware Performance Monitor Counter 5
localparam MHPMC5 = 12'hB05;
localparam MHPMC5H = 12'hB85;
assign mhpmc5_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC5);
assign mhpmc5_wr_en1 = (~perfcnt_halted | perfcnt_during_sleep[2]) & (|(mhpmc_inc_r[2]));
assign mhpmc5_wr_en = mhpmc5_wr_en0 | mhpmc5_wr_en1;
assign mhpmc5_incr[63:0] = {mhpmc5h[31:0],mhpmc5[31:0]} + {63'b0,1'b1};
assign mhpmc5_ns[31:0] = mhpmc5_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc5_incr[31:0];
rvdffe #(32) mhpmc5_ff (.*, .clk(free_l2clk), .en(mhpmc5_wr_en), .din(mhpmc5_ns[31:0]), .dout(mhpmc5[31:0]));
assign mhpmc5h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC5H);
assign mhpmc5h_wr_en = mhpmc5h_wr_en0 | mhpmc5_wr_en1;
assign mhpmc5h_ns[31:0] = mhpmc5h_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc5_incr[63:32];
rvdffe #(32) mhpmc5h_ff (.*, .clk(free_l2clk), .en(mhpmc5h_wr_en), .din(mhpmc5h_ns[31:0]), .dout(mhpmc5h[31:0]));
// ----------------------------------------------------------------------
// MHPMC6H(RW), MHPMC6(RW)
// [63:32][31:0] : Hardware Performance Monitor Counter 6
localparam MHPMC6 = 12'hB06;
localparam MHPMC6H = 12'hB86;
assign mhpmc6_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC6);
assign mhpmc6_wr_en1 = (~perfcnt_halted | perfcnt_during_sleep[3]) & (|(mhpmc_inc_r[3]));
assign mhpmc6_wr_en = mhpmc6_wr_en0 | mhpmc6_wr_en1;
assign mhpmc6_incr[63:0] = {mhpmc6h[31:0],mhpmc6[31:0]} + {63'b0,1'b1};
assign mhpmc6_ns[31:0] = mhpmc6_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc6_incr[31:0];
rvdffe #(32) mhpmc6_ff (.*, .clk(free_l2clk), .en(mhpmc6_wr_en), .din(mhpmc6_ns[31:0]), .dout(mhpmc6[31:0]));
assign mhpmc6h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC6H);
assign mhpmc6h_wr_en = mhpmc6h_wr_en0 | mhpmc6_wr_en1;
assign mhpmc6h_ns[31:0] = mhpmc6h_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc6_incr[63:32];
rvdffe #(32) mhpmc6h_ff (.*, .clk(free_l2clk), .en(mhpmc6h_wr_en), .din(mhpmc6h_ns[31:0]), .dout(mhpmc6h[31:0]));
// ----------------------------------------------------------------------
// MHPME3(RW)
// [9:0] : Hardware Performance Monitor Event 3
localparam MHPME3 = 12'h323;
// we only have events 0-56 with holes, 512-516, HPME* are WARL so zero otherwise.
assign zero_event_r = ( (dec_csr_wrdata_r[9:0] > 10'd516) |
(|dec_csr_wrdata_r[31:10]) |
((dec_csr_wrdata_r[9:0] < 10'd512) & (dec_csr_wrdata_r[9:0] > 10'd56)) |
((dec_csr_wrdata_r[9:0] < 10'd54) & (dec_csr_wrdata_r[9:0] > 10'd50)) |
(dec_csr_wrdata_r[9:0] == 10'd29) |
(dec_csr_wrdata_r[9:0] == 10'd33)
);
assign event_r[9:0] = zero_event_r ? '0 : dec_csr_wrdata_r[9:0];
assign wr_mhpme3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPME3);
rvdffe #(10) mhpme3_ff (.*, .en(wr_mhpme3_r), .din(event_r[9:0]), .dout(mhpme3[9:0]));
// ----------------------------------------------------------------------
// MHPME4(RW)
// [9:0] : Hardware Performance Monitor Event 4
localparam MHPME4 = 12'h324;
assign wr_mhpme4_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPME4);
rvdffe #(10) mhpme4_ff (.*, .en(wr_mhpme4_r), .din(event_r[9:0]), .dout(mhpme4[9:0]));
// ----------------------------------------------------------------------
// MHPME5(RW)
// [9:0] : Hardware Performance Monitor Event 5
localparam MHPME5 = 12'h325;
assign wr_mhpme5_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPME5);
rvdffe #(10) mhpme5_ff (.*, .en(wr_mhpme5_r), .din(event_r[9:0]), .dout(mhpme5[9:0]));
// ----------------------------------------------------------------------
// MHPME6(RW)
// [9:0] : Hardware Performance Monitor Event 6
localparam MHPME6 = 12'h326;
assign wr_mhpme6_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPME6);
rvdffe #(10) mhpme6_ff (.*, .en(wr_mhpme6_r), .din(event_r[9:0]), .dout(mhpme6[9:0]));
//----------------------------------------------------------------------
// Performance Monitor Counters section ends
//----------------------------------------------------------------------
// ----------------------------------------------------------------------
// MCOUNTINHIBIT(RW)
// [31:7] : Reserved, read 0x0
// [6] : HPM6 disable
// [5] : HPM5 disable
// [4] : HPM4 disable
// [3] : HPM3 disable
// [2] : MINSTRET disable
// [1] : reserved, read 0x0
// [0] : MCYCLE disable
localparam MCOUNTINHIBIT = 12'h320;
assign wr_mcountinhibit_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCOUNTINHIBIT);
rvdffs #(6) mcountinhibit_ff (.*, .clk(csr_wr_clk), .en(wr_mcountinhibit_r), .din({dec_csr_wrdata_r[6:2], dec_csr_wrdata_r[0]}), .dout({mcountinhibit[6:2], mcountinhibit[0]}));
assign mcountinhibit[1] = 1'b0;
//--------------------------------------------------------------------------------
// trace
//--------------------------------------------------------------------------------
logic [4:0] dec_tlu_exc_cause_wb1_raw, dec_tlu_exc_cause_wb2;
logic dec_tlu_int_valid_wb1_raw, dec_tlu_int_valid_wb2;
assign {dec_tlu_i0_valid_wb1,
dec_tlu_i0_exc_valid_wb1,
dec_tlu_exc_cause_wb1_raw[4:0],
dec_tlu_int_valid_wb1_raw} = {8{~dec_tlu_trace_disable}} & {i0_valid_wb,
i0_exception_valid_r_d1 | lsu_i0_exc_r_d1 | (trigger_hit_r_d1 & ~trigger_hit_dmode_r_d1),
exc_cause_wb[4:0],
interrupt_valid_r_d1};
// skid buffer for ints, reduces trace port count by 1
rvdffie #(.WIDTH(6), .OVERRIDE(1)) traceskidff (.*, .clk(clk),
.din ({dec_tlu_exc_cause_wb1_raw[4:0],
dec_tlu_int_valid_wb1_raw}),
.dout({dec_tlu_exc_cause_wb2[4:0],
dec_tlu_int_valid_wb2}));
//skid for ints
assign dec_tlu_exc_cause_wb1[4:0] = dec_tlu_int_valid_wb2 ? dec_tlu_exc_cause_wb2[4:0] : dec_tlu_exc_cause_wb1_raw[4:0];
assign dec_tlu_int_valid_wb1 = dec_tlu_int_valid_wb2;
assign dec_tlu_mtval_wb1 = mtval[31:0];
// end trace
//--------------------------------------------------------------------------------
// ----------------------------------------------------------------------
// CSR read mux
// ----------------------------------------------------------------------
// file "csrdecode" is human readable file that has all of the CSR decodes defined and is part of git repo
// modify this file as needed
// to generate all the equations below from "csrdecode" except legal equation:
// 1) coredecode -in csrdecode > corecsrdecode.e
// 2) espresso -Dso -oeqntott corecsrdecode.e | addassign > csrequations
// to generate the legal CSR equation below:
// 1) coredecode -in csrdecode -legal > csrlegal.e
// 2) espresso -Dso -oeqntott csrlegal.e | addassign > csrlegal_equation
// coredecode -in csrdecode > corecsrdecode.e; espresso -Dso -oeqntott corecsrdecode.e | addassign > csrequations; coredecode -in csrdecode -legal > csrlegal.e; espresso -Dso -oeqntott csrlegal.e | addassign > csrlegal_equation
assign csr_misa = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]);
assign csr_mvendorid = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);
assign csr_marchid = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[7]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mimpid = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);
assign csr_mhartid = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[7]
&dec_csr_rdaddr_d[2]);
assign csr_mstatus = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]);
assign csr_mtvec = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]);
assign csr_mip = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[2]);
assign csr_mie = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]);
assign csr_mcyclel = (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&!dec_csr_rdaddr_d[1]);
assign csr_mcycleh = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);
assign csr_minstretl = (!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_minstreth = (!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mscratch = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mepc = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[1]
&dec_csr_rdaddr_d[0]);
assign csr_mcause = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mscause = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[2]);
assign csr_mtval = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[1]
&dec_csr_rdaddr_d[0]);
assign csr_mrac = (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);
assign csr_dmst = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);
assign csr_mdseac = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]);
assign csr_meihap = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
&dec_csr_rdaddr_d[3]);
assign csr_meivt = (!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
&!dec_csr_rdaddr_d[0]);
assign csr_meipt = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[1]
&dec_csr_rdaddr_d[0]);
assign csr_meicurpl = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[2]);
assign csr_meicidpl = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);
assign csr_dcsr = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[0]);
assign csr_mcgc = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[0]);
assign csr_mfdc = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);
assign csr_dpc = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[0]);
assign csr_mtsel = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mtdata1 = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[0]);
assign csr_mtdata2 = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[1]);
assign csr_mhpmc3 = (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[0]);
assign csr_mhpmc4 = (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mhpmc5 = (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]
&dec_csr_rdaddr_d[0]);
assign csr_mhpmc6 = (!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mhpmc3h = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]
&dec_csr_rdaddr_d[0]);
assign csr_mhpmc4h = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mhpmc5h = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
&dec_csr_rdaddr_d[0]);
assign csr_mhpmc6h = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mhpme3 = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[0]);
assign csr_mhpme4 = (dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
&!dec_csr_rdaddr_d[0]);
assign csr_mhpme5 = (dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
&dec_csr_rdaddr_d[0]);
assign csr_mhpme6 = (dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]
&!dec_csr_rdaddr_d[0]);
assign csr_mcountinhibit = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&!dec_csr_rdaddr_d[0]);
assign csr_mitctl0 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mitctl1 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);
assign csr_mitb0 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]);
assign csr_mitb1 = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mitcnt0 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]);
assign csr_mitcnt1 = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[2]
&!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);
assign csr_mpmc = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]);
assign csr_meicpct = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_micect = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_miccmect = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[0]);
assign csr_mdccmect = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mfdht = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_mfdhs = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[0]);
assign csr_dicawics = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
&!dec_csr_rdaddr_d[0]);
assign csr_dicad0h = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);
assign csr_dicad0 = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]
&dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);
assign csr_dicad1 = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);
assign csr_dicago = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);
assign presync = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[7]
&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[11]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
&!dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (
dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]);
assign postsync = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[10]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[0]) | (
!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[7]
&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]);
assign legal = (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]) | (
!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (
dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
&!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]) | (
dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]) | (!dec_csr_rdaddr_d[11]
&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[2]) | (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (
!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[1]) | (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]
&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]) | (dec_csr_rdaddr_d[11]
&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]) | (
!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]) | (
dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]) | (
dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]
&!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[2]) | (!dec_csr_rdaddr_d[11]
&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[1]) | (
!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[0]) | (
!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[2]) | (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]) | (
dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
&dec_csr_rdaddr_d[1]) | (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]
&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]) | (!dec_csr_rdaddr_d[11]
&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (
!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[3]) | (dec_csr_rdaddr_d[11]
&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[3]) | (
!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
&dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]) | (dec_csr_rdaddr_d[11]
&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]);
assign dec_tlu_presync_d = presync & dec_csr_any_unq_d & ~dec_csr_wen_unq_d;
assign dec_tlu_postsync_d = postsync & dec_csr_any_unq_d;
// allow individual configuration of these features
assign conditionally_illegal = ((csr_mitcnt0 | csr_mitcnt1 | csr_mitb0 | csr_mitb1 | csr_mitctl0 | csr_mitctl1) & !pt.TIMER_LEGAL_EN);
assign valid_csr = ( legal & (~(csr_dcsr | csr_dpc | csr_dmst | csr_dicawics | csr_dicad0 | csr_dicad0h | csr_dicad1 | csr_dicago) | dbg_tlu_halted_f)
& ~fast_int_meicpct & ~conditionally_illegal);
assign dec_csr_legal_d = ( dec_csr_any_unq_d &
valid_csr & // of a valid CSR
~(dec_csr_wen_unq_d & (csr_mvendorid | csr_marchid | csr_mimpid | csr_mhartid | csr_mdseac | csr_meihap)) // that's not a write to a RO CSR
);
// CSR read mux
assign dec_csr_rddata_d[31:0] = ( ({32{csr_misa}} & 32'h40001104) |
({32{csr_mvendorid}} & 32'h00000045) |
({32{csr_marchid}} & 32'h00000010) |
({32{csr_mimpid}} & 32'h3) |
({32{csr_mhartid}} & {core_id[31:4], 4'b0}) |
({32{csr_mstatus}} & {19'b0, 2'b11, 3'b0, mstatus[1], 3'b0, mstatus[0], 3'b0}) |
({32{csr_mtvec}} & {mtvec[30:1], 1'b0, mtvec[0]}) |
({32{csr_mip}} & {1'b0, mip[5:3], 16'b0, mip[2], 3'b0, mip[1], 3'b0, mip[0], 3'b0}) |
({32{csr_mie}} & {1'b0, mie[5:3], 16'b0, mie[2], 3'b0, mie[1], 3'b0, mie[0], 3'b0}) |
({32{csr_mcyclel}} & mcyclel[31:0]) |
({32{csr_mcycleh}} & mcycleh_inc[31:0]) |
({32{csr_minstretl}} & minstretl_read[31:0]) |
({32{csr_minstreth}} & minstreth_read[31:0]) |
({32{csr_mscratch}} & mscratch[31:0]) |
({32{csr_mepc}} & {mepc[31:1], 1'b0}) |
({32{csr_mcause}} & mcause[31:0]) |
({32{csr_mscause}} & {28'b0, mscause[3:0]}) |
({32{csr_mtval}} & mtval[31:0]) |
({32{csr_mrac}} & mrac[31:0]) |
({32{csr_mdseac}} & mdseac[31:0]) |
({32{csr_meivt}} & {meivt[31:10], 10'b0}) |
({32{csr_meihap}} & {meivt[31:10], meihap[9:2], 2'b0}) |
({32{csr_meicurpl}} & {28'b0, meicurpl[3:0]}) |
({32{csr_meicidpl}} & {28'b0, meicidpl[3:0]}) |
({32{csr_meipt}} & {28'b0, meipt[3:0]}) |
({32{csr_mcgc}} & {22'b0, mcgc[9:0]}) |
({32{csr_mfdc}} & {13'b0, mfdc[18:0]}) |
({32{csr_dcsr}} & {16'h4000, dcsr[15:2], 2'b11}) |
({32{csr_dpc}} & {dpc[31:1], 1'b0}) |
({32{csr_dicad0}} & dicad0[31:0]) |
({32{csr_dicad0h}} & dicad0h[31:0]) |
({32{csr_dicad1}} & dicad1[31:0]) |
({32{csr_dicawics}} & {7'b0, dicawics[16], 2'b0, dicawics[15:14], 3'b0, dicawics[13:0], 3'b0}) |
({32{csr_mtsel}} & {30'b0, mtsel[1:0]}) |
({32{csr_mtdata1}} & {mtdata1_tsel_out[31:0]}) |
({32{csr_mtdata2}} & {mtdata2_tsel_out[31:0]}) |
({32{csr_micect}} & {micect[31:0]}) |
({32{csr_miccmect}} & {miccmect[31:0]}) |
({32{csr_mdccmect}} & {mdccmect[31:0]}) |
({32{csr_mhpmc3}} & mhpmc3[31:0]) |
({32{csr_mhpmc4}} & mhpmc4[31:0]) |
({32{csr_mhpmc5}} & mhpmc5[31:0]) |
({32{csr_mhpmc6}} & mhpmc6[31:0]) |
({32{csr_mhpmc3h}} & mhpmc3h[31:0]) |
({32{csr_mhpmc4h}} & mhpmc4h[31:0]) |
({32{csr_mhpmc5h}} & mhpmc5h[31:0]) |
({32{csr_mhpmc6h}} & mhpmc6h[31:0]) |
({32{csr_mfdht}} & {26'b0, mfdht[5:0]}) |
({32{csr_mfdhs}} & {30'b0, mfdhs[1:0]}) |
({32{csr_mhpme3}} & {22'b0,mhpme3[9:0]}) |
({32{csr_mhpme4}} & {22'b0,mhpme4[9:0]}) |
({32{csr_mhpme5}} & {22'b0,mhpme5[9:0]}) |
({32{csr_mhpme6}} & {22'b0,mhpme6[9:0]}) |
({32{csr_mcountinhibit}} & {25'b0, mcountinhibit[6:0]}) |
({32{csr_mpmc}} & {30'b0, mpmc[1], 1'b0}) |
({32{dec_timer_read_d}} & dec_timer_rddata_d[31:0])
);
endmodule // el2_dec_tlu_ctl
module el2_dec_timer_ctl #(
`include "el2_param.vh"
)
(
input logic clk,
input logic free_l2clk,
input logic csr_wr_clk,
input logic rst_l,
input logic dec_csr_wen_r_mod, // csr write enable at wb
input logic [11:0] dec_csr_wraddr_r, // write address for csr
input logic [31:0] dec_csr_wrdata_r, // csr write data at wb
input logic csr_mitctl0,
input logic csr_mitctl1,
input logic csr_mitb0,
input logic csr_mitb1,
input logic csr_mitcnt0,
input logic csr_mitcnt1,
input logic dec_pause_state, // Paused
input logic dec_tlu_pmu_fw_halted, // pmu/fw halted
input logic internal_dbg_halt_timers, // debug halted
output logic [31:0] dec_timer_rddata_d, // timer CSR read data
output logic dec_timer_read_d, // timer CSR address match
output logic dec_timer_t0_pulse, // timer0 int
output logic dec_timer_t1_pulse, // timer1 int
input logic scan_mode
);
localparam MITCTL_ENABLE = 0;
localparam MITCTL_ENABLE_HALTED = 1;
localparam MITCTL_ENABLE_PAUSED = 2;
logic [31:0] mitcnt0_ns, mitcnt0, mitcnt1_ns, mitcnt1, mitb0, mitb1, mitb0_b, mitb1_b, mitcnt0_inc, mitcnt1_inc;
logic [2:0] mitctl0_ns, mitctl0;
logic [3:0] mitctl1_ns, mitctl1;
logic wr_mitcnt0_r, wr_mitcnt1_r, wr_mitb0_r, wr_mitb1_r, wr_mitctl0_r, wr_mitctl1_r;
logic mitcnt0_inc_ok, mitcnt1_inc_ok;
logic mitcnt0_inc_cout, mitcnt1_inc_cout;
logic mit0_match_ns;
logic mit1_match_ns;
logic mitctl0_0_b_ns;
logic mitctl0_0_b;
logic mitctl1_0_b_ns;
logic mitctl1_0_b;
assign mit0_match_ns = (mitcnt0[31:0] >= mitb0[31:0]);
assign mit1_match_ns = (mitcnt1[31:0] >= mitb1[31:0]);
assign dec_timer_t0_pulse = mit0_match_ns;
assign dec_timer_t1_pulse = mit1_match_ns;
// ----------------------------------------------------------------------
// MITCNT0 (RW)
// [31:0] : Internal Timer Counter 0
localparam MITCNT0 = 12'h7d2;
assign wr_mitcnt0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITCNT0);
assign mitcnt0_inc_ok = mitctl0[MITCTL_ENABLE] & (~dec_pause_state | mitctl0[MITCTL_ENABLE_PAUSED]) & (~dec_tlu_pmu_fw_halted | mitctl0[MITCTL_ENABLE_HALTED]) & ~internal_dbg_halt_timers;
assign {mitcnt0_inc_cout, mitcnt0_inc[7:0]} = mitcnt0[7:0] + {7'b0, 1'b1};
assign mitcnt0_inc[31:8] = mitcnt0[31:8] + {23'b0, mitcnt0_inc_cout};
assign mitcnt0_ns[31:0] = wr_mitcnt0_r ? dec_csr_wrdata_r[31:0] : mit0_match_ns ? 'b0 : mitcnt0_inc[31:0];
rvdffe #(24) mitcnt0_ffb (.*, .clk(free_l2clk), .en(wr_mitcnt0_r | (mitcnt0_inc_ok & mitcnt0_inc_cout) | mit0_match_ns), .din(mitcnt0_ns[31:8]), .dout(mitcnt0[31:8]));
rvdffe #(8) mitcnt0_ffa (.*, .clk(free_l2clk), .en(wr_mitcnt0_r | mitcnt0_inc_ok | mit0_match_ns), .din(mitcnt0_ns[7:0]), .dout(mitcnt0[7:0]));
// ----------------------------------------------------------------------
// MITCNT1 (RW)
// [31:0] : Internal Timer Counter 0
localparam MITCNT1 = 12'h7d5;
assign wr_mitcnt1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITCNT1);
assign mitcnt1_inc_ok = mitctl1[MITCTL_ENABLE] &
(~dec_pause_state | mitctl1[MITCTL_ENABLE_PAUSED]) &
(~dec_tlu_pmu_fw_halted | mitctl1[MITCTL_ENABLE_HALTED]) &
~internal_dbg_halt_timers &
(~mitctl1[3] | mit0_match_ns);
// only inc MITCNT1 if not cascaded with 0, or if 0 overflows
assign {mitcnt1_inc_cout, mitcnt1_inc[7:0]} = mitcnt1[7:0] + {7'b0, 1'b1};
assign mitcnt1_inc[31:8] = mitcnt1[31:8] + {23'b0, mitcnt1_inc_cout};
assign mitcnt1_ns[31:0] = wr_mitcnt1_r ? dec_csr_wrdata_r[31:0] : mit1_match_ns ? 'b0 : mitcnt1_inc[31:0];
rvdffe #(24) mitcnt1_ffb (.*, .clk(free_l2clk), .en(wr_mitcnt1_r | (mitcnt1_inc_ok & mitcnt1_inc_cout) | mit1_match_ns), .din(mitcnt1_ns[31:8]), .dout(mitcnt1[31:8]));
rvdffe #(8) mitcnt1_ffa (.*, .clk(free_l2clk), .en(wr_mitcnt1_r | mitcnt1_inc_ok | mit1_match_ns), .din(mitcnt1_ns[7:0]), .dout(mitcnt1[7:0]));
// ----------------------------------------------------------------------
// MITB0 (RW)
// [31:0] : Internal Timer Bound 0
localparam MITB0 = 12'h7d3;
assign wr_mitb0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITB0);
rvdffe #(32) mitb0_ff (.*, .en(wr_mitb0_r), .din(~dec_csr_wrdata_r[31:0]), .dout(mitb0_b[31:0]));
assign mitb0[31:0] = ~mitb0_b[31:0];
// ----------------------------------------------------------------------
// MITB1 (RW)
// [31:0] : Internal Timer Bound 1
localparam MITB1 = 12'h7d6;
assign wr_mitb1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITB1);
rvdffe #(32) mitb1_ff (.*, .en(wr_mitb1_r), .din(~dec_csr_wrdata_r[31:0]), .dout(mitb1_b[31:0]));
assign mitb1[31:0] = ~mitb1_b[31:0];
// ----------------------------------------------------------------------
// MITCTL0 (RW) Internal Timer Ctl 0
// [31:3] : Reserved, reads 0x0
// [2] : Enable while PAUSEd
// [1] : Enable while HALTed
// [0] : Enable (resets to 0x1)
localparam MITCTL0 = 12'h7d4;
assign wr_mitctl0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITCTL0);
assign mitctl0_ns[2:0] = wr_mitctl0_r ? {dec_csr_wrdata_r[2:0]} : {mitctl0[2:0]};
assign mitctl0_0_b_ns = ~mitctl0_ns[0];
rvdffs #(3) mitctl0_ff (.*, .clk(csr_wr_clk), .en(wr_mitctl0_r), .din({mitctl0_ns[2:1], mitctl0_0_b_ns}), .dout({mitctl0[2:1], mitctl0_0_b}));
assign mitctl0[0] = ~mitctl0_0_b;
// ----------------------------------------------------------------------
// MITCTL1 (RW) Internal Timer Ctl 1
// [31:4] : Reserved, reads 0x0
// [3] : Cascade
// [2] : Enable while PAUSEd
// [1] : Enable while HALTed
// [0] : Enable (resets to 0x1)
localparam MITCTL1 = 12'h7d7;
assign wr_mitctl1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITCTL1);
assign mitctl1_ns[3:0] = wr_mitctl1_r ? {dec_csr_wrdata_r[3:0]} : {mitctl1[3:0]};
assign mitctl1_0_b_ns = ~mitctl1_ns[0];
rvdffs #(4) mitctl1_ff (.*, .clk(csr_wr_clk), .en(wr_mitctl1_r), .din({mitctl1_ns[3:1], mitctl1_0_b_ns}), .dout({mitctl1[3:1], mitctl1_0_b}));
assign mitctl1[0] = ~mitctl1_0_b;
assign dec_timer_read_d = csr_mitcnt1 | csr_mitcnt0 | csr_mitb1 | csr_mitb0 | csr_mitctl0 | csr_mitctl1;
assign dec_timer_rddata_d[31:0] = ( ({32{csr_mitcnt0}} & mitcnt0[31:0]) |
({32{csr_mitcnt1}} & mitcnt1[31:0]) |
({32{csr_mitb0}} & mitb0[31:0]) |
({32{csr_mitb1}} & mitb1[31:0]) |
({32{csr_mitctl0}} & {29'b0, mitctl0[2:0]}) |
({32{csr_mitctl1}} & {28'b0, mitctl1[3:0]})
);
endmodule // dec_timer_ctl