// © 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:
//*
//* NAME: iuq_ic_miss.v
//*
//*********************************************************************

`include "tri_a2o.vh"


module iuq_ic_miss(
   vdd,
   gnd,
   nclk,
   pc_iu_func_sl_thold_0_b,
   pc_iu_sg_0,
   force_t,
   d_mode,
   delay_lclkr,
   mpw1_b,
   mpw2_b,
   scan_in,
   scan_out,
   iu_flush,
   br_iu_redirect,
   bp_ic_iu4_redirect,
   ic_bp_iu3_ecc_err,
   ics_icm_iu0_t0_ifar,
 `ifndef THREADS1
   ics_icm_iu0_t1_ifar,
 `endif
   ics_icm_iu0_inval,
   ics_icm_iu0_inval_addr,
   ics_icm_iu2_flush,
   icm_ics_hold_thread,
   icm_ics_hold_iu0,
   icm_ics_iu3_miss_match,
   icm_ics_iu3_ecc_fp_cancel,
   icm_ics_iu0_preload_val,
   icm_ics_iu0_preload_ifar,
   icm_ics_prefetch_req,
   icm_ics_prefetch_sm_idle,
   icm_icd_lru_addr,
   icm_icd_dir_inval,
   icm_icd_dir_val,
   icm_icd_data_write,
   icm_icd_reload_addr,
   icm_icd_reload_data,
   icm_icd_reload_way,
   icm_icd_load,
   icm_icd_load_addr,
   icm_icd_load_2ucode,
   icm_icd_load_2ucode_type,
   icm_icd_dir_write,
   icm_icd_dir_write_addr,
   icm_icd_dir_write_endian,
   icm_icd_dir_write_way,
   icm_icd_lru_write,
   icm_icd_lru_write_addr,
   icm_icd_lru_write_way,
   icm_icd_ecc_inval,
   icm_icd_ecc_addr,
   icm_icd_ecc_way,
   icm_icd_iu3_ecc_fp_cancel,
   icm_icd_any_reld_r2,
   icd_icm_miss,
   icd_icm_prefetch,
   icd_icm_tid,
   icd_icm_addr_real,
   icd_icm_addr_eff,
   icd_icm_wimge,
   icd_icm_userdef,
   icd_icm_2ucode,
   icd_icm_2ucode_type,
   icd_icm_iu2_inval,
   icd_icm_any_iu2_valid,
   icd_icm_row_lru,
   icd_icm_row_val,
   ic_perf_t0_event,
 `ifndef THREADS1
   ic_perf_t1_event,
 `endif
   cp_async_block,
   iu_mm_lmq_empty,
   iu_xu_icache_quiesce,
   iu_pc_icache_quiesce,
   an_ac_reld_data_vld,
   an_ac_reld_core_tag,
   an_ac_reld_qw,
   an_ac_reld_data,
   an_ac_reld_ecc_err,
   an_ac_reld_ecc_err_ue,
   spr_ic_cls,
   spr_ic_bp_config,
   iu_lq_request,
   iu_lq_ctag,
   iu_lq_ra,
   iu_lq_wimge,
   iu_lq_userdef,
   event_bus_enable
);


   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_sg_0;
   input                           force_t;
   input                           d_mode;
   input                           delay_lclkr;
   input                           mpw1_b;
   input                           mpw2_b;
   input                           scan_in;
   output                          scan_out;

   input [0:`THREADS-1]            iu_flush;
   input [0:`THREADS-1]            br_iu_redirect;
   input [0:`THREADS-1]            bp_ic_iu4_redirect;

   output                          ic_bp_iu3_ecc_err;

   input [46:52]                   ics_icm_iu0_t0_ifar;
 `ifndef THREADS1
   input [46:52]                   ics_icm_iu0_t1_ifar;
 `endif

   input                           ics_icm_iu0_inval;
   input [51:57]                   ics_icm_iu0_inval_addr;

   input [0:`THREADS-1]            ics_icm_iu2_flush;
   output [0:`THREADS-1]           icm_ics_hold_thread;
   output                          icm_ics_hold_iu0;
   output                          icm_ics_iu3_miss_match;
   output [0:`THREADS-1]           icm_ics_iu3_ecc_fp_cancel;

   output [0:`THREADS-1]           icm_ics_iu0_preload_val;
   output [50:59]                  icm_ics_iu0_preload_ifar;
   output [0:`THREADS-1]           icm_ics_prefetch_req;
   output [0:`THREADS-1]           icm_ics_prefetch_sm_idle;

   output [51:57]                  icm_icd_lru_addr;
   output                          icm_icd_dir_inval;
   output                          icm_icd_dir_val;
   output                          icm_icd_data_write;
   output [51:59]                  icm_icd_reload_addr;
   output [0:143]                  icm_icd_reload_data;
   output [0:3]                    icm_icd_reload_way;
   output [0:`THREADS-1]           icm_icd_load;
   output [62-`EFF_IFAR_WIDTH:61]  icm_icd_load_addr;
   output                          icm_icd_load_2ucode;
   output                          icm_icd_load_2ucode_type;
   output                          icm_icd_dir_write;
   output [64-`REAL_IFAR_WIDTH:57] icm_icd_dir_write_addr;
   output                          icm_icd_dir_write_endian;
   output [0:3]                    icm_icd_dir_write_way;
   output                          icm_icd_lru_write;
   output [51:57]                  icm_icd_lru_write_addr;
   output [0:3]                    icm_icd_lru_write_way;
   output                          icm_icd_ecc_inval;
   output [51:57]                  icm_icd_ecc_addr;
   output [0:3]                    icm_icd_ecc_way;
   output                          icm_icd_iu3_ecc_fp_cancel;
   output                          icm_icd_any_reld_r2;

   input                           icd_icm_miss;        // These signals, except icd_icm_miss, come off a latch
   input                           icd_icm_prefetch;
   input [0:`THREADS-1]            icd_icm_tid;
   input [64-`REAL_IFAR_WIDTH:61]  icd_icm_addr_real;
   input [62-`EFF_IFAR_WIDTH:51]   icd_icm_addr_eff;    // Shares bits 52:61 with real_ifar
   input [0:4]                     icd_icm_wimge;       // (1): CI, (4): Endian
   input [0:3]                     icd_icm_userdef;
   input                           icd_icm_2ucode;
   input                           icd_icm_2ucode_type;
   input                           icd_icm_iu2_inval;
   input                           icd_icm_any_iu2_valid;

   input [0:2]                     icd_icm_row_lru;     // valid same cycle as read_lru
   input [0:3]                     icd_icm_row_val;     // valid same cycle as read_lru

   output [0:2]                    ic_perf_t0_event;
 `ifndef THREADS1
   output [0:2]                    ic_perf_t1_event;
 `endif

   input [0:`THREADS-1]            cp_async_block;
   output                          iu_mm_lmq_empty;
   output [0:`THREADS-1]           iu_xu_icache_quiesce;
   output [0:`THREADS-1]           iu_pc_icache_quiesce;

   input                           an_ac_reld_data_vld;         // This comes back two cycles before the data
   input [0:4]                     an_ac_reld_core_tag;         // This signal comes active two cycles before the data
   input [58:59]                   an_ac_reld_qw;               // This signal comes active two cycles before the data
   input [0:127]                   an_ac_reld_data;             // This signal comes active two cycles after the valid
   input                           an_ac_reld_ecc_err;          // This signal comes active one cycle after data
   input                           an_ac_reld_ecc_err_ue;       // This signal comes active one cycle after data

   input                           spr_ic_cls;                  // (0): 64B cacheline, (1): 128B cacheline
   input [0:3]                     spr_ic_bp_config;            // (0): bc, (1): bclr, (2): bcctr, (3): sw

   output [0:`THREADS-1]           iu_lq_request;
   output [0:1]                    iu_lq_ctag;                  // (0): thread ID, (1): prefetch
   output [64-`REAL_IFAR_WIDTH:59] iu_lq_ra;
   output [0:4]                    iu_lq_wimge;
   output [0:3]                    iu_lq_userdef;

   input                           event_bus_enable;


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

   parameter                      SM_MAX = 4;   // max # of state machines (# of tables)
   parameter                      TAGS_USED = `THREADS * 2;

   parameter                      spr_ic_cls_offset = 0;
   parameter                      bp_config_offset = spr_ic_cls_offset + 1;
   parameter                      an_ac_reld_data_vld_offset = bp_config_offset + 4;
   parameter                      an_ac_reld_core_tag_offset = an_ac_reld_data_vld_offset + 1;
   parameter                      an_ac_reld_qw_offset = an_ac_reld_core_tag_offset + 5;
   parameter                      reld_data_offset = an_ac_reld_qw_offset + 2;
   parameter                      an_ac_reld_ecc_err_offset = reld_data_offset + 128;
   parameter                      an_ac_reld_ecc_err_ue_offset = an_ac_reld_ecc_err_offset + 1;
   parameter                      reld_r1_val_offset = an_ac_reld_ecc_err_ue_offset + 1;
   parameter                      reld_r1_qw_offset = reld_r1_val_offset + TAGS_USED;
   parameter                      reld_r2_val_offset = reld_r1_qw_offset + 2;
   parameter                      reld_r2_qw_offset = reld_r2_val_offset + TAGS_USED;
   parameter                      r2_crit_qw_offset = reld_r2_qw_offset + 2;
   parameter                      reld_r3_val_offset = r2_crit_qw_offset + 1;
   parameter                      r3_loaded_offset = reld_r3_val_offset + TAGS_USED;
   parameter                      request_offset = r3_loaded_offset + 1;
   parameter                      req_ctag_offset = request_offset + `THREADS;
   parameter                      req_ra_offset = req_ctag_offset + 2;
   parameter                      req_wimge_offset = req_ra_offset + `REAL_IFAR_WIDTH - 4;
   parameter                      req_userdef_offset = req_wimge_offset + 5;
   parameter                      iu3_miss_match_offset = req_userdef_offset + 4;

   parameter                      miss_tid_sm_offset = iu3_miss_match_offset + 1;
   parameter                      miss_count_offset = miss_tid_sm_offset + TAGS_USED * 6;
   parameter                      miss_flush_occurred_offset = miss_count_offset + TAGS_USED * 3;
   parameter                      miss_flushed_offset = miss_flush_occurred_offset + TAGS_USED;
   parameter                      miss_inval_offset = miss_flushed_offset + TAGS_USED;
   parameter                      miss_block_fp_offset = miss_inval_offset + TAGS_USED;
   parameter                      miss_ecc_err_offset = miss_block_fp_offset + TAGS_USED;
   parameter                      miss_ecc_err_ue_offset = miss_ecc_err_offset + TAGS_USED;
   parameter                      miss_wrote_dir_offset = miss_ecc_err_ue_offset + TAGS_USED;
   parameter                      miss_need_hold_offset = miss_wrote_dir_offset + TAGS_USED;
   parameter                      miss_addr_real_offset = miss_need_hold_offset + TAGS_USED;
   parameter                      miss_addr_eff_offset = miss_addr_real_offset + TAGS_USED * (`REAL_IFAR_WIDTH - 2);
   parameter                      miss_ci_offset = miss_addr_eff_offset + TAGS_USED * (`EFF_IFAR_WIDTH - 10);
   parameter                      miss_endian_offset = miss_ci_offset + TAGS_USED;
   parameter                      miss_2ucode_offset = miss_endian_offset + TAGS_USED;
   parameter                      miss_2ucode_type_offset = miss_2ucode_offset + TAGS_USED;
   parameter                      miss_way_offset = miss_2ucode_type_offset + TAGS_USED;
   parameter                      lru_write_next_cycle_offset = miss_way_offset + 4 * TAGS_USED;
   parameter                      lru_write_offset = lru_write_next_cycle_offset + TAGS_USED;
   parameter                      miss_prefetch_perf_offset = lru_write_offset + TAGS_USED;
   parameter                      perf_event_offset = miss_prefetch_perf_offset + `THREADS;
   parameter                      scan_right = perf_event_offset + `THREADS * 3 - 1;

   parameter                      IDLE = 0;
   parameter                      WAITMISS = 1;
   parameter                      WAITSTATE = 2;
   parameter                      DATA = 3;
   parameter                      CI = 4;
   parameter                      CHECK_ECC = 5;

   wire [1:24]                    select_lru_way_pt;

   // Latch definition begin
   wire [0:TAGS_USED-1]           reld_r1_val_d;
   wire                           spr_ic_cls_d;
   wire [0:3]                     bp_config_d;
   wire                           an_ac_reld_data_vld_d;
   wire [0:4]                     an_ac_reld_core_tag_d;
   wire [58:59]                   an_ac_reld_qw_d;
   wire [0:127]                   reld_data_d;
   wire                           an_ac_reld_ecc_err_d;
   wire                           an_ac_reld_ecc_err_ue_d;
   wire [0:1]                     reld_r1_qw_d;
   wire [0:TAGS_USED-1]           reld_r2_val_d;
   wire [0:1]                     reld_r2_qw_d;
   wire                           r2_crit_qw_d;
   wire [0:TAGS_USED-1]           reld_r3_val_d;
   wire                           r3_loaded_d;
   wire [0:`THREADS-1]            request_d;
   wire [0:1]                     req_ctag_d;
   wire [64-`REAL_IFAR_WIDTH:59]  req_ra_d;
   wire [0:4]                     req_wimge_d;
   wire [0:3]                     req_userdef_d;
   wire                           iu3_miss_match_d;
   wire [0:5]                     miss_tid_sm_d[0:SM_MAX-1];
   wire [0:2]                     miss_count_d[0:TAGS_USED-1];
   wire [64-`REAL_IFAR_WIDTH:61]  miss_addr_real_d[0:TAGS_USED-1];
   wire [62-`EFF_IFAR_WIDTH:51]   miss_addr_eff_d[0:TAGS_USED-1];
   wire [0:3]                     miss_way_d[0:TAGS_USED-1];
   wire [0:TAGS_USED-1]           miss_flush_occurred_d;
   wire [0:SM_MAX-1]              miss_flushed_d;
   wire [0:SM_MAX-1]              miss_inval_d;
   wire [0:TAGS_USED-1]           miss_block_fp_d;
   wire [0:TAGS_USED-1]           miss_ecc_err_d;
   wire [0:TAGS_USED-1]           miss_ecc_err_ue_d;
   wire [0:TAGS_USED-1]           miss_wrote_dir_d;
   wire [0:TAGS_USED-1]           miss_need_hold_d;
   wire [0:SM_MAX-1]              miss_ci_d;
   wire [0:TAGS_USED-1]           miss_endian_d;
   wire [0:TAGS_USED-1]           miss_2ucode_d;
   wire [0:TAGS_USED-1]           miss_2ucode_type_d;
   wire [0:TAGS_USED-1]           lru_write_next_cycle_d;
   wire [0:TAGS_USED-1]           lru_write_d;
   wire [0:`THREADS-1]            miss_prefetch_perf_d;
   wire [0:2]                     perf_event_d[0:`THREADS-1];

   wire [0:SM_MAX-1]              reld_r1_val_l2;
   wire                           spr_ic_cls_l2;
   wire [0:3]                     bp_config_l2;
   wire                           an_ac_reld_data_vld_l2;
   wire [0:4]                     an_ac_reld_core_tag_l2;
   wire [58:59]                   an_ac_reld_qw_l2;
   wire [0:127]                   reld_data_l2;
   wire                           an_ac_reld_ecc_err_l2;
   wire                           an_ac_reld_ecc_err_ue_l2;
   wire [0:1]                     reld_r1_qw_l2;
   wire [0:TAGS_USED-1]           reld_r2_val_l2;
   wire [0:1]                     reld_r2_qw_l2;
   wire                           r2_crit_qw_l2;
   wire [0:TAGS_USED-1]           reld_r3_val_l2;
   wire                           r3_loaded_l2;
   wire [0:`THREADS-1]            request_l2;
   wire [0:1]                     req_ctag_l2;
   wire [64-`REAL_IFAR_WIDTH:59]  req_ra_l2;
   wire [0:4]                     req_wimge_l2;
   wire [0:3]                     req_userdef_l2;
   wire                           iu3_miss_match_l2;
   wire [0:5]                     miss_tid_sm_l2[0:SM_MAX-1];       //state machine for each tag
   wire [0:2]                     miss_count_l2[0:TAGS_USED-1];
   wire [64-`REAL_IFAR_WIDTH:61]  miss_addr_real_l2[0:TAGS_USED-1];
   wire [62-`EFF_IFAR_WIDTH:51]   miss_addr_eff_l2[0:TAGS_USED-1];
   wire [0:3]                     miss_way_l2[0:TAGS_USED-1];
   wire [0:TAGS_USED-1]           miss_flush_occurred_l2;
   wire [0:SM_MAX-1]              miss_flushed_l2;
   wire [0:SM_MAX-1]              miss_inval_l2;
   wire [0:TAGS_USED-1]           miss_block_fp_l2;     //block fastpath
   wire [0:TAGS_USED-1]           miss_ecc_err_l2;
   wire [0:TAGS_USED-1]           miss_ecc_err_ue_l2;
   wire [0:TAGS_USED-1]           miss_wrote_dir_l2;
   wire [0:TAGS_USED-1]           miss_need_hold_l2;
   wire [0:SM_MAX-1]              miss_ci_l2;
   wire [0:TAGS_USED-1]           miss_endian_l2;
   wire [0:TAGS_USED-1]           miss_2ucode_l2;
   wire [0:TAGS_USED-1]           miss_2ucode_type_l2;
   wire [0:TAGS_USED-1]           lru_write_next_cycle_l2;
   wire [0:TAGS_USED-1]           lru_write_l2;
   wire [0:`THREADS-1]            miss_prefetch_perf_l2;
   wire [0:2]                     perf_event_l2[0:`THREADS-1];
   // Latch definition end

   wire [46:52]                   iu0_ifar[0:TAGS_USED-1];

   // Act control; only needed for power reduction
   wire [0:TAGS_USED-1]           default_reld_act_v;
   wire                           default_reld_act;
   wire                           miss_or_default_act;
   wire                           reld_r2_act;
   wire [0:TAGS_USED-1]           miss_act;

   // reload pipeline
   wire                           reld_r0_vld;
   wire [0:TAGS_USED-1]           reld_r0_tag;
   wire [0:`THREADS-1]            reld_r3_tid;

   wire [0:`THREADS-1]            iu_xu_icache_quiesce_int;

   wire [0:SM_MAX-1]              iu2_flush;
   wire [0:SM_MAX-1]              new_miss;
   wire [0:SM_MAX-1]              last_data;
   wire [0:TAGS_USED-1]           no_data;
   wire [0:TAGS_USED-1]           set_flush_occurred;
   wire [0:TAGS_USED-1]           flush_addr_outside_range;

   wire [0:TAGS_USED-1]           set_flushed;
   wire [0:TAGS_USED-1]           inval_equal;
   wire [0:TAGS_USED-1]           set_invalidated;
   wire [0:SM_MAX-1]              reset_state;
   wire [0:TAGS_USED-1]           sent_fp;
   wire [0:TAGS_USED-1]           set_block_fp;

   // this signal will check incoming addr against current valid addresses
   wire [0:TAGS_USED-1]           addr_equal;
   wire [0:TAGS_USED-1]           addr_match_tag;
   wire                           addr_match;
   wire                           miss_thread_has_idle;

   wire                           release_sm;
   wire [0:SM_MAX-1]              release_sm_hold /*verilator split_var*/;

   // IU0 inval
   wire [0:TAGS_USED-1]           iu0_inval_match;

   // OR these together to get iu_lq_request
   wire [0:SM_MAX-1]              request_tag;

   // fastpath
   wire [0:TAGS_USED-1]           preload_r0_tag;
   wire [0:`THREADS-1]            preload_r0_tid;
   wire [0:`THREADS-1]            preload_hold_iu0;
   reg [50:59]                    r0_addr;
   wire [0:SM_MAX-1]              load_tag;
   reg [62-`EFF_IFAR_WIDTH:61]    load_addr;
   wire                           load_2ucode;
   wire                           load_2ucode_type;
   wire [0:TAGS_USED-1]           load_tag_no_block;
   wire [0:`THREADS-1]            load_tid_no_block;

   // this signal indicates critical quadword is in r0, r1
   wire [0:TAGS_USED-1]           r0_crit_qw;
   wire [0:TAGS_USED-1]           r1_crit_qw;

   // lru
   wire                           lru_write_hit;
   wire [0:2]                     hit_lru;
   wire [0:2]                     row_lru;
   wire [0:TAGS_USED-1]           select_lru;
   reg [51:57]                    lru_addr;
   wire [0:TAGS_USED-1]           lru_valid;
   wire [0:TAGS_USED-1]           row_match;
   reg [0:3]                      row_match_way;
   wire [0:3]                     val_or_match;
   wire [0:3]                     next_lru_way;
   wire [0:3]                     next_way;

   // this signal is set by each state machine; OR bits together for final holds
   wire [0:SM_MAX-1]              hold_tid;
   wire                           hold_iu0;

   // OR these together to get icm_icd_*
   wire [0:SM_MAX-1]              write_dir_inval;
   wire [0:SM_MAX-1]              write_dir_val;
   wire [0:SM_MAX-1]              data_write;
   wire [0:SM_MAX-1]              dir_write;
   wire [0:TAGS_USED-1]           dir_write_no_block;

   reg [64-`REAL_IFAR_WIDTH:57]   reload_addr;
   reg [0:3]                      reload_way;
   wire                           reload_endian;
   wire                           reld_r1_endian;
   wire [0:127]                   swap_endian_data;

   wire [0:3]                     branch_decode0;
   wire [0:3]                     branch_decode1;
   wire [0:3]                     branch_decode2;
   wire [0:3]                     branch_decode3;

   wire [0:143]                   instr_data;

   wire [0:TAGS_USED-1]           lru_write;
   reg [51:57]                    lru_write_addr;
   reg [0:3]                      lru_write_way;

   // ECC Error handling
   wire [0:TAGS_USED-1]           new_ecc_err;
   wire [0:TAGS_USED-1]           new_ecc_err_ue;
   wire [0:SM_MAX-1]              ecc_err;
   wire [0:SM_MAX-1]              ecc_err_ue;
   wire [0:TAGS_USED-1]           ecc_inval;
   wire [0:TAGS_USED-1]           ecc_block_iu0;
   wire                           ecc_fp;
   reg [51:57]                    r3_addr;
   reg [0:3]                      r3_way;

   wire [0:SM_MAX-1]              active_l1_miss;
   wire [0:scan_right]            siv;
   wire [0:scan_right]            sov;

   wire [0:31]                    tidn32;


    (* analysis_not_referenced="true" *)

   wire                           miss_unused;

   //@@ START OF EXECUTABLE CODE FOR IUQ_IC_MISS

   assign tidn32 = 32'b0;

   generate
   begin : xhdl1
     if (TAGS_USED < SM_MAX)
     begin : gen_unused_t1
	   assign miss_unused = | {load_tag[TAGS_USED:SM_MAX - 1], reset_state[TAGS_USED:SM_MAX - 1], request_tag[TAGS_USED:SM_MAX - 1], write_dir_val[TAGS_USED:SM_MAX - 1], hold_tid[TAGS_USED:SM_MAX - 1], dir_write[TAGS_USED:SM_MAX - 1], miss_ci_d[TAGS_USED:SM_MAX - 1], miss_flushed_d[TAGS_USED:SM_MAX - 1], miss_inval_d[TAGS_USED:SM_MAX - 1], active_l1_miss[TAGS_USED:SM_MAX-1], miss_tid_sm_d[TAGS_USED], miss_tid_sm_d[SM_MAX - 1]};    // ??? tid_sm isn't covered for (sm_max-tags_used > 2)

       // sourceless unused
       assign iu2_flush[TAGS_USED:SM_MAX - 1]       = {SM_MAX-TAGS_USED{1'b0}};
       assign new_miss[TAGS_USED:SM_MAX - 1]        = {SM_MAX-TAGS_USED{1'b0}};
       assign last_data[TAGS_USED:SM_MAX - 1]       = {SM_MAX-TAGS_USED{1'b0}};
       assign ecc_err[TAGS_USED:SM_MAX - 1]         = {SM_MAX-TAGS_USED{1'b0}};
       assign ecc_err_ue[TAGS_USED:SM_MAX - 1]      = {SM_MAX-TAGS_USED{1'b0}};

       // Latches
       assign reld_r1_val_l2[TAGS_USED:SM_MAX - 1]  = {SM_MAX-TAGS_USED{1'b0}};

       assign miss_flushed_d[TAGS_USED:SM_MAX - 1]  = {SM_MAX-TAGS_USED{1'b0}};
       assign miss_inval_d[TAGS_USED:SM_MAX - 1]    = {SM_MAX-TAGS_USED{1'b0}};
       assign miss_ci_d[TAGS_USED:SM_MAX - 1]       = {SM_MAX-TAGS_USED{1'b0}};

       assign miss_flushed_l2[TAGS_USED:SM_MAX - 1] = {SM_MAX-TAGS_USED{1'b0}};
       assign miss_inval_l2[TAGS_USED:SM_MAX - 1]   = {SM_MAX-TAGS_USED{1'b0}};
       assign miss_ci_l2[TAGS_USED:SM_MAX - 1]      = {SM_MAX-TAGS_USED{1'b0}};

       genvar  i;
       for (i = TAGS_USED; i < SM_MAX; i = i + 1)
       begin : gen_sm_t1
         assign miss_tid_sm_l2[i][0] = 1'b1;
         assign miss_tid_sm_l2[i][1:CHECK_ECC] = {CHECK_ECC{1'b0}};
       end
     end

     if (TAGS_USED >= SM_MAX)
     begin : gen_unused_t2
       assign miss_unused = 1'b0;
     end

   end
   endgenerate

   assign iu0_ifar[0] = ics_icm_iu0_t0_ifar;
   assign iu0_ifar[1] = ics_icm_iu0_t0_ifar;

  `ifndef THREADS1
     assign iu0_ifar[2] = ics_icm_iu0_t1_ifar;
     assign iu0_ifar[3] = ics_icm_iu0_t1_ifar;
  `endif

   //---------------------------------------------------------------------
   // Latch Inputs, Reload pipeline
   //---------------------------------------------------------------------
   generate
   begin : xhdl2
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_default_reld_act
       assign default_reld_act_v[i] = (~miss_tid_sm_l2[i][IDLE]);
     end
   end
   endgenerate

   assign default_reld_act = |(default_reld_act_v);
   assign miss_or_default_act = default_reld_act | (|(miss_act));
   assign reld_r2_act = |(reld_r1_val_l2);

   assign bp_config_d = spr_ic_bp_config;        // ??? Do I need to latch these?  How far away is spr?
   assign spr_ic_cls_d = spr_ic_cls;

   // d-2 (r0)
   assign an_ac_reld_data_vld_d = an_ac_reld_data_vld;
   assign an_ac_reld_core_tag_d = an_ac_reld_core_tag;
   assign an_ac_reld_qw_d = an_ac_reld_qw;

   // d-1 (r1)
   // Core_tag(0:2) specifies unit (IU is '010'); Core_tag(3:4) is encoded Thread ID
   assign reld_r0_vld = an_ac_reld_data_vld_l2 & (an_ac_reld_core_tag_l2[0:2] == 3'b010);

   generate
   begin : xhdl3
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_reld_tag
       wire [0:1]  index = i;
       assign reld_r0_tag[i] = (an_ac_reld_core_tag_l2[3:4] == index);
     end
   end
   endgenerate

   assign reld_r1_val_d = {TAGS_USED{reld_r0_vld}} & reld_r0_tag;
   assign reld_r1_qw_d = an_ac_reld_qw_l2;

   // d (r2)
   // Use reld_r1_vld as act to gate clock
   assign reld_r2_val_d = reld_r1_val_l2[0:TAGS_USED - 1];
   assign reld_r2_qw_d = reld_r1_qw_l2;

   // d+1 (r3)
   assign reld_r3_val_d = reld_r2_val_l2;
   assign an_ac_reld_ecc_err_d = an_ac_reld_ecc_err;
   assign an_ac_reld_ecc_err_ue_d = an_ac_reld_ecc_err_ue;

   generate
   begin : xhdl4
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_reld_r3_tid
       assign reld_r3_tid[i] = reld_r3_val_l2[2 * i] | reld_r3_val_l2[2 * i + 1];
       assign iu2_flush[2 * i] = ics_icm_iu2_flush[i];
       assign iu2_flush[2 * i + 1] = ics_icm_iu2_flush[i];
     end
   end
   endgenerate

   //---------------------------------------------------------------------
   // State Machine
   //---------------------------------------------------------------------
   // Example State Ordering for cacheable reloads
   // OLD:
   //  64B Cacheline, No Gaps    :  (1)(3)(4)(5)(6)(11)            - Wait 0, Data0, Data1, Data2, Data3, CheckECC
   //  64B Cacheline, Always Gaps:  (1)(3)(8)(4)(9)(5)(10)(6)(11)  - Wait 0, Data0, Wait1, Data1, Wait2, Data2, Wait3, Data3, CheckECC
   // 128B Cacheline, No Gaps    :  (1)(3)(4)(5)(12)(13)(14)(15)(6)(11)    - Wait 0, Data0, Data1, Data2, Data3_128B, Data4_128B, Data5_128B, Data6_128B, Data3/7, CheckECC
   // 128B Cacheline, Always Gaps:  (1)(3)(8)(4)(9)(5)(16)(12)(17)(13)(18)(14)(19)(15)(10)(6)(11)
   //          - Wait 0, Data0, Wait1, Data1, Wait2, Data2, Wait3_128B, Data3_128B, Wait4_128B, Data4_128B, Wait5_128B, Data5_128B, Wait6_128B, Data6_128B, Data3/7, CheckECC
   //
   // New:
   //  64B Cacheline, No Gaps      : (2)(3)(3)(3)(3)(5)            - Wait, Data, Data, Data, Data, CheckECC
   //  64B Cacheline, Always Gaps  : (2)(3)(2)(3)(2)(3)(2)(3)(5)   - Wait, Data, Wait, Data, Wait, Data, Wait, Data, CheckECC
   // similar pattern for 128B
   //
   // For now, always generating 4 tables, even if only 1 thread.  Can't generate based on a generic, and don't want to include config file.  Extra tables should optimize out when not needed.
   //
   generate
   begin
     genvar  i;
     for (i = 0; i < SM_MAX; i = i + 1)
     begin : miss_sm_loop
       iuq_ic_miss_table  miss_sm(
          .new_miss(new_miss[i]),
          .miss_ci_l2(miss_ci_l2[i]),
          .reld_r1_val_l2(reld_r1_val_l2[i]),
          .r2_crit_qw_l2(r2_crit_qw_l2),
          .ecc_err(ecc_err[i]),
          .ecc_err_ue(ecc_err_ue[i]),
          .addr_match(addr_match),
          .iu2_flush(iu2_flush[i]),
          .release_sm(release_sm),
          .miss_flushed_l2(miss_flushed_l2[i]),
          .miss_inval_l2(miss_inval_l2[i]),
          .miss_tid_sm_l2(miss_tid_sm_l2[i]),
          .last_data(last_data[i]),
          .miss_tid_sm_d(miss_tid_sm_d[i]),
          .reset_state(reset_state[i]),
          .request_tag(request_tag[i]),
          .write_dir_inval(write_dir_inval[i]),
          .write_dir_val(write_dir_val[i]),
          .hold_tid(hold_tid[i]),
          .data_write(data_write[i]),
          .dir_write(dir_write[i]),
          .load_tag(load_tag[i]),
          .release_sm_hold(release_sm_hold[i])
       );
     end
   end
   endgenerate

   //---------------------------------------------------------------------

   assign iu_mm_lmq_empty = &(iu_xu_icache_quiesce_int) & (~(|(cp_async_block)));
   assign iu_xu_icache_quiesce = iu_xu_icache_quiesce_int;
   assign iu_pc_icache_quiesce = iu_xu_icache_quiesce_int;

   // SM0 is only for non-prefetches, SM1 is for prefetches, or for new IFetches if SM1 is free and SM0 is busy (e.g. sometimes after flush)
   generate
   begin : xhdl5
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_new_miss
       assign new_miss[2*i]     = icd_icm_miss & icd_icm_tid[i] & (~icd_icm_prefetch);
       assign new_miss[2*i+1] = icd_icm_miss & icd_icm_tid[i] & ((icd_icm_prefetch & (~icd_icm_wimge[1]) & (~icd_icm_wimge[3])) | (~miss_tid_sm_l2[2*i][IDLE]));

       // Only active when performance enabled
       assign miss_prefetch_perf_d[i] = (icd_icm_miss & icd_icm_tid[i] & miss_tid_sm_l2[2*i+1][IDLE]) ?
	 (icd_icm_prefetch & (~icd_icm_wimge[1]) & (~icd_icm_wimge[3])) :
	  miss_prefetch_perf_l2[i];

       assign iu_xu_icache_quiesce_int[i] = miss_tid_sm_l2[2*i][IDLE] & miss_tid_sm_l2[2*i+1][IDLE];
       assign icm_ics_prefetch_req[i] = icd_icm_miss & icd_icm_tid[i] & (~icd_icm_prefetch) & (~icd_icm_wimge[1]) & (~icd_icm_wimge[3]) & (~addr_match) & (miss_tid_sm_l2[2*i][IDLE] | miss_tid_sm_l2[2*i+1][IDLE]) & (~ics_icm_iu2_flush[i]);
       assign icm_ics_prefetch_sm_idle[i] = miss_tid_sm_l2[2*i+1][IDLE];
     end

     //genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_miss
       // Count down from 3 (if 64B) or 7 (if 128B)
       assign miss_count_d[i] = ((request_tag[i] | (miss_tid_sm_l2[i][CHECK_ECC] & ecc_err[i])) == 1'b1) ? {spr_ic_cls_l2, 2'b11} :
                                (miss_tid_sm_l2[i][DATA] == 1'b1) ? miss_count_l2[i] - 3'b001 :
                                 miss_count_l2[i];

       assign last_data[i] = miss_count_l2[i] == 3'b000;
       assign no_data[i] = miss_count_l2[i] == {spr_ic_cls_l2, 2'b11};

       assign miss_act[i] = miss_tid_sm_l2[i][IDLE] & icd_icm_any_iu2_valid & icd_icm_tid[i/2];         // Idle state and processing this thread
       assign miss_addr_real_d[i] = icd_icm_addr_real;          // uses miss_act
       assign miss_addr_eff_d[i] = icd_icm_addr_eff;            // uses miss_act
       assign miss_ci_d[i] = icd_icm_wimge[1];                  // uses miss_act
       assign miss_endian_d[i] = icd_icm_wimge[4];              // uses miss_act
       assign miss_2ucode_d[i] = icd_icm_2ucode;                // uses miss_act
       assign miss_2ucode_type_d[i] = icd_icm_2ucode_type;      // uses miss_act

       // State-related latches
       assign set_flush_occurred[i] = (iu_flush[i/2] | br_iu_redirect[i/2] | bp_ic_iu4_redirect[i/2]) & (~miss_tid_sm_l2[i][IDLE]) & (~miss_tid_sm_l2[i][WAITMISS]);
       assign miss_flush_occurred_d[i] = (reset_state[i] == 1'b1) ?        1'b0 :  // reset when going back to idle state
                                         (set_flush_occurred[i] == 1'b1) ? 1'b1 :  // set when new flush
                                         miss_flush_occurred_l2[i];

       // Flushed before entering Data0 - don't load ICache if flushed outside range
       assign flush_addr_outside_range[i] = iu0_ifar[i] != {miss_addr_eff_l2[i][46:51], miss_addr_real_l2[i][52]};    // eff address shares lower bits with real addr

       assign set_flushed[i] = miss_flush_occurred_l2[i] & flush_addr_outside_range[i] & reld_r1_val_l2[i] &
           ((miss_tid_sm_l2[i][WAITSTATE] & no_data[i]) | miss_tid_sm_l2[i][CHECK_ECC]);

       assign miss_flushed_d[i] = (reset_state[i] == 1'b1) ? 1'b0 :  // reset when going back to idle state
                                  (set_flushed[i] == 1'b1) ? 1'b1 :  // set when new flush
                                  miss_flushed_l2[i];
     end

     assign inval_equal = {TAGS_USED{icd_icm_iu2_inval}} & addr_equal;

     //genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_miss_inval
       assign set_invalidated[i] = inval_equal[i] & (~miss_tid_sm_l2[i][IDLE]) & (~miss_tid_sm_l2[i][WAITMISS]) & (~miss_ci_l2[i]);
       assign miss_inval_d[i] = (reset_state[i] == 1'b1)     ? 1'b0 :  // reset when going back to idle state
                                (set_invalidated[i] == 1'b1) ? 1'b1 :  // set when new back_inv
                                miss_inval_l2[i];
     end

     //genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_miss_block_fp
       assign sent_fp[i] = (r3_loaded_l2 & (~(an_ac_reld_ecc_err_l2))) & reld_r3_val_l2[i];   // sent critical qw last cycle (unless it was blocked)
       assign set_block_fp[i] = sent_fp[i] |    // sent critical qw last cycle and not ecc err
           (iu2_flush[i] & (~(miss_tid_sm_l2[i][IDLE] | miss_tid_sm_l2[i][WAITMISS]))) |
           (icd_icm_prefetch & new_miss[i] & miss_tid_sm_l2[i][IDLE] & miss_tid_sm_d[i][WAITSTATE]);
       assign miss_block_fp_d[i] = (reset_state[i] == 1'b1)  ? 1'b0 :  // reset when going back to idle state
                                   (set_block_fp[i] == 1'b1) ? 1'b1 :  // set when new block condition
                                   miss_block_fp_l2[i];
     end

     //genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_miss_ecc_err
       assign miss_ecc_err_d[i] = ((miss_tid_sm_l2[i][WAITSTATE] & no_data[i]) == 1'b1) ? 1'b0 :  // reset before starting or resending data
                                  (new_ecc_err[i] == 1'b1) ? 1'b1 :
                                  miss_ecc_err_l2[i];

       assign miss_ecc_err_ue_d[i] = ((miss_tid_sm_l2[i][WAITSTATE] & no_data[i]) == 1'b1) ? 1'b0 :  // reset before starting or resending data
                                     (new_ecc_err_ue[i] == 1'b1) ? an_ac_reld_ecc_err_ue_l2 :
                                     miss_ecc_err_ue_l2[i];

       assign addr_equal[i] = (icd_icm_addr_real[64 - `REAL_IFAR_WIDTH:56] == miss_addr_real_l2[i][64 - `REAL_IFAR_WIDTH:56]) &
                              (spr_ic_cls_l2 | (icd_icm_addr_real[57] == miss_addr_real_l2[i][57]));

       assign addr_match_tag[i] = (addr_equal[i] & (~miss_tid_sm_l2[i][IDLE]));
     end

     assign addr_match = |(addr_match_tag);

     if (`THREADS == 1)
     begin : gen_is_idle_t1
       assign miss_thread_has_idle = miss_tid_sm_l2[0][IDLE] | miss_tid_sm_l2[1][IDLE];
     end
     if (`THREADS == 2)
     begin : gen_is_idle_t2
       assign miss_thread_has_idle = ((miss_tid_sm_l2[0][IDLE] | miss_tid_sm_l2[1][IDLE]) & icd_icm_tid[0]) |
                                     ((miss_tid_sm_l2[2][IDLE] | miss_tid_sm_l2[3][IDLE]) & icd_icm_tid[1]);
     end

     assign iu3_miss_match_d = (miss_thread_has_idle == 1'b1) ? addr_match :    // new miss matches other reload
                                                                1'b1;  //(not miss_thread_has_idle)  --2nd (or 3rd) miss for thread - SM's full;
     assign icm_ics_iu3_miss_match = iu3_miss_match_l2;

     assign release_sm = |(release_sm_hold);

     //genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_miss_wrote
       // Detect write through collision with invalidate array read
       assign iu0_inval_match[i] = ics_icm_iu0_inval & (ics_icm_iu0_inval_addr[51:56] == miss_addr_real_l2[i][51:56]) &
                                      (spr_ic_cls_l2 | (ics_icm_iu0_inval_addr[57] == miss_addr_real_l2[i][57]));

       assign miss_wrote_dir_d[i] = (reset_state[i] == 1'b1) ? 1'b0 :  // reset when going back to idle state
                                    (dir_write_no_block[i] | miss_wrote_dir_l2[i]);
     end

     //genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_need_hold
       // Hold if new miss to SM0, or if new miss and no SMs available
       assign miss_need_hold_d[2*i] = (iu2_flush[2*i] == 1'b1) ? 1'b0 :
                ((new_miss[2*i] &
                  (miss_tid_sm_l2[2*i][IDLE] | ((~miss_tid_sm_l2[2*i][IDLE]) & (~miss_tid_sm_l2[2*i+1][IDLE])))) == 1'b1) ? 1'b1 :
                miss_need_hold_l2[2*i];

       // Hold if new miss to SM1
       assign miss_need_hold_d[2*i+1] = ((iu2_flush[2*i+1] | reset_state[2*i+1]) == 1'b1) ? 1'b0 :
                                        ((new_miss[2*i] &     // -- yes, I meant new_miss(2*i) - this is miss and tid and not prefetch
                                          miss_tid_sm_l2[2*i+1][IDLE] & (~miss_tid_sm_l2[2*i][IDLE])) == 1'b1) ? 1'b1 :
                                        miss_need_hold_l2[2 * i + 1];
     end
   end
   endgenerate

   //---------------------------------------------------------------------
   // Send request
   //---------------------------------------------------------------------
   generate
   begin : xhdl12
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_request
       assign request_d[i] = request_tag[2*i] | request_tag[2*i+1];
     end

     if (`THREADS == 1)
     begin : gen_ctag_t1
       assign req_ctag_d[0] = 1'b0;
     end
     if (`THREADS == 2)
     begin : gen_ctag_t2
       assign req_ctag_d[0] = icd_icm_tid[1];
     end
   end
   endgenerate

   assign req_ctag_d[1] = new_miss[1] | new_miss[TAGS_USED - 1];        // prefetch or extra IFetch

   assign req_ra_d = icd_icm_addr_real[64 - `REAL_IFAR_WIDTH:59];
   assign req_wimge_d = icd_icm_wimge;
   assign req_userdef_d = icd_icm_userdef;

   assign iu_lq_request = request_l2;
   assign iu_lq_ctag = req_ctag_l2;
   assign iu_lq_ra = req_ra_l2;
   assign iu_lq_wimge = req_wimge_l2;
   assign iu_lq_userdef = req_userdef_l2;

   //---------------------------------------------------------------------
   // address muxing
   //---------------------------------------------------------------------

//   always @(reld_r0_tag or reld_r1_val_l2 or reld_r2_val_l2 or lru_write_l2 or reld_r3_val_l2 or row_match or miss_addr_eff_l2 or miss_addr_real_l2 or miss_way_l2)
   always @(*)
   begin: addr_mux_proc
     reg [50:59]                    r0_addr_calc;
     reg [51:57]                    lru_addr_calc;
     reg [62-`EFF_IFAR_WIDTH:61]    load_addr_calc;
     reg [64-`REAL_IFAR_WIDTH:57]   reload_addr_calc;
     reg [0:3]                      reload_way_calc;
     reg [51:57]                    lru_write_addr_calc;
     reg [0:3]                      lru_write_way_calc;
     reg [51:57]                    r3_addr_calc;
     reg [0:3]                      r3_way_calc;
     reg [0:3]                      row_match_way_calc;
     //(* analysis_not_referenced="true" *)
     integer                        i;
     r0_addr_calc = 10'b0;
     lru_addr_calc = 7'b0;
     load_addr_calc = {`EFF_IFAR_WIDTH{1'b0}};
     reload_addr_calc = {`REAL_IFAR_WIDTH-6{1'b0}};
     reload_way_calc = 4'b0;
     lru_write_addr_calc = 7'b0;
     lru_write_way_calc = 4'b0;
     r3_addr_calc = 7'b0;
     r3_way_calc = 4'b0;
     row_match_way_calc = 4'b0;

     for (i = 0; i < TAGS_USED; i = i + 1)
     begin
       r0_addr_calc = r0_addr_calc |
           {10{reld_r0_tag[i]}} & {miss_addr_eff_l2[i][50:51], miss_addr_real_l2[i][52:59]};
       lru_addr_calc = lru_addr_calc |
           {7{reld_r1_val_l2[i]}} & miss_addr_real_l2[i][51:57];
       load_addr_calc = load_addr_calc |
           {`EFF_IFAR_WIDTH{reld_r2_val_l2[i]}} & {miss_addr_eff_l2[i], miss_addr_real_l2[i][52:61]};
       reload_addr_calc = reload_addr_calc |
           {`REAL_IFAR_WIDTH-6{reld_r2_val_l2[i]}} & miss_addr_real_l2[i][64 - `REAL_IFAR_WIDTH:57];
       reload_way_calc = reload_way_calc |
           {4{reld_r2_val_l2[i]}} & miss_way_l2[i];
       lru_write_addr_calc = lru_write_addr_calc |
           {7{lru_write_l2[i]}} & miss_addr_real_l2[i][51:57];
       lru_write_way_calc = lru_write_way_calc |
           {4{lru_write_l2[i]}} & miss_way_l2[i];
       r3_addr_calc = r3_addr_calc |
           {7{reld_r3_val_l2[i]}} & miss_addr_real_l2[i][51:57];
       r3_way_calc = r3_way_calc |
           {4{reld_r3_val_l2[i]}} & miss_way_l2[i];
       row_match_way_calc = row_match_way_calc |
           {4{row_match[i]}} & miss_way_l2[i];
     end
     r0_addr = r0_addr_calc;
     lru_addr = lru_addr_calc;
     load_addr = load_addr_calc;
     reload_addr = reload_addr_calc;
     reload_way = reload_way_calc;
     lru_write_addr = lru_write_addr_calc;
     lru_write_way = lru_write_way_calc;
     r3_addr = r3_addr_calc;
     r3_way = r3_way_calc;
     row_match_way = row_match_way_calc;
   end

   //---------------------------------------------------------------------
   // fastpath-related signals
   //---------------------------------------------------------------------
   // for first beat of data: create hole in IU0 so we can fastpath data into IU2
   assign preload_r0_tag = r0_crit_qw & reld_r0_tag & (~miss_block_fp_l2) & (~miss_flushed_l2[0:TAGS_USED - 1]);

   generate
   begin : xhdl13
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_preload_r0_tid
       assign preload_r0_tid[i] = preload_r0_tag[2*i] | preload_r0_tag[2*i+1];
     end
   end
   endgenerate

   assign preload_hold_iu0 = {`THREADS{reld_r0_vld}} & preload_r0_tid;

   assign icm_ics_iu0_preload_val = preload_hold_iu0;
   assign icm_ics_iu0_preload_ifar = r0_addr;

   assign load_2ucode = |(reld_r2_val_l2 & miss_2ucode_l2);
   assign load_2ucode_type = |(reld_r2_val_l2 & miss_2ucode_type_l2);
   assign load_tag_no_block = load_tag[0:TAGS_USED - 1] & (~miss_block_fp_l2[0:TAGS_USED - 1]);

   generate
   begin : xhdl14
     genvar  i;
     for (i = 0; i < `THREADS; i = i + 1)
     begin : gen_load_tid
       assign load_tid_no_block[i] = load_tag_no_block[2*i] | load_tag_no_block[2*i+1];
     end
   end
   endgenerate

   assign icm_icd_load = load_tid_no_block;
   assign icm_icd_load_addr = load_addr;
   assign icm_icd_load_2ucode = load_2ucode;
   assign icm_icd_load_2ucode_type = load_2ucode_type;

   assign r3_loaded_d = |(load_tid_no_block);

   //---------------------------------------------------------------------
   // Critical Quadword
   //---------------------------------------------------------------------
   // Note: Could latch reld_crit_qw signal from L2, but we need addr (60:61), so might as well keep whole address
   generate
   begin : xhdl15
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_crit_qw
       assign r0_crit_qw[i] = an_ac_reld_qw_l2[58:59] == miss_addr_real_l2[i][58:59];
       assign r1_crit_qw[i] = reld_r1_qw_l2 == miss_addr_real_l2[i][58:59];
     end
   end
   endgenerate

   assign r2_crit_qw_d = |(r1_crit_qw & reld_r1_val_l2[0:TAGS_USED - 1]);

   //---------------------------------------------------------------------
   // Get LRU
   //---------------------------------------------------------------------
   // ??? Might have to read in r0

   assign lru_write_hit = |(lru_write) & (lru_addr[51:56] == lru_write_addr[51:56]) &
                         (spr_ic_cls_l2 | (lru_addr[57] == lru_write_addr[57]));

   assign hit_lru = ({3{lru_write_way[0]}} & {2'b11, icd_icm_row_lru[2]}) |
                    ({3{lru_write_way[1]}} & {2'b10, icd_icm_row_lru[2]}) |
                    ({3{lru_write_way[2]}} & {1'b0, icd_icm_row_lru[1], 1'b1}) |
                    ({3{lru_write_way[3]}} & {1'b0, icd_icm_row_lru[1], 1'b0});

   assign row_lru = (lru_write_hit == 1'b0) ? icd_icm_row_lru :
                    hit_lru;

   generate
   begin : xhdl16
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_lru
       // Select_lru in r1
       assign select_lru[i] = (~miss_ci_l2[i]) & reld_r1_val_l2[i] & (miss_tid_sm_l2[i][WAITSTATE] & no_data[i]) & (~miss_flushed_l2[i]) & (~miss_inval_l2[i]);

       // lru/way is valid in Data0-3, Wait1-3, CheckECC
       // lru_valid(<a>) <= (miss_tid<a>_sm_l2(3) or miss_tid<a>_sm_l2(4) or miss_tid<a>_sm_l2(5) or miss_tid<a>_sm_l2(6) or
       //                   miss_tid<a>_sm_l2(8) or miss_tid<a>_sm_l2(9) or miss_tid<a>_sm_l2(10) or miss_tid<a>_sm_l2(11) ) and not miss_flushed<a>_l2 and not miss_inval<a>_l2;
       assign lru_valid[i] = (~(miss_tid_sm_l2[i][IDLE] | miss_tid_sm_l2[i][WAITMISS] | (miss_tid_sm_l2[i][WAITSTATE] & no_data[i]) | miss_flushed_l2[i] | miss_inval_l2[i] | miss_ci_l2[i]));

       // check if any other thread is writing into this spot in the cache
       assign row_match[i] = lru_valid[i] & (lru_addr[51:56] == miss_addr_real_l2[i][51:56]) & (spr_ic_cls_l2 | (lru_addr[57] == miss_addr_real_l2[i][57]));
     end
   end
   endgenerate

   assign val_or_match = icd_icm_row_val | row_match_way;

   // Old: Use if can never hit more than one entry, since only two reloads are in data mode at a time
   //?TABLE select_lru_way LISTING(final) OPTIMIZE PARMS(ON-SET, OFF-SET);
   //*INPUTS*=================*OUTPUTS*======*
   //|                        |              |
   //| row_match_way          |              |
   //| |     row_lru          |              |
   //| |     |                | next_lru_way |
   //| |     |                | |            |
   //| |     |                | |            |
   //| 0123  012              | 0123         |
   //*TYPE*===================+==============+
   //| PPPP  PPP              | PPPP         |
   //*TERMS*==================+==============+
   //| 0---  00-              | 1000         |
   //| 1---  000              | 0010         |
   //| 1---  001              | 0001         |
   //|                        |              |
   //| -0--  01-              | 0100         |
   //| -1--  010              | 0010         |
   //| -1--  011              | 0001         |
   //|                        |              |
   //| --0-  1-0              | 0010         |
   //| --1-  100              | 1000         |
   //| --1-  110              | 0100         |
   //|                        |              |
   //| ---0  1-1              | 0001         |
   //| ---1  101              | 1000         |
   //| ---1  111              | 0100         |
   //*END*====================+==============+
   //?TABLE END select_lru_way;

   // Could have all 4 tags going to same row
/*
//table_start
?TABLE select_lru_way LISTING(final) OPTIMIZE PARMS(ON-SET, OFF-SET);
*INPUTS*=================*OUTPUTS*======*
|                        |              |
| row_lru                |              |
| |    row_match_way     |              |
| |    |                 | next_lru_way |
| |    |                 | |            |
| |    |                 | |            |
| 012  0123              | 0123         |
*TYPE*===================+==============+
| PPP  PPPP              | PPPP         |
*TERMS*==================+==============+
| 00-  0---              | 1000         |
| 000  1-0-              | 0010         |
| 000  101-              | 0100         |
| 000  111-              | 0001         |
| 001  1--0              | 0001         |
| 001  10-1              | 0100         |
| 001  11-1              | 0010         |
|                        |              |
| 01-  -0--              | 0100         |
| 010  -10-              | 0010         |
| 010  011-              | 1000         |
| 010  111-              | 0001         |
| 011  -1-0              | 0001         |
| 011  01-1              | 1000         |
| 011  11-1              | 0010         |
|                        |              |
| 1-0  --0-              | 0010         |
| 100  0-1-              | 1000         |
| 100  1-10              | 0001         |
| 100  1-11              | 0100         |
| 110  -01-              | 0100         |
| 110  -110              | 0001         |
| 110  -111              | 1000         |
|                        |              |
| 1-1  ---0              | 0001         |
| 101  0--1              | 1000         |
| 101  1-01              | 0010         |
| 101  1-11              | 0100         |
| 111  -0-1              | 0100         |
| 111  -101              | 0010         |
| 111  -111              | 1000         |
*END*====================+==============+
?TABLE END select_lru_way;
//table_end
*/

//assign_start

assign select_lru_way_pt[1] =
    (({ row_lru[0] , row_lru[2] ,
    row_match_way[0] , row_match_way[1] ,
    row_match_way[3] }) === 5'b01011);
assign select_lru_way_pt[2] =
    (({ row_lru[0] , row_lru[2] ,
    row_match_way[0] , row_match_way[1] ,
    row_match_way[2] }) === 5'b00011);
assign select_lru_way_pt[3] =
    (({ row_lru[0] , row_lru[2] ,
    row_match_way[0] , row_match_way[1] ,
    row_match_way[3] }) === 5'b01101);
assign select_lru_way_pt[4] =
    (({ row_lru[0] , row_lru[2] ,
    row_match_way[0] , row_match_way[1] ,
    row_match_way[2] }) === 5'b00101);
assign select_lru_way_pt[5] =
    (({ row_lru[0] , row_lru[1] ,
    row_match_way[1] , row_match_way[2] ,
    row_match_way[3] }) === 5'b11101);
assign select_lru_way_pt[6] =
    (({ row_lru[0] , row_lru[1] ,
    row_match_way[0] , row_match_way[2] ,
    row_match_way[3] }) === 5'b10101);
assign select_lru_way_pt[7] =
    (({ row_lru[0] , row_lru[1] ,
    row_match_way[1] , row_match_way[2] ,
    row_match_way[3] }) === 5'b11110);
assign select_lru_way_pt[8] =
    (({ row_lru[0] , row_lru[1] ,
    row_match_way[0] , row_match_way[2] ,
    row_match_way[3] }) === 5'b10110);
assign select_lru_way_pt[9] =
    (({ row_lru[0] , row_lru[1] ,
    row_match_way[1] , row_match_way[2] ,
    row_match_way[3] }) === 5'b11111);
assign select_lru_way_pt[10] =
    (({ row_lru[0] , row_lru[1] ,
    row_match_way[0] , row_match_way[2] ,
    row_match_way[3] }) === 5'b10111);
assign select_lru_way_pt[11] =
    (({ row_lru[0] , row_lru[2] ,
    row_match_way[0] , row_match_way[1] ,
    row_match_way[3] }) === 5'b01111);
assign select_lru_way_pt[12] =
    (({ row_lru[0] , row_lru[2] ,
    row_match_way[0] , row_match_way[1] ,
    row_match_way[2] }) === 5'b00111);
assign select_lru_way_pt[13] =
    (({ row_lru[1] , row_lru[2] ,
    row_match_way[0] , row_match_way[3]
     }) === 4'b0101);
assign select_lru_way_pt[14] =
    (({ row_lru[1] , row_lru[2] ,
    row_match_way[0] , row_match_way[2]
     }) === 4'b0001);
assign select_lru_way_pt[15] =
    (({ row_lru[1] , row_lru[2] ,
    row_match_way[1] , row_match_way[3]
     }) === 4'b1101);
assign select_lru_way_pt[16] =
    (({ row_lru[1] , row_lru[2] ,
    row_match_way[1] , row_match_way[2]
     }) === 4'b1001);
assign select_lru_way_pt[17] =
    (({ row_lru[1] , row_lru[2] ,
    row_match_way[1] , row_match_way[2]
     }) === 4'b1010);
assign select_lru_way_pt[18] =
    (({ row_lru[1] , row_lru[2] ,
    row_match_way[0] , row_match_way[2]
     }) === 4'b0010);
assign select_lru_way_pt[19] =
    (({ row_lru[1] , row_lru[2] ,
    row_match_way[1] , row_match_way[3]
     }) === 4'b1110);
assign select_lru_way_pt[20] =
    (({ row_lru[1] , row_lru[2] ,
    row_match_way[0] , row_match_way[3]
     }) === 4'b0110);
assign select_lru_way_pt[21] =
    (({ row_lru[0] , row_lru[1] ,
    row_match_way[0] }) === 3'b000);
assign select_lru_way_pt[22] =
    (({ row_lru[0] , row_lru[1] ,
    row_match_way[1] }) === 3'b010);
assign select_lru_way_pt[23] =
    (({ row_lru[0] , row_lru[2] ,
    row_match_way[2] }) === 3'b100);
assign select_lru_way_pt[24] =
    (({ row_lru[0] , row_lru[2] ,
    row_match_way[3] }) === 3'b110);
assign next_lru_way[0] =
    (select_lru_way_pt[1] | select_lru_way_pt[2]
     | select_lru_way_pt[9] | select_lru_way_pt[13]
     | select_lru_way_pt[14] | select_lru_way_pt[21]
    );
assign next_lru_way[1] =
    (select_lru_way_pt[3] | select_lru_way_pt[4]
     | select_lru_way_pt[10] | select_lru_way_pt[15]
     | select_lru_way_pt[16] | select_lru_way_pt[22]
    );
assign next_lru_way[2] =
    (select_lru_way_pt[5] | select_lru_way_pt[6]
     | select_lru_way_pt[11] | select_lru_way_pt[17]
     | select_lru_way_pt[18] | select_lru_way_pt[23]
    );
assign next_lru_way[3] =
    (select_lru_way_pt[7] | select_lru_way_pt[8]
     | select_lru_way_pt[12] | select_lru_way_pt[19]
     | select_lru_way_pt[20] | select_lru_way_pt[24]
    );

//assign_end

   assign next_way = (val_or_match[0] == 1'b0) ? 4'b1000 :
                     (val_or_match[1] == 1'b0) ? 4'b0100 :
                     (val_or_match[2] == 1'b0) ? 4'b0010 :
                     (val_or_match[3] == 1'b0) ? 4'b0001 :
                     next_lru_way;

   generate
   begin : xhdl17
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_miss_way
       assign miss_way_d[i] = (select_lru[i] == 1'b1) ? next_way :
                                                        miss_way_l2[i];
     end
   end
   endgenerate

   //---------------------------------------------------------------------
   // setting output signals
   //---------------------------------------------------------------------
   generate
   begin : xhdl18
     genvar  i;
     for (i = 0; i < `THREADS ; i = i + 1)
     begin : gen_hold_thread
       assign icm_ics_hold_thread[i] = ((hold_tid[2*i] | ecc_block_iu0[2*i]) & miss_need_hold_l2[2*i]) | ((hold_tid[2*i+1] | ecc_block_iu0[2*i+1]) & miss_need_hold_l2[2*i+1]);
     end
   end
   endgenerate

   // Note: If data_write timing is bad, can switch back to using hold_all_tids, but use reld_r2
   // Hold iu0 when writing into Data this cycle or fastpath 2 cycles from now.
   // For reld in Wait0, not checking flush for timing reasons.
   assign hold_iu0 = |(data_write) | (|(preload_hold_iu0));

   assign icm_ics_hold_iu0 = hold_iu0;
   assign icm_icd_lru_addr = lru_addr;
   assign icm_icd_data_write = |(data_write);
   assign icm_icd_dir_inval = |(write_dir_inval);

   // ??? Move inval_equal for timing?
   assign icm_icd_dir_val = | (write_dir_val[0:TAGS_USED - 1] & miss_wrote_dir_l2 & (~inval_equal));

   assign icm_icd_reload_addr = {reload_addr[51:57], reld_r2_qw_l2};
   assign icm_icd_reload_way = reload_way;

   // Check which endian
   assign reload_endian = | (reld_r2_val_l2 & miss_endian_l2);
   assign reld_r1_endian = | (reld_r1_val_l2[0:TAGS_USED - 1] & miss_endian_l2);

   assign swap_endian_data =
       {an_ac_reld_data[24:31],   an_ac_reld_data[16:23],   an_ac_reld_data[8:15],    an_ac_reld_data[0:7],
        an_ac_reld_data[56:63],   an_ac_reld_data[48:55],   an_ac_reld_data[40:47],   an_ac_reld_data[32:39],
        an_ac_reld_data[88:95],   an_ac_reld_data[80:87],   an_ac_reld_data[72:79],   an_ac_reld_data[64:71],
        an_ac_reld_data[120:127], an_ac_reld_data[112:119], an_ac_reld_data[104:111], an_ac_reld_data[96:103]};

   assign reld_data_d = (reld_r1_endian == 1'b0) ? an_ac_reld_data :
                        swap_endian_data;

   // Branch Decode
   iuq_bd br_decode0(
      .instruction(reld_data_l2[0:31]),
      .instruction_next(reld_data_l2[32:63]),
      .branch_decode(branch_decode0[0:3]),
      .bp_bc_en(bp_config_l2[0]),
      .bp_bclr_en(bp_config_l2[1]),
      .bp_bcctr_en(bp_config_l2[2]),
      .bp_sw_en(bp_config_l2[3])
   );

   iuq_bd br_decode1(
      .instruction(reld_data_l2[32:63]),
      .instruction_next(reld_data_l2[64:95]),
      .branch_decode(branch_decode1[0:3]),
      .bp_bc_en(bp_config_l2[0]),
      .bp_bclr_en(bp_config_l2[1]),
      .bp_bcctr_en(bp_config_l2[2]),
      .bp_sw_en(bp_config_l2[3])
   );

   iuq_bd br_decode2(
      .instruction(reld_data_l2[64:95]),
      .instruction_next(reld_data_l2[96:127]),
      .branch_decode(branch_decode2[0:3]),
      .bp_bc_en(bp_config_l2[0]),
      .bp_bclr_en(bp_config_l2[1]),
      .bp_bcctr_en(bp_config_l2[2]),
      .bp_sw_en(bp_config_l2[3])
   );

   iuq_bd br_decode3(
      .instruction(reld_data_l2[96:127]),
      .instruction_next(tidn32[0:31]),
      .branch_decode(branch_decode3[0:3]),
      .bp_bc_en(bp_config_l2[0]),
      .bp_bclr_en(bp_config_l2[1]),
      .bp_bcctr_en(bp_config_l2[2]),
      .bp_sw_en(bp_config_l2[3])
   );

   assign instr_data = {reld_data_l2[0:31],   branch_decode0[0:3],
                        reld_data_l2[32:63],  branch_decode1[0:3],
                        reld_data_l2[64:95],  branch_decode2[0:3],
                        reld_data_l2[96:127], branch_decode3[0:3]};

   assign icm_icd_reload_data = instr_data;

   // Dir Write moved to r2
   assign dir_write_no_block = dir_write[0:TAGS_USED - 1] & (~iu0_inval_match);
   assign icm_icd_dir_write = |(dir_write_no_block);
   assign icm_icd_dir_write_addr = reload_addr;
   assign icm_icd_dir_write_endian = reload_endian;
   assign icm_icd_dir_write_way = reload_way;

   // LRU Write: Occurs 2 cycles after Data 2 data_write (64B mode) or Data6 (128B mode)
   generate
   begin : xhdl19
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_lru_write
       assign lru_write_next_cycle_d[i] = data_write[i] & (miss_tid_sm_l2[i][DATA] & (miss_count_l2[i] == 3'b001));
       assign lru_write[i] = lru_write_l2[i] & (~miss_inval_l2[i]);
     end
   end
   endgenerate

   assign lru_write_d = lru_write_next_cycle_l2;

   assign icm_icd_lru_write = |(lru_write);
   assign icm_icd_lru_write_addr = lru_write_addr;
   assign icm_icd_lru_write_way = lru_write_way;

   // For act's in idir
   assign icm_icd_any_reld_r2 = |(reld_r2_val_l2);

   //---------------------------------------------------------------------
   // ECC Error handling
   //---------------------------------------------------------------------
   assign new_ecc_err = {TAGS_USED{an_ac_reld_ecc_err_l2}} & reld_r3_val_l2;
   assign new_ecc_err_ue = {TAGS_USED{an_ac_reld_ecc_err_ue_l2}} & reld_r3_val_l2;
   assign ecc_err[0:TAGS_USED - 1] = new_ecc_err | miss_ecc_err_l2;
   assign ecc_err_ue[0:TAGS_USED - 1] = new_ecc_err_ue | miss_ecc_err_ue_l2;

   generate
   begin : xhdl20
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_ecc_inval
       assign ecc_inval[i] = (an_ac_reld_ecc_err_l2 | an_ac_reld_ecc_err_ue_l2 | inval_equal[i]) &
            miss_tid_sm_l2[i][CHECK_ECC] & (~miss_ci_l2[i]) & (~miss_flushed_l2[i]) & (~miss_inval_l2[i]);
       assign ecc_block_iu0[i] = ecc_err[i] & (miss_tid_sm_l2[i][CHECK_ECC] | (miss_tid_sm_l2[i][DATA] & last_data[i]));  // moved last data check here from hold_tid for timing; check need_hold in hold_thread logic
     end
   end
   endgenerate

   // CheckECC stage
   // Non-CI: If last beat of data has bad ECC, invalidate cache & flush IU1

   // Back inval in Check ECC state
   assign icm_icd_ecc_inval = |(ecc_inval);    //or back_inval_check_ecc;

   assign icm_icd_ecc_addr = r3_addr[51:57];
   assign icm_icd_ecc_way  = r3_way;

   // CI/Critical QW: Invalidate IU3 or set error bit
   assign ecc_fp = r3_loaded_l2 & an_ac_reld_ecc_err_l2;
   assign icm_icd_iu3_ecc_fp_cancel = ecc_fp;
   assign icm_ics_iu3_ecc_fp_cancel = {`THREADS{ecc_fp}} & reld_r3_tid;
   assign ic_bp_iu3_ecc_err = r3_loaded_l2 & an_ac_reld_ecc_err_ue_l2;

   //---------------------------------------------------------------------
   // Performance Events
   //---------------------------------------------------------------------
   generate
   begin : xhdl11
     genvar  i;
     for (i = 0; i < SM_MAX; i = i + 1)
     begin : g11
       //      - not CI, not Idle, not WaitMiss, & not (CheckECC & done)
       assign active_l1_miss[i] = ~miss_ci_l2[i] & ~miss_tid_sm_l2[i][IDLE] & ~miss_tid_sm_l2[i][WAITMISS] & ~(miss_tid_sm_l2[i][CHECK_ECC] & ~ecc_err[i]);
     end

     genvar  t;
     for (t = 0; t < `THREADS; t = t + 1)
     begin : gen_perf
       // IL1 Miss Cycles
       //      - not CI, not Idle, not WaitMiss, & not (CheckECC & done)
       //      - event mode/edge should not count multiple times if flushed and recycled
       assign perf_event_d[t][0] = active_l1_miss[2*t] | (active_l1_miss[2*t+1] & ~miss_prefetch_perf_l2[t]);

       // IL1 Reload Dropped
       //     - not CI, flushed, & returning to Idle; includes prefetches
       assign perf_event_d[t][1] =
	 (~miss_ci_l2[2*t]   & miss_flushed_l2[2*t]   & (miss_tid_sm_l2[2*t][CHECK_ECC]   & ~ecc_err[2*t])) |
	 (~miss_ci_l2[2*t+1] & miss_flushed_l2[2*t+1] & (miss_tid_sm_l2[2*t+1][CHECK_ECC] & ~ecc_err[2*t+1]));

       // Prefetch cycles
       assign perf_event_d[t][2] = active_l1_miss[2*t+1] & miss_prefetch_perf_l2[t];
     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)) spr_ic_cls_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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_ic_cls_offset]),
      .scout(sov[spr_ic_cls_offset]),
      .din(spr_ic_cls_d),
      .dout(spr_ic_cls_l2)
      );

   tri_rlmreg_p #(.WIDTH(4), .INIT(0)) bp_config_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[bp_config_offset:bp_config_offset + 4 - 1]),
      .scout(sov[bp_config_offset:bp_config_offset + 4 - 1]),
      .din(bp_config_d),
      .dout(bp_config_l2)
      );

   tri_rlmlatch_p #(.INIT(0)) an_ac_reld_data_vld_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[an_ac_reld_data_vld_offset]),
      .scout(sov[an_ac_reld_data_vld_offset]),
      .din(an_ac_reld_data_vld_d),
      .dout(an_ac_reld_data_vld_l2)
      );

   tri_rlmreg_p #(.WIDTH(5), .INIT(0)) an_ac_reld_core_tag_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[an_ac_reld_core_tag_offset:an_ac_reld_core_tag_offset + 5 - 1]),
      .scout(sov[an_ac_reld_core_tag_offset:an_ac_reld_core_tag_offset + 5 - 1]),
      .din(an_ac_reld_core_tag_d),
      .dout(an_ac_reld_core_tag_l2)
      );

   tri_rlmreg_p #(.WIDTH(2), .INIT(0)) an_ac_reld_qw_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[an_ac_reld_qw_offset:an_ac_reld_qw_offset + 2 - 1]),
      .scout(sov[an_ac_reld_qw_offset:an_ac_reld_qw_offset + 2 - 1]),
      .din(an_ac_reld_qw_d),
      .dout(an_ac_reld_qw_l2)
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) reld_r1_val_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[reld_r1_val_offset:reld_r1_val_offset + TAGS_USED - 1]),
      .scout(sov[reld_r1_val_offset:reld_r1_val_offset + TAGS_USED - 1]),
      .din(reld_r1_val_d),
      .dout(reld_r1_val_l2[0:TAGS_USED - 1])
      );

   tri_rlmreg_p #(.WIDTH(2), .INIT(0)) reld_r1_qw_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[reld_r1_qw_offset:reld_r1_qw_offset + 2 - 1]),
      .scout(sov[reld_r1_qw_offset:reld_r1_qw_offset + 2 - 1]),
      .din(reld_r1_qw_d),
      .dout(reld_r1_qw_l2)
      );

   tri_rlmreg_p #(.WIDTH(128), .INIT(0)) reld_data_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(reld_r2_act),
      .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[reld_data_offset:reld_data_offset + 128 - 1]),
      .scout(sov[reld_data_offset:reld_data_offset + 128 - 1]),
      .din(reld_data_d),
      .dout(reld_data_l2)
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) reld_r2_val_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[reld_r2_val_offset:reld_r2_val_offset + TAGS_USED - 1]),
      .scout(sov[reld_r2_val_offset:reld_r2_val_offset + TAGS_USED - 1]),
      .din(reld_r2_val_d),
      .dout(reld_r2_val_l2)
      );

   tri_rlmreg_p #(.WIDTH(2), .INIT(0)) reld_r2_qw_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(reld_r2_act),
      .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[reld_r2_qw_offset:reld_r2_qw_offset + 2 - 1]),
      .scout(sov[reld_r2_qw_offset:reld_r2_qw_offset + 2 - 1]),
      .din(reld_r2_qw_d),
      .dout(reld_r2_qw_l2)
      );

   tri_rlmlatch_p #(.INIT(0)) r2_crit_qw_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[r2_crit_qw_offset]),
      .scout(sov[r2_crit_qw_offset]),
      .din(r2_crit_qw_d),
      .dout(r2_crit_qw_l2)
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) reld_r3_val_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[reld_r3_val_offset:reld_r3_val_offset + TAGS_USED - 1]),
      .scout(sov[reld_r3_val_offset:reld_r3_val_offset + TAGS_USED - 1]),
      .din(reld_r3_val_d),
      .dout(reld_r3_val_l2)
      );

   tri_rlmlatch_p #(.INIT(0)) r3_loaded_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[r3_loaded_offset]),
      .scout(sov[r3_loaded_offset]),
      .din(r3_loaded_d),
      .dout(r3_loaded_l2)
      );

   tri_rlmlatch_p #(.INIT(0)) an_ac_reld_ecc_err_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[an_ac_reld_ecc_err_offset]),
      .scout(sov[an_ac_reld_ecc_err_offset]),
      .din(an_ac_reld_ecc_err_d),
      .dout(an_ac_reld_ecc_err_l2)
      );

   tri_rlmlatch_p #(.INIT(0)) an_ac_reld_ecc_err_ue_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[an_ac_reld_ecc_err_ue_offset]),
      .scout(sov[an_ac_reld_ecc_err_ue_offset]),
      .din(an_ac_reld_ecc_err_ue_d),
      .dout(an_ac_reld_ecc_err_ue_l2)
      );

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) request_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(miss_or_default_act),
      .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[request_offset:request_offset + `THREADS - 1]),
      .scout(sov[request_offset:request_offset + `THREADS - 1]),
      .din(request_d),
      .dout(request_l2)
      );

   tri_rlmreg_p #(.WIDTH(2), .INIT(0)) req_ctag_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(icd_icm_any_iu2_valid),
      .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[req_ctag_offset:req_ctag_offset + 2 - 1]),
      .scout(sov[req_ctag_offset:req_ctag_offset + 2 - 1]),
      .din(req_ctag_d),
      .dout(req_ctag_l2)
      );

   tri_rlmreg_p #(.WIDTH(`REAL_IFAR_WIDTH-4), .INIT(0)) req_ra_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(icd_icm_any_iu2_valid),
      .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[req_ra_offset:req_ra_offset + (`REAL_IFAR_WIDTH-4) - 1]),
      .scout(sov[req_ra_offset:req_ra_offset + (`REAL_IFAR_WIDTH-4) - 1]),
      .din(req_ra_d),
      .dout(req_ra_l2)
      );

   tri_rlmreg_p #(.WIDTH(5), .INIT(0)) req_wimge_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(icd_icm_any_iu2_valid),
      .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[req_wimge_offset:req_wimge_offset + 5 - 1]),
      .scout(sov[req_wimge_offset:req_wimge_offset + 5 - 1]),
      .din(req_wimge_d),
      .dout(req_wimge_l2)
      );

   tri_rlmreg_p #(.WIDTH(4), .INIT(0)) req_userdef_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(icd_icm_any_iu2_valid),
      .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[req_userdef_offset:req_userdef_offset + 4 - 1]),
      .scout(sov[req_userdef_offset:req_userdef_offset + 4 - 1]),
      .din(req_userdef_d),
      .dout(req_userdef_l2)
      );

   tri_rlmlatch_p #(.INIT(0)) iu3_miss_match_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(icd_icm_any_iu2_valid),
      .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[iu3_miss_match_offset]),
      .scout(sov[iu3_miss_match_offset]),
      .din(iu3_miss_match_d),
      .dout(iu3_miss_match_l2)
      );

   generate
   begin : xhdl21
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen_sm

       tri_rlmreg_p #(.WIDTH(CHECK_ECC+1), .INIT({1'b1, {CHECK_ECC{1'b0}} })) miss_tid_sm_latch(
          .vd(vdd),
          .gd(gnd),
          .nclk(nclk),
          .act(miss_or_default_act),
          .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[miss_tid_sm_offset + i * (CHECK_ECC+1):miss_tid_sm_offset + (i + 1) * (CHECK_ECC+1) - 1]),
          .scout(sov[miss_tid_sm_offset + i * (CHECK_ECC+1):miss_tid_sm_offset + (i + 1) * (CHECK_ECC+1) - 1]),
          .din(miss_tid_sm_d[i]),
          .dout(miss_tid_sm_l2[i])
          );

       tri_rlmreg_p #(.WIDTH(3), .INIT(0)) miss_count_latch(
          .vd(vdd),
          .gd(gnd),
          .nclk(nclk),
          .act(miss_or_default_act),
          .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[miss_count_offset + i * 3:miss_count_offset + (i + 1) * 3 - 1]),
          .scout(sov[miss_count_offset + i * 3:miss_count_offset + (i + 1) * 3 - 1]),
          .din(miss_count_d[i]),
          .dout(miss_count_l2[i])
          );
     end
   end
   endgenerate

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) miss_flush_occurred_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[miss_flush_occurred_offset:miss_flush_occurred_offset + TAGS_USED - 1]),
      .scout(sov[miss_flush_occurred_offset:miss_flush_occurred_offset + TAGS_USED - 1]),
      .din(miss_flush_occurred_d),
      .dout(miss_flush_occurred_l2)
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) miss_flushed_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[miss_flushed_offset:miss_flushed_offset + TAGS_USED - 1]),
      .scout(sov[miss_flushed_offset:miss_flushed_offset + TAGS_USED - 1]),
      .din(miss_flushed_d[0:TAGS_USED - 1]),
      .dout(miss_flushed_l2[0:TAGS_USED - 1])
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) miss_inval_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[miss_inval_offset:miss_inval_offset + TAGS_USED - 1]),
      .scout(sov[miss_inval_offset:miss_inval_offset + TAGS_USED - 1]),
      .din(miss_inval_d[0:TAGS_USED - 1]),
      .dout(miss_inval_l2[0:TAGS_USED - 1])
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) miss_block_fp_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(miss_or_default_act),
      .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[miss_block_fp_offset:miss_block_fp_offset + TAGS_USED - 1]),
      .scout(sov[miss_block_fp_offset:miss_block_fp_offset + TAGS_USED - 1]),
      .din(miss_block_fp_d),
      .dout(miss_block_fp_l2)
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) miss_ecc_err_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[miss_ecc_err_offset:miss_ecc_err_offset + TAGS_USED - 1]),
      .scout(sov[miss_ecc_err_offset:miss_ecc_err_offset + TAGS_USED - 1]),
      .din(miss_ecc_err_d),
      .dout(miss_ecc_err_l2)
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) miss_ecc_err_ue_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[miss_ecc_err_ue_offset:miss_ecc_err_ue_offset + TAGS_USED - 1]),
      .scout(sov[miss_ecc_err_ue_offset:miss_ecc_err_ue_offset + TAGS_USED - 1]),
      .din(miss_ecc_err_ue_d),
      .dout(miss_ecc_err_ue_l2)
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0), .NEEDS_SRESET(1)) miss_wrote_dir_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[miss_wrote_dir_offset:miss_wrote_dir_offset + TAGS_USED - 1]),
      .scout(sov[miss_wrote_dir_offset:miss_wrote_dir_offset + TAGS_USED - 1]),
      .din(miss_wrote_dir_d),
      .dout(miss_wrote_dir_l2)
      );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0), .NEEDS_SRESET(1)) miss_need_hold_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(miss_or_default_act),
      .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[miss_need_hold_offset:miss_need_hold_offset + TAGS_USED - 1]),
      .scout(sov[miss_need_hold_offset:miss_need_hold_offset + TAGS_USED - 1]),
      .din(miss_need_hold_d),
      .dout(miss_need_hold_l2)
      );

   generate
   begin : xhdl22
     genvar  i;
     for (i = 0; i < TAGS_USED; i = i + 1)
     begin : gen
       tri_rlmreg_p #(.WIDTH(`REAL_IFAR_WIDTH - 2), .INIT(0)) miss_addr_real_latch(
          .vd(vdd),
          .gd(gnd),
          .nclk(nclk),
          .act(miss_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[miss_addr_real_offset + i * (`REAL_IFAR_WIDTH - 2):miss_addr_real_offset + (i + 1) * (`REAL_IFAR_WIDTH - 2) - 1]),
          .scout(sov[miss_addr_real_offset + i * (`REAL_IFAR_WIDTH - 2):miss_addr_real_offset + (i + 1) * (`REAL_IFAR_WIDTH - 2) - 1]),
          .din(miss_addr_real_d[i]),
          .dout(miss_addr_real_l2[i])
          );

       tri_rlmreg_p #(.WIDTH(`EFF_IFAR_WIDTH - 10), .INIT(0)) miss_addr_eff_latch(
          .vd(vdd),
          .gd(gnd),
          .nclk(nclk),
          .act(miss_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[miss_addr_eff_offset + i * (`EFF_IFAR_WIDTH - 10):miss_addr_eff_offset + (i + 1) * (`EFF_IFAR_WIDTH - 10) - 1]),
          .scout(sov[miss_addr_eff_offset + i * (`EFF_IFAR_WIDTH - 10):miss_addr_eff_offset + (i + 1) * (`EFF_IFAR_WIDTH - 10) - 1]),
          .din(miss_addr_eff_d[i]),
          .dout(miss_addr_eff_l2[i])
          );

      tri_rlmlatch_p #(.INIT(0)) miss_ci_latch(
         .vd(vdd),
         .gd(gnd),
         .nclk(nclk),
         .act(miss_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[miss_ci_offset + i]),
         .scout(sov[miss_ci_offset + i]),
         .din(miss_ci_d[i]),
         .dout(miss_ci_l2[i])
         );

      tri_rlmlatch_p #(.INIT(0)) miss_endian_latch(
         .vd(vdd),
         .gd(gnd),
         .nclk(nclk),
         .act(miss_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[miss_endian_offset + i]),
         .scout(sov[miss_endian_offset + i]),
         .din(miss_endian_d[i]),
         .dout(miss_endian_l2[i])
         );

      tri_rlmlatch_p #(.INIT(0)) miss_2ucode_latch(
         .vd(vdd),
         .gd(gnd),
         .nclk(nclk),
         .act(miss_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[miss_2ucode_offset + i]),
         .scout(sov[miss_2ucode_offset + i]),
         .din(miss_2ucode_d[i]),
         .dout(miss_2ucode_l2[i])
         );

      tri_rlmlatch_p #(.INIT(0)) miss_2ucode_type_latch(
         .vd(vdd),
         .gd(gnd),
         .nclk(nclk),
         .act(miss_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[miss_2ucode_type_offset + i]),
         .scout(sov[miss_2ucode_type_offset + i]),
         .din(miss_2ucode_type_d[i]),
         .dout(miss_2ucode_type_l2[i])
         );

      tri_rlmreg_p #(.WIDTH(4), .INIT(0)) miss_way_latch(
         .vd(vdd),
         .gd(gnd),
         .nclk(nclk),
         .act(reld_r2_act),
         .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[miss_way_offset + i * 4:miss_way_offset + (i + 1) * 4 - 1]),
         .scout(sov[miss_way_offset + i * 4:miss_way_offset + (i + 1) * 4 - 1]),
         .din(miss_way_d[i]),
         .dout(miss_way_l2[i])
         );
     end
   end
   endgenerate

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) lru_write_next_cycle_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[lru_write_next_cycle_offset:lru_write_next_cycle_offset + TAGS_USED - 1]),
      .scout(sov[lru_write_next_cycle_offset:lru_write_next_cycle_offset + TAGS_USED - 1]),
      .din(lru_write_next_cycle_d),
      .dout(lru_write_next_cycle_l2)
     );

   tri_rlmreg_p #(.WIDTH(TAGS_USED), .INIT(0)) lru_write_latch(
      .vd(vdd),
      .gd(gnd),
      .nclk(nclk),
      .act(default_reld_act),
      .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[lru_write_offset:lru_write_offset + TAGS_USED - 1]),
      .scout(sov[lru_write_offset:lru_write_offset + TAGS_USED - 1]),
      .din(lru_write_d),
      .dout(lru_write_l2)
     );

   generate
   begin : xhdl23
      genvar  i;
      for (i = 0; i < `THREADS; i = i + 1)
      begin : t
        tri_rlmreg_p #(.WIDTH(3), .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 * 3:perf_event_offset + (i+1) * 3 - 1]),
           .scout(sov[perf_event_offset + i * 3:perf_event_offset + (i+1) * 3 - 1]),
           .din(perf_event_d[i]),
           .dout(perf_event_l2[i])
          );
      end
   end
   endgenerate

   tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) miss_prefetch_perf_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[miss_prefetch_perf_offset:miss_prefetch_perf_offset + `THREADS - 1]),
      .scout(sov[miss_prefetch_perf_offset:miss_prefetch_perf_offset + `THREADS - 1]),
      .din(miss_prefetch_perf_d),
      .dout(miss_prefetch_perf_l2)
     );

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

endmodule
