/******************************************************************************/
/* */
/* 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.
//
******************************************************************************/
/*****************************
*****************************/
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
This page: |
Created: | Thu Aug 19 12:02:31 1999 |
| From: |
../../../sparc_v8/ssparc/cc/rl_ic_cntl/rtl/rl_ic_cntl.v
|