// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: utilsClass.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 <vera_defines.vrh>
#include <std_display_defines.vri>
#include <ccxDevicesDefines.vri>
#include <baseParamsClass.vrh>
#include <sparcParams.vrh>
#include <baseUtilsClass.vrh>
#include <sparcBenchUtils.vrh>
#include <std_display_class.vrh>
#include <basePktClass.vrh>
#include <cpxPktClass.vrh>
#include <pcxPktClass.vrh>
#include <ccxDevBaseBFM.vrh>
#include <ccxDevMemBFM.vrh>
#include <ccxDevSpcBFM.vrh>
#include <ccx_tag_class.vrh>
#include <MCUStub_class.vrh>
#define CLASSNAMEQ "Utils"
class CLASSNAME extends SparcBenchUtils {
local string className = "UtilsClass";
local StandardDisplay dbg;
local integer clockPeriod;
local randc reg [5:0] startThread;
// local integer count = 0;
task new(StandardDisplay dbgHndl, integer clockPeriod = 100);
task initTB(integer useMCUbfms = 0,
task initDut(integer wait = 0);
// local task enableL2(bit [7:0] enable=8'hff, reg [5:0] useThread=63);
//local task sendPOR(reg [31:0] resetThis=0, integer sendPort = DEV_NCU);
task sendIntrLoop(integer sendPort = DEV_NCU);
task sendIntr(reg [5:0] tid,
integer sendPort = DEV_NCU);
task CLASSNAME::new(StandardDisplay dbgHndl, integer clockPeriod = 100) {
super.new(dbgHndl, clockPeriod);
void = randomize(); // keep!
task CLASSNAME::resetDut()
// useMCUbfms 0=no, 1=yes, 2=monitor
task CLASSNAME::initTB(integer useMCUbfms = 0,
reg loadOnlyIOmem = 1) { // do not load vera array if !using it
if (gParam.asmDiagName != null) {
// 3rd param will return random data (in place of 0) from mem if set.
// Initialize main memory from mem.image
gMem.loadMem("mem.image", loadOnlyIOmem, gParam.hash_on, this);
// Put all binds into global handles so that various objects
// will have access to HW.
gPcxPort[DEV_SPC0] = pcxBindDEV_SPC0;
gCpxPort[DEV_SPC0] = cpxBindDEV_SPC0;
gPcxPort[DEV_SPC1] = pcxBindDEV_SPC1;
gCpxPort[DEV_SPC1] = cpxBindDEV_SPC1;
gPcxPort[DEV_SPC2] = pcxBindDEV_SPC2;
gCpxPort[DEV_SPC2] = cpxBindDEV_SPC2;
gPcxPort[DEV_SPC3] = pcxBindDEV_SPC3;
gCpxPort[DEV_SPC3] = cpxBindDEV_SPC3;
gPcxPort[DEV_SPC4] = pcxBindDEV_SPC4;
gCpxPort[DEV_SPC4] = cpxBindDEV_SPC4;
gPcxPort[DEV_SPC5] = pcxBindDEV_SPC5;
gCpxPort[DEV_SPC5] = cpxBindDEV_SPC5;
gPcxPort[DEV_SPC6] = pcxBindDEV_SPC6;
gCpxPort[DEV_SPC6] = cpxBindDEV_SPC6;
gPcxPort[DEV_SPC7] = pcxBindDEV_SPC7;
gCpxPort[DEV_SPC7] = cpxBindDEV_SPC7;
gPcxPort[DEV_MEM0] = pcxBindDEV_MEM0;
gCpxPort[DEV_MEM0] = cpxBindDEV_MEM0;
gPcxPort[DEV_MEM1] = pcxBindDEV_MEM1;
gCpxPort[DEV_MEM1] = cpxBindDEV_MEM1;
gPcxPort[DEV_MEM2] = pcxBindDEV_MEM2;
gCpxPort[DEV_MEM2] = cpxBindDEV_MEM2;
gPcxPort[DEV_MEM3] = pcxBindDEV_MEM3;
gCpxPort[DEV_MEM3] = cpxBindDEV_MEM3;
gPcxPort[DEV_MEM4] = pcxBindDEV_MEM4;
gCpxPort[DEV_MEM4] = cpxBindDEV_MEM4;
gPcxPort[DEV_MEM5] = pcxBindDEV_MEM5;
gCpxPort[DEV_MEM5] = cpxBindDEV_MEM5;
gPcxPort[DEV_MEM6] = pcxBindDEV_MEM6;
gCpxPort[DEV_MEM6] = cpxBindDEV_MEM6;
gPcxPort[DEV_MEM7] = pcxBindDEV_MEM7;
gCpxPort[DEV_MEM7] = cpxBindDEV_MEM7;
gPcxPort[DEV_NCU] = pcxBindDEV_NCU;
gCpxPort[DEV_NCU] = cpxBindDEV_NCU;
gProbesPort = probesBind;
gMcuPort[0] = mcu_bind_0;
gMcuPort[1] = mcu_bind_1;
gMcuDataPort[0] = mcu_bind_data_01;
gMcuDataPort[1] = mcu_bind_data_01;
gMcuPort[2] = mcu_bind_2;
gMcuPort[3] = mcu_bind_3;
gMcuDataPort[2] = mcu_bind_data_23;
gMcuDataPort[3] = mcu_bind_data_23;
gMcuPort[4] = mcu_bind_4;
gMcuPort[5] = mcu_bind_5;
gMcuDataPort[4] = mcu_bind_data_45;
gMcuDataPort[5] = mcu_bind_data_45;
gMcuPort[6] = mcu_bind_6;
gMcuPort[7] = mcu_bind_7;
gMcuDataPort[6] = mcu_bind_data_67;
gMcuDataPort[7] = mcu_bind_data_67;
// these are used when L2 is BFMs, not RTL
gLdStSyncPort[8] = ldStSync_bind_b0;
gLdStSyncPort[9] = ldStSync_bind_b1;
gLdStSyncPort[10] = ldStSync_bind_b2;
gLdStSyncPort[11] = ldStSync_bind_b3;
gLdStSyncPort[12] = ldStSync_bind_b4;
gLdStSyncPort[13] = ldStSync_bind_b5;
gLdStSyncPort[14] = ldStSync_bind_b6;
gLdStSyncPort[15] = ldStSync_bind_b7;
gLdStSyncPort[16] = ldStSync_bind_b8;
// Always Initialize ncu BFM/stub as ACTIVE
gCcxDevMem[DEV_NCU] = new(DEV_NCU); // gCcxDevMem[15] #8 mem device
gCcxDevice[DEV_NCU] = gCcxDevMem[DEV_NCU]; // generic handle gCcxDevice[16] = gCcxDevMem[8]
// Always Initialize core BFMs/stubs if enabled & no real core on port
for (i=DEV_SPC0;i<=DEV_SPC7; i++) { // 0-7
if (gParam.enableSpcBFM[i])
if (gParam.coreAvilable[i]) gCcxDevSpc[i] = new(i,1,0);
else gCcxDevSpc[i] = new(i,0,0);
else gCcxDevSpc[i] = null;
gCcxDevice[i] = gCcxDevSpc[i]; // generic handle 0-7
// Always Initialize L1 duplicate tags, one pair for each core
if ((useL1Tags || useL2bfms) && gParam.coreAvilable[i]) {
dtag[i] = new (DATA_TAG, 127, 3, i);
itag[i] = new (INSTR_TAG, 63, 7, i);
// Initialize L2 BFMs/stubs 8-15
// can access as gCcxDevice[8-15]
vera_save_rng_state(this);
if (gParam.enableMemBFM[i-8]) gCcxDevMem[i] = new(i, ~useL2bfms); // (instance, passive)
else gCcxDevMem[i] = null;
gCcxDevice[i] = gCcxDevMem[i]; // generic handle gCcxDevice[8] = gCcxDevMem[8]
if (gParam.enableMemBFM[i-8]) gCcxDevMem[i] = new(i, ~useL2bfms); // (instance, passive)
else gCcxDevMem[i] = null;
gCcxDevice[i] = gCcxDevMem[i]; // generic handle gCcxDevice[8] = gCcxDevMem[8]
if (gParam.enableMemBFM[i-8]) gCcxDevMem[i] = new(i, ~useL2bfms); // (instance, passive)
else gCcxDevMem[i] = null;
gCcxDevice[i] = gCcxDevMem[i]; // generic handle gCcxDevice[8] = gCcxDevMem[8]
if (gParam.enableMemBFM[i-8]) gCcxDevMem[i] = new(i, ~useL2bfms); // (instance, passive)
else gCcxDevMem[i] = null;
gCcxDevice[i] = gCcxDevMem[i]; // generic handle gCcxDevice[8] = gCcxDevMem[8]
if (gParam.enableMemBFM[i-8]) gCcxDevMem[i] = new(i, ~useL2bfms); // (instance, passive)
else gCcxDevMem[i] = null;
gCcxDevice[i] = gCcxDevMem[i]; // generic handle gCcxDevice[8] = gCcxDevMem[8]
if (gParam.enableMemBFM[i-8]) gCcxDevMem[i] = new(i, ~useL2bfms); // (instance, passive)
else gCcxDevMem[i] = null;
gCcxDevice[i] = gCcxDevMem[i]; // generic handle gCcxDevice[8] = gCcxDevMem[8]
if (gParam.enableMemBFM[i-8]) gCcxDevMem[i] = new(i, ~useL2bfms); // (instance, passive)
else gCcxDevMem[i] = null;
gCcxDevice[i] = gCcxDevMem[i]; // generic handle gCcxDevice[8] = gCcxDevMem[8]
if (gParam.enableMemBFM[i-8]) gCcxDevMem[i] = new(i, ~useL2bfms); // (instance, passive)
else gCcxDevMem[i] = null;
gCcxDevice[i] = gCcxDevMem[i]; // generic handle gCcxDevice[8] = gCcxDevMem[8]
vera_restore_rng_state(this);
// Initialize MCU BFMs/stubs (CMP bench)
vera_save_rng_state(this);
gMcuDev[0] = new(gMcuPort[0], gMcuDataPort[0], 0);
gMcuDev[1] = new(gMcuPort[1], gMcuDataPort[1], 1);
gMcuDev[2] = new(gMcuPort[2], gMcuDataPort[2], 2);
gMcuDev[3] = new(gMcuPort[3], gMcuDataPort[3], 3);
gMcuDev[4] = new(gMcuPort[4], gMcuDataPort[4], 4);
gMcuDev[5] = new(gMcuPort[5], gMcuDataPort[5], 5);
gMcuDev[6] = new(gMcuPort[6], gMcuDataPort[6], 6);
gMcuDev[7] = new(gMcuPort[7], gMcuDataPort[7], 7);
vera_restore_rng_state(this);
// optional packet printing
if (gParam.ccxPktPrintOn) {
vera_save_rng_state(this);
for (i=DEV_SPC0;i<=DEV_SPC7; i++) { // 0-7
if (gParam.coreAvilable[i]) pktMon[i] = new(i, gPcxPort[i], gCpxPort[i]);
for (i=DEV_MEM0;i<=DEV_MEM7; i++) {
if (gParam.banksMask[i-8]) pktMon[i] = new(i, gPcxPort[i], gCpxPort[i]);
pktMon[DEV_NCU] = new(DEV_NCU, gPcxPort[DEV_NCU], gCpxPort[DEV_NCU]);
vera_restore_rng_state(this);
task CLASSNAME::initDut(integer wait = 0) {
if (gProbesPort.$rst_l == 0) @(posedge gProbesPort.$rst_l);
repeat (wait) @(posedge CLOCK);
/////////////////////////////////////////////////////////////////////////////////
// This task enables each L2 bank by
// writing the Control Status Register of that bank.
// Send a diag store PCX packet
// review to use boot code
/////////////////////////////////////////////////////////////////////////////////
// task CLASSNAME::enableL2(bit [7:0] enable=8'hff, reg [5:0] useThread=63) {
// if (gCcxDevSpc[useThread[5:3]] == null)
// error("Utils::enableL2 Can't find SPC BFM requested!!!\n");
// sndPkt.sendPort = useThread[5:3];
// sndPkt.recvPorts = 1 << i;
// sndPkt.rqtyp = PCX_DIAG_ST;
// sndPkt.cpuId = useThread[5:3];
// sndPkt.tid = useThread[2:0];
// sndPkt.l1wayMMUid = 3;
// sndPkt.addr = 40'ha9_0000_0000;
// loop to send periodic interrupt packets like spc2 bench
task CLASSNAME::sendIntrLoop(integer sendPort = DEV_NCU)
if (gParam.intr_en == 0) return;
// # clocks before Intr packets start
repeat (gParam.intr_wait) @(posedge CLOCK);
// 1st TID that get Interrupt packet
if (gParam.intr_tid == -1) {
tid = urandom_range(maxTid,0);
while (gParam.intr_en[tid] == 0) tid = urandom_range(maxTid,0);
else tid = gParam.intr_tid;
PR_NORMAL (className, MON_NORMAL,
psprintf("Interrupt to thread T%0d (type/vec %b/%b)",
tid,gParam.intr_type,gParam.intr_vect));
this.sendIntr(tid,gParam.intr_type,gParam.intr_vect); // INTR_RESET,INTR_POR
repeat (gParam.intr_delay) @(posedge CLOCK); // # clocks between Intr packets
tid = urandom_range(maxTid,0);
while (gParam.intr_en[tid] == 0) tid = urandom_range(maxTid,0);
// generic call to send intr from NCU port. for $EV user events
task CLASSNAME::sendIntr(reg [5:0] tid,
integer sendPort = DEV_NCU)
reqPkt.createIntr(tid,type,vect); // INTR_RESET,INTR_POR
reqPkt.sendPorts = 1 << sendPort;
reqPkt.targetPorts = 1 << tid[5:3];
PR_NORMAL(CLASSNAMEQ, MON_NORMAL,
psprintf ("Send Interrupt to C%0d T%0d type=%b vector=%b",
tid[5:3],tid[2:0],type,vect));
// random evictor for the CMP bench
// Any L2 BFM can send the eviction packet(s).
// Requires that the L2$ BFMs be in use!
task CLASSNAME::randEvict() {
if (!gParam.inval_rate) return;
repeat (500) @(posedge CLOCK);
repeat (wait) @(posedge CLOCK);
// odds of doing an evict this time
(10000-gParam.inval_rate): continue; // no
evictPA = evictAddr(gParam.coreEnable,
*, // reg [3:0] cid = 4'hf,
*); // integer dCacheWeight = 60) // 100 % based
if (evictPA !== 64'hffffffffffffffff) {
sendPort = whichBank(evictPA) + 8; // have to use right bank for this address!!!
gCcxDevMem[sendPort].enqueueEvict(gParam.coreEnable,