// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: siu_order_checker.vr
// 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
// ========== Copyright Header End ============================================
#include "siumon_ports_binds.vrh"
#include "std_display_class.vrh"
// added these #ifndefs for excluding code for NIU
#include "siu_niu_packet.vrh"
#include "siu_dmu_packet.vrh"
#include "siu_ncu_packet.vrh"
#include "siu_l2_packet.vrh"
#include "siu_monitor.vrh"
#include "siu_jtag_packet.vrh"
//extern bit siu_RDDord_pass_niuord_diffbank;
//extern bit siu_RDDord_not_pass_niuord_samebank;
//extern bit siu_WRIord_not_pass_niuord;
//extern bit siu_niubyp_pass_niubyp_diffbank;
//extern bit siu_niubyp_not_pass_niubyp_samebank;
//extern bit siu_niubyp_pass_niuord_diffbank;
//extern bit siu_RDDbyp_pass_RDDord_samebank;
//extern bit siu_WRIbyp_not_pass_niuord_samebank;
ExternVeraList(siu_niu_packet);
ExternVeraList(siu_dmu_packet);
class siu_order_checker {
VeraList_siu_niu_packet niu_fifo;
VeraListIterator_siu_niu_packet niu_fifo_ptr;
VeraList_siu_dmu_packet dmu_ordered_list, dmu_bypass_list;
VeraListIterator_siu_dmu_packet dmu_ordered_ptr, dmu_bypass_ptr;
public bit siu_RDDord_pass_niuord_diffbank = 0;
public bit siu_RDDord_not_pass_niuord_samebank = 0;
public bit siu_WRIord_not_pass_niuord = 0;
public bit siu_niubyp_pass_niubyp_diffbank = 0;
public bit siu_niubyp_not_pass_niubyp_samebank = 0;
public bit siu_niubyp_pass_niuord_diffbank = 0;
public bit siu_RDDbyp_pass_RDDord_samebank = 0;
public bit siu_WRIbyp_not_pass_niuord_samebank = 0;
local integer wrm_in_progress;
local bit checker_disabled;
local bit ibl2_checker_proceed[8];
local bit obl2_checker_proceed[8];
siu_jtag_packet pending_jtag;
task check_l2_snd(integer i);
task check_l2_rec(integer i);
local function integer check_inbound_l2_order(Siu_L2_Packet packet, integer i);
local function integer check_outbound_l2_order(Siu_L2_Packet packet, integer i);
local function integer check_inbound_ncu_order(siu_ncu_packet packet);
local function integer check_outbound_order(siu_basic_packet packet);
local function integer check_niu_order_rules(Siu_Packet_Type btype, bit[39:0] bpa, bit bbypass,
Siu_Packet_Type ttype, bit[39:0] tpa, bit tbypass);
local function integer check_dmu_order_rules(Siu_Packet_Type btype, bit[39:0] bpa, Siu_Packet_Type ttype, bit[39:0] tpa);
task siu_order_checker::new(
this.niu_snd_mbox = niu_snd_mbox;
this.niu_rec_mbox = niu_rec_mbox;
this.dmu_snd_mbox = dmu_snd_mbox;
this.dmu_rec_mbox = dmu_rec_mbox;
this.ncu_rec_mbox = ncu_rec_mbox;
this.l2_snd_mbox[0] = l2_snd_mbox_0;
this.l2_rec_mbox[0] = l2_rec_mbox_0;
this.l2_snd_mbox[1] = l2_snd_mbox_1;
this.l2_rec_mbox[1] = l2_rec_mbox_1;
this.l2_snd_mbox[2] = l2_snd_mbox_2;
this.l2_rec_mbox[2] = l2_rec_mbox_2;
this.l2_snd_mbox[3] = l2_snd_mbox_3;
this.l2_rec_mbox[3] = l2_rec_mbox_3;
this.l2_snd_mbox[4] = l2_snd_mbox_4;
this.l2_rec_mbox[4] = l2_rec_mbox_4;
this.l2_snd_mbox[5] = l2_snd_mbox_5;
this.l2_rec_mbox[5] = l2_rec_mbox_5;
this.l2_snd_mbox[6] = l2_snd_mbox_6;
this.l2_rec_mbox[6] = l2_rec_mbox_6;
this.l2_snd_mbox[7] = l2_snd_mbox_7;
this.l2_rec_mbox[7] = l2_rec_mbox_7;
if ( get_plus_arg(CHECK, "siu_order_chk_off") ) {
dbg.dispmon(myname, MON_NORMAL, psprintf ("siu order checker off!"));
dbg.dispmon(myname, MON_NORMAL, psprintf ("siu order checker ready!"));
dmu_ordered_list = new();
pending_jtag = new(JRD,0,0);
ibl2_checker_proceed[i] = 1;
obl2_checker_proceed[i] = 1;
fork { check_niu_snd(); } join none
fork { check_niu_rec(); } join none
fork { check_dmu_snd(); } join none
fork { check_dmu_rec(); } join none
fork { check_ncu_rec(); } join none
fork { check_l2_snd(0); } join none
fork { check_l2_snd(1); } join none
fork { check_l2_snd(2); } join none
fork { check_l2_snd(3); } join none
fork { check_l2_snd(4); } join none
fork { check_l2_snd(5); } join none
fork { check_l2_snd(6); } join none
fork { check_l2_snd(7); } join none
fork { check_l2_rec(0); } join none
fork { check_l2_rec(1); } join none
fork { check_l2_rec(2); } join none
fork { check_l2_rec(3); } join none
fork { check_l2_rec(4); } join none
fork { check_l2_rec(5); } join none
fork { check_l2_rec(6); } join none
fork { check_l2_rec(7); } join none
task siu_order_checker::check_niu_snd()
siu_niu_packet niu_pkt, tmp_pkt;
mb_var = mailbox_get(WAIT, niu_snd_mbox, tmp_pkt);
niu_pkt = tmp_pkt.object_copy();
niu_fifo.push_back(niu_pkt);
task siu_order_checker::check_niu_rec()
mb_var = mailbox_get(WAIT, niu_rec_mbox, niu_pkt);
// check outbound ordering rule
fail = check_outbound_order(niu_pkt);
task siu_order_checker::check_dmu_snd()
mb_var = mailbox_get(WAIT, dmu_snd_mbox, dmu_pkt);
dmu_bypass_list.push_back(dmu_pkt);
dmu_ordered_list.push_back(dmu_pkt);
task siu_order_checker::check_dmu_rec()
mb_var = mailbox_get(WAIT, dmu_rec_mbox, dmu_pkt);
// check outbound ordering rule
fail = check_outbound_order(dmu_pkt);
task siu_order_checker::check_ncu_rec()
mb_var = mailbox_get(WAIT, ncu_rec_mbox, ncu_pkt);
// check inbound ordering
fail = check_inbound_ncu_order(ncu_pkt);
task siu_order_checker::check_l2_rec(integer i)
while (ibl2_checker_proceed[i] && obl2_checker_proceed[i])
mb_var = mailbox_get(WAIT, this.l2_rec_mbox[i], l2_pkt);
fail = check_inbound_l2_order(l2_pkt, i);
task siu_order_checker::check_l2_snd(integer i)
while (ibl2_checker_proceed[i] && obl2_checker_proceed[i])
mb_var = mailbox_get(WAIT, this.l2_snd_mbox[i], l2_pkt);
fail = check_outbound_l2_order(l2_pkt, i);
function integer siu_order_checker::check_outbound_l2_order(Siu_L2_Packet l2_pkt, integer i)
check_outbound_l2_order = 1;
if (l2_pkt.type == JRD || l2_pkt.type == JWR)
if (pending_jtag.valid == 0)
dbg.dispmon (myname, MON_ERR, psprintf ("l2 send jtag packet but no pending jtag packet pa=%x", l2_pkt.pa));
fail = (pending_jtag.type != l2_pkt.type) ? 1 : 0;
check_outbound_l2_order = fail;
obl2_checker_proceed[i] = ~fail;
function integer siu_order_checker::check_inbound_l2_order(Siu_L2_Packet l2_pkt, integer i)
check_inbound_l2_order = 1;
if (l2_pkt.type == JRD || l2_pkt.type == JWR)
if (pending_jtag.valid == 1)
dbg.dispmon (myname, MON_ERR, psprintf (" more than one jtag packet, pending jtag packet pa=%x", pending_jtag.pa));
pending_jtag.type = l2_pkt.type;
pending_jtag.pa = l2_pkt.pa;
pending_jtag.data = l2_pkt.data[0];
if (l2_pkt.source == 1) // dmu
dbg.dispmon (myname, MON_NORMAL, psprintf ("chk dmu pkt[%x] pa=%x", l2_pkt.id, l2_pkt.pa));
dmu_ordered_ptr = dmu_ordered_list.start();
if (dmu_ordered_list.size() == 0)
if (l2_pkt.type == WRM && wrm_in_progress)
dbg.dispmon (myname, MON_ERR, psprintf ("l2 receive dmu pkt[%x] but dmu list is empty!", l2_pkt.id));
while (!found && dmu_ordered_ptr != null && !fail)
dmu_pkt = dmu_ordered_ptr.data();
// if I found the packet, then no problem
if ((dmu_pkt.id === l2_pkt.id) || (dmu_pkt.type == WRM && l2_pkt.type == WRM))
wrm_in_progress = (l2_pkt.type == WRM) ? 1 : 0;
dbg.dispmon (myname, MON_NORMAL, psprintf ("dmu order chkP pkt[%x]", dmu_pkt.id));
dmu_ordered_ptr = dmu_ordered_list.erase(dmu_ordered_ptr);
else // I shall check can my pkt pass this packet in the list
dbg.dispmon (myname, MON_NORMAL, psprintf ("chk rules for bypassing pkt[%x] pa=%x bp=%1d", dmu_pkt.id, dmu_pkt.pa, dmu_pkt.bypass));
fail = check_dmu_order_rules(l2_pkt.type, l2_pkt.pa, dmu_pkt.type, dmu_pkt.pa);
dbg.dispmon (myname, MON_NORMAL, psprintf ("chk niu pkt[%x] pa=%x", l2_pkt.id, l2_pkt.pa));
niu_fifo_ptr = niu_fifo.start();
while (!found && niu_fifo_ptr != null && !fail)
niu_pkt = niu_fifo_ptr.data();
// if I found the packet, then no problem
if (niu_pkt.id === l2_pkt.id)
dbg.dispmon (myname, MON_NORMAL, psprintf ("niu order chkP pkt[%x]", niu_pkt.id));
niu_fifo_ptr = niu_fifo.erase(niu_fifo_ptr);
else // I shall check can my pkt pass this packet in the list
dbg.dispmon (myname, MON_NORMAL, psprintf ("chk rules for bypassing pkt[%x] pa=%x bp=%1d", niu_pkt.id, niu_pkt.pa, niu_pkt.bypass));
fail = check_niu_order_rules(l2_pkt.type, l2_pkt.pa, l2_pkt.bypass, niu_pkt.type, niu_pkt.pa, niu_pkt.bypass);
//if (!fail) dbg.dispmon (myname, MON_NORMAL, psprintf ("order chkP pkt[%x]", l2_pkt.id));
check_inbound_l2_order = fail;
ibl2_checker_proceed[i] = ~fail;
function integer siu_order_checker::check_inbound_ncu_order(siu_ncu_packet ncu_pkt)
function integer siu_order_checker::check_outbound_order(siu_basic_packet packet)
function integer siu_order_checker::check_niu_order_rules(Siu_Packet_Type btype, bit[39:0] bpa, bit bbypass, Siu_Packet_Type ttype, bit[39:0] tpa, bit tbypass)
// ord RDD pkt can bypass other order WRI pkt, if the addr is different
// ord RDD pkt can bypass other order RDD pkt, if the addr is different
if (btype == RDD && tbypass == 0)
if (bpa[38:6] !== tpa[38:6])
dbg.dispmon (myname, MON_INFO, psprintf ("RDD order pkt can bypass order pkt in different bank %x:%x", bpa, tpa));
siu_RDDord_pass_niuord_diffbank = 1;
dbg.dispmon (myname, MON_NORMAL, psprintf ("RDD order pkt cannot bypass order pkt in same bank %x:%x", bpa, tpa));
siu_RDDord_not_pass_niuord_samebank = 1;
dbg.dispmon (myname, MON_NORMAL, psprintf ("WRI order pkt cannot bypass"));
siu_WRIord_not_pass_niuord = 1;
// bp pkt can bypass other bp pkt, if other are for different banks
// bp pkt can bypass order pkt, if no address dependency
// bp RDD pkt can bypass order RDD pkt, with the same address
if (bpa[38:6] !== tpa[38:6])
dbg.dispmon (myname, MON_INFO, psprintf ("bypass pkt can bypass bypass pkt in different bank %x:%x", bpa, tpa));
siu_niubyp_pass_niubyp_diffbank = 1;
dbg.dispmon (myname, MON_NORMAL, psprintf ("bypass pkt cannot bypass bypass pkt in same bank "));
siu_niubyp_not_pass_niubyp_samebank = 1;
if (bpa[38:6] !== tpa[38:6])
dbg.dispmon (myname, MON_INFO, psprintf ("bypass pkt can bypass order pkt in different bank %x:%x", bpa, tpa));
siu_niubyp_pass_niuord_diffbank = 1;
if (btype == RDD && ttype == RDD)
dbg.dispmon (myname, MON_INFO, psprintf ("bypass RDD pkt can bypass order RDD pkt in same bank %x:%x", bpa, tpa));
siu_RDDbyp_pass_RDDord_samebank = 1;
dbg.dispmon (myname, MON_NORMAL, psprintf ("WRI bypass pkt cannot bypass order pkt in same bank "));
siu_WRIbyp_not_pass_niuord_samebank = 1;
check_niu_order_rules = fail;
// For N2, dmu only use order queue for DMA and Mondo interrupt, so we do not check the bypass queue
function integer siu_order_checker::check_dmu_order_rules(Siu_Packet_Type btype, bit[39:0] bpa, Siu_Packet_Type ttype, bit[39:0] tpa)
// RDD pkt can bypass other order WRI pkt, if the addr is different
// RDD pkt can bypass other order RDD pkt, if the addr is different
if (bpa[38:6] !== tpa[38:6])
dbg.dispmon (myname, MON_INFO, psprintf ("RDD order pkt can bypass order pkt in different bank %x:%x", bpa, tpa));
//RDDord_pass_niuord_diffbank = 1;
dbg.dispmon (myname, MON_NORMAL, psprintf ("RDD order pkt cannot bypass order pkt in same bank %x:%x", bpa, tpa));
//RDDord_not_pass_niuord_samebank = 1;
dbg.dispmon (myname, MON_NORMAL, psprintf ("WRI order pkt cannot bypass"));
//WRIord_not_pass_niuord = 1;
check_dmu_order_rules = fail;