// © IBM Corp. 2020
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by
// the terms below; you may not use the files in this repository except in
// compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
//    1) For the purpose of the patent license granted to you in Section 3 of the
//    License, the "Work" hereby includes implementations of the work of authorship
//    in physical form.
//
//    2) Notwithstanding any terms to the contrary in the License, any licenses
//    necessary for implementation of the Work that are available from OpenPOWER
//    via the Power ISA End User License Agreement (EULA) are explicitly excluded
//    hereunder, and may be obtained from OpenPOWER under the terms and conditions
//    of the EULA.
//
// Unless required by applicable law or agreed to in writing, the reference design
// 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.
//
// Additional rights, including the ability to physically implement a softcore that
// is compliant with the required sections of the Power ISA Specification, are
// available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be
// obtained (along with the Power ISA) here: https://openpowerfoundation.org.

`timescale 1 ns / 1 ns

//********************************************************************
//*
//* TITLE: Instruction Select
//*
//* NAME: iuq_ic_select.v
//*
//*********************************************************************

`include "tri_a2o.vh"

module iuq_ic_select(
   inout                            vdd,
   inout                            gnd,

    (* pin_data ="PIN_FUNCTION=/G_CLK/" *)
   input [0:`NCLK_WIDTH-1]          nclk,
   input                            pc_iu_func_sl_thold_0_b,
   input                            pc_iu_func_slp_sl_thold_0_b,
   input                            pc_iu_sg_0,
   input                            force_t,
   input                            funcslp_force,
   input                            d_mode,
   input                            delay_lclkr,
   input                            mpw1_b,
   input                            mpw2_b,
    (* pin_data ="PIN_FUNCTION=/SCAN_IN/" *)
   input                            func_scan_in,
    (* pin_data ="PIN_FUNCTION=/SCAN_OUT/" *)
   output                           func_scan_out,

   input [0:`THREADS-1]             pc_iu_ram_active,
   input [0:`THREADS-1]             pc_iu_pm_fetch_halt,
   input [0:`THREADS-1]             xu_iu_run_thread,
   input [0:`THREADS-1]             cp_ic_stop,
   input [0:`THREADS-1]             xu_iu_msr_cm,		// 0=32bit, 1=64bit address mode

   input [0:`THREADS-1]             cp_flush,
   input [0:`THREADS-1]             cp_flush_into_uc,
   input [0:`THREADS-1]             br_iu_redirect,
   input [62-`EFF_IFAR_ARCH:61]     br_iu_bta,
   input [62-`EFF_IFAR_ARCH:61]     cp_iu0_t0_flush_ifar,
 `ifndef THREADS1
   input [62-`EFF_IFAR_ARCH:61]     cp_iu0_t1_flush_ifar,
 `endif
   input [0:`THREADS-1]             cp_iu0_flush_2ucode,
   input [0:`THREADS-1]             cp_iu0_flush_2ucode_type,
   input [0:`THREADS-1]             cp_iu0_flush_nonspec,

   output [0:`THREADS-1]            ic_cp_nonspec_hit,

   input                            an_ac_back_inv,		// Arrives 1 cycle before addr
   input [64-`REAL_IFAR_WIDTH:57]   an_ac_back_inv_addr,
   input                            an_ac_back_inv_target,	// connect to bit(0); arrives 1 cycle before addr

   input                            spr_ic_prefetch_dis,
   input                            spr_ic_ierat_byp_dis,

   input                            spr_ic_idir_read,
   input [51:57]                    spr_ic_idir_row,

   output [3:8]                     ic_perf_t0_event,
 `ifndef THREADS1
   output [3:8]                     ic_perf_t1_event,
 `endif

   output                           iu_ierat_iu0_val,
   output [0:`THREADS-1]            iu_ierat_iu0_thdid,
   output [0:51]                    iu_ierat_iu0_ifar,
   output                           iu_ierat_iu0_nonspec,
   output                           iu_ierat_iu0_prefetch,
   output [0:`THREADS-1]            iu_ierat_flush,
   output                           iu_ierat_ium1_back_inv,
   input [0:`THREADS-1]             ierat_iu_hold_req,
   input [0:`THREADS-1]             ierat_iu_iu2_flush_req,
   input                            ierat_iu_iu2_miss,
   input                            ierat_iu_cam_change,

   // MMU Connections
   input [0:`THREADS-1]             mm_iu_hold_req,
   input [0:`THREADS-1]             mm_iu_hold_done,
   input [0:`THREADS-1]             mm_iu_bus_snoop_hold_req,
   input [0:`THREADS-1]             mm_iu_bus_snoop_hold_done,

   // ICBI Interface to IU
   input [0:`THREADS-1]             lq_iu_icbi_val,
   input [64-`REAL_IFAR_WIDTH:57]   lq_iu_icbi_addr,
   output [0:`THREADS-1]            iu_lq_icbi_complete,

   // IU IC Miss
   input [0:`THREADS-1]             icm_ics_iu0_preload_val,
   input [50:59]                    icm_ics_iu0_preload_ifar,
   input [0:`THREADS-1]             icm_ics_prefetch_req,
   input [0:`THREADS-1]             icm_ics_prefetch_sm_idle,

   input [0:`THREADS-1]             icm_ics_hold_thread,
   input                            icm_ics_hold_iu0,
   input                            icm_ics_iu3_miss_match,
   input [0:`THREADS-1]             icm_ics_iu3_ecc_fp_cancel,

   output [46:52]                   ics_icm_iu0_t0_ifar,
 `ifndef THREADS1
   output [46:52]                   ics_icm_iu0_t1_ifar,
 `endif
   output                           ics_icm_iu0_inval,
   output [51:57]                   ics_icm_iu0_inval_addr,
   output [0:`THREADS-1]            ics_icm_iu2_flush,

   // IU IC Dir
   output                           ics_icd_dir_rd_act,
   output [0:1]                     ics_icd_data_rd_act,
   output                           ics_icd_iu0_valid,
   output [0:`THREADS-1]            ics_icd_iu0_tid,
   output [62-`EFF_IFAR_ARCH:61]    ics_icd_iu0_ifar,
   output                           ics_icd_iu0_index51,
   output                           ics_icd_iu0_inval,
   output                           ics_icd_iu0_2ucode,
   output                           ics_icd_iu0_2ucode_type,
   output                           ics_icd_iu0_prefetch,
   output                           ics_icd_iu0_read_erat,
   output                           ics_icd_iu0_spr_idir_read,

   output [0:`THREADS-1]            ics_icd_iu1_flush,
   output [0:`THREADS-1]            ics_icd_iu2_flush,
   input                            icd_ics_iu1_valid,
   input [0:`THREADS-1]             icd_ics_iu1_tid,
   input [62-`EFF_IFAR_WIDTH:61]    icd_ics_iu1_ifar,
   input                            icd_ics_iu1_2ucode,
   input                            icd_ics_iu1_2ucode_type,
   input [0:`THREADS-1]             icd_ics_iu1_read_erat,
   input [0:`THREADS-1]             icd_ics_iu3_miss_flush,
   input [0:`THREADS-1]             icd_ics_iu2_wrong_ra_flush,
   input [0:`THREADS-1]             icd_ics_iu2_cam_etc_flush,
   input [62-`EFF_IFAR_WIDTH:61]    icd_ics_iu2_ifar_eff,
   input                            icd_ics_iu2_2ucode,
   input                            icd_ics_iu2_2ucode_type,
   input                            icd_ics_iu2_valid,
   input [0:`THREADS-1]             icd_ics_iu2_read_erat_error,
   input [0:`THREADS-1]             icd_ics_iu3_parity_flush,
   input [62-`EFF_IFAR_WIDTH:61]    icd_ics_iu3_ifar,
   input                            icd_ics_iu3_2ucode,
   input                            icd_ics_iu3_2ucode_type,

   // BP
   output [0:`THREADS-1]            ic_bp_iu0_val,
   output [50:59]                   ic_bp_iu0_ifar,
   output [0:`THREADS-1]            ic_bp_iu2_flush,

   //iu5 hold/redirect
   input [0:`THREADS-1]             bp_ic_iu2_redirect,
   input [0:`THREADS-1]             bp_ic_iu3_redirect,
   input [0:`THREADS-1]             bp_ic_iu4_redirect,
   input [62-`EFF_IFAR_WIDTH:61]    bp_ic_t0_redirect_ifar,
 `ifndef THREADS1
   input [62-`EFF_IFAR_WIDTH:61]    bp_ic_t1_redirect_ifar,
 `endif

   // ucode
   input [0:`THREADS-1]             uc_ic_hold,
   input [0:`THREADS-1]             uc_iu4_flush,
   input [62-`EFF_IFAR_WIDTH:61]    uc_iu4_t0_flush_ifar,
 `ifndef THREADS1
   input [62-`EFF_IFAR_WIDTH:61]    uc_iu4_t1_flush_ifar,
 `endif

   //Instruction Buffer
 `ifndef THREADS1
   input [0:`IBUFF_DEPTH/4-1]       ib_ic_t1_need_fetch,
 `endif
   input [0:`IBUFF_DEPTH/4-1]       ib_ic_t0_need_fetch,

   input                            event_bus_enable
);

   // iuq_ic_select

   localparam [0:31]               value_1 = 32'h00000001;

   parameter                       an_ac_back_inv_offset = 0;
   parameter                       an_ac_back_inv_target_offset = an_ac_back_inv_offset + 1;
   parameter                       an_ac_back_inv_addr_offset = an_ac_back_inv_target_offset + 1;
   parameter                       spr_idir_read_offset = an_ac_back_inv_addr_offset + `REAL_IFAR_WIDTH - 6;
   parameter                       spr_idir_row_offset = spr_idir_read_offset + 1;
   parameter                       oldest_prefetch_offset = spr_idir_row_offset + 7;
   parameter                       iu0_need_prefetch_offset = oldest_prefetch_offset + `THREADS - 1;
   parameter                       iu0_prefetch_ifar_offset = iu0_need_prefetch_offset + `THREADS;
   parameter                       lq_iu_icbi_val_offset = iu0_prefetch_ifar_offset + (`THREADS) * (`EFF_IFAR_WIDTH - 4);
   parameter                       lq_iu_icbi_addr_offset = lq_iu_icbi_val_offset + `THREADS * `THREADS;		//4
   parameter                       back_inv_offset = lq_iu_icbi_addr_offset + (`THREADS) * (`REAL_IFAR_WIDTH - 6);
   parameter                       back_inv_icbi_offset = back_inv_offset + 1;
   parameter                       xu_iu_msr_cm_offset = back_inv_icbi_offset + `THREADS;
   parameter                       xu_iu_msr_cm2_offset = xu_iu_msr_cm_offset + `THREADS;
   parameter                       xu_iu_msr_cm3_offset = xu_iu_msr_cm2_offset + `THREADS;
   parameter                       xu_iu_run_thread_offset = xu_iu_msr_cm3_offset + `THREADS;
   parameter                       cp_ic_stop_offset = xu_iu_run_thread_offset + `THREADS;		//2
   parameter                       pc_iu_pm_fetch_halt_offset = cp_ic_stop_offset + `THREADS;		//2
   parameter                       ierat_hold_offset = pc_iu_pm_fetch_halt_offset + `THREADS;		//2
   parameter                       iu0_2ucode_offset = ierat_hold_offset + `THREADS;		//2
   parameter                       iu0_2ucode_type_offset = iu0_2ucode_offset + `THREADS;		//2
   parameter                       iu0_flip_index51_offset = iu0_2ucode_type_offset + `THREADS;		//2
   parameter                       iu0_last_tid_sent_offset = iu0_flip_index51_offset + `THREADS;		//2
   parameter                       iu0_sent_offset = iu0_last_tid_sent_offset + 1 * (`THREADS - 1);		//1
   parameter                       iu0_ifar_offset = iu0_sent_offset + `THREADS * 3 * (`IBUFF_DEPTH/4);
   parameter                       stored_erat_ifar_offset = iu0_ifar_offset + `THREADS * `EFF_IFAR_ARCH;
   parameter                       stored_erat_valid_offset = stored_erat_ifar_offset + `THREADS * (`EFF_IFAR_WIDTH - 10);
   parameter                       mm_hold_req_offset = stored_erat_valid_offset + `THREADS;
   parameter                       mm_bus_snoop_hold_req_offset = mm_hold_req_offset + `THREADS;		//2
   parameter                       cp_flush_offset = mm_bus_snoop_hold_req_offset + `THREADS;		//2
   parameter                       cp_flush_into_uc_offset = cp_flush_offset + `THREADS;		//2
   parameter                       cp_flush_ifar_offset = cp_flush_into_uc_offset + `THREADS;		//2
   parameter                       cp_flush_2ucode_offset = cp_flush_ifar_offset + `THREADS * `EFF_IFAR_ARCH;
   parameter                       cp_flush_2ucode_type_offset = cp_flush_2ucode_offset + `THREADS;		//2
   parameter                       cp_flush_nonspec_offset = cp_flush_2ucode_type_offset + `THREADS;		//2
   parameter                       br_iu_redirect_offset = cp_flush_nonspec_offset + `THREADS;		//2
   parameter                       br_iu_bta_offset = br_iu_redirect_offset + `THREADS;		//2
   parameter                       next_fetch_nonspec_offset = br_iu_bta_offset + `EFF_IFAR_ARCH;
   parameter                       iu1_nonspec_offset = next_fetch_nonspec_offset + `THREADS;
   parameter                       iu2_nonspec_offset = iu1_nonspec_offset + `THREADS;
   parameter                       perf_event_offset = iu2_nonspec_offset + `THREADS;
   parameter                       scan_right = perf_event_offset + `THREADS * 6 - 1;

   wire                             tiup;

   // Latch inputs
   wire                             an_ac_back_inv_d;
   wire                             an_ac_back_inv_l2;

   wire                             an_ac_back_inv_target_d;
   wire                             an_ac_back_inv_target_l2;

   wire [64-`REAL_IFAR_WIDTH:57]    an_ac_back_inv_addr_d;
   wire [64-`REAL_IFAR_WIDTH:57]    an_ac_back_inv_addr_l2;

   wire                             spr_idir_read_d;
   wire                             spr_idir_read_l2;

   wire [51:57]                     spr_idir_row_d;
   wire [51:57]                     spr_idir_row_l2;

   wire                             oldest_prefetch_d;
   wire                             oldest_prefetch_l2;

   wire [0:`THREADS-1]              iu0_need_prefetch_d;
   wire [0:`THREADS-1]              iu0_need_prefetch_l2;

   wire [62-`EFF_IFAR_WIDTH:57]     iu0_prefetch_ifar_d[0:`THREADS-1];
   wire [62-`EFF_IFAR_WIDTH:57]     iu0_prefetch_ifar_l2[0:`THREADS-1];

   wire [0:`THREADS*`THREADS-1]     lq_iu_icbi_val_d;		// 2*2
   wire [0:`THREADS*`THREADS-1]     lq_iu_icbi_val_l2;		// 2*2

   wire [64-`REAL_IFAR_WIDTH:57]    lq_iu_icbi_addr_d[0:`THREADS-1];
   wire [64-`REAL_IFAR_WIDTH:57]    lq_iu_icbi_addr_l2[0:`THREADS-1];

   wire                             back_inv_d;
   wire                             back_inv_l2;

   wire [0:`THREADS-1]              back_inv_icbi_d;
   wire [0:`THREADS-1]              back_inv_icbi_l2;

   wire [0:`THREADS-1]              xu_iu_run_thread_d;
   wire [0:`THREADS-1]              xu_iu_run_thread_l2;

   wire [0:`THREADS-1]              xu_iu_msr_cm_d;
   wire [0:`THREADS-1]              xu_iu_msr_cm_l2;

   wire [0:`THREADS-1]              xu_iu_msr_cm2_d;
   wire [0:`THREADS-1]              xu_iu_msr_cm2_l2;

   wire [0:`THREADS-1]              xu_iu_msr_cm3_d;
   wire [0:`THREADS-1]              xu_iu_msr_cm3_l2;

   wire [0:`THREADS-1]              cp_ic_stop_d;
   wire [0:`THREADS-1]              cp_ic_stop_l2;

   wire [0:`THREADS-1]              pc_iu_pm_fetch_halt_d;
   wire [0:`THREADS-1]              pc_iu_pm_fetch_halt_l2;

   wire [0:`THREADS-1]              ierat_hold_d;
   wire [0:`THREADS-1]              ierat_hold_l2;

   // Current IFARs for each of the threads
   reg [62-`EFF_IFAR_ARCH:61]       iu0_ifar_temp[0:`THREADS-1];
   wire [62-`EFF_IFAR_ARCH:61]      iu0_ifar_d[0:`THREADS-1];
   wire [62-`EFF_IFAR_ARCH:61]      iu0_ifar_l2[0:`THREADS-1];

   reg [0:`THREADS-1]               iu0_2ucode_d;
   wire [0:`THREADS-1]              iu0_2ucode_l2;
   reg [0:`THREADS-1]               iu0_2ucode_type_d;
   wire [0:`THREADS-1]              iu0_2ucode_type_l2;

   wire [0:`THREADS-1]              iu0_flip_index51_d;
   wire [0:`THREADS-1]              iu0_flip_index51_l2;

   wire [62-`EFF_IFAR_WIDTH:51]     stored_erat_ifar_d[0:`THREADS-1];
   wire [62-`EFF_IFAR_WIDTH:51]     stored_erat_ifar_l2[0:`THREADS-1];
   wire [0:`THREADS-1]              stored_erat_valid_d;
   wire [0:`THREADS-1]              stored_erat_valid_l2;

   wire [0:`THREADS-1]              mm_hold_req_d;
   wire [0:`THREADS-1]              mm_hold_req_l2;

   wire [0:`THREADS-1]              mm_bus_snoop_hold_req_d;
   wire [0:`THREADS-1]              mm_bus_snoop_hold_req_l2;

   wire [0:`THREADS-1]              cp_flush_l2;
   wire [0:`THREADS-1]              cp_flush_into_uc_l2;
   wire [0:`THREADS-1]              br_iu_redirect_d;
   wire [62-`EFF_IFAR_ARCH:61]      cp_flush_ifar_d[0:`THREADS-1];
   wire [0:`THREADS-1]              br_iu_redirect_l2;
   wire [62-`EFF_IFAR_ARCH:61]      br_iu_bta_l2;
   wire [62-`EFF_IFAR_ARCH:61]      cp_flush_ifar_l2[0:`THREADS-1];
   wire [0:`THREADS-1]              cp_flush_2ucode_l2;
   wire [0:`THREADS-1]              cp_flush_2ucode_type_l2;
   wire [0:`THREADS-1]              cp_flush_nonspec_l2;

   wire [0:`THREADS-1]              next_fetch_nonspec_d;
   wire [0:`THREADS-1]              next_fetch_nonspec_l2;

   wire [0:`THREADS-1]              iu1_nonspec_d;
   wire [0:`THREADS-1]              iu2_nonspec_d;
   wire [0:`THREADS-1]              iu1_nonspec_l2;
   wire [0:`THREADS-1]              iu2_nonspec_l2;

   wire                             iu0_last_tid_sent_d;
   wire                             iu0_last_tid_sent_l2;

   // Used to keep track of the commands in flight to IB
   reg [0:2]                        iu0_sent_d[0:`THREADS-1][0:(`IBUFF_DEPTH/4)-1];
   wire [0:2]                       iu0_sent_l2[0:`THREADS-1][0:(`IBUFF_DEPTH/4)-1];

   wire [3:8]                       perf_event_d[0:`THREADS-1];
   wire [3:8]                       perf_event_l2[0:`THREADS-1];

   wire [62-`EFF_IFAR_WIDTH:61]     bp_ic_redirect_ifar[0:`THREADS-1];
   wire [62-`EFF_IFAR_WIDTH:61]     uc_iu4_flush_ifar[0:`THREADS-1];
   wire [0:`IBUFF_DEPTH/4-1]        ib_ic_need_fetch[0:`THREADS-1];


   wire [62-`EFF_IFAR_WIDTH:57]     new_prefetch_ifar;
   wire                             prefetch_wrap;
   wire [0:`THREADS-1]              msr_cm_changed;
   wire [0:`THREADS-1]              oldest_prefetch_v;
   wire [0:`THREADS-1]              iu2_prefetch_retry;
   wire [0:`THREADS-1]              iu0_prefetch_ifar_act;
   wire [0:`THREADS-1]              prefetch_addr_outside_range;
   wire [0:`THREADS-1]              flush_prefetch;
   wire [0:`THREADS-1]              prefetch_ready;
   wire [0:`THREADS-1]              next_prefetch;
   wire [0:`THREADS-1]              send_prefetch;

   wire                             back_inv_addr_act;

   wire [0:`THREADS-1]              toggle_flip;

   wire [0:`THREADS-1]              iu0_need_new_erat;
   wire [0:`THREADS-1]              clear_erat_valid;
   wire [0:`THREADS-1]              stored_erat_act;
   wire [0:`THREADS-1]              iu0_cross_4k_fetch;
   wire [0:`THREADS-1]              iu0_cross_4k_prefetch;
   wire [0:`THREADS-1]              iu0_cross_4k;
   wire [0:`THREADS-1]              iu0_read_erat;

   wire [0:`THREADS-1]              hold_thread;
   wire [0:`THREADS-1]              hold_thread_perf_lite;
   wire [0:`THREADS-1]              hold_prefetch;
   wire                             iu0_erat_valid;
   wire [0:`THREADS-1]              iu0_erat_tid;

   wire [0:`THREADS-1]              need_fetch_reduce;
   reg [0:(`IBUFF_DEPTH/4)-1]       need_fetch[0:`THREADS-1] /*verilator split_var*/;
   reg [0:(`IBUFF_DEPTH/4)-1]       next_fetch[0:`THREADS-1];
   reg [0:(`IBUFF_DEPTH/4)-2]       shift1_sent[0:`THREADS-1];
   reg [0:`THREADS-1]               shift1_sent_reduce;
   reg [0:(`IBUFF_DEPTH/4)-3]       shift2_sent[0:`THREADS-1];
   reg [0:`THREADS-1]               shift2_sent_reduce;

   reg [0:`THREADS-1]               set_sent;
   wire [0:`THREADS-1]              thread_ready;
   wire                             iu0_valid;
   wire [0:`THREADS-1]              iu0_tid;
   wire [0:`THREADS-1]              iu0_flush;
   wire [0:`THREADS-1]              iu1_flush;
   wire [0:`THREADS-1]              iu2_flush;
   wire [0:`THREADS-1]              iu3_flush;
   wire [0:`THREADS-1]              iu1_ecc_flush;

   wire [0:1]                       data_rd_act;

   wire [62-`EFF_IFAR_ARCH:61]      iu0_ifar;

   wire                             block_spr_idir_read;

   // scan
   wire [0:scan_right]              siv;
   wire [0:scan_right]              sov;

   // BEGIN

   //tidn <= '0';
   assign tiup = 1'b1;

   assign br_iu_redirect_d = br_iu_redirect & (~(cp_flush_l2));

   assign cp_flush_ifar_d[0]     = cp_iu0_t0_flush_ifar;
   assign bp_ic_redirect_ifar[0] = bp_ic_t0_redirect_ifar;
   assign uc_iu4_flush_ifar[0]   = uc_iu4_t0_flush_ifar;
   assign ib_ic_need_fetch[0]    = ib_ic_t0_need_fetch;
  `ifndef THREADS1
     assign cp_flush_ifar_d[1]     = cp_iu0_t1_flush_ifar;
     assign bp_ic_redirect_ifar[1] = bp_ic_t1_redirect_ifar;
     assign uc_iu4_flush_ifar[1]   = uc_iu4_t1_flush_ifar;
     assign ib_ic_need_fetch[1]    = ib_ic_t1_need_fetch;
  `endif

   // Added logic for Erat invalidates
   assign mm_hold_req_d = (mm_iu_hold_req | mm_hold_req_l2) & (~(mm_iu_hold_done));

   assign mm_bus_snoop_hold_req_d = (mm_iu_bus_snoop_hold_req | mm_bus_snoop_hold_req_l2) & (~(mm_iu_bus_snoop_hold_done));

   //---------------------------------------------------------------------
   // SPR IDir Read
   //---------------------------------------------------------------------
   assign block_spr_idir_read = back_inv_l2 | icm_ics_hold_iu0;

   assign spr_idir_read_d = spr_ic_idir_read | (spr_idir_read_l2 & block_spr_idir_read);	// Invalidates & dir writes have priority

   assign spr_idir_row_d = spr_ic_idir_row;

   assign ics_icd_iu0_spr_idir_read = spr_idir_read_l2 & (~block_spr_idir_read);

   //---------------------------------------------------------------------
   // Prefetch
   //---------------------------------------------------------------------
   assign new_prefetch_ifar = icd_ics_iu2_ifar_eff[62 - `EFF_IFAR_WIDTH:57] + value_1[36-`EFF_IFAR_WIDTH:31];	// ??? Need to change if cls = 128 B
   assign prefetch_wrap = ~|(new_prefetch_ifar);

   // Prefetch request based off of old msr_cm value could occur two cycles after change, so need 3 latches
   assign msr_cm_changed = (xu_iu_msr_cm_d ^ xu_iu_msr_cm_l2) |        // prefetch request same cycle or earlier
                           (xu_iu_msr_cm_l2 ^ xu_iu_msr_cm2_l2) |      // prefetch request 1 cycle after change
                           (xu_iu_msr_cm2_l2 ^ xu_iu_msr_cm3_l2);      // prefetch request 2 cycles after change

   // icm_ics_prefetch_req & (ierat_iu_iu2_flush_req and iu2_prefetch) are mutually exclusive,
   // since you cannot have both iu2_valid & iu2_prefetch at the same time
   // Check iu0_need_prefetch=0 to make sure newer prefetch req didn't sneak in last two cycles
   assign oldest_prefetch_d = ((icm_ics_prefetch_req[`THREADS - 1] | iu2_prefetch_retry[0]) == 1'b1) ? 1'b0 : 		// Thread 1 or Thr 0 when single thread
                              ((icm_ics_prefetch_req[0] | iu2_prefetch_retry[`THREADS - 1]) == 1'b1) ? 1'b1 :
                              oldest_prefetch_l2;

   assign oldest_prefetch_v[0] = (~oldest_prefetch_l2);

  `ifndef THREADS1   // THREADS > 1
     assign oldest_prefetch_v[`THREADS - 1] = oldest_prefetch_l2;
  `endif

   generate
   begin : xhdl1
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_prefetch
       assign iu2_prefetch_retry[i] = (ierat_iu_iu2_flush_req[i] | icd_ics_iu2_cam_etc_flush[i]) & (~icd_ics_iu2_valid) & (~iu0_need_prefetch_l2[i]);

       assign iu0_need_prefetch_d[i] = ((icm_ics_prefetch_req[i] & (~prefetch_wrap)) |          // don't wrap around
                                        (iu0_need_prefetch_l2[i] & (~send_prefetch[i]) & (~flush_prefetch[i])) |
                                        (iu2_prefetch_retry[i] & (~flush_prefetch[i])))  &
                                       (~spr_ic_prefetch_dis) & (~msr_cm_changed[i]);

       assign iu0_prefetch_ifar_act[i] = (icm_ics_prefetch_req[i] & (~prefetch_wrap)) | iu2_prefetch_retry[i];

       assign iu0_prefetch_ifar_d[i] = (icd_ics_iu2_valid == 1'b1) ? new_prefetch_ifar :
                                       icd_ics_iu2_ifar_eff[62 - `EFF_IFAR_WIDTH:57]; 	// prefetch collision w/ ierat op (ierat_iu_iu2_flush_req)

       assign prefetch_addr_outside_range[i] = bp_ic_redirect_ifar[i][46:52] != iu0_prefetch_ifar_l2[i][46:52];
       assign flush_prefetch[i] = cp_flush_l2[i] | br_iu_redirect_l2[i] | (bp_ic_iu4_redirect[i] & prefetch_addr_outside_range[i]);
     end
   end
   endgenerate

   assign prefetch_ready = iu0_need_prefetch_l2 & icm_ics_prefetch_sm_idle & (~hold_prefetch);

   assign next_prefetch = ((&(prefetch_ready)) == 1'b1) ? oldest_prefetch_v :   // both are valid, choose oldest
                          prefetch_ready; 		// 1 or 0 are valid

   assign send_prefetch = next_prefetch & (~flush_prefetch);

   //---------------------------------------------------------------------
   // IU0
   //---------------------------------------------------------------------
   assign an_ac_back_inv_d = an_ac_back_inv;
   assign an_ac_back_inv_target_d = an_ac_back_inv_target;
   assign an_ac_back_inv_addr_d = an_ac_back_inv_addr;
   assign back_inv_addr_act = an_ac_back_inv_l2 & an_ac_back_inv_target_l2;

   generate
   begin
     if (`THREADS == 1)
     begin : gen_icbi_val_t1
       assign lq_iu_icbi_val_d[0] = lq_iu_icbi_val[0] | (lq_iu_icbi_val_l2[0] & an_ac_back_inv_l2 & an_ac_back_inv_target_l2);
     end

     // Two-deep buffer, with 2 bits for Thread0&1
     if (`THREADS == 2)
     begin : gen_icbi_val_t2
       assign lq_iu_icbi_val_d[0:`THREADS - 1] = ((an_ac_back_inv_l2 & an_ac_back_inv_target_l2 &
                                                   (|(lq_iu_icbi_val_l2[0:`THREADS - 1]))) == 1'b1) ? lq_iu_icbi_val_l2[0:`THREADS - 1] :
                                                 ((|(lq_iu_icbi_val_l2[2:3])) == 1'b1)              ? lq_iu_icbi_val_l2[2:3] :
                                                                                                      lq_iu_icbi_val;

       assign lq_iu_icbi_val_d[2:3] = (an_ac_back_inv_l2 & an_ac_back_inv_target_l2 & (|(lq_iu_icbi_val_l2[2:3])) == 1'b1)    ? lq_iu_icbi_val_l2[2:3] :
                                      (an_ac_back_inv_l2 & an_ac_back_inv_target_l2 & (|(lq_iu_icbi_val_l2[0:`THREADS - 1])) == 1'b1) ? lq_iu_icbi_val :
                                      2'b00;
     end

     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_icbi_addr
       assign lq_iu_icbi_addr_d[i] = lq_iu_icbi_addr;
     end
   end
   endgenerate

   assign iu_lq_icbi_complete = {`THREADS{~(an_ac_back_inv_l2 & an_ac_back_inv_target_l2)}} & lq_iu_icbi_val_l2[0:`THREADS - 1];

   assign back_inv_d = (an_ac_back_inv_l2 & an_ac_back_inv_target_l2) | (|(lq_iu_icbi_val_l2[0:`THREADS - 1]));
   assign back_inv_icbi_d = {`THREADS{~(an_ac_back_inv_l2 & an_ac_back_inv_target_l2)}} & lq_iu_icbi_val_l2[0:`THREADS - 1];

   assign iu_ierat_ium1_back_inv = back_inv_d;

   assign xu_iu_msr_cm_d = xu_iu_msr_cm;
   assign xu_iu_msr_cm2_d = xu_iu_msr_cm_l2;
   assign xu_iu_msr_cm3_d = xu_iu_msr_cm2_l2;

   assign xu_iu_run_thread_d = xu_iu_run_thread;
   assign cp_ic_stop_d = cp_ic_stop;
   assign pc_iu_pm_fetch_halt_d = pc_iu_pm_fetch_halt;

   assign ierat_hold_d = ierat_iu_hold_req;

   // This keeps track of the commands in flight to IB
   // Note: icm_ics_iu0_preload_val should only be on if hold_thread='1' because of icm_ics_hold_iu0

   //always @(iu0_sent_l2 or ib_ic_need_fetch or iu0_tid or need_fetch or next_fetch or shift1_sent or shift1_sent_reduce or shift2_sent or shift2_sent_reduce or set_sent or iu0_flush or iu1_flush or iu2_flush or icm_ics_iu0_preload_val)
   always @ (*)
   begin: sent_proc
     reg [0:1]          any_sent[0:`THREADS-1];		//(`THREADS)(0 to 1);
     reg                any_lower_fetch;
     // (* analysis_not_referenced="true" *)
     integer  t;
     // (* analysis_not_referenced="true" *)
     integer  i;
     // (* analysis_not_referenced="true" *)
     integer  j;

     for (t = 0; t < `THREADS; t = t + 1)
     begin
       for (i = 0; i < `IBUFF_DEPTH/4; i = i + 1)
         need_fetch[t][i] = ib_ic_need_fetch[t][i] & (~|(iu0_sent_l2[t][i]));

       next_fetch[t][0] = need_fetch[t][0];
       for (i = 1; i < `IBUFF_DEPTH/4; i = i + 1)
       begin
         any_lower_fetch = 0;
         for (j=0; j < i; j = j + 1)
         begin
           any_lower_fetch = need_fetch[t][j] | any_lower_fetch;
         end

         next_fetch[t][i] = need_fetch[t][i] & (~any_lower_fetch);
       end

       // need to shift as buffer gets emptier
       for (i = 0; i < ((`IBUFF_DEPTH/4) - 1); i = i + 1)
         shift1_sent[t][i] = next_fetch[t][i] & (|(iu0_sent_l2[t][i + 1]));
       shift1_sent_reduce[t] = |(shift1_sent[t]);

       for (i = 0; i < ((`IBUFF_DEPTH/4) - 2); i = i + 1)
         shift2_sent[t][i] = next_fetch[t][i] & (|(iu0_sent_l2[t][i + 2]));
       shift2_sent_reduce[t] = |(shift2_sent[t]);

       any_sent[t] = 2'b00;
       for (i = 0; i < `IBUFF_DEPTH/4; i = i + 1)
       begin
         any_sent[t][0] = any_sent[t][0] | iu0_sent_l2[t][i][0];
         any_sent[t][1] = any_sent[t][1] | iu0_sent_l2[t][i][1];
       end

       set_sent[t] = (iu0_tid[t] | icm_ics_iu0_preload_val[t]) & (~iu0_flush[t]);

       for (i = 0; i < `IBUFF_DEPTH/4; i = i + 1)
         iu0_sent_d[t][i] = iu0_sent_l2[t][i];

       if (shift1_sent_reduce[t] == 1'b1)		// shift 1
       begin
         for (i = 0; i < `IBUFF_DEPTH/4; i = i + 1)
         begin
           // swap with current last position
           if (any_sent[t][0] == 1'b1)
             iu0_sent_d[t][i][0] = set_sent[t] & iu0_sent_l2[t][i][0];
           else if (any_sent[t][1] == 1'b1)
             iu0_sent_d[t][i][0] = set_sent[t] & iu0_sent_l2[t][i][1];
           else
             iu0_sent_d[t][i][0] = set_sent[t] & iu0_sent_l2[t][i][2];
         end

         // shift down
         for (i = 0; i < ((`IBUFF_DEPTH/4) - 1); i = i + 1)
         begin
           iu0_sent_d[t][i][1] = iu0_sent_l2[t][i + 1][0] & (~(iu1_flush[t]));
           iu0_sent_d[t][i][2] = iu0_sent_l2[t][i + 1][1] & (~(iu2_flush[t]));
         end
         iu0_sent_d[t][(`IBUFF_DEPTH/4) - 1][1] = 1'b0;
         iu0_sent_d[t][(`IBUFF_DEPTH/4) - 1][2] = 1'b0;
       end

       else if (shift2_sent_reduce[t] == 1'b1)		// shift 2
       begin
         for (i = 0; i < ((`IBUFF_DEPTH/4) - 1); i = i + 1)
         begin
           // swap with current last position & shift down one
           if (any_sent[t][0] == 1'b1)
             iu0_sent_d[t][i][0] = set_sent[t] & iu0_sent_l2[t][i + 1][0];
           else if (any_sent[t][1] == 1'b1)
             iu0_sent_d[t][i][0] = set_sent[t] & iu0_sent_l2[t][i + 1][1];
           else
             iu0_sent_d[t][i][0] = set_sent[t] & iu0_sent_l2[t][i + 1][2];
         end
         iu0_sent_d[t][(`IBUFF_DEPTH/4) - 1][0] = 1'b0;

         // shift down
         for (i = 0; i < ((`IBUFF_DEPTH/4) - 2); i = i + 1)
         begin
           iu0_sent_d[t][i][1] = iu0_sent_l2[t][i + 2][0] & (~(iu1_flush[t]));
           iu0_sent_d[t][i][2] = iu0_sent_l2[t][i + 2][1] & (~(iu2_flush[t]));
         end
         iu0_sent_d[t][(`IBUFF_DEPTH/4) - 1][1] = 1'b0;
         iu0_sent_d[t][(`IBUFF_DEPTH/4) - 1][2] = 1'b0;

         iu0_sent_d[t][(`IBUFF_DEPTH/4) - 2][1] = 1'b0;
         iu0_sent_d[t][(`IBUFF_DEPTH/4) - 2][2] = 1'b0;
       end

       else
       begin
         // no shifting
         for (i = 0; i < `IBUFF_DEPTH/4; i = i + 1)
         begin
           iu0_sent_d[t][i][0] = set_sent[t] & next_fetch[t][i];
                      //(next_fetch(i) and not(hold_thread) and not(iu0_flush)) or
                      //(next_load(i) and not (iu0_flush));
           iu0_sent_d[t][i][1] = iu0_sent_l2[t][i][0] & (~(iu1_flush[t]));
           iu0_sent_d[t][i][2] = iu0_sent_l2[t][i][1] & (~(iu2_flush[t]));
         end
       end
     end  // t loop
   end

   assign thread_ready = need_fetch_reduce & (~hold_thread);

  `ifdef THREADS1             //(`THREADS == 1)
      assign iu0_tid[0] = thread_ready[0];
  `endif
  `ifndef THREADS1            //(`THREADS == 2)
      assign iu0_tid[0] = thread_ready[0] & ((iu0_last_tid_sent_l2 == 1'b1) | ((~thread_ready[1])));
      assign iu0_tid[1] = thread_ready[1] & ((iu0_last_tid_sent_l2 == 1'b0) | ((~thread_ready[0])));
  `endif

   assign iu0_last_tid_sent_d = (iu0_valid == 1'b1) ? iu0_tid[`THREADS - 1] :
                                                      iu0_last_tid_sent_l2;

   // We drop hold thread on the last beat of data, so there's 1 cycle where we might have sent the next ifar
   assign iu1_ecc_flush = {`THREADS{icd_ics_iu1_valid}} & icd_ics_iu1_tid & icm_ics_iu3_ecc_fp_cancel;

   always @ (*)
   begin: iu0_ifar_proc
      //(* analysis_not_referenced="true" *)
      integer  i;

      iu0_2ucode_d = iu0_2ucode_l2;
      iu0_2ucode_type_d = iu0_2ucode_type_l2;

      for (i = 0; i < `THREADS; i = i + 1)
      begin
         iu0_ifar_temp[i] = iu0_ifar_l2[i];

         if ((cp_flush_l2[i] == 1'b1) & (cp_flush_into_uc_l2[i] == 1'b0))
         begin
            iu0_ifar_temp[i] = cp_flush_ifar_l2[i];
            iu0_2ucode_d[i] = cp_flush_2ucode_l2[i] & (~pc_iu_ram_active[i]);
            iu0_2ucode_type_d[i] = cp_flush_2ucode_type_l2[i] & (~pc_iu_ram_active[i]);
         end
         else if ((cp_flush_l2[i] == 1'b1) & (cp_flush_into_uc_l2[i] == 1'b1))
         begin
            iu0_ifar_temp[i] = cp_flush_ifar_l2[i] + 1;
            iu0_2ucode_d[i] = 1'b0;
            iu0_2ucode_type_d[i] = 1'b0;
         end
         else if (br_iu_redirect_l2[i] == 1'b1)
         begin
            iu0_ifar_temp[i] = br_iu_bta_l2;
            iu0_2ucode_d[i] = 1'b0;
            iu0_2ucode_type_d[i] = 1'b0;
         end
         else if (uc_iu4_flush[i] == 1'b1)
         begin
            iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], uc_iu4_flush_ifar[i]};
            iu0_2ucode_d[i] = 1'b0;
            iu0_2ucode_type_d[i] = 1'b0;
         end
         else if (bp_ic_iu4_redirect[i] == 1'b1)
         begin
            iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], bp_ic_redirect_ifar[i]};
            iu0_2ucode_d[i] = 1'b0;
            iu0_2ucode_type_d[i] = 1'b0;
         end
         else if (icd_ics_iu3_parity_flush[i] == 1'b1 | (icd_ics_iu3_miss_flush[i] & icm_ics_iu3_miss_match))
         begin
            iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], icd_ics_iu3_ifar};
            iu0_2ucode_d[i] = icd_ics_iu3_2ucode;
            iu0_2ucode_type_d[i] = icd_ics_iu3_2ucode_type;
         end
         else if (icd_ics_iu3_miss_flush[i] == 1'b1)		// and not icm_ics_iu2_miss_match
         begin
            iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], (icd_ics_iu3_ifar[62-`EFF_IFAR_WIDTH:59] + value_1[34-`EFF_IFAR_WIDTH:31]), 2'b00};
            iu0_2ucode_d[i] = 1'b0;
            iu0_2ucode_type_d[i] = 1'b0;
         end
         else if ((bp_ic_iu3_redirect[i] == 1'b1) & (icm_ics_iu3_ecc_fp_cancel[i] == 1'b0))
         begin
            iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], bp_ic_redirect_ifar[i]};
            iu0_2ucode_d[i] = 1'b0;
            iu0_2ucode_type_d[i] = 1'b0;
         end
         // for ierat flush, only update ifar if iu2_valid (i.e. not iu2_prefetch)
         else if ((((ierat_iu_iu2_flush_req[i] | icd_ics_iu2_cam_etc_flush[i]) & icd_ics_iu2_valid) |
                   icd_ics_iu2_wrong_ra_flush[i]) == 1'b1)
         begin
            iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], icd_ics_iu2_ifar_eff};
            iu0_2ucode_d[i] = icd_ics_iu2_2ucode;
            iu0_2ucode_type_d[i] = icd_ics_iu2_2ucode_type;
         end
         else if ((bp_ic_iu2_redirect[i] == 1'b1) & (icm_ics_iu3_ecc_fp_cancel[i] == 1'b0))
         begin
            iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], bp_ic_redirect_ifar[i]};
            iu0_2ucode_d[i] = 1'b0;
            iu0_2ucode_type_d[i] = 1'b0;
         end
         else if(iu1_ecc_flush[i] == 1'b1)
         begin
	   iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], icd_ics_iu1_ifar};
           iu0_2ucode_d[i] = icd_ics_iu1_2ucode;
           iu0_2ucode_type_d[i] = icd_ics_iu1_2ucode_type;
         end
         else if (iu0_tid[i] == 1'b1)
         begin
            iu0_ifar_temp[i] = {iu0_ifar_l2[i][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], (iu0_ifar_l2[i][62-`EFF_IFAR_WIDTH:59] + value_1[34-`EFF_IFAR_WIDTH:31]), 2'b00};
            iu0_2ucode_d[i] = 1'b0;
            iu0_2ucode_type_d[i] = 1'b0;
         end
      end
   end   // iu0_ifar_proc

   generate
   begin : xhdl4
     genvar  t;
     for (t = 0; t < `THREADS; t = t + 1)
     begin : thread_iu0_ifar_mask
       genvar  i;
       for (i = (62 - `EFF_IFAR_ARCH); i < 62; i = i + 1)
       begin : iu0_ifar0_mask
         if (i < 32)
         begin
           assign iu0_ifar_d[t][i] = (xu_iu_msr_cm[t] & iu0_ifar_temp[t][i]);
         end
         if (i >= 32)
         begin
           assign iu0_ifar_d[t][i] = iu0_ifar_temp[t][i];
         end
       end
     end
   end
   endgenerate

   assign toggle_flip = icd_ics_iu2_wrong_ra_flush & (~ierat_iu_iu2_flush_req) & (~iu3_flush);
   assign iu0_flip_index51_d = (  toggle_flip  & (~iu0_flip_index51_l2)) |
                               ((~toggle_flip) &   iu0_flip_index51_l2);

   //---------------------------------------------------------------------
   // Stored ERAT
   //---------------------------------------------------------------------
   // Keep 42:51 to compare, and flush if cp or br flush

   generate
   begin : xhdl5
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : stored_erat_gen
       assign stored_erat_act[i] = iu0_read_erat[i] & (~spr_ic_ierat_byp_dis);
       assign stored_erat_ifar_d[i] = iu0_ifar[62-`EFF_IFAR_WIDTH:51];

       assign iu0_cross_4k_fetch[i] = (iu0_ifar_l2[i][62-`EFF_IFAR_WIDTH:51] != stored_erat_ifar_l2[i]);
       assign iu0_cross_4k_prefetch[i] = (iu0_prefetch_ifar_l2[i][62-`EFF_IFAR_WIDTH:51] != stored_erat_ifar_l2[i]);

       assign iu0_cross_4k[i] = (iu0_tid[i] & iu0_cross_4k_fetch[i]) |
                                (next_prefetch[i] & iu0_cross_4k_prefetch[i]);

       assign iu0_read_erat[i] = (iu0_erat_valid & iu0_erat_tid[i]) &
           ((~stored_erat_valid_l2[i]) | iu0_need_new_erat[i] | next_fetch_nonspec_l2[i] | spr_ic_ierat_byp_dis);

       // This is a subset of clear_erat_valid that does not include any of the flush terms
       // (because we would be dropping fetch anyways if it is flushed).  For timing & helps power.
       assign iu0_need_new_erat[i] = (iu0_cross_4k[i] & (~bp_ic_iu4_redirect[i])) |
                           ierat_iu_cam_change | icd_ics_iu2_read_erat_error[i];

       assign clear_erat_valid[i] = cp_flush_l2[i] | br_iu_redirect_l2[i] | (iu0_cross_4k[i] & (~bp_ic_iu4_redirect[i])) |       // Might be on new page
           ierat_iu_cam_change | icd_ics_iu2_read_erat_error[i] |
           (icd_ics_iu2_valid & ierat_iu_iu2_flush_req[i]) |
           (icd_ics_iu1_read_erat[i] & iu1_flush[i]);		// not going to be stored

       assign stored_erat_valid_d[i] = (~spr_ic_ierat_byp_dis) &
               ((iu0_read_erat[i] & (~iu0_flush[i])) | (stored_erat_valid_l2[i] & (~clear_erat_valid[i])));
     end
   end
   endgenerate

   assign ics_icd_iu0_read_erat = |(iu0_read_erat);

   //---------------------------------------------------------------------
   // Outputs
   //---------------------------------------------------------------------
   // ???? Do I want to split up threaded/non-threaded signals?
   generate
   begin : xhdl6
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : hold_t
       assign hold_thread[i] = (~xu_iu_run_thread_l2[i] & ~next_fetch_nonspec_l2[i]) | cp_ic_stop_l2[i] | pc_iu_pm_fetch_halt_l2[i] | mm_hold_req_l2[i] | mm_bus_snoop_hold_req_l2[i] |
                               ierat_hold_l2[i] | back_inv_l2 | icm_ics_hold_iu0 | spr_idir_read_l2 | uc_ic_hold[i] | icm_ics_hold_thread[i];

       // Everything except icm_ics_hold_iu0
       assign hold_thread_perf_lite[i] = (~xu_iu_run_thread_l2[i] & ~next_fetch_nonspec_l2[i]) | cp_ic_stop_l2[i] | pc_iu_pm_fetch_halt_l2[i] | mm_hold_req_l2[i] | mm_bus_snoop_hold_req_l2[i] |
                               ierat_hold_l2[i] | back_inv_l2 | spr_idir_read_l2 | uc_ic_hold[i] | icm_ics_hold_thread[i];

       assign hold_prefetch[i] = (~xu_iu_run_thread_l2[i]) | cp_ic_stop_l2[i] | pc_iu_pm_fetch_halt_l2[i] | mm_hold_req_l2[i] | mm_bus_snoop_hold_req_l2[i]  |
                               ierat_hold_l2[i] | back_inv_l2 | icm_ics_hold_iu0 | spr_idir_read_l2 | (|(need_fetch_reduce & (~hold_thread)));
     end

     //genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_need_fetch_reduce
       assign need_fetch_reduce[i] = |(need_fetch[i]);
     end
   end
   endgenerate

   assign iu0_erat_valid = |(need_fetch_reduce & (~hold_thread)) | (|(prefetch_ready));
   assign iu0_erat_tid = iu0_tid | next_prefetch;
   assign iu_ierat_iu0_val = |(iu0_read_erat);
   assign iu_ierat_iu0_thdid = iu0_erat_tid;
   assign iu_ierat_iu0_prefetch = |(prefetch_ready) & (~(|(need_fetch_reduce & (~hold_thread))));

   generate
   begin : xhdl8
     genvar  i;
     for (i = 0; i < 52; i = i + 1)
     begin : ierat_ifar
       if (i < 62 - `EFF_IFAR_ARCH)
         assign iu_ierat_iu0_ifar[i] = 1'b0;
       if (i >= 62 - `EFF_IFAR_ARCH)
         assign iu_ierat_iu0_ifar[i] = iu0_ifar[i];
     end
   end
   endgenerate

   assign next_fetch_nonspec_d = (~cp_flush) &
       (cp_flush_nonspec_l2 | (next_fetch_nonspec_l2 & (~iu0_tid)) |
        ({`THREADS{icd_ics_iu2_valid}} & ierat_iu_iu2_flush_req & iu2_nonspec_l2));
   assign iu_ierat_iu0_nonspec = |(next_fetch_nonspec_l2 & iu0_tid);

   assign iu1_nonspec_d = {`THREADS{iu0_erat_valid}} & iu0_erat_tid & next_fetch_nonspec_l2 & (~cp_flush);
   assign iu2_nonspec_d = iu1_nonspec_l2 & (~cp_flush);

   // Tell CP if nonspec hit in ierat
   assign ic_cp_nonspec_hit = iu2_nonspec_l2 & ~{`THREADS{ierat_iu_iu2_miss}} &
      ~cp_flush_l2 & ~({`THREADS{icd_ics_iu2_valid}} & ierat_iu_iu2_flush_req & iu2_nonspec_l2);

   assign iu_ierat_flush = cp_flush_l2 | uc_iu4_flush | icd_ics_iu3_miss_flush | ({`THREADS{icd_ics_iu2_valid}} & icd_ics_iu2_cam_etc_flush) |
       icd_ics_iu2_wrong_ra_flush | icd_ics_iu3_parity_flush | (bp_ic_iu2_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | (bp_ic_iu3_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | bp_ic_iu4_redirect | br_iu_redirect_l2 | iu1_ecc_flush;
   assign ics_icm_iu2_flush = cp_flush_l2 | uc_iu4_flush | icd_ics_iu3_parity_flush |
      (bp_ic_iu3_redirect & (~icm_ics_iu3_ecc_fp_cancel) & (~icd_ics_iu3_miss_flush)) | bp_ic_iu4_redirect | br_iu_redirect_l2;
   assign ics_icd_iu1_flush = cp_flush_l2 | uc_iu4_flush | ({`THREADS{icd_ics_iu2_valid}} & (ierat_iu_iu2_flush_req | icd_ics_iu2_cam_etc_flush)) |
       icd_ics_iu3_miss_flush | icd_ics_iu2_wrong_ra_flush | icd_ics_iu3_parity_flush | (bp_ic_iu2_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | (bp_ic_iu3_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | bp_ic_iu4_redirect | br_iu_redirect_l2 | iu1_ecc_flush;
   assign ics_icd_iu2_flush = cp_flush_l2 | uc_iu4_flush | ierat_iu_iu2_flush_req | icd_ics_iu2_cam_etc_flush | icd_ics_iu3_miss_flush | icd_ics_iu2_wrong_ra_flush | (bp_ic_iu3_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | icd_ics_iu3_parity_flush | bp_ic_iu4_redirect | br_iu_redirect_l2;

   assign ic_bp_iu2_flush = ierat_iu_iu2_flush_req | icd_ics_iu2_cam_etc_flush | icd_ics_iu2_wrong_ra_flush;

   assign iu0_flush = cp_flush_l2 | uc_iu4_flush | ({`THREADS{icd_ics_iu2_valid}} & (ierat_iu_iu2_flush_req | icd_ics_iu2_cam_etc_flush)) |
       icd_ics_iu3_miss_flush | icd_ics_iu2_wrong_ra_flush | icd_ics_iu3_parity_flush | (bp_ic_iu2_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | (bp_ic_iu3_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | bp_ic_iu4_redirect | br_iu_redirect_l2 | iu1_ecc_flush;

   assign iu1_flush = cp_flush_l2 | uc_iu4_flush | ierat_iu_iu2_flush_req | ({`THREADS{icd_ics_iu2_valid}} & icd_ics_iu2_cam_etc_flush) |
       icd_ics_iu3_miss_flush | icd_ics_iu2_wrong_ra_flush | icd_ics_iu3_parity_flush | (bp_ic_iu2_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | (bp_ic_iu3_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | bp_ic_iu4_redirect | br_iu_redirect_l2 | iu1_ecc_flush;

   assign iu2_flush = cp_flush_l2 | uc_iu4_flush | ierat_iu_iu2_flush_req | ({`THREADS{icd_ics_iu2_valid}} & icd_ics_iu2_cam_etc_flush) |
       icd_ics_iu3_miss_flush | icd_ics_iu2_wrong_ra_flush | icd_ics_iu3_parity_flush | (bp_ic_iu3_redirect & (~icm_ics_iu3_ecc_fp_cancel)) | bp_ic_iu4_redirect | br_iu_redirect_l2;

	 assign iu3_flush = cp_flush_l2 | uc_iu4_flush | icd_ics_iu3_parity_flush | bp_ic_iu4_redirect | br_iu_redirect_l2 |
	     (icd_ics_iu3_miss_flush & {`THREADS{icm_ics_iu3_miss_match}});   // used by toggle_flip.  If miss matches, will use old page; if miss hits, next address should be the same that caused wrong_ra, so want to flip for new page

   assign ics_icm_iu0_t0_ifar = iu0_ifar_l2[0][46:52];
  `ifndef THREADS1
     assign ics_icm_iu0_t1_ifar = iu0_ifar_l2[1][46:52];
  `endif

   assign ics_icd_dir_rd_act = |(need_fetch_reduce & (~(hold_thread))) | back_inv_l2 | (spr_idir_read_l2 & ~icm_ics_hold_iu0) | (|(prefetch_ready));
   assign data_rd_act[0] = (iu0_tid[0] & (~(iu0_ifar_l2[0][51] ^ iu0_flip_index51_l2[0]))) | (iu0_tid[`THREADS - 1] & (~(iu0_ifar_l2[`THREADS - 1][51] ^ iu0_flip_index51_l2[`THREADS - 1])));
   assign data_rd_act[1] = (iu0_tid[0] & (iu0_ifar_l2[0][51] ^ iu0_flip_index51_l2[0])) | (iu0_tid[`THREADS - 1] & (iu0_ifar_l2[`THREADS - 1][51] ^ iu0_flip_index51_l2[`THREADS - 1]));
   assign ics_icd_data_rd_act = data_rd_act;

   assign iu0_valid = |(iu0_tid & (~iu0_flush));
   assign ics_icd_iu0_valid = iu0_valid;
   assign ics_icd_iu0_tid = iu0_tid | next_prefetch;

   generate
   begin
     if (`THREADS == 1)
     begin : gen_bp_iu0_val_t0
       assign ic_bp_iu0_val[0] = iu0_tid[0] | icm_ics_iu0_preload_val[0];
     end

     if (`THREADS == 2)
     begin : gen_bp_iu0_val
       assign ic_bp_iu0_val[0] = (iu0_tid[0] & (~icm_ics_iu0_preload_val[`THREADS - 1])) | icm_ics_iu0_preload_val[0];
       assign ic_bp_iu0_val[`THREADS - 1] = (iu0_tid[`THREADS - 1] & (~icm_ics_iu0_preload_val[0])) | icm_ics_iu0_preload_val[`THREADS - 1];
     end
   end
   endgenerate

   assign ic_bp_iu0_ifar = (|(icm_ics_iu0_preload_val) == 1'b1) ? icm_ics_iu0_preload_ifar[50:59] :
                           (iu0_tid[0] == 1'b1)                 ? iu0_ifar_l2[0][50:59] :
                                                                  iu0_ifar_l2[`THREADS - 1][50:59];

   generate
   begin
     if (`EFF_IFAR_ARCH > (`REAL_IFAR_WIDTH-2))
     begin : iu0_ifar_gen0

       assign iu0_ifar = ({`EFF_IFAR_ARCH{(~(back_inv_l2 | spr_idir_read_l2)) & iu0_tid[0]}} & iu0_ifar_l2[0]) |
                         ({`EFF_IFAR_ARCH{(~(back_inv_l2 | spr_idir_read_l2)) & iu0_tid[`THREADS-1]}} & iu0_ifar_l2[`THREADS-1]) |	  // should be duplicate if 1 thread
                         ({ {(`EFF_IFAR_ARCH - `REAL_IFAR_WIDTH + 2){1'b0}}, ({(`REAL_IFAR_WIDTH-6){(back_inv_l2 & (~|(back_inv_icbi_l2)))}} & an_ac_back_inv_addr_l2), 4'b0000 }) |
                         ({ {(`EFF_IFAR_ARCH - `REAL_IFAR_WIDTH + 2){1'b0}}, ({(`REAL_IFAR_WIDTH-6){back_inv_icbi_l2[0]}} & lq_iu_icbi_addr_l2[0]), 4'b0000 }) |   // back_inv_l2 includes back_inv_icbi_l2, was redundant
                         ({ {(`EFF_IFAR_ARCH - `REAL_IFAR_WIDTH + 2){1'b0}}, ({(`REAL_IFAR_WIDTH-6){back_inv_icbi_l2[`THREADS - 1]}} & lq_iu_icbi_addr_l2[`THREADS - 1]), 4'b0000}) |
                         ({ {(`EFF_IFAR_ARCH - 11){1'b0}}, ({7{(~(back_inv_l2)) & spr_idir_read_l2}} & spr_idir_row_l2), 4'b0000}) |
                         ({ ({(`EFF_IFAR_ARCH-4){next_prefetch[0]}} & {iu0_ifar_l2[0][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], iu0_prefetch_ifar_l2[0]}), 4'b0000}) |
                         ({ ({(`EFF_IFAR_ARCH-4){next_prefetch[`THREADS - 1]}} & {iu0_ifar_l2[`THREADS-1][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], iu0_prefetch_ifar_l2[`THREADS-1]}), 4'b0000});
     end

     if (`EFF_IFAR_ARCH <= (`REAL_IFAR_WIDTH-2))
     begin : iu0_ifar_gen1
       assign iu0_ifar = ({`EFF_IFAR_ARCH{(~(back_inv_l2 | spr_idir_read_l2)) & iu0_tid[0]}} & iu0_ifar_l2[0]) |
                         ({`EFF_IFAR_ARCH{(~(back_inv_l2 | spr_idir_read_l2)) & iu0_tid[`THREADS-1]}} & iu0_ifar_l2[`THREADS-1]) |
                         ({ ({`EFF_IFAR_ARCH-4{back_inv_l2 & (~|(back_inv_icbi_l2))}} & an_ac_back_inv_addr_l2[62-`EFF_IFAR_ARCH:57]), 4'b0000}) |
                         ({ ({`EFF_IFAR_ARCH-4{back_inv_icbi_l2[0]}} & lq_iu_icbi_addr_l2[0][62-`EFF_IFAR_ARCH:57]), 4'b0000}) |		// back_inv_l2 includes back_inv_icbi_l2, was redundant
                         ({ ({`EFF_IFAR_ARCH-4{back_inv_icbi_l2[`THREADS-1]}} & lq_iu_icbi_addr_l2[`THREADS-1][62-`EFF_IFAR_ARCH:57]), 4'b0000}) |
                         ({ {(`EFF_IFAR_ARCH - 11){1'b0}}, ({7{(~(back_inv_l2)) & spr_idir_read_l2}} & spr_idir_row_l2), 4'b0000}) |
                         ({ ({(`EFF_IFAR_ARCH-4){next_prefetch[0]}} & {iu0_ifar_l2[0][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], iu0_prefetch_ifar_l2[0]}), 4'b0000}) |
                         ({ ({(`EFF_IFAR_ARCH-4){next_prefetch[`THREADS-1]}} & {iu0_ifar_l2[`THREADS-1][62-`EFF_IFAR_ARCH:62-`EFF_IFAR_WIDTH-1], iu0_prefetch_ifar_l2[`THREADS-1]}), 4'b0000});
     end
   end
   endgenerate

   assign ics_icd_iu0_ifar = iu0_ifar;
   assign ics_icd_iu0_index51 = ( ((~(back_inv_l2 | spr_idir_read_l2)) & iu0_tid[0]) & (iu0_ifar_l2[0][51] ^ iu0_flip_index51_l2[0])) |
                                ( ((~(back_inv_l2 | spr_idir_read_l2)) & iu0_tid[`THREADS - 1]) & (iu0_ifar_l2[`THREADS - 1][51] ^ iu0_flip_index51_l2[`THREADS - 1])) |	// should be duplicate if `THREADS=1
                                ( (back_inv_l2 & (~|(back_inv_icbi_l2))) & an_ac_back_inv_addr_l2[51]) |
                                ( back_inv_icbi_l2[0] & lq_iu_icbi_addr_l2[0][51]) |   // back_inv_l2 includes back_inv_icbi_l2, was redundant
                                ( back_inv_icbi_l2[`THREADS - 1] & lq_iu_icbi_addr_l2[`THREADS - 1][51]) |
                                ( ((~(back_inv_l2)) & spr_idir_read_l2) & spr_idir_row_l2[51]) |
                                ( next_prefetch[0] & (iu0_prefetch_ifar_l2[0][51] ^ iu0_flip_index51_l2[0])) |
                                ( next_prefetch[`THREADS - 1] & (iu0_prefetch_ifar_l2[`THREADS - 1][51] ^ iu0_flip_index51_l2[`THREADS - 1]));

   assign ics_icd_iu0_2ucode = |(iu0_2ucode_l2 & iu0_tid);
   assign ics_icd_iu0_2ucode_type = |(iu0_2ucode_type_l2 & iu0_tid);

   assign ics_icd_iu0_inval = back_inv_l2;
   assign ics_icm_iu0_inval = back_inv_l2;

   assign ics_icm_iu0_inval_addr = ( {7{back_inv_l2 & (~|(back_inv_icbi_l2))}} & an_ac_back_inv_addr_l2[51:57]) |
                                   ( {7{back_inv_icbi_l2[0]}}                  & lq_iu_icbi_addr_l2[0][51:57]) |
                                   ( {7{back_inv_icbi_l2[`THREADS - 1]}}       & lq_iu_icbi_addr_l2[`THREADS - 1][51:57]);

   // Block prefetch if new prefetch req on this thread
   assign ics_icd_iu0_prefetch = |(send_prefetch & ~(icm_ics_prefetch_req & ~{`THREADS{prefetch_wrap}}));

   //---------------------------------------------------------------------
   // Performance Events
   //---------------------------------------------------------------------

   generate
   begin : xhdl9
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : perf
       // Reload Collisions - Blocked by reload writing into the cache
       assign perf_event_d[i][3] = icm_ics_hold_iu0 & need_fetch_reduce[i] & ~hold_thread_perf_lite[i];

       // IU0 Redirected - any flush condition
       assign perf_event_d[i][4] = iu0_flush[i];

       // Various flushes: BP iu2, BP iu3, BP iu4, uc
       assign perf_event_d[i][5] = bp_ic_iu2_redirect[i] & ~icm_ics_iu3_ecc_fp_cancel[i];
       assign perf_event_d[i][6] = bp_ic_iu3_redirect[i] & ~icm_ics_iu3_ecc_fp_cancel[i];
       assign perf_event_d[i][7] = bp_ic_iu4_redirect[i];
       assign perf_event_d[i][8] = uc_iu4_flush[i];
     end
   end
   endgenerate

   assign ic_perf_t0_event = perf_event_l2[0];
 `ifndef THREADS1
     assign ic_perf_t1_event = perf_event_l2[1];
 `endif

   //---------------------------------------------------------------------
   // Latches
   //---------------------------------------------------------------------

   tri_rlmlatch_p #(.INIT(0)) an_ac_back_inv_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[an_ac_back_inv_offset]),
      .scout(sov[an_ac_back_inv_offset]),
      .din(an_ac_back_inv_d),
      .dout(an_ac_back_inv_l2)
   );

   tri_rlmlatch_p #(.INIT(0)) an_ac_back_inv_target_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[an_ac_back_inv_target_offset]),
      .scout(sov[an_ac_back_inv_target_offset]),
      .din(an_ac_back_inv_target_d),
      .dout(an_ac_back_inv_target_l2)
   );

   tri_rlmreg_p #(.WIDTH(`REAL_IFAR_WIDTH-6), .INIT(0)) an_ac_back_inv_addr_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(back_inv_addr_act),		//back_inv_d,
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[an_ac_back_inv_addr_offset:an_ac_back_inv_addr_offset + (`REAL_IFAR_WIDTH-6) - 1]),
      .scout(sov[an_ac_back_inv_addr_offset:an_ac_back_inv_addr_offset + (`REAL_IFAR_WIDTH-6) - 1]),
      .din(an_ac_back_inv_addr_d),
      .dout(an_ac_back_inv_addr_l2)
   );

   tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) spr_idir_read_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[spr_idir_read_offset]),
      .scout(sov[spr_idir_read_offset]),
      .din(spr_idir_read_d),
      .dout(spr_idir_read_l2)
   );

   tri_rlmreg_p #(.WIDTH(7), .INIT(0), .NEEDS_SRESET(0)) spr_idir_row_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[spr_idir_row_offset:spr_idir_row_offset + 7 - 1]),
      .scout(sov[spr_idir_row_offset:spr_idir_row_offset + 7 - 1]),
      .din(spr_idir_row_d),
      .dout(spr_idir_row_l2)
   );

   generate
   begin
     if (`THREADS == 1)
     begin : gen_oldest_t1
        assign oldest_prefetch_l2 = oldest_prefetch_d & 1'b0;
     end

     if (`THREADS > 1)
     begin : gen_oldest_t2
       tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) oldest_prefetch_latch(
          .vd(vdd),
          .gd(gnd),
          .nclk(nclk),
          .act(tiup),
          .thold_b(pc_iu_func_sl_thold_0_b),
          .sg(pc_iu_sg_0),
          .force_t(force_t),
          .delay_lclkr(delay_lclkr),
          .mpw1_b(mpw1_b),
          .mpw2_b(mpw2_b),
          .d_mode(d_mode),
          .scin(siv[oldest_prefetch_offset]),
          .scout(sov[oldest_prefetch_offset]),
          .din(oldest_prefetch_d),
          .dout(oldest_prefetch_l2)
       );
     end
   end
   endgenerate

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) iu0_need_prefetch_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[iu0_need_prefetch_offset:iu0_need_prefetch_offset + `THREADS - 1]),
      .scout(sov[iu0_need_prefetch_offset:iu0_need_prefetch_offset + `THREADS - 1]),
      .din(iu0_need_prefetch_d),
      .dout(iu0_need_prefetch_l2)
   );

   generate
   begin : xhdl10
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : t
       tri_rlmreg_p #(.WIDTH(`EFF_IFAR_WIDTH-4), .INIT(0)) iu0_prefetch_ifar_latch(
          .vd(vdd),
          .gd(gnd),
          .nclk(nclk),
          .act(iu0_prefetch_ifar_act[i]),
          .thold_b(pc_iu_func_sl_thold_0_b),
          .sg(pc_iu_sg_0),
          .force_t(force_t),
          .delay_lclkr(delay_lclkr),
          .mpw1_b(mpw1_b),
          .mpw2_b(mpw2_b),
          .d_mode(d_mode),
          .scin(siv[iu0_prefetch_ifar_offset + i * (`EFF_IFAR_WIDTH-4):iu0_prefetch_ifar_offset + ((i + 1) * (`EFF_IFAR_WIDTH-4)) - 1]),
          .scout(sov[iu0_prefetch_ifar_offset + i * (`EFF_IFAR_WIDTH-4):iu0_prefetch_ifar_offset + ((i + 1) * (`EFF_IFAR_WIDTH-4)) - 1]),
          .din(iu0_prefetch_ifar_d[i]),
          .dout(iu0_prefetch_ifar_l2[i])
       );
     end
   end
   endgenerate

   tri_rlmreg_p #(.WIDTH((`THREADS*`THREADS-1+1)), .INIT(0)) lq_iu_icbi_val_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[lq_iu_icbi_val_offset:lq_iu_icbi_val_offset + (`THREADS*`THREADS-1+1) - 1]),
      .scout(sov[lq_iu_icbi_val_offset:lq_iu_icbi_val_offset + (`THREADS*`THREADS-1+1) - 1]),
      .din(lq_iu_icbi_val_d),
      .dout(lq_iu_icbi_val_l2)
   );

   generate
   begin : xhdl11
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : t
       tri_rlmreg_p #(.WIDTH(`REAL_IFAR_WIDTH-6), .INIT(0)) lq_iu_icbi_addr_latch(
          .vd(vdd),
          .gd(gnd),
          .nclk(nclk),
          .act(lq_iu_icbi_val[i]),
          .thold_b(pc_iu_func_sl_thold_0_b),
          .sg(pc_iu_sg_0),
          .force_t(force_t),
          .delay_lclkr(delay_lclkr),
          .mpw1_b(mpw1_b),
          .mpw2_b(mpw2_b),
          .d_mode(d_mode),
          .scin(siv[lq_iu_icbi_addr_offset + i * (`REAL_IFAR_WIDTH-6):lq_iu_icbi_addr_offset + ((i + 1) * (`REAL_IFAR_WIDTH-6)) - 1]),
          .scout(sov[lq_iu_icbi_addr_offset + i * (`REAL_IFAR_WIDTH-6):lq_iu_icbi_addr_offset + ((i + 1) * (`REAL_IFAR_WIDTH-6)) - 1]),
          .din(lq_iu_icbi_addr_d[i]),
          .dout(lq_iu_icbi_addr_l2[i])
       );
     end
   end
   endgenerate

   tri_rlmlatch_p #(.INIT(0)) back_inv_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[back_inv_offset]),
      .scout(sov[back_inv_offset]),
      .din(back_inv_d),
      .dout(back_inv_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) back_inv_icbi_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[back_inv_icbi_offset:back_inv_icbi_offset + `THREADS - 1]),
      .scout(sov[back_inv_icbi_offset:back_inv_icbi_offset + `THREADS - 1]),
      .din(back_inv_icbi_d),
      .dout(back_inv_icbi_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) xu_iu_run_thread_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[xu_iu_run_thread_offset:xu_iu_run_thread_offset + `THREADS - 1]),
      .scout(sov[xu_iu_run_thread_offset:xu_iu_run_thread_offset + `THREADS - 1]),
      .din(xu_iu_run_thread_d),
      .dout(xu_iu_run_thread_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) xu_iu_msr_cm_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[xu_iu_msr_cm_offset:xu_iu_msr_cm_offset + `THREADS - 1]),
      .scout(sov[xu_iu_msr_cm_offset:xu_iu_msr_cm_offset + `THREADS - 1]),
      .din(xu_iu_msr_cm_d),
      .dout(xu_iu_msr_cm_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) xu_iu_msr_cm2_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[xu_iu_msr_cm2_offset:xu_iu_msr_cm2_offset + `THREADS - 1]),
      .scout(sov[xu_iu_msr_cm2_offset:xu_iu_msr_cm2_offset + `THREADS - 1]),
      .din(xu_iu_msr_cm2_d),
      .dout(xu_iu_msr_cm2_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) xu_iu_msr_cm3_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[xu_iu_msr_cm3_offset:xu_iu_msr_cm3_offset + `THREADS - 1]),
      .scout(sov[xu_iu_msr_cm3_offset:xu_iu_msr_cm3_offset + `THREADS - 1]),
      .din(xu_iu_msr_cm3_d),
      .dout(xu_iu_msr_cm3_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) cp_ic_stop_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[cp_ic_stop_offset:cp_ic_stop_offset + `THREADS - 1]),
      .scout(sov[cp_ic_stop_offset:cp_ic_stop_offset + `THREADS - 1]),
      .din(cp_ic_stop_d),
      .dout(cp_ic_stop_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) pc_iu_pm_fetch_halt_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[pc_iu_pm_fetch_halt_offset:pc_iu_pm_fetch_halt_offset + `THREADS - 1]),
      .scout(sov[pc_iu_pm_fetch_halt_offset:pc_iu_pm_fetch_halt_offset + `THREADS - 1]),
      .din(pc_iu_pm_fetch_halt_d),
      .dout(pc_iu_pm_fetch_halt_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) ierat_hold_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[ierat_hold_offset:ierat_hold_offset + `THREADS - 1]),
      .scout(sov[ierat_hold_offset:ierat_hold_offset + `THREADS - 1]),
      .din(ierat_hold_d),
      .dout(ierat_hold_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) iu0_2ucode_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[iu0_2ucode_offset:iu0_2ucode_offset + `THREADS - 1]),
      .scout(sov[iu0_2ucode_offset:iu0_2ucode_offset + `THREADS - 1]),
      .din(iu0_2ucode_d),
      .dout(iu0_2ucode_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) iu0_2ucode_type_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[iu0_2ucode_type_offset:iu0_2ucode_type_offset + `THREADS - 1]),
      .scout(sov[iu0_2ucode_type_offset:iu0_2ucode_type_offset + `THREADS - 1]),
      .din(iu0_2ucode_type_d),
      .dout(iu0_2ucode_type_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) iu0_flip_index51_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[iu0_flip_index51_offset:iu0_flip_index51_offset + `THREADS - 1]),
      .scout(sov[iu0_flip_index51_offset:iu0_flip_index51_offset + `THREADS - 1]),
      .din(iu0_flip_index51_d),
      .dout(iu0_flip_index51_l2)
   );

   generate
   begin
     if (`THREADS == 1)
     begin : gen_last_tid_t1
        assign iu0_last_tid_sent_l2 = 1'b0 & iu0_last_tid_sent_d;
     end

     if (`THREADS > 1)
     begin : gen_last_tid_t2
       tri_rlmlatch_p #(.INIT(0)) iu0_last_tid_sent_latch(
          .vd(vdd),
          .gd(gnd),
          .nclk(nclk),
          .act(tiup),
          .thold_b(pc_iu_func_sl_thold_0_b),
          .sg(pc_iu_sg_0),
          .force_t(force_t),
          .delay_lclkr(delay_lclkr),
          .mpw1_b(mpw1_b),
          .mpw2_b(mpw2_b),
          .d_mode(d_mode),
          .scin(siv[iu0_last_tid_sent_offset]),
          .scout(sov[iu0_last_tid_sent_offset]),
          .din(iu0_last_tid_sent_d),
          .dout(iu0_last_tid_sent_l2)
       );
     end
   end
   endgenerate

   generate
   begin : xhdl13
     genvar  t;
     for (t = 0; t < `THREADS; t = t + 1)
     begin : th
       genvar  i;
       for (i = 0; i < `IBUFF_DEPTH/4; i = i + 1)
       begin : ibuff
         tri_rlmreg_p #(.WIDTH(3), .INIT(0)) iu0_sent_latch(
            .vd(vdd),
            .gd(gnd),
            .nclk(nclk),
            .act(tiup),
            .thold_b(pc_iu_func_sl_thold_0_b),
            .sg(pc_iu_sg_0),
            .force_t(force_t),
            .delay_lclkr(delay_lclkr),
            .mpw1_b(mpw1_b),
            .mpw2_b(mpw2_b),
            .d_mode(d_mode),
            .scin(siv[iu0_sent_offset + (t * (`IBUFF_DEPTH/4) + i) * 3:iu0_sent_offset + (t * (`IBUFF_DEPTH/4) + i + 1) * 3 - 1]),
            .scout(sov[iu0_sent_offset + (t * (`IBUFF_DEPTH/4) + i) * 3:iu0_sent_offset + (t * (`IBUFF_DEPTH/4) + i + 1) * 3 - 1]),
            .din(iu0_sent_d[t][i]),
            .dout(iu0_sent_l2[t][i])
         );
       end
     end
   end
   endgenerate

   // IU0
   generate
   begin : xhdl14
     genvar  t;
     for (t = 0; t < `THREADS; t = t + 1)
     begin : th
       genvar  i;
       for (i = 0; i < `EFF_IFAR_ARCH; i = i + 1)
       begin : q_gen
         if((62-`EFF_IFAR_ARCH+i) > 31)
           tri_rlmlatch_p #(.INIT(1), .NEEDS_SRESET(1)) iu0_ifar_latch(
              .vd(vdd),
              .gd(gnd),
              .nclk(nclk),
              .act(tiup),
              .thold_b(pc_iu_func_slp_sl_thold_0_b),
              .sg(pc_iu_sg_0),
              .force_t(funcslp_force),
              .delay_lclkr(delay_lclkr),
              .mpw1_b(mpw1_b),
              .mpw2_b(mpw2_b),
              .d_mode(d_mode),
              .scin(siv[iu0_ifar_offset + t * `EFF_IFAR_ARCH + i]),
              .scout(sov[iu0_ifar_offset + t * `EFF_IFAR_ARCH + i]),
              .din(iu0_ifar_d[t][62 - `EFF_IFAR_ARCH + i]),
              .dout(iu0_ifar_l2[t][62 - `EFF_IFAR_ARCH + i])
           );
         else
           tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) iu0_ifar_latch(
              .vd(vdd),
              .gd(gnd),
              .nclk(nclk),
              .act(tiup),
              .thold_b(pc_iu_func_slp_sl_thold_0_b),
              .sg(pc_iu_sg_0),
              .force_t(funcslp_force),
              .delay_lclkr(delay_lclkr),
              .mpw1_b(mpw1_b),
              .mpw2_b(mpw2_b),
              .d_mode(d_mode),
              .scin(siv[iu0_ifar_offset + t * `EFF_IFAR_ARCH + i]),
              .scout(sov[iu0_ifar_offset + t * `EFF_IFAR_ARCH + i]),
              .din(iu0_ifar_d[t][62 - `EFF_IFAR_ARCH + i]),
              .dout(iu0_ifar_l2[t][62 - `EFF_IFAR_ARCH + i])
           );
       end
     end
   end
   endgenerate

   generate
   begin : xhdl15
     if (`INCLUDE_IERAT_BYPASS == 0)
     begin : gen0
       genvar  i;
       for (i = 0; i < `THREADS; i = i + 1)
       begin : t
         //assign stored_erat_ifar_l2[i] = gate_and(1'b0, stored_erat_ifar_d[i]);		// ..._d part is to get rid of unused warnings
         //assign stored_erat_valid_l2[i] = gate_and(1'b0, stored_erat_valid_d[i]);		// '0'
       end

       assign sov[stored_erat_ifar_offset:stored_erat_valid_offset + `THREADS - 1] = siv[stored_erat_ifar_offset:stored_erat_valid_offset + `THREADS - 1];
     end

     if (`INCLUDE_IERAT_BYPASS == 1)
     begin : gen1
       genvar  i;
       for (i = 0; i < `THREADS; i = i + 1)
       begin : t
         tri_rlmreg_p #(.WIDTH(`EFF_IFAR_WIDTH-10), .INIT(0)) stored_erat_ifar_latch(
            .vd(vdd),
            .gd(gnd),
            .nclk(nclk),
            .act(stored_erat_act[i]),
            .thold_b(pc_iu_func_sl_thold_0_b),
            .sg(pc_iu_sg_0),
            .force_t(force_t),
            .delay_lclkr(delay_lclkr),
            .mpw1_b(mpw1_b),
            .mpw2_b(mpw2_b),
            .d_mode(d_mode),
            .scin(siv[stored_erat_ifar_offset + i * (`EFF_IFAR_WIDTH-10):stored_erat_ifar_offset + ((i + 1) * (`EFF_IFAR_WIDTH-10)) - 1]),
            .scout(sov[stored_erat_ifar_offset + i * (`EFF_IFAR_WIDTH-10):stored_erat_ifar_offset + ((i + 1) * (`EFF_IFAR_WIDTH-10)) - 1]),
            .din(stored_erat_ifar_d[i]),
            .dout(stored_erat_ifar_l2[i])
         );
       end
     end

     tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) stored_erat_valid_latch(
        .vd(vdd),
        .gd(gnd),
        .nclk(nclk),
        .act(tiup),
        .thold_b(pc_iu_func_slp_sl_thold_0_b),
        .sg(pc_iu_sg_0),
        .force_t(funcslp_force),
        .delay_lclkr(delay_lclkr),
        .mpw1_b(mpw1_b),
        .mpw2_b(mpw2_b),
        .d_mode(d_mode),
        .scin(siv[stored_erat_valid_offset:stored_erat_valid_offset + `THREADS - 1]),
        .scout(sov[stored_erat_valid_offset:stored_erat_valid_offset + `THREADS - 1]),
        .din(stored_erat_valid_d),
        .dout(stored_erat_valid_l2)
      );
   end
   endgenerate

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) mm_hold_req_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[mm_hold_req_offset:mm_hold_req_offset + `THREADS - 1]),
      .scout(sov[mm_hold_req_offset:mm_hold_req_offset + `THREADS - 1]),
      .din(mm_hold_req_d),
      .dout(mm_hold_req_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) mm_bus_snoop_hold_req_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[mm_bus_snoop_hold_req_offset:mm_bus_snoop_hold_req_offset + `THREADS - 1]),
      .scout(sov[mm_bus_snoop_hold_req_offset:mm_bus_snoop_hold_req_offset + `THREADS - 1]),
      .din(mm_bus_snoop_hold_req_d),
      .dout(mm_bus_snoop_hold_req_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) cp_flush_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[cp_flush_offset:cp_flush_offset + `THREADS - 1]),
      .scout(sov[cp_flush_offset:cp_flush_offset + `THREADS - 1]),
      .din(cp_flush),
      .dout(cp_flush_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) cp_flush_into_uc_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[cp_flush_into_uc_offset:cp_flush_into_uc_offset + `THREADS - 1]),
      .scout(sov[cp_flush_into_uc_offset:cp_flush_into_uc_offset + `THREADS - 1]),
      .din(cp_flush_into_uc),
      .dout(cp_flush_into_uc_l2)
    );

   generate
   begin : xhdl17
      genvar  i;
      for (i = 0; i < `THREADS; i = i + 1)
      begin : t
        tri_rlmreg_p #(.WIDTH(`EFF_IFAR_ARCH), .INIT(0)) cp_flush_ifar_latch(
           .vd(vdd),
           .gd(gnd),
           .nclk(nclk),
           .act(tiup),
           .thold_b(pc_iu_func_slp_sl_thold_0_b),
           .sg(pc_iu_sg_0),
           .force_t(funcslp_force),
           .delay_lclkr(delay_lclkr),
           .mpw1_b(mpw1_b),
           .mpw2_b(mpw2_b),
           .d_mode(d_mode),
           .scin(siv[cp_flush_ifar_offset + i * `EFF_IFAR_ARCH:cp_flush_ifar_offset + (i + 1) * `EFF_IFAR_ARCH - 1]),
           .scout(sov[cp_flush_ifar_offset + i * `EFF_IFAR_ARCH:cp_flush_ifar_offset + (i + 1) * `EFF_IFAR_ARCH - 1]),
           .din(cp_flush_ifar_d[i]),
           .dout(cp_flush_ifar_l2[i])
        );
     end
   end
   endgenerate

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) cp_flush_2ucode_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[cp_flush_2ucode_offset:cp_flush_2ucode_offset + `THREADS - 1]),
      .scout(sov[cp_flush_2ucode_offset:cp_flush_2ucode_offset + `THREADS - 1]),
      .din(cp_iu0_flush_2ucode),
      .dout(cp_flush_2ucode_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) cp_flush_2ucode_type_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[cp_flush_2ucode_type_offset:cp_flush_2ucode_type_offset + `THREADS - 1]),
      .scout(sov[cp_flush_2ucode_type_offset:cp_flush_2ucode_type_offset + `THREADS - 1]),
      .din(cp_iu0_flush_2ucode_type),
      .dout(cp_flush_2ucode_type_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) cp_flush_nonspec_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_slp_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(funcslp_force),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[cp_flush_nonspec_offset:cp_flush_nonspec_offset + `THREADS - 1]),
      .scout(sov[cp_flush_nonspec_offset:cp_flush_nonspec_offset + `THREADS - 1]),
      .din(cp_iu0_flush_nonspec),
      .dout(cp_flush_nonspec_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) br_iu_redirect_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[br_iu_redirect_offset:br_iu_redirect_offset + `THREADS - 1]),
      .scout(sov[br_iu_redirect_offset:br_iu_redirect_offset + `THREADS - 1]),
      .din(br_iu_redirect_d),
      .dout(br_iu_redirect_l2)
   );

   tri_rlmreg_p #(.WIDTH(`EFF_IFAR_ARCH), .INIT(0)) br_iu_bta_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[br_iu_bta_offset:br_iu_bta_offset + `EFF_IFAR_ARCH - 1]),
      .scout(sov[br_iu_bta_offset:br_iu_bta_offset + `EFF_IFAR_ARCH - 1]),
      .din(br_iu_bta),
      .dout(br_iu_bta_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) next_fetch_nonspec_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[next_fetch_nonspec_offset:next_fetch_nonspec_offset + `THREADS - 1]),
      .scout(sov[next_fetch_nonspec_offset:next_fetch_nonspec_offset + `THREADS - 1]),
      .din(next_fetch_nonspec_d),
      .dout(next_fetch_nonspec_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) iu1_nonspec_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[iu1_nonspec_offset:iu1_nonspec_offset + `THREADS - 1]),
      .scout(sov[iu1_nonspec_offset:iu1_nonspec_offset + `THREADS - 1]),
      .din(iu1_nonspec_d),
      .dout(iu1_nonspec_l2)
   );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) iu2_nonspec_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(tiup),
      .thold_b(pc_iu_func_sl_thold_0_b),
      .sg(pc_iu_sg_0),
      .force_t(force_t),
      .delay_lclkr(delay_lclkr),
      .mpw1_b(mpw1_b),
      .mpw2_b(mpw2_b),
      .d_mode(d_mode),
      .scin(siv[iu2_nonspec_offset:iu2_nonspec_offset + `THREADS - 1]),
      .scout(sov[iu2_nonspec_offset:iu2_nonspec_offset + `THREADS - 1]),
      .din(iu2_nonspec_d),
      .dout(iu2_nonspec_l2)
   );

   generate
   begin : xhdl18
      genvar  i;
      for (i = 0; i < `THREADS; i = i + 1)
      begin : t
        tri_rlmreg_p #(.WIDTH(6), .INIT(0)) perf_event_latch(
           .vd(vdd),
           .gd(gnd),
           .nclk(nclk),
           .act(event_bus_enable),
           .thold_b(pc_iu_func_sl_thold_0_b),
           .sg(pc_iu_sg_0),
           .force_t(force_t),
           .delay_lclkr(delay_lclkr),
           .mpw1_b(mpw1_b),
           .mpw2_b(mpw2_b),
           .d_mode(d_mode),
           .scin(siv[perf_event_offset + i * 6:perf_event_offset + (i + 1) * 6 - 1]),
           .scout(sov[perf_event_offset + i * 6:perf_event_offset + (i + 1) * 6 - 1]),
           .din(perf_event_d[i]),
           .dout(perf_event_l2[i])
        );
     end
   end
   endgenerate

   //---------------------------------------------------------------------
   // Scan
   //---------------------------------------------------------------------
   assign siv[0:scan_right] = {sov[1:scan_right], func_scan_in};
   assign func_scan_out = sov[0];

endmodule
