/******************************************************************************/
/* */
/* 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_dc_sm.v 1.15 4/5/93
// This is state machine for the D$ controller.
module rl_dc_sm
(
dcc_state ,
wb_empty ,
ic_miss ,
nonheld_once ,
normal_asi_w,
parity_error_in_fill ,
dc_miss,
dcc_st_miss ,
mm_dabort ,
mm_dcstben ,
mm_dstat_avail ,
cached ,
iu_held ,
iu_in_trap ,
ss_reset,
ss_clock
);
output [11:0] dcc_state
;
input normal_asi_w
;
input ic_miss
;
input nonheld_once
;
input wb_empty
;
input parity_error_in_fill
;
input dc_miss
;
input dcc_st_miss
;
input mm_dabort
; // From mmu control
input mm_dcstben
; // From mmu control
input mm_dstat_avail
; // From mmu control
input cached
; // From mmu over misc[12] bus.
input iu_held
; // From rl_dc_cnt
input iu_in_trap
; // From iu
input ss_reset
; // From rl_dc_cnt
input ss_clock
; // From rl_dc_cnt
// State encoding
parameter
IDLE = 12'b000000000001,
STAT_WAIT = 12'b000000000010,
STAT = 12'b000000000100,
FILL_WAIT = 12'b000000001000,
FILL_WRITE_F = 12'b000000010000,
DEAD_CYC_1 = 12'b000000100000,
DEAD_CYC_2 = 12'b000001000000,
DEAD_CYC_3 = 12'b000010000000,
FILL_WRITE_L = 12'b000100000000,
NC_WAIT = 12'b001000000000,
NC_BYP = 12'b010000000000,
NC_RETRY = 12'b100000000000;
wire [11:0] dcc_state, dcc_state_b0l
, dcc_next_state_b0l
;
function [11:0] next_dcc_state ;
input [11:0] dcc_state ;
input normal_asi_w ;
input ic_miss ;
input nonheld_once ;
input wb_empty ;
input parity_error_in_fill ;
input dc_miss ;
input dcc_st_miss ;
input mm_dabort ; // From mmu control
input mm_dcstben ; // From mmu control
input mm_dstat_avail ; // From mmu control
input cached ; // From mmu over misc[12] bus.
input iu_held ; // From rl_dc_cnt
input iu_in_trap ; // From iu
// Too much bother to make synopsys do something intelligent with
// case/endcase with a one-hot state encoding. Just use if's.
begin
// =====================================================================
if (IDLE & dcc_state) begin // Reset state
if( iu_in_trap)
next_dcc_state = IDLE ; // TRAP .. don't start
else if(dc_miss)
next_dcc_state = STAT_WAIT ;
else next_dcc_state = IDLE ;
end
// Simulate 'parallel case'
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
// Wait for either mm_dabort | mm_dstat_avail
if (STAT_WAIT & dcc_state) begin
// Traps do not effect the D$ controller, otherwise MMU gets confused.
// Hence we complete the present miss as it would be done normally.
// This is only for the load case. The store case should not occur,
// (since FPU takes care of this condition).
if( mm_dabort)
next_dcc_state = NC_BYP ; // miss aborted
else if(~mm_dabort & mm_dstat_avail ) begin
if( ~cached & normal_asi_w) begin
if (dcc_st_miss) next_dcc_state = NC_BYP ;
else next_dcc_state = STAT ;
end
else next_dcc_state = STAT ;
end
else next_dcc_state = STAT_WAIT ;
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
if (STAT & dcc_state) begin
// Cached | non-cached ? That is the question.
if( cached )
next_dcc_state = FILL_WAIT ; // miss aborted
else if( ~cached ) begin // Tag data received
if (dcc_st_miss) next_dcc_state = NC_BYP ;
else next_dcc_state = NC_WAIT ;
end
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
if (FILL_WAIT & dcc_state) begin
// Wait for data to come back (mm_dcstben)
// No streaming here, unlike in DEAD_CYCLE
if(mm_dcstben)
next_dcc_state = FILL_WRITE_F ; // 64 bit data back
else if( ~mm_dcstben )
next_dcc_state = FILL_WAIT; // Waiting for data
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
// First fill write
if (FILL_WRITE_F & dcc_state) begin // Write data to D$
next_dcc_state = DEAD_CYC_1; // Fill still in progress
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
// We have at least three dead cycles, depending on memory speed
// First dead cycle.
if (DEAD_CYC_1 & dcc_state) begin // Dead cycles, streaming allowed now.
next_dcc_state = DEAD_CYC_2; // Fill wait, stream now!
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
// Second dead cycle.
if (DEAD_CYC_2 & dcc_state) begin // Dead cycles, streaming allowed now.
next_dcc_state = DEAD_CYC_3; // Fill wait, stream now!
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
// Third through last dead cycles.
if (DEAD_CYC_3 & dcc_state) begin // Dead cycles, streaming allowed now.
if( mm_dcstben )
next_dcc_state = FILL_WRITE_L; // Fill data back
else if( ~mm_dcstben )
next_dcc_state = DEAD_CYC_3; // Fill wait, stream now!
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
// Last fill write
if (FILL_WRITE_L & dcc_state) begin // Write data to D$
if(parity_error_in_fill & ic_miss & ~wb_empty)
next_dcc_state = IDLE; // Deadlock case Bug #523
else if( parity_error_in_fill & ~nonheld_once)
next_dcc_state = NC_BYP;
else if( parity_error_in_fill & nonheld_once)
next_dcc_state = IDLE;
else if( ~parity_error_in_fill )
next_dcc_state = IDLE;
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
if (NC_WAIT & dcc_state) begin // Waiting for non-cached data.
if( mm_dcstben )
next_dcc_state = NC_BYP; // Fill data back
else if( ~mm_dcstben )
next_dcc_state = NC_WAIT; // Fill wait, no streaming
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
if (NC_BYP & dcc_state) begin // If load, non-cached data is back.
if( iu_held )
next_dcc_state = NC_RETRY; // Wait until hold goes away
else if( ~iu_held )
next_dcc_state = IDLE;
end
// synopsys translate_off
else
// synopsys translate_on
// =====================================================================
if (NC_RETRY & dcc_state) begin // If load, non-cached data is back.
next_dcc_state = NC_BYP; // Wait until hold goes away
end
// =====================================================================
// Simulate default case
// synopsys translate_off
else next_dcc_state = 'bx ;
// synopsys translate_on
end
endfunction
assign dcc_next_state_b0l =
IDLE ^ next_dcc_state(
dcc_state ,
normal_asi_w,
ic_miss,
nonheld_once,
wb_empty,
parity_error_in_fill,
dc_miss,
dcc_st_miss,
mm_dabort ,
mm_dcstben ,
mm_dstat_avail ,
cached ,
iu_held ,
iu_in_trap
);
// DCache state machine register
// The IDLE bit is stored inverted in this register, so that it resets
// to the IDLE state.
Mflipflop_r_12 dcc_st (dcc_state_b0l, dcc_next_state_b0l,
~ss_reset, ss_clock) ;
assign dcc_state = dcc_state_b0l ^ IDLE ;
// synopsys translate_off
// Check to see if mmu violates the mm_dstat_avail protocol
wire mm_dstat_avail_d1
, cached_d1
;
Mflipflop_r mm_dstat_avail_d1_ff (mm_dstat_avail_d1,
mm_dstat_avail, ~ss_reset, ss_clock);
Mflipflop_r cached_d1_ff (cached_d1,
cached, ~ss_reset, ss_clock);
always @(posedge ss_clock)
if (mm_dstat_avail_d1 & (cached !== cached_d1) & normal_asi_w)
Mclocks.print_error(
"dcache: mmu violated mm_dstat_avail protocol for cached bit.");
// synopsys translate_on
endmodule
This page: |
Created: | Thu Aug 19 12:03:14 1999 |
| From: |
../../../sparc_v8/ssparc/cc/rl_dc_cntl/rtl/rl_dc_sm.v
|