// ========== Copyright Header Begin ========================================== // // OpenSPARC T1 Processor File: sparc_ifu_errctl.v // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. // // The above named program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public // License version 2 as published by the Free Software Foundation. // // The above named program is distributed in the hope that it will be // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this work; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. // // ========== Copyright Header End ============================================ //////////////////////////////////////////////////////////////////////// /* // Module Name: sparc_ifu_errctl */ //////////////////////////////////////////////////////////////////////// // Global header file includes //////////////////////////////////////////////////////////////////////// `include "lsu.h" module sparc_ifu_errctl(/*AUTOARG*/ // Outputs erc_erd_pgsz_b0, erc_erd_pgsz_b1, ifu_lsu_asi_rd_unc, ifu_lsu_ldxa_tid_w2, ifu_lsu_ldxa_data_vld_w2, ifu_lsu_fwd_data_vld, ifu_lsu_error_inj, ifu_exu_ecc_mask, ifu_exu_inj_irferr, ifu_ffu_inj_frferr, ifu_exu_nceen_e, ifu_lsu_nceen, ifu_spu_nceen, erb_fcl_spu_uetrap, erb_ifq_itlberr_s1, erb_ifq_ifeterr_d1, erb_dtu_ifeterr_d1, erb_fcl_itlb_ce_d1, erb_fcl_ce_trapvec, erb_fcl_ue_trapvec, erb_fcl_ifet_uevec_d1, erc_erd_errstat_asidata, erc_erd_errinj_asidata, erc_erd_erren_asidata, erc_erd_eadr0_sel_irf_l, erc_erd_eadr0_sel_itlb_l, erc_erd_eadr0_sel_frf_l, erc_erd_eadr0_sel_lsu_l, erc_erd_asiway_s1_l, erc_erd_eadr1_sel_pcd1_l, erc_erd_eadr1_sel_l1pa_l, erc_erd_eadr1_sel_l2pa_l, erc_erd_eadr1_sel_other_l, erc_erd_eadr2_sel_mx1_l, erc_erd_eadr2_sel_wrt_l, erc_erd_eadr2_sel_mx0_l, erc_erd_eadr2_sel_old_l, erc_erd_asi_thr_l, erc_erd_asisrc_sel_icd_s_l, erc_erd_asisrc_sel_misc_s_l, erc_erd_asisrc_sel_err_s_l, erc_erd_asisrc_sel_itlb_s_l, erc_erd_errasi_sel_en_l, erc_erd_errasi_sel_stat_l, erc_erd_errasi_sel_inj_l, erc_erd_errasi_sel_addr_l, erc_erd_miscasi_sel_ict_l, erc_erd_miscasi_sel_imask_l, erc_erd_miscasi_sel_other_l, erc_erd_ld_imask, erb_reset, so, // Inputs rclk, se, si, arst_l, grst_l, erd_erc_tte_pgsz, icv_itlb_valid_f, fcl_erb_ievld_s1, fcl_erb_tevld_s1, fcl_erb_immuevld_s1, fcl_erb_inst_issue_d, fcl_erb_inst_vld_d1, ifu_tlu_inst_vld_w, ifu_lsu_thrid_s, fcl_erb_asi_tid_f, ifq_fcl_asi_tid_bf, fcl_erb_clear_iferr, fcl_erb_itlbrd_vld_s, fcl_erb_itlbrd_data_s, erd_erc_tagpe_s1, erd_erc_nirpe_s1, erd_erc_fetpe_s1, erd_erc_tlbt_pe_s1, erd_erc_tlbd_pe_s1, tlu_lsu_pstate_priv, tlu_hpstate_priv, lsu_ifu_dtlb_data_su, lsu_ifu_dtlb_data_ue, lsu_ifu_dtlb_tag_ue, lsu_ifu_dcache_data_perror, lsu_ifu_dcache_tag_perror, lsu_ifu_l2_unc_error, lsu_ifu_l2_corr_error, lsu_ifu_io_error, lsu_ifu_error_tid, spu_ifu_unc_err_w1, spu_ifu_mamem_err_w1, spu_ifu_corr_err_w2, spu_ifu_int_w2, spu_ifu_ttype_tid_w2, lsu_ifu_inj_ack, ffu_ifu_ecc_ce_w2, ffu_ifu_ecc_ue_w2, ffu_ifu_inj_ack, ffu_ifu_tid_w2, exu_ifu_ecc_ce_m, exu_ifu_ecc_ue_m, exu_ifu_inj_ack, ifq_erb_ue_rep, ifq_erb_ce_rep, ifq_erb_l2_ue, ifq_erb_io_ue, ifq_erb_ifet_ce, ifq_erb_l2err_tid, ifq_erb_rdtag_f, ifq_erb_rdinst_f, ifq_erb_asi_erren_i2, ifq_erb_asi_errstat_i2, ifq_erb_asi_errinj_i2, ifq_erb_asi_erraddr_i2, ifq_erb_asi_imask_i2, ifq_erb_asiwr_i2, ifq_fcl_asird_bf, ifq_erb_fwdrd_bf, ifq_erb_asidata_i2, ifq_erb_asiway_f ); input rclk, se, si, arst_l, grst_l; input [2:0] erd_erc_tte_pgsz; input [3:0] icv_itlb_valid_f; input fcl_erb_ievld_s1, fcl_erb_tevld_s1, fcl_erb_immuevld_s1; input fcl_erb_inst_issue_d; input fcl_erb_inst_vld_d1; input ifu_tlu_inst_vld_w; input [1:0] ifu_lsu_thrid_s, fcl_erb_asi_tid_f, ifq_fcl_asi_tid_bf; input [3:0] fcl_erb_clear_iferr; input fcl_erb_itlbrd_vld_s, fcl_erb_itlbrd_data_s; input [3:0] erd_erc_tagpe_s1; input erd_erc_nirpe_s1, erd_erc_fetpe_s1; input [1:0] erd_erc_tlbt_pe_s1, erd_erc_tlbd_pe_s1; input [3:0] tlu_lsu_pstate_priv; input [3:0] tlu_hpstate_priv; input lsu_ifu_dtlb_data_su, lsu_ifu_dtlb_data_ue, lsu_ifu_dtlb_tag_ue, lsu_ifu_dcache_data_perror, lsu_ifu_dcache_tag_perror, lsu_ifu_l2_unc_error, lsu_ifu_l2_corr_error, lsu_ifu_io_error; input [1:0] lsu_ifu_error_tid; input spu_ifu_unc_err_w1, // 1 cycle earlier for timing reasons spu_ifu_mamem_err_w1,// 1 cycle earlier for timing reasons spu_ifu_corr_err_w2, spu_ifu_int_w2; input [1:0] spu_ifu_ttype_tid_w2; input [3:0] lsu_ifu_inj_ack; input ffu_ifu_ecc_ce_w2; input ffu_ifu_ecc_ue_w2; input ffu_ifu_inj_ack; input [1:0] ffu_ifu_tid_w2; input exu_ifu_ecc_ce_m, exu_ifu_ecc_ue_m; input exu_ifu_inj_ack; input ifq_erb_ue_rep; input ifq_erb_ce_rep; input ifq_erb_l2_ue; input ifq_erb_io_ue; input ifq_erb_ifet_ce; input [1:0] ifq_erb_l2err_tid; input ifq_erb_rdtag_f; input ifq_erb_rdinst_f; input ifq_erb_asi_erren_i2; input ifq_erb_asi_errstat_i2; input ifq_erb_asi_errinj_i2; input ifq_erb_asi_erraddr_i2; input ifq_erb_asi_imask_i2; input ifq_erb_asiwr_i2; input ifq_fcl_asird_bf; input ifq_erb_fwdrd_bf; input [31:0] ifq_erb_asidata_i2; input [1:0] ifq_erb_asiway_f; output erc_erd_pgsz_b0; output erc_erd_pgsz_b1; output ifu_lsu_asi_rd_unc; output [1:0] ifu_lsu_ldxa_tid_w2; output ifu_lsu_ldxa_data_vld_w2; output ifu_lsu_fwd_data_vld; output [3:0] ifu_lsu_error_inj; output [7:0] ifu_exu_ecc_mask; output ifu_exu_inj_irferr; output ifu_ffu_inj_frferr; output ifu_exu_nceen_e; output [3:0] ifu_lsu_nceen; output [3:0] ifu_spu_nceen; // copy going north output [3:0] erb_fcl_spu_uetrap; output erb_ifq_itlberr_s1; output erb_ifq_ifeterr_d1; output erb_dtu_ifeterr_d1; output erb_fcl_itlb_ce_d1; output [3:0] erb_fcl_ce_trapvec; output [3:0] erb_fcl_ue_trapvec; output [3:0] erb_fcl_ifet_uevec_d1; output [22:0] erc_erd_errstat_asidata; output [31:0] erc_erd_errinj_asidata; output [1:0] erc_erd_erren_asidata; // mux selects output [3:0] erc_erd_eadr0_sel_irf_l, erc_erd_eadr0_sel_itlb_l, erc_erd_eadr0_sel_frf_l, erc_erd_eadr0_sel_lsu_l; output [3:0] erc_erd_asiway_s1_l; output [3:0] erc_erd_eadr1_sel_pcd1_l, erc_erd_eadr1_sel_l1pa_l, erc_erd_eadr1_sel_l2pa_l, erc_erd_eadr1_sel_other_l; output [3:0] erc_erd_eadr2_sel_mx1_l, erc_erd_eadr2_sel_wrt_l, erc_erd_eadr2_sel_mx0_l, erc_erd_eadr2_sel_old_l; output [3:0] erc_erd_asi_thr_l; output erc_erd_asisrc_sel_icd_s_l, erc_erd_asisrc_sel_misc_s_l, erc_erd_asisrc_sel_err_s_l, erc_erd_asisrc_sel_itlb_s_l; output erc_erd_errasi_sel_en_l, erc_erd_errasi_sel_stat_l, erc_erd_errasi_sel_inj_l, erc_erd_errasi_sel_addr_l; output erc_erd_miscasi_sel_ict_l, erc_erd_miscasi_sel_imask_l, erc_erd_miscasi_sel_other_l; output erc_erd_ld_imask; output erb_reset, so; // Local Signals wire spu_unc_err_w2, spu_mamem_err_w2; wire lsu_dtlb_data_su, lsu_dtlb_data_ue, lsu_dtlb_tag_ue, lsu_dcache_data_perror, lsu_dcache_tag_perror, lsu_l2_unc_error, lsu_l2_corr_error, lsu_io_error; wire [1:0] lsu_error_tid; wire [3:0] valid_s1; wire [1:0] tid_d, ffu_tid_w3, l2ierr_tid, spu_tid_w2, asi_tid_w2, asi_tid_s1; wire [3:0] thr_e, thr_d, thr_d1, thr_m, thr_w, ffu_thr_w3, asi_thr_s, asi_thr_w2, asi_thr_i2, thr_lsu_err, thr_spu_err, thr_l2ie; wire itlb_feterr_s1, tlb_feterr_d1, itlb_errtr_s1_l, itlb_errtr_d1_l; wire tlb_fet_ce_d1, tlb_fet_ue_d1; wire [3:0] alltag_err_s1; wire itlb_tagerr_s1, itlb_dataerr_s1, insterr_d1, insterr_s1, insterr_qual_d1, ictagerr_s1, ictagerr_d1, ictagerr_qual_d1; wire asi_daterr_d1, asi_tagerr_d1, asi_rd_err_d1; wire asi_ttevld_s1, asi_tdevld_s1; wire [3:0] any_tlbasi_err; wire [3:0] dmdu, dmdu_nxt, dmsu, dmsu_nxt, dmt, dmt_nxt, ddc, ddc_nxt, dtc, dtc_nxt, ldau, ldau_nxt, ncu, ncu_nxt, mau, mau_nxt, any_lsu_err, any_lsu_ue, any_lsu_ce, any_spu_ce, any_spu_ue, imt, imt_nxt, frc, frc_nxt, irc, irc_nxt, fru, fru_nxt, iru, iru_nxt, any_rf_err, any_rf_ce, any_rf_ue, any_irf_err, any_frf_err, idc, idc_nxt, itc, itc_nxt, imdu, imdu_nxt, any_err_vld, any_ue_vld, // any_ce_vld, early_idc, early_idc_nxt, early_itc, early_itc_nxt, early_imdu, early_imdu_nxt, early_ldau, early_ldau_nxt, early_ncu, early_ncu_nxt, early_l2ce, early_l2ce_nxt, any_ifu_ce, any_ifu_ue, any_ifu_err, any_iferr_vld; wire [3:0] meu, meu_nxt, mec, mec_nxt, priv, priv_nxt, early_meu, early_meu_nxt, early_mec, early_mec_nxt, early_priv, early_priv_nxt; wire [22:0] err_stat0, err_stat1, err_stat2, err_stat3; wire [3:0] ifet_ce_vld, ifet_ue_vld; wire [3:0] l2if_unc_err, l2if_corr_err; wire [3:0] ce_trapvec, ue_trapvec, ifu_ce_trap; wire wrt_errinj_i2; wire [7:0] ecc_mask, ecc_mask_nxt; wire [1:0] errinj_ctl, errinj_ctl_nxt; wire [5:0] errinj_vec, errinj_vec_nxt, corr_errinj_vec; // wire [3:0] icache_pa_err_d1; wire irf_ce_w, irf_ce_unq, irf_ue_w, irf_ue_unq; wire [3:0] sel_lsu_err, sel_ifuspu_err, sel_rftlb_err; wire clr_err_qual_e, clr_elyff_e, clr_elyff_m, clr_elyff_w; wire [3:0] early_err_vec_e, clear_ely_reg_w, mov_ely_reg_w; wire [3:0] clear_iferr_d1; wire [1:0] asi_way_s1; wire [3:0] dec_asiway_s1; wire [3:0] asi_wrt_err_stat, asi_wrt_err_en, // asi_wrt_err_inj, asi_wrt_err_addr; wire dmdu_wrt_data, dmsu_wrt_data, imdu_wrt_data, idc_wrt_data, itc_wrt_data, ddc_wrt_data, dtc_wrt_data, imt_wrt_data, dmt_wrt_data, ldau_wrt_data, ncu_wrt_data, mau_wrt_data, fru_wrt_data, frc_wrt_data, iru_wrt_data, irc_wrt_data, meu_wrt_data, mec_wrt_data, priv_wrt_data; wire nceen_wrt_data, ceen_wrt_data; wire [3:0] ceen, ceen_nxt, nceen, nceen_nxt; wire nceen_d; wire rdtag_s, rdinst_s, asi_erren_f, asi_errstat_f, asi_errinj_f, asi_erraddr_f, asi_imask_f, asi_erren_s, asi_errstat_s, asi_errinj_s, asi_erraddr_s, asi_imask_s; wire asird_f, asird_s; wire fwdrd_f, fwdrd_s, asifwd_rd_s, rdinst_f, fwdrd_d; wire ldxa_data_vld_s, ldxa_data_vld_d; wire err_asi_s; wire erb_reset_l; wire ffu_ce_w3; wire ffu_ue_w3; wire [3:0] any_lsu_ue_priv_state; wire [3:0] any_priv_state; wire clk; // // Code Begins Here // assign clk = rclk; // reset buffer dffrl_async rstff(.din (grst_l), .q (erb_reset_l), .clk (clk), .se(se), .si(), .so(), .rst_l (arst_l)); assign erb_reset = ~erb_reset_l; // need to encode page size before sending it back assign erc_erd_pgsz_b0 = (erd_erc_tte_pgsz[2] | erd_erc_tte_pgsz[1] | erd_erc_tte_pgsz[0]); assign erc_erd_pgsz_b1 = (~erd_erc_tte_pgsz[2] & erd_erc_tte_pgsz[1]); // Don't need this with SPARC_HPV_EN // default to tte_lock_d1 = 0 // 05/30/03: tlb correctible errors disabled. // so treat as if lock = 1 and force ue. // dff #(1) lk_ff(.din (erd_erc_tte_lock_s1), // .q (tte_lock_d1), // .clk (clk), .se(se), .si(), .so()); //----------------------- // Basic pipeline signals //----------------------- // thr_s1 also contains asi tid dff_s #(2) tidd_reg(.din (ifu_lsu_thrid_s), .q (tid_d), .clk (clk), .se(se), .si(), .so()); assign thr_d[0] = ~tid_d[1] & ~tid_d[0]; assign thr_d[1] = ~tid_d[1] & tid_d[0]; assign thr_d[2] = tid_d[1] & ~tid_d[0]; assign thr_d[3] = tid_d[1] & tid_d[0]; dff_s #(4) thre_reg(.din (thr_d), .q (thr_e), .clk (clk), .se(se), .si(), .so()); assign thr_d1 = thr_e; dff_s #(4) thrm_reg(.din (thr_e), .q (thr_m), .clk (clk), .se(se), .si(), .so()); dff_s #(4) thrw_reg(.din (thr_m), .q (thr_w), .clk (clk), .se(se), .si(), .so()); //----------------------------- // lsu flops (added for timing) //----------------------------- // all the lsu signals go to the final mux in the errdp, to help // with timing. This is no longer necessary, in fact it is no // longer desired, since we have added the flop below to stage all // the lsu signals. However, the design is not changed, to save // the extra effort in physical composition to rip up the errdp. dff_s #(10) lspipe_reg(.din ({lsu_ifu_dtlb_data_su, lsu_ifu_dtlb_data_ue, lsu_ifu_dtlb_tag_ue, lsu_ifu_dcache_data_perror, lsu_ifu_dcache_tag_perror, lsu_ifu_l2_unc_error, lsu_ifu_l2_corr_error, lsu_ifu_io_error, lsu_ifu_error_tid[1:0]}), .q ({lsu_dtlb_data_su, lsu_dtlb_data_ue, lsu_dtlb_tag_ue, lsu_dcache_data_perror, lsu_dcache_tag_perror, lsu_l2_unc_error, lsu_l2_corr_error, lsu_io_error, lsu_error_tid[1:0]}), .clk (clk), .se(se), .si(), .so()); assign any_priv_state = tlu_lsu_pstate_priv | tlu_hpstate_priv; //Bug 6821: added so that lsu ue's errors pickup the delayed priv level dff_s #(4) lsu_priv_reg(.din (any_priv_state), .q (any_lsu_ue_priv_state), .clk (clk), .se(se), .si(), .so()); // thread from lsu assign thr_lsu_err[0] = ~lsu_error_tid[1] & ~lsu_error_tid[0]; assign thr_lsu_err[1] = ~lsu_error_tid[1] & lsu_error_tid[0]; assign thr_lsu_err[2] = lsu_error_tid[1] & ~lsu_error_tid[0]; assign thr_lsu_err[3] = lsu_error_tid[1] & lsu_error_tid[0]; // thread from spu // From Farnad: tid is ready several cycles before everything else. // In the ifu, I will assume 1 cycle before dff_s #(2) sptid_reg(.din (spu_ifu_ttype_tid_w2), .q (spu_tid_w2), .clk (clk), .se(se), .so(), .si()); dff_s #(2) spe1_reg(.din ({spu_ifu_unc_err_w1, spu_ifu_mamem_err_w1}), .q ({spu_unc_err_w2, spu_mamem_err_w2}), .clk (clk), .se(se), .so(), .si()); assign thr_spu_err[0] = ~spu_tid_w2[1] & ~spu_tid_w2[0]; assign thr_spu_err[1] = ~spu_tid_w2[1] & spu_tid_w2[0]; assign thr_spu_err[2] = spu_tid_w2[1] & ~spu_tid_w2[0]; assign thr_spu_err[3] = spu_tid_w2[1] & spu_tid_w2[0]; // thread from ifq dff_s #(2) ifqthr_reg(.din (ifq_erb_l2err_tid), .q (l2ierr_tid), .clk (clk), .se(se), .so(), .si()); assign thr_l2ie[0] = ~l2ierr_tid[1] & ~l2ierr_tid[0]; assign thr_l2ie[1] = ~l2ierr_tid[1] & l2ierr_tid[0]; assign thr_l2ie[2] = l2ierr_tid[1] & ~l2ierr_tid[0]; assign thr_l2ie[3] = l2ierr_tid[1] & l2ierr_tid[0]; //--------------------------------------- // Error Detection -- icache errors //--------------------------------------- // itlb inst fetch errors assign itlb_feterr_s1 = (erd_erc_tlbd_pe_s1[0] ^ erd_erc_tlbd_pe_s1[1]) & fcl_erb_immuevld_s1; assign erb_ifq_itlberr_s1 = itlb_feterr_s1 & nceen_d; dff_s #(1) itfete_ff(.din (itlb_feterr_s1), .q (tlb_feterr_d1), .clk (clk), .se(se), .si(), .so()); assign itlb_errtr_s1_l = ~erb_ifq_itlberr_s1; dff_s #(1) itume_ff(.din (itlb_errtr_s1_l), .q (itlb_errtr_d1_l), .clk (clk), .se(se), .si(), .so()); // assign tlb_fet_ce_d1 = tlb_feterr_d1 & ~tte_lock_d1; // assign tlb_fet_ue_d1 = tlb_feterr_d1 & tte_lock_d1; assign tlb_fet_ce_d1 = 1'b0; assign tlb_fet_ue_d1 = tlb_feterr_d1; // instruction errors // assign insterr_s1 = (erd_erc_nirpe_s1 | erd_erc_fetpe_s1) & // fcl_erb_ievld_s1; // dff #(1) inserr_ff(.din (insterr_s1), // .q (insterr_d1), // .clk (clk), .se(se), .si(), .so()); assign insterr_s1 = (erd_erc_fetpe_s1 | erd_erc_nirpe_s1) & fcl_erb_ievld_s1; dff_s #(1) feterr_ff(.din (insterr_s1), .q (insterr_d1), .clk (clk), .se(se), .si(), .so()); // dff #(1) nirerr_ff(.din (erd_erc_nirpe_s1), // .q (nirpe_d1), // .clk (clk), .se(se), .si(), .so()); // dff #(1) ievld1_ff(.din (fcl_erb_ievld_s1), // .q (ievld_d1), // .clk (clk), .se(se), .si(), .so()); assign insterr_qual_d1 = insterr_d1 & ~tlb_feterr_d1; // tag errors dff_s #(4) vld_reg(.din (icv_itlb_valid_f), .q (valid_s1), .clk (clk), .se(se), .si(), .so()); assign alltag_err_s1 = erd_erc_tagpe_s1 & valid_s1; assign ictagerr_s1 = (|alltag_err_s1[3:0]) & fcl_erb_tevld_s1; dff_s #(1) itagerr_ff(.din (ictagerr_s1), .q (ictagerr_d1), .clk (clk), .se(se), .si(), .so()); assign ictagerr_qual_d1 = ictagerr_d1 & ~insterr_d1 & ~tlb_feterr_d1; // Corrective action for IFU errors // force an imiss if there is a inst/tag parity error assign erb_ifq_ifeterr_d1 = (ictagerr_d1 | insterr_d1) & itlb_errtr_d1_l; // moved qualification with inst_vld_d1 to the dtu. assign erb_dtu_ifeterr_d1 = erb_ifq_ifeterr_d1; //assign erb_dtu_ifeterr_d1 = erb_ifq_ifeterr_d1 & fcl_erb_inst_vld_d1; // assign icache_pa_err_d1 = {4{ictagerr_d1 | insterr_d1}} & thr_d1; // force a tlbmiss if there is a correctible tlb data parity error assign erb_fcl_itlb_ce_d1 = tlb_fet_ce_d1; // take a precise trap if there is an uncorrectible error assign erb_fcl_ifet_uevec_d1 = ({4{tlb_fet_ue_d1 & fcl_erb_inst_vld_d1}} & thr_d1 | {4{ifq_erb_l2_ue | ifq_erb_io_ue}} & thr_l2ie) & nceen; // errors in ifetch to l2 or iob assign l2if_unc_err = {4{ifq_erb_l2_ue | ifq_erb_io_ue}} & thr_l2ie; assign l2if_corr_err = {4{ifq_erb_ifet_ce}} & thr_l2ie; //------------------------------------- // Error Detection -- itlb asi errors //------------------------------------- assign itlb_tagerr_s1 = (erd_erc_tlbt_pe_s1[0] ^ erd_erc_tlbt_pe_s1[1]) & asi_ttevld_s1; assign itlb_dataerr_s1 = (erd_erc_tlbd_pe_s1[0] ^ erd_erc_tlbd_pe_s1[1]) & asi_tdevld_s1; dff_s #(1) itdate_ff(.din (itlb_dataerr_s1), .q (asi_daterr_d1), .clk (clk), .se(se), .si(), .so()); dff_s #(1) ittage_ff(.din (itlb_tagerr_s1), .q (asi_tagerr_d1), .clk (clk), .se(se), .si(), .so()); assign asi_rd_err_d1 = asi_daterr_d1 | asi_tagerr_d1; assign ifu_lsu_asi_rd_unc = asi_rd_err_d1; assign any_tlbasi_err = {4{asi_rd_err_d1}} & asi_thr_w2; //------------------------------ // RF errors //------------------------------ dff_s #(1) irfu_ff(.din (exu_ifu_ecc_ue_m), .q (irf_ue_unq), .clk (clk), .se (se), .si(), .so()); dff_s #(1) irfc_ff(.din (exu_ifu_ecc_ce_m), .q (irf_ce_unq), .clk (clk), .se (se), .si(), .so()); assign irf_ce_w = irf_ce_unq & ifu_tlu_inst_vld_w; assign irf_ue_w = irf_ue_unq & ifu_tlu_inst_vld_w; //------------------ // Error Logging //------------------ // List of all logged errors // itlbt u // itlbd u/c // ict c // icd c // irf c/u // frf c/u // dtlb d/t u // dct c // dcd c // mau u // l2-d u // l2-i u // dram u -- not any more // io u // // Errors not logged but causing a trap // l2-d c // l2-i c // l2-s c // // latest errors have highest priority // lsu is latest and sometimes asynchronous // spu has low priority // irf/frf are always "current" // ifu errors are speculative ("early") // All lsu errors are prioritised at the source assign dmdu_nxt = {4{lsu_dtlb_data_ue & ~erb_reset}} & thr_lsu_err & ~any_ue_vld | dmdu & ~({4{dmdu_wrt_data}} & asi_wrt_err_stat); // 6310 assign dmsu_nxt = {4{lsu_dtlb_data_su & ~erb_reset}} & thr_lsu_err & ~any_ue_vld | dmsu & ~({4{dmsu_wrt_data}} & asi_wrt_err_stat); assign dmt_nxt = {4{lsu_dtlb_tag_ue & ~erb_reset}} & thr_lsu_err & ~any_ue_vld | dmt & ~({4{dmt_wrt_data}} & asi_wrt_err_stat); assign ddc_nxt = {4{lsu_dcache_data_perror & ~erb_reset}} & thr_lsu_err & ~any_err_vld | ddc & ~({4{ddc_wrt_data}} & asi_wrt_err_stat); assign dtc_nxt = {4{lsu_dcache_tag_perror & ~erb_reset}} & thr_lsu_err & ~any_err_vld | dtc & ~({4{dtc_wrt_data}} & asi_wrt_err_stat); assign ldau_nxt = (mov_ely_reg_w & early_ldau | {4{lsu_l2_unc_error}} & thr_lsu_err | {4{spu_unc_err_w2}} & thr_spu_err) & ~any_ue_vld | ldau & ~({4{ldau_wrt_data}} & asi_wrt_err_stat); assign ncu_nxt = (mov_ely_reg_w & early_ncu | {4{lsu_io_error}} & thr_lsu_err) & ~any_ue_vld | ncu & ~({4{ncu_wrt_data}} & asi_wrt_err_stat); assign any_lsu_ue = thr_lsu_err & {4{lsu_dtlb_data_ue | lsu_dtlb_data_su | lsu_dtlb_tag_ue | lsu_l2_unc_error | lsu_io_error}}; assign any_lsu_ce = thr_lsu_err & {4{(lsu_dcache_data_perror | lsu_dcache_tag_perror | lsu_l2_corr_error) & ~lsu_dtlb_data_ue & ~lsu_dtlb_data_su}}; assign any_lsu_err = (any_lsu_ue | thr_lsu_err & {4{lsu_dcache_data_perror | lsu_dcache_tag_perror}}); // MAmem parity error assign mau_nxt = {4{spu_mamem_err_w2}} & thr_spu_err & ~any_ue_vld | mau & ~({4{mau_wrt_data}} & asi_wrt_err_stat); assign any_spu_ce = {4{spu_ifu_corr_err_w2 & ~spu_unc_err_w2}} & thr_spu_err; assign any_spu_ue = {4{spu_unc_err_w2 | spu_mamem_err_w2}} & thr_spu_err; // tlb asi read error assign imt_nxt = {4{asi_tagerr_d1 & ~erb_reset}} & asi_thr_w2 & ~any_ue_vld | imt & ~({4{imt_wrt_data}} & asi_wrt_err_stat); dff_s #(2) ffu_err_reg(.din ({ffu_ifu_ecc_ce_w2, ffu_ifu_ecc_ue_w2}), .q ({ffu_ce_w3, ffu_ue_w3}), .clk (clk), .se(se), .si(), .so()); dff_s #(2) fptid_reg(.din (ffu_ifu_tid_w2[1:0]), .q (ffu_tid_w3[1:0]), .clk (clk), .se(se), .si(), .so()); assign ffu_thr_w3[0] = ~ffu_tid_w3[1] & ~ffu_tid_w3[0]; assign ffu_thr_w3[1] = ~ffu_tid_w3[1] & ffu_tid_w3[0]; assign ffu_thr_w3[2] = ffu_tid_w3[1] & ~ffu_tid_w3[0]; assign ffu_thr_w3[3] = ffu_tid_w3[1] & ffu_tid_w3[0]; // regfile error //Bug6420: log frc and irc bits as well when fru and iru are detected simulatneously assign frc_nxt = {4{ffu_ce_w3 & ~erb_reset}} & ffu_thr_w3 & ~any_err_vld & ~any_lsu_err | frc & ~({4{frc_wrt_data}} & asi_wrt_err_stat); assign fru_nxt = {4{ffu_ue_w3 & ~erb_reset}} & ffu_thr_w3 & ~any_ue_vld & ~any_lsu_ue | fru & ~({4{fru_wrt_data}} & asi_wrt_err_stat); //Bug6420 assign irc_nxt = {4{irf_ce_w & ~erb_reset}} & thr_w & ~any_err_vld & ~any_lsu_err | irc & ~({4{irc_wrt_data}} & asi_wrt_err_stat); assign iru_nxt = {4{irf_ue_w & ~erb_reset}} & thr_w & ~any_ue_vld & ~any_lsu_ue | iru & ~({4{iru_wrt_data}} & asi_wrt_err_stat); assign any_irf_err = thr_w & {4{irf_ce_w | irf_ue_w}}; assign any_frf_err = ffu_thr_w3 & {4{ffu_ce_w3 | ffu_ue_w3}}; //Bug6420 assign any_rf_ce = thr_w & {4{irf_ce_w}} | ffu_thr_w3 & {4{ffu_ce_w3}}; assign any_rf_ue = thr_w & {4{irf_ue_w}} | ffu_thr_w3 & {4{ffu_ue_w3}}; assign any_rf_err = any_irf_err | any_frf_err; // ifu errors assign idc_nxt = mov_ely_reg_w & ~any_err_vld & early_idc | idc & ~({4{idc_wrt_data}} & asi_wrt_err_stat); assign itc_nxt = mov_ely_reg_w & ~any_err_vld & early_itc | itc & ~({4{itc_wrt_data}} & asi_wrt_err_stat); // bug 6310 assign imdu_nxt = (mov_ely_reg_w & early_imdu | {4{asi_daterr_d1 & ~erb_reset}} & asi_thr_w2) & ~any_ue_vld | imdu & ~({4{imdu_wrt_data}} & asi_wrt_err_stat); // assign imdc_nxt = mov_ely_reg_w & ~any_err_vld & early_imdc | // imdc & ~({4{imdc_wrt_data}} & asi_wrt_err_stat); dff_s #(64) errvec_reg(.din ({imt_nxt, imdu_nxt, idc_nxt, itc_nxt, iru_nxt, irc_nxt, fru_nxt, frc_nxt, dmt_nxt, dmdu_nxt, dmsu_nxt, ddc_nxt, dtc_nxt, ldau_nxt, ncu_nxt, mau_nxt}), .q ({imt, imdu, idc, itc, iru, irc, fru, frc, dmt, dmdu, dmsu, ddc, dtc, ldau, ncu, mau}), .clk (clk), .se (se), .si(), .so()); assign any_err_vld = imt | imdu | idc | itc | iru | irc | fru | frc | dmt | dmdu | dmsu | ddc | dtc | ldau | ncu | mau; assign any_ue_vld = imt | imdu | iru | fru | dmt | dmdu | dmsu | ldau | ncu | mau; // assign any_ce_vld = imdc | idc | itc | irc | frc | // dmdc | ddc | dtc; // IFU errors assign any_ifu_ue = {4{(ifq_erb_l2_ue | ifq_erb_io_ue) & ~erb_reset}} & thr_l2ie | {4{tlb_fet_ue_d1 & ~erb_reset}} & thr_d1; assign any_ifu_ce = {4{ifq_erb_ifet_ce & ~erb_reset}} & thr_l2ie | {4{(tlb_fet_ce_d1 | insterr_qual_d1 | ictagerr_qual_d1) & ~erb_reset}} & thr_d1; assign any_ifu_err = any_ifu_ce | any_ifu_ue; assign ifet_ce_vld = early_idc | early_itc | early_l2ce; assign ifet_ue_vld = early_imdu | early_ldau | early_ncu; // l2ce's are not logged in sparc, so leave them out assign any_iferr_vld = ifet_ue_vld | early_idc | early_itc; // Early errors assign early_idc_nxt = {4{insterr_qual_d1}} & thr_d1 & ~any_iferr_vld & ~any_rf_err & ~any_lsu_err | early_idc & ~clear_iferr_d1 & ~mov_ely_reg_w; assign early_itc_nxt = {4{ictagerr_qual_d1}} & thr_d1 & ~any_iferr_vld & ~any_rf_err & ~any_lsu_err | early_itc & ~clear_iferr_d1 & ~mov_ely_reg_w; assign early_imdu_nxt = {4{tlb_fet_ue_d1}} & thr_d1 & ~ifet_ue_vld & ~any_rf_ue & ~any_lsu_ue | early_imdu & ~clear_iferr_d1 & ~mov_ely_reg_w; // assign early_imdc_nxt = {4{tlb_fet_ce_d1}} & thr_d1 & // ~any_iferr_vld & ~any_rf_err & ~any_lsu_err | // early_imdc & ~clear_iferr_d1 & // ~mov_ely_reg_w; assign early_ldau_nxt = {4{ifq_erb_l2_ue & ~erb_reset}} & thr_l2ie & ~ifet_ue_vld & ~any_rf_ue & ~any_lsu_ue | early_ldau & ~clear_iferr_d1 & ~mov_ely_reg_w; assign early_ncu_nxt = {4{ifq_erb_io_ue & ~erb_reset}} & thr_l2ie & ~ifet_ue_vld & ~any_rf_ue & ~any_lsu_ue | early_ncu & ~clear_iferr_d1 & ~mov_ely_reg_w; assign early_l2ce_nxt = {4{ifq_erb_ifet_ce}} & thr_l2ie & ~any_iferr_vld & ~any_rf_err & ~any_lsu_err | early_l2ce & ~clear_iferr_d1 & ~mov_ely_reg_w; dffr_s #(24) elyerr_reg(.din ({early_idc_nxt, early_itc_nxt, early_imdu_nxt, early_ldau_nxt, early_ncu_nxt, early_l2ce_nxt}), .q ({early_idc, early_itc, early_imdu, early_ldau, early_ncu, early_l2ce}), .clk (clk), .rst (erb_reset), .se (se), .si(), .so()); // Multipl errors assign meu_nxt = any_ue_vld & (any_lsu_ue | any_rf_ue | any_tlbasi_err | any_spu_ue | mov_ely_reg_w & ifet_ue_vld) | // known bug - wontfix // mov_ely_reg_w & early_meu | meu & ~({4{meu_wrt_data}} & asi_wrt_err_stat); assign mec_nxt = any_err_vld & (any_lsu_ce | any_rf_ce | mov_ely_reg_w & ifet_ce_vld) | // known bug - wontfix // mov_ely_reg_w & early_mec | mec & ~({4{mec_wrt_data}} & asi_wrt_err_stat); //Bug6821 assign priv_nxt = ~any_err_vld & (any_lsu_ue_priv_state & any_lsu_ue | any_priv_state & (any_lsu_ce | any_rf_err | any_tlbasi_err) | mov_ely_reg_w & early_priv) | priv & ~({4{priv_wrt_data}} & asi_wrt_err_stat); dffr_s #(12) me_reg(.din ({meu_nxt, mec_nxt, priv_nxt}), .q ({meu, mec, priv}), .clk (clk), .rst (erb_reset), .se (se), .si(), .so()); // Early multiple errors assign early_meu_nxt = any_ifu_ue & ifet_ue_vld | early_meu & ~clear_iferr_d1 & ~mov_ely_reg_w; assign early_mec_nxt = any_ifu_ce & any_iferr_vld | early_mec & ~clear_iferr_d1 & ~mov_ely_reg_w; // bug 6155 & 6821 assign early_priv_nxt = any_priv_state & ~any_iferr_vld & ~any_rf_err & ~any_lsu_err & any_ifu_err | early_priv & ~clear_iferr_d1 & ~mov_ely_reg_w; dffr_s #(12) elyme_reg(.din ({early_meu_nxt, early_mec_nxt, early_priv_nxt}), .q ({early_meu, early_mec, early_priv}), .clk (clk), .rst (erb_reset), .se (se), .si(), .so()); // pipeline progress dff_s #(1) clre_ff(.din (fcl_erb_inst_issue_d), .q (clr_elyff_e), .clk (clk), .se(se), .si(), .so()); assign early_err_vec_e = (any_iferr_vld | early_l2ce) & thr_e; assign clr_err_qual_e = (|early_err_vec_e[3:0]) & clr_elyff_e; dff_s #(1) clrm_ff(.din (clr_err_qual_e), .q (clr_elyff_m), .clk (clk), .se(se), .si(), .so()); dff_s #(1) clrw_ff(.din (clr_elyff_m), .q (clr_elyff_w), .clk (clk), .se(se), .si(), .so()); // fix for 6142 and 6159 // delay err reg clear by one cycle to prevent clearing your own errors dff_s #(4) clree_reg(.din (fcl_erb_clear_iferr), .q (clear_iferr_d1), .clk (clk), .se(se), .si(), .so()); assign clear_ely_reg_w = {4{clr_elyff_w}} & thr_w & (any_iferr_vld | early_l2ce); // why again? assign mov_ely_reg_w = clear_ely_reg_w & {4{ifu_tlu_inst_vld_w & ~erb_reset}}; // asi error status output assign err_stat0 = {meu[0], mec[0], priv[0], 3'b100, // rw, enc, ma imdu[0], imt[0], dmdu[0], dmt[0], idc[0], itc[0], ddc[0], dtc[0], irc[0], iru[0], frc[0], fru[0], ldau[0], ncu[0], dmsu[0], 1'b0, mau[0]}; assign err_stat1 = {meu[1], mec[1], priv[1], 3'b100, imdu[1], imt[1], dmdu[1], dmt[1], idc[1], itc[1], ddc[1], dtc[1], irc[1], iru[1], frc[1], fru[1], ldau[1], ncu[1], dmsu[1], 1'b0, mau[1]}; assign err_stat2 = {meu[2], mec[2], priv[2], 3'b100, imdu[2], imt[2], dmdu[2], dmt[2], idc[2], itc[2], ddc[2], dtc[2], irc[2], iru[2], frc[2], fru[2], ldau[2], ncu[2], dmsu[2], 1'b0, mau[2]}; assign err_stat3 = {meu[3], mec[3], priv[3], 3'b100, imdu[3], imt[3], dmdu[3], dmt[3], idc[3], itc[3], ddc[3], dtc[3], irc[3], iru[3], frc[3], fru[3], ldau[3], ncu[3], dmsu[3], 1'b0, mau[3]}; mux4ds #(23) err_stat_asi(.dout (erc_erd_errstat_asidata), .in0 (err_stat0), .in1 (err_stat1), .in2 (err_stat2), .in3 (err_stat3), .sel0 (asi_thr_s[0]), .sel1 (asi_thr_s[1]), .sel2 (asi_thr_s[2]), .sel3 (asi_thr_s[3])); //---------------------------------- // Error Address Selection //---------------------------------- // TBD: Uncorrectible errors have to overwrite correctible errors // mux 0 // FRF errors are mutex with everything else // ITLB asi errors are mutex with everything else // ASI writes are mutex with everything else // only one of these errors could occur at a given time assign erc_erd_eadr0_sel_lsu_l = ~(sel_lsu_err); assign erc_erd_eadr0_sel_irf_l = ~(~sel_lsu_err & any_irf_err); assign erc_erd_eadr0_sel_itlb_l = ~(~sel_lsu_err & ~any_irf_err & any_tlbasi_err); assign erc_erd_eadr0_sel_frf_l = ~(~sel_lsu_err & ~any_irf_err & ~any_tlbasi_err); // mux 1 // l1 pa and tlb feterr can be simultaneous // TBD: need to reorder and make spu lower priority? assign erc_erd_eadr1_sel_other_l = ~(any_spu_ue); assign erc_erd_eadr1_sel_l2pa_l = ~(~any_spu_ue & (l2if_unc_err | l2if_corr_err)); assign erc_erd_eadr1_sel_pcd1_l = ~(~l2if_unc_err & ~l2if_corr_err & ~any_spu_ue & thr_d1 & {4{tlb_feterr_d1}}); assign erc_erd_eadr1_sel_l1pa_l = ~(~l2if_unc_err & ~l2if_corr_err & ({4{~tlb_feterr_d1}} | ~thr_d1) & ~any_spu_ue); // assign erc_erd_eadr1_sel_other_l = ~(~l2if_unc_err & ~l2if_corr_err & // {4{~tlb_feterr_d1}} & ~icache_pa_err_d1); // mux2 assign sel_lsu_err = ~any_err_vld & any_lsu_err | ~any_ue_vld & any_lsu_ue; assign sel_ifuspu_err = (~any_err_vld & ~any_iferr_vld & any_ifu_err | ~any_ue_vld & any_spu_ue | ~any_ue_vld & ~ifet_ue_vld & any_ifu_ue); assign sel_rftlb_err = ~any_ue_vld & (any_rf_ue | any_tlbasi_err) | ~any_err_vld & any_rf_ce; assign erc_erd_eadr2_sel_wrt_l = ~(asi_wrt_err_addr); assign erc_erd_eadr2_sel_mx0_l = ~(~asi_wrt_err_addr & (sel_lsu_err | sel_rftlb_err)); assign erc_erd_eadr2_sel_mx1_l = ~(~sel_lsu_err & ~asi_wrt_err_addr & ~sel_rftlb_err & sel_ifuspu_err); assign erc_erd_eadr2_sel_old_l = ~(~sel_lsu_err & ~asi_wrt_err_addr & ~sel_rftlb_err & ~sel_ifuspu_err); //----------------------------- // Error Enable Reg //----------------------------- assign nceen_nxt = asi_wrt_err_en & {4{nceen_wrt_data}} | ~asi_wrt_err_en & nceen; assign ceen_nxt = asi_wrt_err_en & {4{ceen_wrt_data}} | ~asi_wrt_err_en & ceen; dffr_s #(8) err_en_reg(.din ({nceen_nxt, ceen_nxt}), .q ({nceen, ceen}), .rst (erb_reset), .clk (clk), .se(se), .si(), .so()); assign nceen_d = (thr_d[0] & nceen[0] | thr_d[1] & nceen[1] | thr_d[2] & nceen[2] | thr_d[3] & nceen[3]); dff_s #(1) nce_ff(.din (nceen_d), .q (ifu_exu_nceen_e), .clk (clk), .se(se), .si(), .so()); assign ifu_lsu_nceen = nceen; assign ifu_spu_nceen = nceen; assign ifu_ce_trap = mov_ely_reg_w & ifet_ce_vld; assign ce_trapvec = (ifu_ce_trap | any_rf_ce | {4{ifq_erb_ce_rep}} & thr_l2ie | any_spu_ce | any_lsu_ce) & ceen; dff_s #(4) ceint_reg(.din (ce_trapvec), .q (erb_fcl_ce_trapvec), .clk (clk), .se(se), .si(), .so()); assign ue_trapvec = ({4{ifq_erb_ue_rep}} & thr_l2ie | any_spu_ue & {4{spu_ifu_int_w2}}) & nceen; assign erb_fcl_spu_uetrap = any_spu_ue & nceen; dff_s #(4) ueint_reg(.din (ue_trapvec), .q (erb_fcl_ue_trapvec), .clk (clk), .se(se), .si(), .so()); mux4ds #(2) err_en_asi(.dout (erc_erd_erren_asidata), .in0 ({nceen[0], ceen[0]}), .in1 ({nceen[1], ceen[1]}), .in2 ({nceen[2], ceen[2]}), .in3 ({nceen[3], ceen[3]}), .sel0 (asi_thr_s[0]), .sel1 (asi_thr_s[1]), .sel2 (asi_thr_s[2]), .sel3 (asi_thr_s[3])); //------------------------- // Error Inject //------------------------- assign wrt_errinj_i2 = (ifq_erb_asi_errinj_i2 & ifq_erb_asiwr_i2); assign ecc_mask_nxt = wrt_errinj_i2 ? ifq_erb_asidata_i2[7:0] : ecc_mask[7:0]; assign errinj_ctl_nxt[1:0] = wrt_errinj_i2 ? ifq_erb_asidata_i2[31:30] : errinj_ctl[1:0]; // correct for single shot assign errinj_vec_nxt[5:0] = wrt_errinj_i2 ? ifq_erb_asidata_i2[29:24] : errinj_ctl[0] ? corr_errinj_vec : errinj_vec; dffr_s #(16) errinj_reg(.din ({errinj_ctl_nxt, errinj_vec_nxt, ecc_mask_nxt}), .q ({errinj_ctl, errinj_vec, ecc_mask}), .rst (erb_reset), .clk (clk), .se (se), .si(), .so()); assign ifu_exu_ecc_mask = ecc_mask; assign ifu_exu_inj_irferr = errinj_vec[1] & errinj_ctl[1]; assign ifu_ffu_inj_frferr = errinj_vec[0] & errinj_ctl[1]; assign ifu_lsu_error_inj[3:0] = errinj_vec[5:2] & {4{errinj_ctl[1]}}; assign corr_errinj_vec[5:0] = errinj_vec[5:0] & ~{lsu_ifu_inj_ack[3:0], exu_ifu_inj_ack, ffu_ifu_inj_ack}; assign erc_erd_errinj_asidata = {errinj_ctl, errinj_vec, 16'b0, ecc_mask}; //-------------------------- // ASI Stuff //-------------------------- dff_s #(2) asiways_reg(.din (ifq_erb_asiway_f), .q (asi_way_s1), .clk (clk), .se(se), .si(), .so()); assign dec_asiway_s1[0] = ~asi_way_s1[1] & ~asi_way_s1[0]; assign dec_asiway_s1[1] = ~asi_way_s1[1] & asi_way_s1[0]; assign dec_asiway_s1[2] = asi_way_s1[1] & ~asi_way_s1[0]; assign dec_asiway_s1[3] = asi_way_s1[1] & asi_way_s1[0]; assign erc_erd_asiway_s1_l = ~dec_asiway_s1; assign asi_thr_i2[0] = ~ifq_fcl_asi_tid_bf[1] & ~ifq_fcl_asi_tid_bf[0]; assign asi_thr_i2[1] = ~ifq_fcl_asi_tid_bf[1] & ifq_fcl_asi_tid_bf[0]; assign asi_thr_i2[2] = ifq_fcl_asi_tid_bf[1] & ~ifq_fcl_asi_tid_bf[0]; assign asi_thr_i2[3] = ifq_fcl_asi_tid_bf[1] & ifq_fcl_asi_tid_bf[0]; dff_s #(2) asi_tids_reg(.din (fcl_erb_asi_tid_f), .q (asi_tid_s1), .clk (clk), .se(se), .si(), .so()); dff_s #(2) asi_tidw2_reg(.din (asi_tid_s1), .q (asi_tid_w2), .clk (clk), .se(se), .si(), .so()); assign ifu_lsu_ldxa_tid_w2 = asi_tid_w2; assign erc_erd_asi_thr_l = ~asi_thr_s; assign asi_thr_s[0] = ~asi_tid_s1[1] & ~asi_tid_s1[0]; assign asi_thr_s[1] = ~asi_tid_s1[1] & asi_tid_s1[0]; assign asi_thr_s[2] = asi_tid_s1[1] & ~asi_tid_s1[0]; assign asi_thr_s[3] = asi_tid_s1[1] & asi_tid_s1[0]; assign asi_thr_w2[0] = ~asi_tid_w2[1] & ~asi_tid_w2[0]; assign asi_thr_w2[1] = ~asi_tid_w2[1] & asi_tid_w2[0]; assign asi_thr_w2[2] = asi_tid_w2[1] & ~asi_tid_w2[0]; assign asi_thr_w2[3] = asi_tid_w2[1] & asi_tid_w2[0]; // F stage flops dff_s #(1) asi_en_ff(.din (ifq_erb_asi_erren_i2), .q (asi_erren_f), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_stat_ff(.din (ifq_erb_asi_errstat_i2), .q (asi_errstat_f), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_addr_ff(.din (ifq_erb_asi_erraddr_i2), .q (asi_erraddr_f), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_inj_ff(.din (ifq_erb_asi_errinj_i2), .q (asi_errinj_f), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_im_ff(.din (ifq_erb_asi_imask_i2), .q (asi_imask_f), .clk (clk), .se(se), .si(), .so()); // S stage Flops dff_s #(1) asi_ens_ff(.din (asi_erren_f), .q (asi_erren_s), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_stats_ff(.din (asi_errstat_f), .q (asi_errstat_s), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_addrs_ff(.din (asi_erraddr_f), .q (asi_erraddr_s), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_injs_ff(.din (asi_errinj_f), .q (asi_errinj_s), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_ims_ff(.din (asi_imask_f), .q (asi_imask_s), .clk (clk), .se(se), .si(), .so()); // ASI Reads // All ASI reads except TLB dff_s #(1) asi_rdf_ff(.din (ifq_fcl_asird_bf), .q (asird_f), .clk (clk), .se(se), .si(), .so()); dff_s #(1) asi_rds_ff(.din (asird_f), .q (asird_s), .clk (clk), .se(se), .si(), .so()); // fwd reads dff_s #(1) fwd_rdf_ff(.din (ifq_erb_fwdrd_bf), .q (fwdrd_f), .clk (clk), .se(se), .si(), .so()); dff_s #(1) fwd_rds_ff(.din (fwdrd_f), .q (fwdrd_s), .clk (clk), .se(se), .si(), .so()); dff_s #(1) fwd_rdd_ff(.din (fwdrd_s), .q (fwdrd_d), .clk (clk), .se(se), .si(), .so()); assign ifu_lsu_fwd_data_vld = fwdrd_d; assign asifwd_rd_s = asird_s | fwdrd_s; // asi reads from icache dff_s #(1) ic_rdts_ff(.din (ifq_erb_rdtag_f), .q (rdtag_s), .clk (clk), .se(se), .si(), .so()); // forward requests also read instruction memory assign rdinst_f = fwdrd_f | ifq_erb_rdinst_f; dff_s #(1) ic_rdds_ff(.din (rdinst_f), .q (rdinst_s), .clk (clk), .se(se), .si(), .so()); // assign rst_tri_en = 1'b0; // pick err asi source assign erc_erd_errasi_sel_en_l = ~asi_erren_s; assign erc_erd_errasi_sel_stat_l = ~asi_errstat_s | asi_erren_s; assign erc_erd_errasi_sel_inj_l = ~asi_errinj_s | asi_errstat_s | asi_erren_s; assign erc_erd_errasi_sel_addr_l = asi_erren_s | asi_errstat_s | asi_errinj_s; assign err_asi_s = (asi_erren_s | asi_errstat_s | asi_errinj_s | asi_erraddr_s); // pick other asi source assign erc_erd_miscasi_sel_ict_l = ~rdtag_s; assign erc_erd_miscasi_sel_imask_l = ~asi_imask_s | rdtag_s; assign erc_erd_miscasi_sel_other_l = rdtag_s | asi_imask_s; // pick source for final asi loads assign erc_erd_asisrc_sel_icd_s_l = ~(asifwd_rd_s & rdinst_s); assign erc_erd_asisrc_sel_err_s_l = ~(asifwd_rd_s & ~rdinst_s & err_asi_s); assign erc_erd_asisrc_sel_misc_s_l = ~(asifwd_rd_s & ~rdinst_s & ~err_asi_s); assign erc_erd_asisrc_sel_itlb_s_l = ~(~asifwd_rd_s); // is this asi read valid (for checking parity) assign asi_ttevld_s1 = fcl_erb_itlbrd_vld_s & ~fcl_erb_itlbrd_data_s; assign asi_tdevld_s1 = fcl_erb_itlbrd_vld_s & fcl_erb_itlbrd_data_s; assign ldxa_data_vld_s = fcl_erb_itlbrd_vld_s | asird_s; // assign ifu_lsu_ldxa_data_vld_w1 = ldxa_data_vld_s; dff_s #(1) asirdd_ff(.din (ldxa_data_vld_s), .q (ldxa_data_vld_d), .clk (clk), .se (se), .si(), .so()); assign ifu_lsu_ldxa_data_vld_w2 = ldxa_data_vld_d; // ASI Writes assign asi_wrt_err_en = asi_thr_i2 & {4{ifq_erb_asiwr_i2 & ifq_erb_asi_erren_i2}}; assign asi_wrt_err_stat = asi_thr_i2 & {4{ifq_erb_asiwr_i2 & ifq_erb_asi_errstat_i2}}; // err inj is common to the core // assign asi_wrt_err_inj = asi_thr_i2 & {4{ifq_erb_asiwr_i2 & // ifq_erb_asi_errinj_i2}}; assign asi_wrt_err_addr = asi_thr_i2 & {4{ifq_erb_asiwr_i2 & ifq_erb_asi_erraddr_i2}}; assign erc_erd_ld_imask = ifq_erb_asiwr_i2 & ifq_erb_asi_imask_i2; // ASI Write Data assign meu_wrt_data = ifq_erb_asidata_i2[31]; assign mec_wrt_data = ifq_erb_asidata_i2[30]; assign priv_wrt_data = ifq_erb_asidata_i2[29]; assign imdu_wrt_data = ifq_erb_asidata_i2[25]; assign imt_wrt_data = ifq_erb_asidata_i2[24]; assign dmdu_wrt_data = ifq_erb_asidata_i2[23]; assign dmt_wrt_data = ifq_erb_asidata_i2[22]; assign idc_wrt_data = ifq_erb_asidata_i2[21]; assign itc_wrt_data = ifq_erb_asidata_i2[20]; assign ddc_wrt_data = ifq_erb_asidata_i2[19]; assign dtc_wrt_data = ifq_erb_asidata_i2[18]; assign irc_wrt_data = ifq_erb_asidata_i2[17]; assign iru_wrt_data = ifq_erb_asidata_i2[16]; assign frc_wrt_data = ifq_erb_asidata_i2[15]; assign fru_wrt_data = ifq_erb_asidata_i2[14]; assign ldau_wrt_data = ifq_erb_asidata_i2[13]; assign ncu_wrt_data = ifq_erb_asidata_i2[12]; assign dmsu_wrt_data = ifq_erb_asidata_i2[11]; assign mau_wrt_data = ifq_erb_asidata_i2[9]; assign nceen_wrt_data = ifq_erb_asidata_i2[1]; assign ceen_wrt_data = ifq_erb_asidata_i2[0]; // sink s0(.in (ifq_erb_asidata_i2[8])); sink s1(.in (ifq_erb_asidata_i2[10])); endmodule