HierarchyFilesModulesSignalsTasksFunctionsHelp
12

/******************************************************************************/ 
/*                                                                            */ 
/* Copyright (c) 1999 Sun Microsystems, Inc. All rights reserved.             */ 
/*                                                                            */ 
/* The contents of this file are subject to the current version of the Sun    */ 
/* Community Source License, microSPARCII ("the License"). You may not use    */ 
/* this file except in compliance with the License.  You may obtain a copy    */ 
/* of the License by searching for "Sun Community Source License" on the      */ 
/* World Wide Web at http://www.sun.com. See the License for the rights,      */ 
/* obligations, and limitations governing use of the contents of this file.   */ 
/*                                                                            */ 
/* Sun Microsystems, Inc. has intellectual property rights relating to the    */ 
/* technology embodied in these files. In particular, and without limitation, */ 
/* these intellectual property rights may include one or more U.S. patents,   */ 
/* foreign patents, or pending applications.                                  */ 
/*                                                                            */ 
/* Sun, Sun Microsystems, the Sun logo, all Sun-based trademarks and logos,   */ 
/* Solaris, Java and all Java-based trademarks and logos are trademarks or    */ 
/* registered trademarks of Sun Microsystems, Inc. in the United States and   */ 
/* other countries. microSPARC is a trademark or registered trademark of      */ 
/* SPARC International, Inc. All SPARC trademarks are used under license and  */ 
/* are trademarks or registered trademarks of SPARC International, Inc. in    */ 
/* the United States and other countries. Products bearing SPARC trademarks   */ 
/* are based upon an architecture developed by Sun Microsystems, Inc.         */ 
/*                                                                            */ 
/******************************************************************************/ 
// @(#)rl_ic_cntl.v	1.91 8/5/93
/******************************************************************************
// 
//      Description:
//              This is the control block for icache. This module contains
//		the icache control state machine and other control logic
//		for handling icache-misses, streaming, instruction access
//		tlb misses and datapath for Icache ASI read/write.
//
******************************************************************************/

/*****************************
*****************************/

