Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / spc / ifu / rtl / ifu_cmu_csm_ctl.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: ifu_cmu_csm_ctl.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
//
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
//
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
// ========== Copyright Header End ============================================
module ifu_cmu_csm_ctl (
l1clk,
scan_in,
spc_aclk,
spc_bclk,
ftu_cmiss,
ftu_redirect,
ftu_inv_req,
lsc_l15_valid,
mct_fill_complete,
cmu_data_ready,
cmu_has_dup_miss,
cmu_mbhit_c,
mct_rst_dupmiss,
mct_ignore_cmiss,
mdp_mbhit_q,
csm_valid_req,
cmu_null_st,
cmu_dupmiss_st,
cmu_req_st,
cmu_canleave_st,
scan_out) ;
wire siclk;
wire soclk;
wire inv_req_reg_scanin;
wire inv_req_reg_scanout;
wire inv_req_ff;
wire redirect_reg_scanin;
wire redirect_reg_scanout;
wire ftu_redirect_lat;
wire go_to_null_state;
wire null_state;
wire req_state;
wire canleave_state;
wire fillwait_state;
wire dupmiss_state;
wire invreq_state;
wire next_null_state_;
wire null_state_;
wire null_state_reg_scanin;
wire null_state_reg_scanout;
wire go_to_req_state;
wire next_req_state;
wire req_state_reg_scanin;
wire req_state_reg_scanout;
wire go_to_canleave_state;
wire next_canleave_state;
wire canleave_state_reg_scanin;
wire canleave_state_reg_scanout;
wire go_to_retwait_state;
wire retwait_state;
wire next_retwait_state;
wire retwait_state_reg_scanin;
wire retwait_state_reg_scanout;
wire go_to_fillwait_state;
wire next_fillwait_state;
wire fillwait_state_reg_scanin;
wire fillwait_state_reg_scanout;
wire go_to_dupmiss_state;
wire next_dupmiss_state;
wire dupmiss_state_reg_scanin;
wire dupmiss_state_reg_scanout;
wire go_to_invreq_state;
wire next_invreq_state;
wire invreq_state_reg_scanin;
wire invreq_state_reg_scanout;
input l1clk;
input scan_in;
input spc_aclk;
input spc_bclk;
input ftu_cmiss; // cmiss request
input ftu_redirect; // indicates the thread is flushed/redirected
input ftu_inv_req; // invalidation request
input lsc_l15_valid; // req sent to gkt
input mct_fill_complete; // indicates that fill has been completed
input cmu_data_ready; // gkt rtn data and is ready to be written to I$
input cmu_has_dup_miss; // from MB ctl logic, current thread has outstanding duplicate miss.
input cmu_mbhit_c; // from MB ctl logic, current thread hits in missbuff, it is not real miss
input mct_rst_dupmiss; // comes on with data_ready, all dup miss waiting on current thread are reset.
input mct_ignore_cmiss; // current cmiss is a duplicate miss which needs to be ignored, data sent to I$.
input mdp_mbhit_q; // A qualified mbhit
output csm_valid_req; // valid request indicator
output cmu_null_st;
output cmu_dupmiss_st;
output cmu_req_st;
output cmu_canleave_st;
output scan_out;
// scan renames
assign siclk = spc_aclk;
assign soclk = spc_bclk;
// end scan
// flop inv_req.
// It means that inv_req will not take part in arbitration for
// two cycles after it arrives.
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 inv_req_reg (
.scan_in(inv_req_reg_scanin),
.scan_out(inv_req_reg_scanout),
.l1clk(l1clk),
.din (ftu_inv_req),
.dout (inv_req_ff),
.siclk(siclk),
.soclk(soclk)
);
// flop ftu_redirect
// use the delayed version for qualifying valid req.
// clearing of wom bits in mct should also use delayed version.
// use raw version to clear dup miss states
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 redirect_reg (
.scan_in(redirect_reg_scanin),
.scan_out(redirect_reg_scanout),
.l1clk(l1clk),
.din (ftu_redirect),
.dout (ftu_redirect_lat),
.siclk(siclk),
.soclk(soclk)
);
///////////////////////////////////////////////////
// CASE STATEMENT DESCRIPTION OF TSM MACHINE
///////////////////////////////////////////////////
//case(`CSM_STATE)
// `NULL_ST:
// if (~(ftu_cmiss & ~mct_ignore_cmiss) & ~inv_req_ff)
// next_state = `NULL_ST;
// if (ftu_cmiss & ~cmu_mbhit_c)
// next_state = `REQ_ST;
// if (ftu_cmiss & cmu_mbhit_c & ~ignore_cmiss)
// next_state = `DUPMISS_ST;
// if (inv_req_ff)
// next_state = `INVREQ_ST;
//
// `REQ_ST:
// if (lsc_l15_valid)
// next_state = `RETWAIT_ST;
// if (~lsc_l15_valid & ftu_redirect_lat & cmu_has_dup_miss)
// next_state = `CANLEAVE_ST;
// if (~lsc_l15_valid & ftu_redirect_lat & ~cmu_has_dup_miss & mdp_mbhit_q)
// next_state = `CANLEAVE_ST;
// if (~lsc_l15_valid & ftu_redirect_lat & ~cmu_has_dup_miss & ~mdp_mbhit_q)
// next_state = `NULL_ST;
// if (~lsc_l15_valid & ~ftu_redirect_lat)
// next_state = `REQ_ST;
//
// `CANLEAVE_ST:
// if (lsc_l15_valid)
// next_state = `RETWAIT_ST;
// if (~lsc_l15_valid & ~cmu_has_dup_miss & ~mdp_mbhit_q)
// next_state = `NULL_ST;
// if (~lsc_l15_valid & cmu_has_dup_miss)
// next_state = `CANLEAVE_ST;
// if (~lsc_l15_valid & mdp_mbhit_q)
// next_state = `CANLEAVE_ST;
//
// `RETWAIT_ST:
// if (~cmu_data_ready)
// next_state = `RETWAIT_ST;
// if (cmu_data_ready)
// next_state = `FILLWAIT_ST;
//
// `FILLWAIT_ST:
// if (~mct_fill_complete)
// next_state = `FILLWAIT_ST;
// if (mct_fill_complete)
// next_state = `NULL_ST;
//
// `DUPMISS_ST:
// if (~ftu_redirect & ~mct_rst_dupmiss)
// next_state = `DUPMISS_ST;
// if (ftu_redirect | mct_rst_dupmiss)
// next_state = `NULL_ST;
//
// `INVREQ_ST:
// if (lsc_l15_valid)
// next_state = `NULL_ST;
// if (~lsc_l15_valid)
// next_state = `INVREQ_ST;
//
// endcase
//
//
// 0in one_hot -var {null_state,req_state,canleave_state,retwait_state,fillwait_state,dupmiss_state,invreq_state}
////////////////////////////////////////////////////////
// NULL STATE
////////////////////////////////////////////////////////
// cmu_mbhit_c indicates a duplicate miss
// ignore_cmiss indicates a duplicate miss which needs to be ignored
//
// null_st is default state.
//
assign go_to_null_state = (null_state & ~(ftu_cmiss & ~mct_ignore_cmiss) & ~inv_req_ff) |
(req_state & ~lsc_l15_valid & ftu_redirect_lat & ~cmu_has_dup_miss & ~mdp_mbhit_q) |
(canleave_state & ~lsc_l15_valid & ~cmu_has_dup_miss & ~mdp_mbhit_q) |
(fillwait_state & mct_fill_complete) |
(dupmiss_state & (ftu_redirect | mct_rst_dupmiss)) |
(invreq_state & lsc_l15_valid);
assign next_null_state_ = ~go_to_null_state;
assign null_state = ~null_state_;
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 null_state_reg (
.scan_in(null_state_reg_scanin),
.scan_out(null_state_reg_scanout),
.l1clk(l1clk),
.din (next_null_state_),
.dout (null_state_),
.siclk(siclk),
.soclk(soclk)
);
////////////////////////////////////////////////////////
// REQUEST STATE
////////////////////////////////////////////////////////
// Go to request state on a real miss
// Stay in request state until the request is sent out or redirect.
assign go_to_req_state = (null_state & ftu_cmiss & ~cmu_mbhit_c) |
(req_state & ~lsc_l15_valid & ~ftu_redirect_lat) ;
assign next_req_state = go_to_req_state;
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 req_state_reg (
.scan_in(req_state_reg_scanin),
.scan_out(req_state_reg_scanout),
.l1clk(l1clk),
.din (next_req_state),
.dout (req_state),
.siclk(siclk),
.soclk(soclk)
);
////////////////////////////////////////////////////////
// CANLEAVE STATE
////////////////////////////////////////////////////////
// Go to canleave_st when a real miss is flushed, but it has
// other outstanding duplicate misses waiting on it.
// Leave canleave_st when the request is sent out, or it has no
// other duplicate misses waiting on it (This can happen if
// all duplicate misses get flushed out).
assign go_to_canleave_state = (req_state & ftu_redirect_lat & cmu_has_dup_miss & ~lsc_l15_valid) |
(req_state & ftu_redirect_lat & mdp_mbhit_q & ~lsc_l15_valid) |
(canleave_state & cmu_has_dup_miss & ~lsc_l15_valid) |
(canleave_state & mdp_mbhit_q & ~lsc_l15_valid);
assign next_canleave_state = go_to_canleave_state;
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 canleave_state_reg (
.scan_in(canleave_state_reg_scanin),
.scan_out(canleave_state_reg_scanout),
.l1clk(l1clk),
.din (next_canleave_state),
.dout (canleave_state),
.siclk(siclk),
.soclk(soclk)
);
////////////////////////////////////////////////////////
// Return Wait State
////////////////////////////////////////////////////////
// Go to return wait state when a request is sent to gkt/xbar.
// Stay in this state until data comes back and data_ready is
// signalled to ifu.
assign go_to_retwait_state = (req_state & lsc_l15_valid) |
(canleave_state & lsc_l15_valid) |
(retwait_state & ~cmu_data_ready);
assign next_retwait_state = go_to_retwait_state;
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 retwait_state_reg (
.scan_in(retwait_state_reg_scanin),
.scan_out(retwait_state_reg_scanout),
.l1clk(l1clk),
.din (next_retwait_state),
.dout (retwait_state),
.siclk(siclk),
.soclk(soclk)
);
////////////////////////////////////////////////////////
// Fill Wait State
////////////////////////////////////////////////////////
// Fillwait_st indicates that data_ready has been sent, wait
// until fill_complete is signalled by ifu
assign go_to_fillwait_state = (retwait_state & cmu_data_ready ) |
(fillwait_state & ~mct_fill_complete);
assign next_fillwait_state = go_to_fillwait_state;
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 fillwait_state_reg (
.scan_in(fillwait_state_reg_scanin),
.scan_out(fillwait_state_reg_scanout),
.l1clk(l1clk),
.din (next_fillwait_state),
.dout (fillwait_state),
.siclk(siclk),
.soclk(soclk)
);
////////////////////////////////////////////////////////
// DupMiss State
////////////////////////////////////////////////////////
// go to dupmiss_st on a dup miss.
assign go_to_dupmiss_state = (null_state & ftu_cmiss & cmu_mbhit_c & ~mct_ignore_cmiss) |
(dupmiss_state & ~ftu_redirect & ~mct_rst_dupmiss);
assign next_dupmiss_state = go_to_dupmiss_state;
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 dupmiss_state_reg (
.scan_in(dupmiss_state_reg_scanin),
.scan_out(dupmiss_state_reg_scanout),
.l1clk(l1clk),
.din (next_dupmiss_state),
.dout (dupmiss_state),
.siclk(siclk),
.soclk(soclk)
);
////////////////////////////////////////////////////////
// INVREQ STATE
////////////////////////////////////////////////////////
// go to invreq state on a invalidation request.
assign go_to_invreq_state = (null_state & inv_req_ff) |
(invreq_state & ~lsc_l15_valid);
assign next_invreq_state = go_to_invreq_state;
ifu_cmu_csm_ctl_msff_ctl_macro__width_1 invreq_state_reg (
.scan_in(invreq_state_reg_scanin),
.scan_out(invreq_state_reg_scanout),
.l1clk(l1clk),
.din (next_invreq_state),
.dout (invreq_state),
.siclk(siclk),
.soclk(soclk)
);
////////////////////////////////////////////////////////
// State Machine output signals
////////////////////////////////////////////////////////
// csm_valid_req indicates that a valid request exists which
// takes part in arbitration
// If a request was sent out previous cycle, then the thread
// will still be in REQ state this cycle. Validreq will still come
// on for this thread, but it will get killed in lsi_ctl before
// it takes part in arbitration.
// To ease timing, mbhit_q is not used to generate the valid req.
// valid_req comes on if
// 1. in req state, and no flush or has_dup_miss.
// if a flush happens and there are no dup misses, then the thread
// will not take part in arb, even though a new dup miss could be
// happening at the same time. The new dup miss will show up in
// can_leave state the next cycle.
// 2. in canleave state and has_dup_miss. Again, if in canleave state
// and no dup miss, then thread will not take part in arb even though
// a dup miss could be happening in same cycle. The dup miss will
// force the state the stay in can_leave and it will set the has_dup
// signal next cycle. So the thread will take part in arb next cycle.
// 3. In inv_req state.
assign csm_valid_req = (req_state & ~(ftu_redirect_lat & ~cmu_has_dup_miss)) |
(canleave_state & cmu_has_dup_miss) |
(invreq_state);
// cmu_cmiss_is_sent
// Indicates that a request has been sent.
// This signal serves two purposes:
// 1. used in conjunction with has_dup_miss in msb_ctl and ifu_ftu to
// qualify missbuffer hits.
// If a parent thread has not been sent, and it has a redirect, and
// it does not have other dup misses outstanding, then an incoming
// thread cannot hit on it.
// 2. Used by ifu to get out of no_new_miss state.
//assign cmu_cmiss_is_sent = lsc_l15_valid | retwait_state | fillwait_state;
// wom_valid bit for each thread comes on when the thread is in dupmiss_st or the req
// has been sent and thread has not been redirected.
// wom_valid is used to qualify bypass for the thread.
// Bypass to a thread only if its wom_valid bit is set.
// dup WOM bit is not reset if there is redirect and req. is already sent. In this scenario,
// bypass is not valid. Hence generating this wom_valid signal to ignore the wom bit.
//assign csm_wom_valid = ~null_state & ~reqredirect_state ;
assign cmu_null_st = null_state;
assign cmu_dupmiss_st = dupmiss_state;
assign cmu_req_st = req_state;
assign cmu_canleave_st = canleave_state;
supply0 vss;
supply1 vdd;
// fixscan start:
assign inv_req_reg_scanin = scan_in ;
assign redirect_reg_scanin = inv_req_reg_scanout ;
assign null_state_reg_scanin = redirect_reg_scanout ;
assign req_state_reg_scanin = null_state_reg_scanout ;
assign canleave_state_reg_scanin = req_state_reg_scanout ;
assign retwait_state_reg_scanin = canleave_state_reg_scanout;
assign fillwait_state_reg_scanin = retwait_state_reg_scanout;
assign dupmiss_state_reg_scanin = fillwait_state_reg_scanout;
assign invreq_state_reg_scanin = dupmiss_state_reg_scanout;
assign scan_out = invreq_state_reg_scanout ;
// fixscan end:
endmodule
// any PARAMS parms go into naming of macro
module ifu_cmu_csm_ctl_msff_ctl_macro__width_1 (
din,
l1clk,
scan_in,
siclk,
soclk,
dout,
scan_out);
wire [0:0] fdin;
input [0:0] din;
input l1clk;
input scan_in;
input siclk;
input soclk;
output [0:0] dout;
output scan_out;
assign fdin[0:0] = din[0:0];
dff #(1) d0_0 (
.l1clk(l1clk),
.siclk(siclk),
.soclk(soclk),
.d(fdin[0:0]),
.si(scan_in),
.so(scan_out),
.q(dout[0:0])
);
endmodule