Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / ilu_peu / vera / N2Test / N2PEUTestBase.vr
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: N2PEUTestBase.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
// have any questions.
//
// ========== Copyright Header End ============================================
class PEUTestBase {
BootPEUStr boot; // A strategy for starting things up
protected PEUTestEnv env; // The test environment
PIOPEUCtx pio; // The context to perform PIO traffic
DMAPEUCtx dma; // The context to perform DMA traffic
protected integer txBadInit = 0; // Tx bad init fc dllps before link up
protected bit slowClock; // Do we have a slow ILU clock?
protected bit stallNpstWr; // Do PIO reqs stall after Cfg/IO write?
protected bit AHBdone = 0; // used to start/stop AHB traffic
protected bit PMmsgDone = 0; // used to start/stop PMmsg traffic
protected event donePMmsgs; // signals when PMmsgs finishes
protected integer numPhyLanes;
protected integer numActiveLanes;
protected bit fastTrain;
protected bit enableL0s;
protected bit [63:0] retryBufSize;
protected PECBool txEnableScramble;
protected PECBool rxEnableScramble;
//N2 - Start
// Only need to create 1 Report class to pass around the whole testbench
ReportClass Report = new;
// The Scenario classes holds some test parameters
ilupeuScenario Scenario = new( Report );
// urandom Seed Generation
bit [31:0] urand_seed = 32'hdeadbeef;
bit seed_with_tod = 1'b0;
// bit seed_with_tod = 1'b1;
public task Seed();
//N2 - End
public task new();
virtual public task execute(); // Run the whole test
virtual public task setBoot(); // Set the params in Boot Str
virtual public task setEnv(); // Set initial params in env.
virtual public task setPIO(); // Set params for PIO Noise Context
virtual public task setDMA(); // Set params for DMA Noise Context
virtual public task runPIO(); // Run the PIO Noise Context
virtual public task runDMA(); // Run the DMA Noise Context
virtual public task runTest(); // Test something interesting
virtual public task startAHB( PEUTestEnv env );
virtual public task stopAHB();
virtual public task startPMmsgs( PEUTestEnv env,
integer minDelay = 100,
integer maxDelay = 200 );
virtual public task stopPMmsgs();
virtual public task startLTSSM( PEUTestEnv env,
integer minDelay, integer maxDelay,
integer recovery, integer L0s );
virtual public task stopLTSSM();
virtual public task stopPioDma();
}
task PEUTestBase::new() {
integer status, unk;
integer print_str;
this.enableL0s = 0;
this.retryBufSize = 64'h0;
this.slowClock = 0;
//Set the print threshold at the command line
//example: sims ... -vcs_run_args=+report_global_print_threshold=RPRT_DEBUG_3
if( get_plus_arg( CHECK, "+report_global_print_threshold=" ) ){
print_str = get_plus_arg( NUM, "+report_global_print_threshold=" );
case( print_str ){
RPRT_INFO: Report.set_global_print_threshold( RPRT_INFO );
RPRT_DEBUG_3: Report.set_global_print_threshold( RPRT_DEBUG_3 );
default: Report.set_global_print_threshold( RPRT_INFO );
}
}else{
//If there is no print level passed in then only print the minimum
Report.set_global_print_threshold( RPRT_NONMASKABLE );
}
// Seed();
//Step 0. Initialize Denali Vera Interface
status = denaliVeraPcieInit();
if (status == -1)
QuickReport(Report,RTYP_TEST_ERROR,"denaliVeraPcieInit() failed. \n" );
status = DenaliDDVinitialize("","",unk,"","API");
if (status == -1)
QuickReport(Report,RTYP_TEST_ERROR,"DenaliDDVinitialize() failed. \n" );
// Set Denali Register Callback Task For PCIE Xactors
status = DenaliDDVaccessSetCallback("FNXPCIEXactorRegCbTask");
if (status == -1)
QuickReport(Report,RTYP_TEST_ERROR,"DenaliDDVaccessSetCallback() failed. \n" );
}
task PEUTestBase::execute() {
bit pioDone;
bit dmaDone;
PioCfgIOWrPEUStr CfgWr0;
printf("**PEUTestBase Begin Execution**\n");
printf("**PEUTestBase Set Up Boot Strategy**\n");
boot = new( Report,
Scenario ); // Let's get ready to rumble ....
this.setBoot();
printf("**PEUTestBase Boot Strategy Set Up Complete**\n");
printf("**PEUTestBase Execute Boot Strategy**\n");
boot.Execute();
printf("**PEUTestBase Boot Strategy Complete**\n");
printf("**PEUTestBase Set Up Environment**\n");
env = boot.getEnv();
this.setEnv();
printf("**PEUTestBase Environment Set Up Complete**\n");
#ifndef N2_FC
//Make the 1st transaction a Cfg Write 0 so that the
// Config ID in Denali can be set
CfgWr0 = new( env );
CfgWr0._type_req_prob_cfg1 = 0;
CfgWr0._type_req_prob_io = 0;
CfgWr0._ep_cpl_prob_true = 0;
CfgWr0._td_cpl_prob_true = 0;
CfgWr0._bcm_prob_true = 0;
CfgWr0.Execute();
printf("**PEUTestBase Sent ConfigWrite0 to Denali**\n");
printf("**PEUTestBase Set Up PIO Traffic**\n");
pio = new(env);
this.setPIO();
printf("**PEUTestBase PIO Traffic Set Up Complete**\n");
printf("**PEUTestBase Set Up DMA Traffic**\n");
dma = new( "DmaTraffic", env, "random" );
this.setDMA();
printf("**PEUTestBase DMA Traffic Set Up Complete**\n");
pioDone = 0;
dmaDone = 0;
fork
{
printf("**PEUTestBase Run PIO Traffic**\n");
this.runPIO();
printf("**PEUTestBase PIO Traffic Complete**\n");
pioDone = 1;
}
{
printf("**PEUTestBase Run DMA Traffic**\n");
this.runDMA();
printf("**PEUTestBase DMA Traffic Complete**\n");
dmaDone = 1;
}
{
printf("**PEUTestBase Run Test**\n");
this.runTest();
printf("**PEUTestBase Test Complete**\n");
printf("**PEUTestBase Signal PIO & DMA Traffic Stop**\n");
pio.StratStop = 1'b1;
dma.StratStop = 1'b1;
printf("**PEUTestBase PIO & DMA Traffic Stop Signal Complete**\n");
while( ( !pioDone && (pio.NumStrat - pio.StratDone) > 100 )
|| ( !dmaDone && (dma.NumStrat - dma.StratDone) > 100 ) )
{
printf( "**PEUTestBase (cyc %0d) PIO/DMA remaining = %0d/%0d\n",
get_cycle(),
pio.NumStrat - pio.StratDone, dma.NumStrat - dma.StratDone );
env.wait(100);
}
printf( "**PEUTestBase (cyc %0d) PIO/DMA remaining = %0d/%0d\n",
get_cycle(),
pio.NumStrat - pio.StratDone, dma.NumStrat - dma.StratDone );
}
join all
printf("**PEUTestBase Expect Idle State**\n");
env.expectIdleState();
printf("**PEUTestBase Expect Idle State Complete**\n");
#endif
printf("**PEUTestBase Execution Complete**\n");
}
/*
* Beat up on the AHB interface to the LPU's CSRs.
* But only if we don't have an LPU hooked up!
*/
task PEUTestBase::startAHB( PEUTestEnv env )
{
/* N2 review - Not Needed???
bit [63:0] data;
bit [31:0] addr;
if ( get_plus_arg( CHECK, "LPU" ) ) return;
repeat(10) @(posedge CLOCK); // Let reset finish...
this.AHBdone = 0;
while( !this.AHBdone )
{
data = { 32'b0, urandom() };
addr = env.getLPUaddr( urandom() % PEC_LPU_CSR_MAX_COUNT );
env.writeCSR( addr, data );
env.expectCSRdirect( addr, data );
data = { 32'b0, urandom() };
addr = env.getLPUaddr( urandom() % PEC_LPU_CSR_MAX_COUNT );
env.writeCSRdirect( addr, data );
env.expectCSR( addr, data );
data = { 32'b0, urandom() };
addr = env.getLPUaddr( urandom() % PEC_LPU_CSR_MAX_COUNT );
data = env.readCSRdirect( addr );
env.expectCSR( addr, data );
}
*/
} /* end startAHB */
task PEUTestBase::stopAHB()
{
//N2 review this.AHBdone = 1;
}
/*
* Write CSRs which cause PM messages to be sent by the TLU.
*/
task PEUTestBase::startPMmsgs( PEUTestEnv env,
integer minDelay = 100,
integer maxDelay = 200 )
{
bit [7:0] msgType;
bit [63:0] data;
bit [63:0] capData;
bit [31:0] expData;
bit [31:0] addr;
integer delay;
event csrWritten;
capData = 64'h00100;
trigger( OFF, this.donePMmsgs );
this.PMmsgDone = 0;
while( !this.PMmsgDone )
{
delay = minDelay + urandom() % (maxDelay-minDelay+1);
repeat(delay) @(posedge CLOCK);
if ( urandom()%2 )
{
data = 64'b01;
expData = 0;
addr = env.getCSRaddr( e_CSR_pme_ctl );
msgType = PEC_PCI__MSG_CODE_PM_TURN_OFF;
}
else
{
capData = capData + 64'h00100;
data = capData;
expData = { 22'b0, capData[16:7] };
addr = env.getCSRaddr( e_CSR_slot_cap );
msgType = PEC_PCI__MSG_CODE_SET_SLOT_POWER_LIMIT;
}
trigger( OFF, csrWritten );
fork
env.expectEgressMsg( msgType, expData, csrWritten );
{
env.writeCSR( addr, data );
trigger( ON, csrWritten );
}
join
}
trigger( ON, this.donePMmsgs );
} /* end exercisePMmsgs */
task PEUTestBase::stopPMmsgs()
{
this.PMmsgDone = 1;
sync( ANY, this.donePMmsgs );
}
task PEUTestBase::startLTSSM( PEUTestEnv env,
integer minDelay, integer maxDelay,
integer recovery, integer L0s )
{
}
task PEUTestBase::stopLTSSM()
{
}
task PEUTestBase::setBoot() {
boot.getPhyConfig( this.numPhyLanes,
this.numActiveLanes,
this.fastTrain,
txEnableScramble,
rxEnableScramble
);
// QuickReport(Report,RTYP_INFO, " PEUTestBase::setBoot() result of get_plus_arg( CHECK, \"vera_random_seed=\" ) is %h\n", get_plus_arg( CHECK, "vera_random_seed=" ) );
//N2 review boot.setClkDrift(8);
//N2 review boot.setDriftPeriod(19);
boot.setPostedCredits( 16, 64 );
boot.setNonpostedCredits( 16, 64 );
boot.setCompletionCredits( 16, 64 );
return;
#ifndef N2_FC
randcase
{
//N2 review 1: { boot.slowClock(1); this.slowClock = 1; }
//N2 review 5: { boot.slowClock(0); }
10: {}
}
randcase
{
//N2 review 1: { boot.setClkDrift(1); boot.setDriftPeriod(2); }
//N2 review 1: { boot.setClkDrift(10); boot.setDriftPeriod( urandom()%20 + 20 ); }
1: {}
}
randcase
{
1: boot.setPostedCredits( 0, 0 );
1: boot.setPostedCredits( 1, 32 );
1: boot.setPostedCredits( 2, 32 );
1: boot.setPostedCredits( 4, 32 );
1: boot.setPostedCredits( 16, 64 );
1: boot.setPostedCredits( 128, 2048 );
}
randcase
{
1: boot.setNonpostedCredits( 0, 0 );
1: boot.setNonpostedCredits( 1, 32 );
1: boot.setNonpostedCredits( 2, 32 );
1: boot.setNonpostedCredits( 4, 32 );
1: boot.setNonpostedCredits( 16, 64 );
1: boot.setNonpostedCredits( 128, 2048 );
}
randcase
{
1: boot.setCompletionCredits( 0, 0 );
1: boot.setCompletionCredits( 1, 32 );
1: boot.setCompletionCredits( 2, 32 );
1: boot.setCompletionCredits( 4, 32 );
1: boot.setCompletionCredits( 16, 64 );
1: boot.setCompletionCredits( 128, 2048 );
}
#endif
}
task PEUTestBase::setEnv() {
bit useLpu;
integer seed;
integer mps;
integer len1;
integer len2;
integer len16;
integer lenBulk;
integer egressThrottle;
integer ingressThrottle;
integer ingressAbortRate;
integer minGap;
integer maxGap;
//N2 useLpu = get_plus_arg( CHECK, "LPU" );
useLpu = 1; //Always set for N2
#ifndef N2_FC
// Randomly select environment / device parameters
randcase
{
1: mps = 128;
1: mps = 256;
1: mps = 512;
}
randcase
{
1: egressThrottle = 0;
1: egressThrottle = 25;
1: egressThrottle = 50;
}
randcase
{
1: ingressThrottle = 0;
//N2 review 1: ingressThrottle = useLpu ? 0 : 25;
//N2 review 1: ingressThrottle = useLpu ? 0 : 50;
}
randcase
{
1: ingressAbortRate = 0;
//N2 review 1: ingressAbortRate = useLpu ? 0 : 10;
//N2 review 1: ingressAbortRate = useLpu ? 0 : 25;
}
randcase
{
1: { minGap = 2; maxGap = 2; }
1: { minGap = 2; maxGap = 6; }
}
randcase // Payload sizes...
{
1: { len1=10; len2=10; len16=10; lenBulk=10; } // A little of each
1: { len1=10; len2=1; len16=1; lenBulk=0; } // Lots of 1DW payloads
1: { len1=10; len2=10; len16=10; lenBulk=0; } // No bulk payloads
}
randcase
{
1: stallNpstWr = 0;
1: stallNpstWr = 1;
}
//
// If the initial (random) seed is small, then choose environment
// parameters based on that seed. In this way, a couple of random runs
// can be used for coverage purposes.
//
if ( get_plus_arg( CHECK, "vera_random_seed=" ) )
{
seed = get_plus_arg( NUM, "vera_random_seed=" );
case ( seed )
{
1: { mps = 128; stallNpstWr = 0; }
2: { mps = 256; stallNpstWr = 0; }
3: { mps = 512; stallNpstWr = 0; }
4: { stallNpstWr = 1; }
}
}
//
// If no "vera random seed" was specified, then we have a directed test.
// Use default values for all tests.
//
else
{
#endif
mps = 128;
len1 = 10;
len2 = 10;
len16 = 0;
lenBulk = 0;
egressThrottle = -1;
ingressThrottle = useLpu ? 0 : -1;
ingressAbortRate = useLpu ? 0 : 10;
stallNpstWr = 0;
minGap = 2;
maxGap = 2;
#ifndef N2_FC
}
#endif
//
// Set the environment parameters determined above.
//
env.setLenWeights( len1, len2, len16, lenBulk );
env.setIngressAbortRate( ingressAbortRate );
env.setIngressThrottle( ingressThrottle );
env.setIngressGap( minGap, maxGap );
env.setEgressThrottle( egressThrottle );
env.setMaxPayloadSize( mps );
env.setMaxRequestSize( 4096 );
// env.setMaxRequestSize( mps );
if ( stallNpstWr && !useLpu )
env.stallNonpostedWrite( 1 );
#ifndef N2_FC
// If we're using the LPU, initialize the replay and acknak timers
//N2 review - Disabled in env
if ( useLpu )
env.initLpuCSRs( this.numActiveLanes, mps, this.fastTrain, this.enableL0s, this.retryBufSize );
//
// Bring up the link and present initial credit advertisements to the TLU
//
env.linkUp( 20 * (urandom()%5) + 20, this.txBadInit );
// Wait a bit and make sure the 'link up' event was recorded
repeat(20) @(posedge CLOCK);
env.expectError( e_ERR_oe_lup, 1, 0 );
#endif
}
task PEUTestBase::setPIO() {
pio.StratStop = 1'b0;
pio._stratNum = 0;
pio.NumStrat = 15000;
pio._ep_cpl_mode = e_fixed;
pio._ep_cpl_fixed = e_false;
pio._cpl_status_mode = e_fixed;
pio._cpl_status_fixed = PEC_PCI__CPL_STATUS_SC;
}
task PEUTestBase::setDMA() {
dma.StratStop = 1'b0;
dma._stratNum = 0;
dma.NumStrat = ( this.slowClock || this.stallNpstWr ) ? 25000 : 15000;
}
task PEUTestBase::runPIO() {
pio.Execute();
if (pio.StratStop !== 1'b1)
error("PIO Background Traffic Finished Early\n");
}
task PEUTestBase::runDMA() {
dma.Execute();
if (dma.StratStop !== 1'b1)
error("DMA Background Traffic Finished Early\n");
}
task PEUTestBase::Seed()
{
string msg;
bit [31:0] time_0;
// Grab Seed With Time of Day Bit
if ( get_plus_arg( CHECK, "seed_with_tod=" ))
seed_with_tod = get_plus_arg( NUM, "seed_with_tod=" );
// Seed With Time of Day if Set
if (seed_with_tod) {
time_0 = get_systime();
urandom(time_0);
urand_seed = time_0 + urandom();
}
// Grab Urandom Seed From Command Line If Present
if ( get_plus_arg( CHECK, "urand_seed=" ))
urand_seed = get_plus_arg( HNUM, "urand_seed=" );
urandom(urand_seed);
if (seed_with_tod)
QuickReport(Report,RTYP_INFO, "ilupeuTestBase: urandom() seeded with time of day, seed=%h \n",
urand_seed );
else
QuickReport(Report,RTYP_INFO,"ilupeuTestBase: urandom() seeded with seed=%h \n", urand_seed );
} // End task Seed()
task PEUTestBase::runTest() { }
task PEUTestBase::stopPioDma(){
pio.StratStop = 1'b1;
dma.StratStop = 1'b1;
}