[Up: rl_cc ic_cntl]
module rl_ic_cntl (
	hold_fetch_f_l,
	sel_last_gen,
	sel_recirc,
	ic_force_ifill_g,
	mm_cache_stat,
	dcc_nc_bypass,
	standby_req,
	ic_standby_f,
	dva_w_2,
	iu_in_trap,
	flush_ic_e,
	ic_asi_store_tag_e,
	ic_asi_store_cache_e,
	nforce_dva_f,
	ic_hld,
        enbl_fetch,
	it_din,
	it_cntx_in,
	cxr,
	ic_power_down,
	it_be,
	it_be_vb,
	it_acc_in,
	iu_iva_g, 		
	icache_adr, 		
	iu_held,

	mm_icstben,
	icstben_asi,
	dp_perr,
	ic_perr_f,
	start_itag_inv,
	mm_iabort,

	misc_in, 
	misc_out, 
	ic_ibus, 
	it_dout_f,
	it_cntx_out,
	it_val_f,
	ic_asi_load_cache_w,
	mm_icdaten,

        ic_wle,
        ic_be,
        it_val_in,

	mm_icache_enbl,
	it_hit_f,
	it_hit_f_mmu,
	it_acc_out,
	ic_sup_only_f,
	mm_fs_lvl,
	it_lvl_in,
	it_lvl_out,
	ic_lvl_f,
	mm_istat_avail,
	iwait_f,
	enbl_itag_match_f,
	ic_miss,
	ic_miss_or_part,
	ic_miss_and_part,
	ic_idle,
	ic_miss_sustain,
	imiss_in_progress,
	i_nfillp,

	ss_scan_in,
	ss_scan_out, 
	ss_scan_mode,

	ss_reset,
	ss_clock 
	) ;

	// To MMU - holds F-cycle during refetched noncached fetch (Bug 547)
	output hold_fetch_f_l ;

	// From IU. When ANDed, says that G-cycle address is same as F-cycle.
	input sel_last_gen ;
	input sel_recirc ;

	// To IU, forces the fill address onto dva_e.
	output ic_force_ifill_g ;

	// Cacheable status of current request.  Valid the cycle after
	//     mm_istat_avail is asserted.
	// 1->cached, 0->noncached.
	input mm_cache_stat ;

	// dc_cntl state decode
	input dcc_nc_bypass ;

	// Standby-mode interface.  Put cache/tag RAMs into powerdown mode
	//     and assert ic_standby_f, when possible, on assertion of
	//     standby_req.  Clock controller will go into standby mode
	//     (ss_clock turned off) when all units have responded to
	//     standby_req.
	input standby_req ;
	output ic_standby_f ;

	// Address bit 2, used here for StA to ICache
	input dva_w_2 ;

	// Decodes
	input ic_asi_store_tag_e ;
	input ic_asi_store_cache_e ;
	input flush_ic_e ;  // E-cycle of IFlush or ASI Flush

	// IU is flushing the pipeline due to a trap
	input iu_in_trap ;

	// iva_g is driven by dva this cycle - used by Flushes and LdA/StA
	input nforce_dva_f ;
 
	// Register holds for {LSW,MSW} (sic) data-in registers
	output [1:0] ic_hld ;

	output [31:`log2_icachesize] it_din ;
	output [7:0] it_cntx_in ;
	input [7:0] cxr ;

    // ic_miss (from ic_cntl to mmu):  Comes on when an ICache miss is
    //     recognized, stays on until mmu acknowledges the miss by asserting
    //     mm_istat_avail:
    // 
    // 			 G F F F F F F F F F F F . . . . .
    // 	~it_hit_f          =
    // 	ic_miss            = = = = =                         
    // 	ic_miss_sustain      = = = =                         
    // 	mm_istat_avail             =                         
    // 	iu_held            = = = = = = = = = = = . . . . .
    // 
    //     Note that, since the first cycle of ic_miss assertion is a function
    //     of it_hit_f, ic_miss will come late in the cycle.  Also, note that
    //     ic_miss will never be asserted for less than two cycles on a miss.
    //     ic_miss must also be asserted for every boot mode fetch, and for
    //     every fetch while the ICache is disabled, regardless of the results
    //     of it_hit_f.  The mm_icache_enbl signal, asserted the cycle *before*
    //     the F-stage of the fetch, tells us not to look at the Tag.
    // ic_miss_sustain is identical to ic_miss except that it is not asserted
    //     in the first cycle of the ic_miss.  Used instead of ic_miss
    //     wherever possible, to avoid timing problems.
    output ic_miss ;
    output ic_miss_or_part ;
    output ic_miss_and_part ;
    output ic_miss_sustain ;

    output ic_idle ;   // (part of bug 223 fix)

    // imiss_in_progress: to IU.  On in the *second* F-cycle of an ICache
    //     miss, stays on until (but not during) the last fill write cycle
    //     (for cache fills).  Don't-care for noncached fetches.
    //
    // 			         G F F F . . . . . . . .
    // 	~it_hit_f                  =
    //  ic_we (cached)                   =     =     =     =
    //  ic_fill_write                      =     =     =     =
    // 	imiss_in_progress            = = = = = = = = = = = =         
    output imiss_in_progress ;

    // IU registers this (freerunning)  to make icache_adr[4:3] for fill writes.
    output [4:3] i_nfillp ;

    output iwait_f ;

    // If deasserted the cycle *before* the F-stage of the fetch, tells us
    //     not to look at the Tag.
    input mm_icache_enbl ;

    // Part of IC/IU interface
    output enbl_itag_match_f ;

    // Tag match
    input it_hit_f ;
    output it_hit_f_mmu ; 		// MMU's copy (moved from Mhold logic)

    // Interface for reporting Supervisor Page instructions to IU
    input it_acc_out ;
    output ic_sup_only_f ;

    // Interface for reporting PTE Level field to IU
    input [1:0] mm_fs_lvl ;
    output [1:0] it_lvl_in ;
    input [1:0] it_lvl_out ;
    output [1:0] ic_lvl_f ;

    // mm_istat_avail (from mmu to ic_cntl):  Asserted for a single cycle,
    //     the cycle before the MMU drives status onto misc during an ic_miss.
    //     For accessed associated with a PTE, the ACC and C fields of misc
    //     contain the corresponding PTE fields; for other accesses, ACC will
    //     be 111 and C will be 1.  mm_istat_avail will be asserted no
    //     earlier than the second ic_miss cycle of an access.  For accesses
    //     which will be aborted by mm_iabort, mm_istat_avail will never be
    //     asserted.
    input mm_istat_avail ;

    output it_be ;
    output it_be_vb ;
    input [31:0] misc_in ;
    output [31:0] misc_out ;
    input [63:0] ic_ibus ;
    input [`it_msb:0] it_dout_f ;
    input [7:0] it_cntx_out ;
    input it_val_f ;
    input ic_asi_load_cache_w ;
    input mm_icdaten ;
    input ss_scan_in;
    input ss_scan_mode;

    // Two slightly different versions of the G-cycle address.  Important
    //     differences:
    //         1) when nforce_dva_f is asserted, icache_adr has dva_e but
    //                iu_iva_g has the next IFetch address.
    //         2) On fill write, icache_adr has the write address but
    //                iu_iva_g has the next IFetch address.
    input [13:3] iu_iva_g ;
    input [31:14] icache_adr ;

    output it_acc_in ;

    input iu_held ;		// The IU pipeline is held

    // mm_icstben (from mmu to ic_cntl):  Asserted the same cycle that each
    //     doubleword of data is driven onto the cache fill bus.  mm_icstben
    //     is never asserted for accesses which were aborted by mm_iabort.
    //     mm_icstben is asserted four times for each ICache fill, once for
    //     each of the four doublewords.  mm_icstben will be asserted no
    //     earlier than *two* cycles after mm_istat_avail is asserted.
    input mm_icstben     ;	// From MMU: 
    input icstben_asi ;         // indicates icstben is for ASI store

    output ic_power_down;

    // Parity error(s) in the doubleword which is coming over
    //     the cache_fill bus - asserted the cycle after the
    //     data appears on cache_fill.  {MSW,LSW}
    // Parity errors during a fill are reported to the IU during streaming
    //     cycles of the bad doublewords, either bypass or dead-cycle.
    //     On detection of a parity error during a fill, ic_perr_f
    //     is asserted during the bypass of the bad doubleword.  In
    //     addition, streaming is disabled during the remaining dead cycles
    //     for all the *other* doublewords of the line, out-of-line
    //     dead cycle streaming will be disabled, and ic_perr_f
    //     will be asserted during all remaining dead cycles of the fill.
    //     Allowing parity errors to be reported by dead cycle streaming
    //     breaks the hang described in Bug 381. 
    //     Bypass streaming for the other (good parity) doublewords of
    //     the line proceed normally - they are not inhibited by parity
    //     errors elsewhere in the line.  The ITag is invalidated after any
    //     fill which wrote bad parity into the cache; the signal
    //     start_itag_inv, asserted during the last fill bypass cycle, tells
    //     the IVA generation logic in IU to extend the fill sequence by
    //      two cycles (ic_tag_inv and ic_tag_inv_write) to write the ITag.
    // Parity errors on noncached fetches are reported to the IU in *all* the
    //     nc_byp cycles of the fetch.
    input [1:0] dp_perr ;   // From memif
    output [1:0] ic_perr_f ;  // To IU, after gating and holding
    output start_itag_inv ;

    // mm_iabort (from mmu to ic_cntl):  Asserted for a single cycle
    //     when the MMU has decided that an ic_miss request will not return
    //     any data.  mm_iabort will be asserted no earlier than the second
    //     ic_miss cycle of an access.  For accesses which are aborted by
    //     mm_iabort, mm_istat_avail will never be asserted.
    // On mm_iabort, go to the NC_BYP state and stay in the NC_BYP/NC_RETRY
    //     loop until the IU releases the pipe and takes the exception status
    //     (see Bug 130).
    input mm_iabort ;

    input ss_clock ;		// single sparc clock
    input ss_reset ;		// reset from system
    output ss_scan_out ;

    output ic_wle ;
    output [1:0] ic_be ;
    output it_val_in ;

    input enbl_fetch ; 	// F-cycle validate for fetch requests
 
	// Moved this buffer Mhold to ic_cntl for timing reason
	wire it_hit_f_mmu = ~it_hit_f;

    // Latch data-in when it's available, otherwise hold.
    // Note that we latch data on every icstben_asi, even if the StA is to
    //     the ITag.  This simplifies timing.
    wire [1:0] ic_hld = {2{(~mm_icstben & ~icstben_asi)}} ;

    MflipflopR sitw_ff(ic_asi_store_tag_w, ic_asi_store_tag_e,
	ss_clock, iu_held, ss_reset) ;
    MflipflopR sicw_ff(ic_asi_store_cache_w, ic_asi_store_cache_e,
	ss_clock, iu_held, ss_reset) ;
    MflipflopR fcw_ff(flush_ic_w, flush_ic_e,
	ss_clock, iu_held, ss_reset) ;

    Mflipflop_r fdf_ff(force_dva_f, nforce_dva_f,
	                              ~ss_reset, ss_clock) ;

    Mflipflop_r isf_ff(ic_standby_f, standby,
	                              ~ss_reset, ss_clock) ;

    // mm_icache_enbl is used as an (F-1)-cycle signal.
    Mflipflop_r ice_ff(icache_enbl_f, mm_icache_enbl,
	                              ~ss_reset, ss_clock) ;

    // Flush algorithm:
    //
    // StA/IFlush      D  e  e  e  E  w  w  w  w  W  R
    // HFlush             d  d  d  D  e  e  e  e  E  W  R
    // dwait_w                        =  =  =  =
    // nforce_dva_f       =           =     
    // check ITag            =   
    // write ITag                        =
    //
    // (nforce_dva_f is asserted for one cycle in first E of StA (for tag
    //      check), then once again (for tag write) in first dwait_w .

    Mflipflop_r fcit_ff(flush_check_itag_f, flush_ic_e & nforce_dva_f,
	                              ~ss_reset, ss_clock) ;
    wire flush_match ;

    // Do the flush even if the ICache is disabled (used by diagnostics)
    wire flush_match_a1 = flush_check_itag_f ? it_hit_f : flush_match ;

    Mflipflop_r fm_ff(flush_match, flush_match_a1,
	                              ~ss_reset, ss_clock) ;
    wire flush_tag_write =
	flush_match_a1 & flush_ic_w & nforce_dva_f & ~iu_in_trap ;

    // IU is trying to fetch in these F-cycles
    wire cancel_fetch_f ; // (forward)
    wire fetch_f =
	enbl_fetch & ~force_dva_f & ~standby_req & ~cancel_fetch_f

	// Bug 577: cancel the fetch cycle if the RAMs are in standby mode.
	& ~ic_standby_f ;

    // Performance enhancement for noncached fetching (e.g. boot mode).
    //     Detect when the IU is requesting the same doubleword as last time.
    //     Use this to stay in the nc_byp<->nc_retry loop (even though hold
    //     is released) instead of starting another request to the MMU.
    //     Don't do it if there is an ICache/ITag StA in E, since this will
    //     cause an icstben_asi which will wipe out our IFetch data.
    wire refetch_g =
	sel_last_gen & sel_recirc
	    & ~ic_asi_store_tag_e & ~ic_asi_store_cache_e ;

    // Needed by MMU to fix Bug 547.
    // Changed to fix Bug 589.
    wire hold_fetch_f_l = ~refetch_g ;

    //  ICache Control state machine

    // State encoding
    // One-hot.  These are the bit indices of the states
    parameter
	IDLE_idx		= 0,
	STAT_WAIT_idx		= 1,
	STAT_idx		= 2,
	NC_WAIT_idx		= 3,
	NC_BYP_idx		= 4,
	NC_RETRY_idx		= 5,
	FILL_WAIT_idx		= 6,
	FILL_WRITE_idx		= 7,
	DEAD_CYC_1_idx		= 8,
	DEAD_CYC_2_idx		= 9,
	DEAD_CYC_3_idx		= 10,
	TAG_INV_idx		= 11,
	TAG_INV_WRITE_idx	= 12,
	IDLE			= (1<<IDLE_idx),
	STAT_WAIT		= (1<<STAT_WAIT_idx),
	STAT			= (1<<STAT_idx),
	NC_WAIT			= (1<<NC_WAIT_idx),
	NC_BYP			= (1<<NC_BYP_idx),
	NC_RETRY		= (1<<NC_RETRY_idx),
	FILL_WAIT		= (1<<FILL_WAIT_idx),
	FILL_WRITE		= (1<<FILL_WRITE_idx),
	DEAD_CYC_1		= (1<<DEAD_CYC_1_idx),
	DEAD_CYC_2		= (1<<DEAD_CYC_2_idx),
	DEAD_CYC_3		= (1<<DEAD_CYC_3_idx),
	TAG_INV			= (1<<TAG_INV_idx),
	TAG_INV_WRITE		= (1<<TAG_INV_WRITE_idx)
	;

    wire [12:0] ic_state, ic_state_b0l, ic_state_a1, ic_state_a1_b0l ;
    wire last_fill_write ;

    // This register holds the state machine state.  The IDLE state bit is
    //     active-low and all other bits are active-high - this allows us to
    //     use a one-hot encoding but still reset the register to all-zeros.
    wire itag_match_f ; // (forward)
    assign ic_state_a1 = ic_state_a1_b0l ^ IDLE ;
    assign ic_state = ic_state_b0l ^ IDLE ;
    assign ic_state_a1_b0l = 
	next_state(
	    ic_state,
	    itag_match_f,
	    mm_iabort,
	    mm_istat_avail,
	    mm_cache_stat,
	    mm_icstben,
	    last_fill_write,
	    start_itag_inv,
	    fetch_f,
	    iu_held,
	    dcc_nc_bypass,
	    refetch_g
	) ^ IDLE ;
    Mflipflop_r_13 ic_state_reg(
	ic_state_b0l[12:0], ic_state_a1_b0l[12:0],
	~ss_reset, ss_clock
    ) ;

    // Some state decodes
    wire 
	ic_tag_inv_write,
	ic_tag_inv,
	ic_dead_cyc_3,
	ic_dead_cyc_2,
	ic_dead_cyc_1,
	ic_fill_write,
	ic_fill_wait,
	ic_nc_retry,
	ic_nc_byp,
	ic_nc_wait,
	ic_stat,
	ic_stat_wait,
	ic_idle
	;
    assign {
	ic_tag_inv_write,
	ic_tag_inv,
	ic_dead_cyc_3,
	ic_dead_cyc_2,
	ic_dead_cyc_1,
	ic_fill_write,
	ic_fill_wait,
	ic_nc_retry,
	ic_nc_byp,
	ic_nc_wait,
	ic_stat,
	ic_stat_wait,
	ic_idle
    } = ic_state ;

    wire ic_dead_cyc_a1 =
	    ic_state_a1[DEAD_CYC_1_idx]
	    | ic_state_a1[DEAD_CYC_2_idx]
	    | ic_state_a1[DEAD_CYC_3_idx]
	    ;
    Mflipflop_r dc_ff(ic_dead_cyc, ic_dead_cyc_a1,
	                              ~ss_reset, ss_clock) ;


    // When cache is disabled, make it look like the tag doesn't match.
    assign itag_match_f = it_hit_f & icache_enbl_f ;

    // This interface signals to the MMU that they need to handle a miss.
    wire ic_miss_and_part = (ic_idle & fetch_f) ;
    wire ic_miss_or_part = (ic_miss_and_part & ~icache_enbl_f) | ic_stat_wait ;
    wire ic_miss = ic_miss_or_part | (~it_hit_f & ic_miss_and_part) ;
    wire ic_miss_sustain = ic_stat_wait ;

    // Used by IU to hold IMAR.  The IMAR is used for fill writes only.
    wire imiss_in_progress = ~ic_idle & ~(ic_fill_write & last_fill_write) ;

    // Active when we're bypassing data that was on ic_din last cycle.
    wire byp_f_a1 = mm_icstben & (ic_fill_wait | ic_dead_cyc_3 | ic_nc_wait) ;
    Mflipflop_r ibf_ff(byp_f, byp_f_a1,
	                              ~ss_reset, ss_clock) ;

    // Report parity error to IU in the original bypass cycle (FILL_WRITE
    //    or NC_BYP), during dead cycle streaming for the *last* bad
    //    doubleword, and in any retried NC_BYP cycles.  See Bug 381.
    wire [1:0] perr_seen ; // (forward)
    wire [1:0] perr_f = ({2{byp_f}} & dp_perr[1:0]) ;
    wire [1:0] ic_perr_f =
	perr_f[1:0] | ({2{ic_nc_byp|ic_dead_cyc}} & perr_seen[1:0]) ;
    wire perr_seen_or = (perr_seen[1:0]!=2'b00) ;
    wire perr_or = (perr_f[1:0]!=2'b00) ;

    // When a parity error is reported by memif, latch it until the next
    //     IDLE cycle.  Used to disable dead cycle streaming, to report error
    //     on NC_BYP retries, and to invalidate the ITag on cache fill.
    wire [1:0] perr_seen_a1 =
	{2{~ic_idle}} & (perr_or ? perr_f[1:0] : perr_seen[1:0]) ;
    Mflipflop_r_2 pes_reg(perr_seen[1:0], perr_seen_a1[1:0],
	                      ~ss_reset, ss_clock) ;

    // Go back and invalidate the ITag write when we've seen a parity error.
    wire start_itag_inv =
	(perr_seen_or | perr_or) & last_fill_write & ic_fill_write ;

    wire [13:3] iva_f ;
    Mflipflop_noop_11 iva (iva_f[13:3], iu_iva_g[13:3], ss_clock) ;

    wire [13:3] imar ;
    Mflipflop_11 imar_reg (imar[13:3], iva_f[13:3], ss_clock, ~ic_idle) ;

    // This sequences through the doublewords of a cache fill.  fill_dw[4:3]
    //     increments *after* the cycle which writes that doubleword.
    wire [4:3] fill_dw, i_nfillp ;
    assign i_nfillp[4:3] = 
	ic_idle ? iva_f[4:3] : (
	ic_fill_write ? (fill_dw[4:3] + 2'b1) : (
	fill_dw[4:3] )) ;
    Mflipflop_noop_2 fill_ctr(fill_dw[4:3], i_nfillp[4:3], ss_clock) ;

    // This keeps track of which doublewords have been filled.
    // On a parity error, mark the bad doubleword as 'filled', and
    //     all other doublewords are marked 'not filled'; subsequent
    //     doublewords will not be marked 'filled' unless they themselves
    //     have parity errors.  Thus, at any one time after a parity error has
    //     occurred, only the *last* bad doubleword is in the 'filled' state.
    //     That way we can report the error to the IU during dead-cycle
    //     stream cycles.  See Bug 381 for why this is necessary.
    wire mark_filled = ic_fill_write & (~perr_seen_or | perr_or) ;
    wire dw_0_filled, dw_1_filled, dw_2_filled, dw_3_filled ;
    wire dw_0_filled_a1 =
	~ic_idle & ((dw_0_filled & ~perr_or)
		    | (mark_filled & (fill_dw[4:3]==2'd0))) ;
    wire dw_1_filled_a1 =
	~ic_idle & ((dw_1_filled & ~perr_or)
		    | (mark_filled & (fill_dw[4:3]==2'd1))) ;
    wire dw_2_filled_a1 =
	~ic_idle & ((dw_2_filled & ~perr_or)
		    | (mark_filled & (fill_dw[4:3]==2'd2))) ;
    wire dw_3_filled_a1 =
	~ic_idle & ((dw_3_filled & ~perr_or)
		    | (mark_filled & (fill_dw[4:3]==2'd3))) ;
    Mflipflop_noop fill_mark0(dw_0_filled, dw_0_filled_a1,
	                              ss_clock) ;
    Mflipflop_noop fill_mark1(dw_1_filled, dw_1_filled_a1,
	                              ss_clock) ;
    Mflipflop_noop fill_mark2(dw_2_filled, dw_2_filled_a1,
	                              ss_clock) ;
    Mflipflop_noop fill_mark3(dw_3_filled, dw_3_filled_a1,
	                              ss_clock) ;
    Mmux4_1 dwf_mux(dw_filled_f, 
	dw_0_filled, dw_1_filled, dw_2_filled, dw_3_filled,
	iva_f[4:3]) ;

    // Address matches used for streaming analysis.
    // Note: these are hard-coded for a 16KB cache, to facilitate synthesis. 
    //       When running with a larger cache (i.e. cache mode), we can get
    //       some needless streaming misses if we access a line whose
    //       IVA differs from the line we're filling only in bits 15:14.
    wire same_dw_f = (iva_f[4:3]==fill_dw[4:3]) ;
    wire same_line_f = (iva_f[13:5]==imar[13:5]) ;

    // The FILL_WRITE cycle which increments the fill pointer back to
    //    the original DW is the last fill write.
    assign last_fill_write = (i_nfillp[4:3]==imar[4:3]) ;

    // This means that the IU should look at it_hit_f to determine
    //     whether data is available.
    wire enbl_itag_match_f_a1 =
	(mm_icache_enbl & ic_state_a1[IDLE_idx])
	    | ic_state_a1[FILL_WRITE_idx] | ic_dead_cyc_a1 ;
    Mflipflop_r eim_ff(enbl_itag_match_f, enbl_itag_match_f_a1,
	                              ~ss_reset, ss_clock) ;

    // Fetch attemped while ICache is disabled.  IU will assert iu_held
    //     in this cycle, we'll assert ic_miss, and ic_state will transition
    //     to ic_stat_wait.
    // Note: This term removed from iwait_f, and duplicated in the IU,
    //       to fix a long path (enbl_fetch->iwait_f->iu_held).
    wire fetch_while_disabled = (ic_idle & fetch_f & ~icache_enbl_f) ;

    // Timing fix for IU.  Instead of using mm_icstben to select fill
    //     address in cycle before fill write, use this faster signal.
    //     Minor disadvantage of this: can do dead cycle streaming only in
    //     1st, 2nd, or 3rd dead cycle - see no_fill_data, below.
    wire ic_force_ifill_g = ic_fill_wait | ic_dead_cyc_3 ;

    // no_fill_data: The IU drove the fill address last cycle, but we didn't
    //     get any data over the cache fill bus.
    wire no_fill_data_a1 = ic_force_ifill_g & ~mm_icstben ;

    // Timing fix - these terms computed a cycle earlier and latched
    wire cancel_fetch_f_a1 ; // (forward)
    wire iwait_term1_a1 =

	// Automatic iwait in these states
	(|(ic_state_a1 & (
	    STAT_WAIT
	    | STAT
	    | NC_WAIT
	    | NC_RETRY
	    | FILL_WAIT
	    // No data available during a parity error tag invalidate sequence
	    //     (see Bug 307)
	    | TAG_INV | TAG_INV_WRITE
	)))

	// No data available if the ICache is being used by dc_cntl
	| nforce_dva_f

	// If we missed an attempted tag match last cycle, we're
	//     addressing a bogus location this cycle.
	| cancel_fetch_f_a1

	| no_fill_data_a1

	// Force a hold in standby cycles (See Bug 524, second part)
	| standby

	;
    Mflipflop_r iwt1_ff(iwait_term1, iwait_term1_a1,
	                              ~ss_reset, ss_clock) ;

    // This means that no data is available in this cycle
    wire iwait_f =
	    iwait_term1
	    | (ic_fill_write & ~(same_line_f & same_dw_f))
	    | (ic_dead_cyc & same_line_f & ~dw_filled_f)

	    // Disable out-of-line dead-cycle streaming when we've had a
	    //     parity error.  See Bug 381.
	    | (ic_dead_cyc & ~same_line_f & perr_seen_or)

	    // Standby mode - don't start a new miss sequence if there is
	    //     a standby request active.
	    | (ic_idle & standby_req)

	    ;

    // When we miss on a tag match, inhibit any effects of the next cycle's
    //     fetch, and hold the IU for that fetch's F-cycle.  Do this because,
    //     in the cycle of the miss, iva_g has falsely advanced to the next
    //     fetch address.
    wire tag_miss =
	enbl_itag_match_f & ~(iwait_f | fetch_while_disabled) & ~it_hit_f ;

    // Don't release the 'tag_miss last cycle' hold if dc_cntl is trying to
    //     bypass.  This fixes Bug 388, by allowing the IU to correctly
    //     re-address the missed fetch in a cycle that lines up with a
    //     dcc_nc_retry cycle.
    //
    //         1:                   G  F  F  F  F  D
    //         tag_miss                =
    //         cancel_fetch_f             =  =
    //         dcc_state                  Nb Nr Nb
    //         iva_g                1  2  1  1  2
    //         iu_held                 =  =  =

    assign cancel_fetch_f_a1 = tag_miss | (cancel_fetch_f & dcc_nc_bypass) ;
    Mflipflop_r mlc_ff(cancel_fetch_f, cancel_fetch_f_a1,
	                              ~ss_reset, ss_clock) ;

    // Tag write: write tag valid when mm_istat_avail is asserted,
    //      and on ASI stores to ITag.
    wire fill_tag_write = ic_stat & mm_cache_stat ;
    wire st_itag_write =
	nforce_dva_f & ic_asi_store_tag_w & icstben_asi & ~iu_in_trap ;
    wire st_idata_write =
	nforce_dva_f & ic_asi_store_cache_w & icstben_asi & ~iu_in_trap ; 
    wire tag_write = fill_tag_write | st_itag_write ;
    wire tagv_write =
	fill_tag_write | st_itag_write | flush_tag_write | ic_tag_inv ; 

    // synopsys translate_off
    always @(posedge ss_clock) if (nforce_dva_f & fill_tag_write) 
	Mclocks.print_error("nforce_dva_f during fill_tag_write") ;
    // synopsys translate_on

    assign it_be       = tag_write ;
    assign it_be_vb    = tagv_write ;

    // Data-in to Tag VA field is normally the MSBs of the IVA (for tag match)
    //     except when we're writing the Tag.
    assign it_din[31:`log2_icachesize] = 
	tag_write ? misc_in[31:`log2_icachesize]
	      : icache_adr[31:`log2_icachesize] ;
    assign it_cntx_in[7:0] = tag_write ? misc_in[11:4] : cxr[7:0] ;
    assign it_acc_in = st_itag_write ? misc_in[3] : (misc_in[3:2]==2'b11) ;
    assign it_lvl_in[1:0] = st_itag_write ? misc_in[2:1] : mm_fs_lvl[1:0] ;

    // Valid bit data_in:  on StA, misc[0]; on cache fill, 1; on flush, 0;
    //     on parity error invalidate, 0.
    assign it_val_in = st_itag_write ? misc_in[0] : fill_tag_write ;

    // Latch the PTE status when MMU drives it on misc and/or the LVL
    //     interface.  On iabort, the MMU sends LVL but not ACC.
    // Latch a 0 for sup_only on iabort - see Bug 404.
    wire stat_strobe = ic_stat | mm_iabort ;
    MflipflopR supv_ff(sup_only, it_acc_in & ~mm_iabort,
	ss_clock, ~stat_strobe, ss_reset) ;
    wire [1:0] lvl ;
    MflipflopR_2 lvl_ff(lvl[1:0], it_lvl_in[1:0],
	ss_clock, ~stat_strobe , ss_reset) ;

    // Report Supervisor Page instructions to IU along with the data
    wire ic_sup_only_f = ic_nc_byp ? sup_only : it_acc_out ;

    // Report PTE Level field to IU along with the data
    wire [1:0] ic_lvl_f = ic_nc_byp ? lvl[1:0] : it_lvl_out[1:0] ;

    wire fill_write = (ic_fill_wait | ic_dead_cyc_3) & mm_icstben ;
    wire [1:0] write = // WARNING: {LSW,MSW} !!!
	{(st_idata_write & dva_w_2), (st_idata_write & ~dva_w_2)}
	    | {2{fill_write}} ;

    // Bypass, without writing, whenever noncached data is present.
    wire byp =
	(ic_nc_wait & mm_icstben)
	    | (ic_nc_retry & ~nforce_dva_f & ~standby_req) ;

    // Turn off power to the RAMs when we're idle in standby mode.  To avoid
    //     any dependency on pipe hold, we can power down while we're holding
    //     noncached data during a pipe hold.  If we didn't do this, dc_cntl
    //     might enter standby mode and hold the pipe, which would prevent
    //     ic_cntl from exiting the ic_nc_byp/ic_nc_retry loop and entering
    //     standby mode - the clocks would then never turn off.
    // (See Bug 524, first part)
    assign standby =
	standby_req & (ic_idle | ic_nc_byp | ic_nc_retry) & ~nforce_dva_f ;

    wire ic_power_down =

	// Don't power down when we're doing a StA, LdA, or flush
	~nforce_dva_f & (

	    // (Remove any of these terms which are timing problems)

	    // Power down for idle (or nc_retry) cycles when cache is disabled.
	    ((ic_idle | ic_nc_byp) & ~mm_icache_enbl)

	    // Power down while we're waiting for data to come from memory
	    | ic_stat_wait
	    | (ic_stat & ~mm_cache_stat)
	    | ((ic_nc_wait | ic_fill_wait) & ~mm_icstben)
	)

	// Power down in standby mode
	| standby
	;

    // ic_be must be asserted for write and bypass cycles
    // WARNING: {LSW,MSW} !!!
    wire [1:0] ic_be = write[1:0] | {2{byp}} ;

    // wle must be asserted for read and write cycles (for both cache and tag)
    wire ic_wle = ~byp & ~ic_power_down ;

    function [12:0] next_state ;
    input [12:0] ic_state ;
    input itag_match_f ;
    input mm_iabort ;
    input mm_istat_avail ;
    input mm_cache_stat ;
    input mm_icstben ;
    input last_fill_write ;
    input start_itag_inv ;
    input fetch_f ;
    input iu_held ;
    input dcc_nc_bypass ;
    input refetch_g ;

    // Too much bother to make synopsys do something intelligent with
    //     case/endcase with a one-hot state encoding.  Just use if's.

    begin

	// Reset all the state bits - we'll set one below
	next_state = 13'b0 ;

	if (ic_state[IDLE_idx]) begin 
		// synopsys translate_off
		if ((fetch_f&~itag_match_f)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    // Miss on ICache accesss
	    if (fetch_f & ~itag_match_f)
		next_state[STAT_WAIT_idx] = 1'b1 ;
	    else next_state[IDLE_idx] = 1'b1 ;
	end

	if (ic_state[STAT_WAIT_idx]) begin

	    // Waiting for address and cacheable status

		// synopsys translate_off
		if ((mm_iabort^mm_istat_avail)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    // On mm_iabort, go to the NC_BYP state and stay there until the
	    //     IU releases the pipe and takes the exception status (see
	    //     Bug 130).
	    if (mm_iabort) next_state[NC_BYP_idx] = 1'b1 ;
	    else if (mm_istat_avail) next_state[STAT_idx] = 1'b1 ;
	    else next_state[STAT_WAIT_idx] = 1'b1 ;
	end

	if (ic_state[STAT_idx]) begin

	    // Status is on misc bus now

		// synopsys translate_off
		if ((^mm_cache_stat)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    if (mm_cache_stat) next_state[FILL_WAIT_idx] = 1'b1 ;
	    else next_state[NC_WAIT_idx] = 1'b1 ;
	end

	if (ic_state[NC_WAIT_idx]) begin // Waiting for noncached data

		// synopsys translate_off
		if ((^mm_icstben)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    if (mm_icstben) next_state[NC_BYP_idx] = 1'b1 ;
	    else next_state[NC_WAIT_idx] = 1'b1 ;
	end

	// Bypassing noncached data, or exception status
	if (ic_state[NC_BYP_idx]) begin

		// synopsys translate_off
		if ((^iu_held^refetch_g)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    // If pipe is held, or if the IU is re-fetching the same address,
	    //     we must retry the bypass.
	    if (iu_held|refetch_g) next_state[NC_RETRY_idx] = 1'b1 ;
	    else next_state[IDLE_idx] = 1'b1 ;
	end

	// Pipe was held when we bypassed noncached data.  We're doing
	//     a read, not a bypass, this cycle.  Go back and try to
	//     bypass again.
	if (ic_state[NC_RETRY_idx]) begin
		// synopsys translate_off
		if ((^dcc_nc_bypass)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    // To prevent the deadlock of Bug 353, synchronize with the
	    //     dc_cntl state machine if we're both trying to bypass
	    //     noncached data.
	    if (dcc_nc_bypass) next_state[NC_RETRY_idx] = 1'b1 ;
	    else next_state[NC_BYP_idx] = 1'b1 ;
	end

	if (ic_state[FILL_WAIT_idx]) begin // Waiting for the first fill data

		// synopsys translate_off
		if ((^mm_icstben)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    if (mm_icstben) next_state[FILL_WRITE_idx] = 1'b1 ;
	    else next_state[FILL_WAIT_idx] = 1'b1 ;
	end

	if (ic_state[FILL_WRITE_idx]) begin

	    // Writing a doubleword of cache fill data

		// synopsys translate_off
		if ((^last_fill_write^start_itag_inv)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    if (start_itag_inv) next_state[TAG_INV_idx] = 1'b1 ;
	    else if (last_fill_write) next_state[IDLE_idx] = 1'b1 ;
	    else next_state[DEAD_CYC_1_idx] = 1'b1 ;

	end

	if (ic_state[DEAD_CYC_1_idx]) begin // No fill data possible
	    next_state[DEAD_CYC_2_idx] = 1'b1 ;
	end

	if (ic_state[DEAD_CYC_2_idx]) begin // No fill data possible
	    next_state[DEAD_CYC_3_idx] = 1'b1 ;
	end

	if (ic_state[DEAD_CYC_3_idx]) begin // Waiting for the next fill data

		// synopsys translate_off
		if ((^mm_icstben)===1'bx)
		    next_state = 'bx ; else
		// synopsys translate_on

	    if (mm_icstben) next_state[FILL_WRITE_idx] = 1'b1 ;
	    else next_state[DEAD_CYC_3_idx] = 1'b1 ;
	end

	// Parity error detected during fill.
	// icache_adr is addressing the bad line for a tag invalidate.
	if (ic_state[TAG_INV_idx]) begin
	    next_state[TAG_INV_WRITE_idx] = 1'b1 ;
	end

	// Parity error detected during fill.  The tag invalidate write is
	//     done this cycle.
	if (ic_state[TAG_INV_WRITE_idx]) begin
	    next_state[IDLE_idx] = 1'b1 ;
	end

    end
    endfunction

    // synopsys translate_off


    // Some state monitors
    always @(posedge ss_clock) #2 if (~ss_reset) begin
	if (( ic_state_a1[0]
		+ ic_state_a1[1]
		+ ic_state_a1[2]
		+ ic_state_a1[3]
		+ ic_state_a1[4]
		+ ic_state_a1[5]
		+ ic_state_a1[6]
		+ ic_state_a1[7]
		+ ic_state_a1[8]
		+ ic_state_a1[9]
		+ ic_state_a1[10]
		+ ic_state_a1[11]
		+ ic_state_a1[12]
	    )!==1
	) Mclocks.print_error("illegal ic_cntl next state") ;

	// MMU priorities should prevent this?  If not, ic_din reg gets
	//     wiped out.
	if ((~ic_hld[0])&&((ic_state==NC_BYP)||(ic_state==NC_RETRY)))
	    Mclocks.print_error(
		"ICache DIN reg strobed during ic_nc_byp or ic_nc_retry") ;

    end

    // For dcc displays:

    // Convert 1-hot state value to binary number
    function [7:0] ic_state_encode ;
	input [12:0] state ;
	ic_state_encode = ((^state)===1'bx) ? 'bx : {
	    ((state & 13'b1111100000000)!=0),
	    ((state & 13'b1000011110000)!=0),
	    ((state & 13'b0110011001100)!=0),
	    ((state & 13'b0101010101010)!=0)
	} ;
    endfunction

    wire [7:0] ic_state_encoded = ic_state_encode(ic_state) ;
    wire [7:0] ic_state_encoded_a1 = ic_state_encode(ic_state_a1) ;

    reg [15:0] ic_state_str [0:12] ;
    initial begin
	ic_state_str[0] = ". " ;	// IDLE
Next12
HierarchyFilesModulesSignalsTasksFunctionsHelp

This page: Created:Thu Aug 19 12:02:31 1999
From: ../../../sparc_v8/ssparc/cc/rl_ic_cntl/rtl/rl_ic_cntl.v

Verilog converted to html by v2html 5.0 (written by Costas Calamvokis).Help