Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / ilu_peu / vera / N2env / PEUTestEnv.vr
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: PEUTestEnv.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 ============================================
#include "report_info.vrh"
#include "plusArgMacros.vri"
#ifdef N2_FC
#include "std_display_class.vrh"
#include "fc_l2_sio_stub.vrh"
extern fc_l2_sio_stub l2sio_stub;
// this is for our own memory model for PIO address
#include "memArray.vrh"
extern MemArray gMem;
// This is for accessing MEMORY
#include "niu_mem.vrh"
extern CSparseMem SparseMem;
#endif
#define NCU_BASE_ADDR_IOCFG_FLD 0
#define NCU_BASE_ADDR_MEM32_FLD 1
#define NCU_BASE_ADDR_MEM64_FLD 2
#define _INFO_MSG(msg) printf("PEUTestEnv (cycle %0d) %s\n", get_cycle(),msg)
#define _REPORT_ERROR(msg) Report.report(RTYP_TEST_ERROR,"PEUTestEnv (cycle %0d) %s\n", get_cycle(),msg)
#define _ERROR_INFO(msg) printf( " %s\n", msg )
#define _DEBUG_MSG printf
//#define _REPORT_ERROR(msg) QuickReport( Report, RTYP_TEST_ERROR,"PEUTestEnv (cycle %0d) %s\n", get_cycle(),msg)
//N2-review #define _CLOCK_TLU TLU_EgressTLP.dack = void
class PEUTestEnv
{
#ifndef N2_FC
DMUXtr f_DMUXtr;
N2fcPiuShadowRegs PiuCsrs;
#else
N2fcIommuMgr MMU;
#endif
ilupeuCSR f_CSR;
ReportClass Report;
ilupeuPodClass Pod;
ilupeuScenario Scenario;
//N2-Not used public LPUXtr f_LPUXtr;
bit FCP_inject = 0;
bit FCP_P_inject = 0;
bit FCP_NP_inject = 0;
bit FCP_CPL_inject = 0;
protected CTTransactionID f_ID;
protected integer sm_mutex;
protected integer activityCounter; // For hang detect
integer activityStalled; // >0 if no activity expected
protected integer activityTimeout; // How long must we wait?!?
protected integer mb_ILUrelRecds; // ILU release recds
protected integer mb_egressReqOrder; // Expected req-order from TLU
protected integer mb_egressReqSeq; // Seq# of that req
protected integer mb_egressCplOrder; // Expected Cpl-order from TLU
protected integer mb_egressCplSeq; // Seq# of that completion
protected bit egressReqOK; // Do we expect a req from TLU?
protected bit egressCplOK; // Do we expect a cpl from TLU?
protected integer egressBadCount; // # of non-OK TLPs from TLU
protected integer egressLastSeq; // Last seq# in a "order" mb_...
protected integer ingressExpectCount; // # of pending DMUXtr expects
protected integer sm_PioTags; // There are 16 available tags
protected bit [15:0] pioTagsUsed;
protected integer sm_DmaTags; // There are 256 available tags
protected bit [255:0] dmaTagsUsed;
protected event ev_douBlkFreed; // There are 32 64-B DOU blocks
protected integer sm_DouMutex;
protected bit [31:0] douBlksUsed;
protected integer douBlksRequest;
protected integer sm_consumePost;
protected integer sm_consumeNonpost;
protected integer sm_consumeCompletion;
protected event ev_creditUpdateReceived;
protected integer mb_egressRetry;
protected integer mb_egressSeqNum;
integer egressNextTransmitSeqNum;
protected integer mb_unexpectedCpls;
protected integer egressIdleWeight;
protected integer egressInitPostWeight;
protected integer egressInitNonpostWeight;
protected integer egressInitCompletionWeight;
protected integer egressUpdtPostWeight;
protected integer egressUpdtNonpostWeight;
protected integer egressUpdtCompletionWeight;
protected integer egressInitPostVCNZWeight;
protected integer egressInitNonpostVCNZWeight;
protected integer egressInitCompletionVCNZWeight;
protected integer egressUpdtPostVCNZWeight;
protected integer egressUpdtNonpostVCNZWeight;
protected integer egressUpdtCompletionVCNZWeight;
protected integer egressUpdtPostNZAftInfWeight;
protected integer egressUpdtNonpostNZAftInfWeight;
protected integer egressUpdtCompletionNZAftInfWeight;
protected integer egressUpdtPostOverflowWeight;
protected integer egressUpdtNonpostOverflowWeight;
protected integer egressUpdtCompletionOverflowWeight;
protected integer egressRetryWeight;
protected integer egressPostHdrAllowed;
protected integer egressPostDataAllowed;
protected integer egressNonpostHdrAllowed;
protected integer egressNonpostDataAllowed;
protected integer egressCompletionHdrAllowed;
protected integer egressCompletionDataAllowed;
protected integer egressPostHdrInit;
protected integer egressPostDataInit;
protected integer egressNonpostHdrInit;
protected integer egressNonpostDataInit;
protected integer egressCompletionHdrInit;
protected integer egressCompletionDataInit;
protected integer egressPostHdrAvail;
protected integer egressPostDataAvail;
protected integer egressNonpostHdrAvail;
protected integer egressNonpostDataAvail;
protected integer egressCompletionHdrAvail;
protected integer egressCompletionDataAvail;
protected integer mb_egressPostHdrAvail;
protected integer mb_egressPostDataAvail;
protected integer mb_egressNonpostHdrAvail;
protected integer mb_egressNonpostDataAvail;
protected integer mb_egressCompletionHdrAvail;
protected integer mb_egressCompletionDataAvail;
protected integer egressPostHdrToReturn;
protected integer egressPostDataToReturn;
protected integer egressNonpostHdrToReturn;
protected integer egressNonpostDataToReturn;
protected integer egressCompletionHdrToReturn;
protected integer egressCompletionDataToReturn;
// protected bit returnAllEgressCredits;
protected bit egressUpdateError;
protected integer egressPostHdrConsumed;
protected integer egressPostDataConsumed;
protected integer egressNonpostHdrConsumed;
protected integer egressNonpostDataConsumed;
protected integer egressCompletionHdrConsumed;
protected integer egressCompletionDataConsumed;
protected event egressPostHdrStopFlag;
protected event egressPostDataStopFlag;
protected event egressNonpostHdrStopFlag;
protected event egressNonpostDataStopFlag;
protected event egressCompletionHdrStopFlag;
protected event egressCompletionDataStopFlag;
protected integer egressPostHdrStopValue;
protected integer egressPostDataStopValue;
protected integer egressNonpostHdrStopValue;
protected integer egressNonpostDataStopValue;
protected integer egressCompletionHdrStopValue;
protected integer egressCompletionDataStopValue;
protected bit[31:0] egressPostStarved;
protected bit[31:0] egressNonpostStarved;
protected bit[31:0] egressCompletionStarved;
protected integer infiniteCredits;
protected integer egressDataWidth;
protected integer ingressDataWidth;
protected integer egressRetryInit;
protected integer egressRetryAvail;
protected integer egressRetryConsumed;
protected integer egressRetryAllowed;
protected integer ingressPostHdrInit;
protected integer ingressPostDataInit;
protected integer ingressNonpostHdrInit;
protected integer ingressNonpostDataInit;
protected integer ingressCompletionHdrInit;
protected integer ingressCompletionDataInit;
protected integer ingressPostHdrAvail;
protected integer ingressPostDataAvail;
protected integer ingressNonpostHdrAvail;
protected integer ingressNonpostDataAvail;
protected integer ingressCompletionHdrAvail;
protected integer ingressCompletionDataAvail;
protected integer ingressPostHdrRsvd;
protected integer ingressPostDataRsvd;
protected integer ingressNonpostHdrRsvd;
protected integer ingressNonpostDataRsvd;
protected integer ingressCompletionHdrRsvd;
protected integer ingressCompletionDataRsvd;
protected integer ingressPostHdrConsumed;
protected integer ingressPostDataConsumed;
protected integer ingressNonpostHdrConsumed;
protected integer ingressNonpostDataConsumed;
protected integer ingressCompletionHdrConsumed;
protected integer ingressCompletionDataConsumed;
protected bit onlyHiIngressUpdates;
protected integer gen4DWratio; // Percentage of TLPs w 4DW hdrs
protected integer gen1Weight; // Relative # of TLPs w LEN=1
protected integer gen16Weight; // Relative # of TLPs w LEN=16
protected integer genPartialWeight; // Relative # of TLPs w LEN=2:15
protected integer genBulkWeight; // Relative # of TLPs in >1 blk
protected integer genMemWeight; // Relative # of Mem Rd/Wr TLPs
protected integer genConfigWeight; // Relative # of Cfg Rd/Wr TLPs
protected integer genIoWeight; // Relative # of I/O Rd/Wr TLPs
protected integer minIngressGap; // Min # DWs from EOP to SOP
protected integer maxIngressGap; // Max # DWs from EOP to SOP
protected integer maxRequestSize; // In bytes, from CSR
protected integer maxPayloadSize; // In bytes, from CSR
event ev_linkUp; // "link up" has been asserted
protected integer ingressThrottle; // % of time "itp_cmd" is IDLE
protected bit ingressThrottleRandom; // Should we diddle with it?
protected integer ingressAbortRate; // % of time TLP is sent twice
protected integer egressThrottle; // % of time "dack" deasserted
protected bit egressThrottleRandom; // Should we diddle with it?
protected integer egressPipelinePlugged; // Should we hold "dack" down?
protected integer interruptExpected; // Do we expect an interrupt?
protected integer interruptUnchecked; // Has a test not seen the int?
protected bit intMonitorActive; // Has the monitor been started?
protected bit[31:0] lpuCsr[PEC_LPU_CSR_MAX_COUNT];// The LPU's CSR register space
protected bit[31:0] localRandomSeed;
protected integer ingressLatency;
protected integer egressLatency;
protected event ev_ingressUnblocked; // See "resumeIngressPipeline"
protected event ev_egressUnblocked; // See "resumeEgressPipeline"
protected integer ingressSuspenders;
protected integer egressSuspenders;
protected bit[63:0] ingressCreditAvailCSR;
protected bit[63:0] ingressCreditUsedCSR;
protected bit[63:0] egressCreditAvailCSR;
protected bit[63:0] egressCreditUsedCSR;
protected bit[63:0] egressRetryCSR;
protected event ev_CSRupdateReq;
protected event ev_CSRupdateComplete;
protected integer iluExpectReq; // Number of ILU Xtr expects.
protected integer iluExpectComplete; // Number TLPs ILU Xtr has rcvd.
protected integer peuExpectTlp; // Number of PCIE Xtr expects.
protected integer peuExpectComplete; // Number TLPs PCIE Xtr has rcvd.
protected integer peuExpectReq; // # of pending PIO requests
protected integer peuExpectCpl; // # of pending DMA completions
protected integer peuExpectMsg; // # of pending messages
protected bit ehbErrorReq; // A mirror of EHB.errReq
protected bit ihbErrorReq; // A mirror of IHB.errReq
protected bit[31:0] nonpostReqPending; // The ILU has seen a PIO req...
protected bit[31:0] nonpostReqTimeout; // Expecting a timeout...
protected bit[31:0] nonpostReqInLimbo; // Maybe TLU sends it, maybe not
protected integer nonpostReqDispatch[32]; // Cycle when req sent by TLU
protected event nonpostReqComplete[32]; // The PIO req has been CPL'd!
protected bit rsbEmpty; // Is the TLU scoreboard empty?
bit drainState; // "enterDrainState" was called
bit drainStateActive; // We got a drained CPL from ILU
bit drainStateSignaled; // We got p2d_drain active
event ev_drainStateEnd; // We're at the end of the test
event ev_removePcie; // Remove all Denali Drives/Expects
protected bit softResetPending;
protected event ev_softReset;
protected event ev_softResetEnd;
protected bit softResetOccurred;
protected bit [63:0] intCSR[];
protected bit [1:0] iluDebugCtlA[8];
protected bit [1:0] iluDebugCtlB[8];
protected bit [7:0] iluDebugA0; // Was a port-A debug bit zero?
protected bit [7:0] iluDebugA1; // Was a port-A debug bit one?
protected bit [7:0] iluDebugB0; // Was a port-B debug bit zero?
protected bit [7:0] iluDebugB1; // Was a port-B debug bit one?
protected bit monitorILUend; // Stop looking a TLU debugs!
protected bit [1:0] tluDebugCtlA[8];
protected bit [1:0] tluDebugCtlB[8];
protected bit [7:0] tluDebugA0; // Was a port-A debug bit zero?
protected bit [7:0] tluDebugA1; // Was a port-A debug bit one?
protected bit [7:0] tluDebugB0; // Was a port-B debug bit zero?
protected bit [7:0] tluDebugB1; // Was a port-B debug bit one?
protected bit monitorTLUend; // Stop looking a TLU debugs!
protected bit [2:0] monitorPMreq; // An expected ASPM request
protected bit [2:0] monitorPMstate; // Our current PM state
protected event ev_monitorPMreq; // Got it!
protected bit stallNpstWr; // Is it enabled?
protected bit stallNpstWrPending; // Is there an outstanding req?
protected bit[7:0] stallNpstWrTag; // If so, what's its tag?
protected integer perfCtr_dmaRead;
protected integer perfCtr_dmaWrite;
protected integer perfCtr_recvDWs;
protected integer perfCtr_xmitDWs;
protected integer perfCtr_pioCpl;
protected bit[63:0] coverageVector;
protected integer reserveIngressCreditsCntr = 0;
integer IngressCredits = 1; //Make available to set from test
//N2 protected bit estarEnabled; // Can we enter Estar mode?
protected integer sm_egrCredit;
bit [7:0] ReceivedReqTag;
integer nmbrTlpsReplayBuffer; //Number of unACKd TLPs in replay buffer
integer AckdSeqNum = 4095; //Current highest ACKed sequence number
//Parms for Receiver Errors
bit enableRcvrErrInjection = 0;
integer nmbrRcvrErrsToInject = 0;
integer nmbrRcvrErrsInjected = 0;
integer nmbrRcvrErrsDriven = 0;
integer rcvrErrPct = 0;
integer rcvrErr8b10bWeight = 10;
integer rcvrErrFramingWeight = 10;
integer rcvrErrDisparityWeight = 10;
integer rcvrErrFlipBitWeight = 10;
integer rcvrErrLcrcWeight = 10;
integer rcvrErrDupSeqNmbrWeight = 0;
integer rcvrErrOutOfSeqNmbrWeight = 0;
integer rcvrErrBadSeqNmbrWeight = 0;
integer InvertLCRCErrWeight = 0;
integer EDBErrWeight = 0;
integer InvertLCRCAndEDBErrWeight = 0;
integer rcvrErr8b10bInjected = 0;
integer rcvrErrFramingInjected = 0;
integer rcvrErrDisparityInjected = 0;
integer rcvrErrFlipBitInjected = 0;
integer rcvrErrLcrcInjected = 0;
integer rcvrErrDupSeqNmbrInjected = 0;
integer rcvrErrOutOfSeqNmbrInjected = 0;
integer rcvrErrBadSeqNmbrInjected = 0;
integer nakExpected = 0;
event ev_rcvrErrsDriven;
//These two bits are needed to indicate that an dup seq error is to be injected on a package. After the package is
//driven out, rcvrErrSeqNmbrErr_justinject bit remembers this so the next consecutive package know not to inject
//error. Since consecutive injection of duplicate seq causes ILU expects to not match on the second injected package
bit rcvrErrSeqNmbrErr_toinject = 0; // indicates that this package will inject rcvrErrSeqNmbrErr
bit rcvrErrSeqNmbrErr_justinjected = 0; // indicates that just inject rcvrErrSeqNmbrErr
integer invertLCRC32ErrInjected = 0 ;
integer EDBErrInjected = 0;
integer InvertLCRCAndEDBErrInjected = 0;
integer invertLCRC32 = 0;
integer set_endsymbol_EDB = 0;
integer InvertLCRCAndEDBErr = 0 ;
event ev_StallPioCpl; // Stall PIO read completions
// N2Fc
protected bit [63:0] fcAddrMsk = 64'h0000_00c0_0000_0000;
public bit [63:0] fcAddrArray [256];
// move from expectPCIE to here for global control from diags
integer expectCompleteTO = 8000;
// for random injection of ECRC
integer inject_ECRC_weight = 0; // use for random inject of ECRC during drive PCIE
bit driftRxClockEnabled = 0;
function bit[31:0] localRandom( (integer Limit=0) );
function integer localRandomRange( integer Hi, integer Lo );
task new( ilupeuPodClass Pod,
ilupeuScenario Scenario,
integer RetryCredits = 4096,
(integer RetryWidth = 16) );
task enableEnv( (bit enableInt=1) );
task wait( integer Cycles, bit start = 0 );
task softReset((bit noReset = 0));
task genIngressWrReq( bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0) );
task genIngressRdReq( bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0) );
task genIngressCpl( bit[127:0] ReadReq,
var bit[127:0] TlpHdr,
var integer TlpPayload );
task genIngressMsg( bit [7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0) );
task genEgressWrReq( bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0),
(bit[4:0] TlpType=5'bx) );
task genEgressRdReq( bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0),
(bit[4:0] TlpType=5'bx) );
task genEgressCpl( bit[127:0] ReadReq,
var bit[127:0] TlpHdr,
var integer TlpPayload );
task genEgressPartialCpl( bit[127:0] ReadReq,
var bit[127:0] TlpHdr,
var integer TlpPayload,
integer DWremaining );
task expectEgressMsg( bit[7:0] MsgCode,
(bit[31:0] MsgData = 0),
(event StimulusDone = null),
(bit Lazy = 0) );
task expectTimeoutCpl( bit[127:0] ReqHdr );
function bit isBulkReq( bit[127:0] TlpHdr );
task setAddrBndy( var bit[127:0] TlpHdr, integer AddrBndy, integer BlkSize );
task payloadFill( var integer TlpPayload );
function bit isPayloadFill( integer TlpPayload );
task poisonPayload( var integer TlpPayload );
function bit isPayloadPoisoned( integer TlpPayload );
task errorPayload( var integer TlpPayload,
(bit[7:0] ErrorMask = 8'b0) );
function bit isPayloadErroneous( integer TlpPayload );
function bit[7:0] getPayloadErrorMask( integer TlpPayload );
task setLenWeights( integer SingleWeight, integer ParialWeight,
integer LineWeight, integer BulkWeight );
task setReqWeights( integer MemoryWeight, integer ConfigWeight,
integer IoWeight );
task linkUp( integer Delay, (integer txBadInit = 0), (bit expectSetSlot=0) );
task linkDown();
task setEgressThrottle( integer Ratio ); // Set % of time "dack" <= 0
task setIngressThrottle( integer Ratio ); // Set % of time itp_cmd is IDLE
task setIngressAbortRate( integer Ratio ); // Set % of TLPs with bad CRC
task setIngressGap( integer MinGap, integer MaxGap );
task setIngressDequeueDelay( integer MinDelay, integer MaxDelay );
task plugIngressPipeline(); // Stop asserting "k2y_rcd_deq"
task unplugIngressPipeline(); // Resume giving credits to ILU
task plugEgressPipeline(); // Stop asserting "l2t_etp_dack"
task unplugEgressPipeline(); // Allow TLPs from TLU to LPU
task disconnectEgressPipeline(); // Ignore 't2l_etp' until reset
task suspendIngressPipeline(); // Stop presenting TLPs to TLU
task resumeIngressPipeline(); // Allow TLPs from LPU to TLU
task quiesceIngressPipeline(); // Wait for pipe to empty
task suspendEgressPipeline(); // Stop presenting TLPs to ILU
task resumeEgressPipeline((event Done=null)); // Allow TLPs from DMU to ILU
task quiesceEgressPipeline(); // Wait for egress pipe to empty
task suspendCreditUpdates( integer CreditType, bit Hdr );
task resumeCreditUpdates( integer CreditType, bit Hdr );
task ignoreNormalUpdates( bit Ignore );
task setEgressCreditWeight(integer CreditType, integer Weight);
function integer getEgressCreditAvail(integer CreditType, bit Hdr);
function integer areEgressCreditsExhausted(integer CreditType, bit Hdr);
task waitEgressCreditsExhausted(integer CreditType, bit Hdr);
task waitEgressCreditRollAround(integer CreditType, bit Hdr);
task waitEgressCredit(integer CreditType, bit Hdr, integer Value);
function integer verifyEgressCreditStatus();
function integer areIngressCreditsExhausted(integer CreditType, bit Hdr);
task waitIngressCreditsExhausted(integer CreditType, bit Hdr);
task waitIngressCreditRollAround(integer CreditType, bit Hdr);
task suspendRetryUpdates();
task resumeRetryUpdates();
function integer areRetryCreditsExhausted();
task waitRetryCreditsExhausted();
task driveILU( // Use DMUXtr to drive a packet
bit[PEC_PCI__HDR] PktHdr,
bit[7:0] DataAddr,
integer DataSpec,
(bit Priority=0) );
task expectILU( // Use DMUXtr to expect a packet
bit[PEC_PCI__HDR] PktHdr,
integer DataSpec,
(bit Optional=0) );
task drivePCIE( // Use FNXPcieXtr to drive a packet
bit[PEC_PCI__HDR] PktHdr,
bit [63:0] DataSpec,
(integer LenAdjust=0),
(integer BadParity=0),
(bit Priority=0),
(bit Abort=0),
(bit CfgRdCpl=0),
(bit isDmaReq=0),
(bit null_tlp=0) );
task expectPCIE( // Use FNXPcieXtr to expect a packet
bit[PEC_PCI__HDR] PktHdr,
bit [63:0] DataSpec,
bit IgnoreTlpReqTag = 0,
(bit isDmaReq=0) ,
(integer dma_ptr=0));
task allocWrTag( // Obtain a PIOWr tag & DOU addr
var bit[7:0] TlpTag,
var bit[7:0] DataAddr );
task allocRdTag( // Obtain a PIO-Read tag
var bit[7:0] TlpTag );
task freePioTag( // Free a PIO (Read) tag
bit[7:0] TlpTag );
task allocDmaTag( // Allocate a DMA Read/Write tag
var bit[7:0] TlpTag );
task freeDmaTag( // Free a DMA tag
bit[7:0] TlpTag );
task allocCplData( // Allocate some DOU blocks
integer Len,
bit[6:0] LowAddr,
var bit[7:0] DataAddr );
task freeCplData( // Free a DOU block
bit[7:0] DataAddr );
task set4DWratio( // Set %-age of TLPs w 4DW hdrs
integer ratio );
task reserveIngressCredits(
bit[PEC_PCI__HDR] PktHdr,
bit bypass_FC_credit_checking=1
);
task consumeIngressCredits(
bit[PEC_PCI__HDR] PktHdr );
task expectIdleState();
function integer getMaxPayloadSize();
task setMaxPayloadSize( integer MaxSize );
function integer getMaxRequestSize();
task setMaxRequestSize( integer MaxSize );
task expectILUrel();
function bit[31:0] nextPayloadDW( var integer DataSpec );
task consumeEgressCredits( bit[PEC_PCI__HDR] PktHdr );
task updateIngressCredits();
task updateEgressCredits();
task genReqHdr( var bit[127:0] TlpHdr, bit IsPioReq, integer TlpLen );
task genCplHdr( bit[127:0] NpstReq, bit IsPioReq,
var bit[127:0] TlpHdr, integer DWremaining );
task hangDetect(); // Ensure "activityCounter" goes up
task diddleDack(); // Raise & lower "l2t_etp_dack"
task enableInterrupt();
task disableInterrupt();
function bit expectInterrupt( bit Expected );
task waitInterrupt();
task enableAllErrors(); // Enable all ILU/TLU interrupts
task monitorInt( bit enab ); // Error if an unexpected interrupt
task getIntStatus(); // Collect all ILU/TLU interrupt CSRs
task dumpIntStatus(); // Dump out all ILU/TLU interrupt CSRs
task showUnexpectedInt(); // Show any unexpected interrupts
task monitorStatusCSRs( bit IngressCredits );
task dumpCreditStatus(); // Dump out ILU/TLU & our credit ideas
task monitorAHB(); // Handle AHB requests from the TLU
function integer getLPUindex( integer addr );
function CSRAccessor getCSR( integer addr );
task monitorCplMailbox();
function integer getCSRaddr( PEC_CSRtype csr );
function bit[63:0] getCSRinit( PEC_CSRtype csr );
function bit isCSRreset( PEC_CSRtype csr );
function bit[63:0] getCSRreadMask( PEC_CSRtype csr );
function bit[63:0] getCSRwriteMask( PEC_CSRtype csr );
function bit[63:0] getCSRsetMask( PEC_CSRtype csr );
function bit[63:0] getCSRclearMask( PEC_CSRtype csr );
function integer getLPUaddr( integer csrIndex );
function bit[63:0] readCSR( integer addr );
function bit[63:0] readCSRdirect( integer addr );
task writeCSR( integer addr, bit [63:0] data );
task writeCSRdirect( integer addr, bit [63:0] data );
task expectCSR( integer addr, bit [63:0] data );
task expectCSRdirect( integer addr, bit [63:0] data );
task setTLUdebug( bit[8:0] SelA, bit[8:0] SelB );
task setILUdebug( bit[5:0] SelA, bit[5:0] SelB );
task expectTLUdebug( integer A[8], integer B[8] );
task expectILUdebug( integer A[8], integer B[8] );
task endTLUdebug();
task endILUdebug();
task monitorTLUdebug();
task monitorILUdebug();
task setIngressLatency( integer Latency );
task setEgressLatency( integer Latency );
function integer getIngressLatency( bit[127:0] PktHdr,
(integer ExtraPayload=0) );
function integer getEgressLatency( bit [127:0] PktHdr );
task waitIngressLatency( bit[127:0] PktHdr, (integer ExtraPayload=0) );
task waitEgressLatency( bit[127:0] PktHdr );
task waitEgressPipeFull();
task expectEgressParityError( bit[15:0] ErrMask );
task injectEHBerror( bit[7:0] TlpTag, bit[3:0] ErrMask );
task injectIHBerror( bit[7:0] TlpTag, bit[3:0] ErrMask );
task enterDrainState( (bit[127:0] TlpHdr = 128'bx) );
task waitDrainState();
task setLPUerror( PEC_ERRtype LpuErr );
task setErrorLogEnable( PEC_ERRtype Err, bit LogEnab );
task setErrorIntEnable( PEC_ERRtype Err, bit Primary, bit Secondary );
task expectError(PEC_ERRtype Err, bit Primary, bit Secondary);
task enableOptionalCheck( (string OptCheck = "all") );
task disableOptionalCheck( (string OptCheck = "all") );
task monitorPM();
task pmDllp( PEC_PMtype PmReq );
task pmStatus( string Status ); // "IDLE", "BUSY", "DLLP", or "TLP"
task expectASPM( string StateReq, // "L0", "L0s", or "L1"
integer ReqTimeout, // How many cycs before req is too late?
integer AckDelay, // How many cycs before req ack'd?
(event ReqAbort=null), // Oops! Don't expect it!
(integer IdleTimeout=10) ); // Window for TLU to end req
task expectPM( string StateReq, // As above, but software PME control
integer ReqTimeout,
integer AckDelay,
(event ReqAbort=null) );
task L1toL0(); // As if remote device leaves L1
// For "drainState" processing, we have to maintain a scoreboard
// of outstanding non-posted PIO requests...
function bit isNonpostReq( bit[127:0] PktHdr );
task recordNonpostReq( bit[127:0] PktHdr );
task dispatchNonpostReq( bit[127:0] PktHdr );
task completeNonpostReq( bit[127:0] PktHdr );
// Change the initial credit totals advertised by the TLU.
task setIngressCredits( integer NpstHdr, integer PostHdr, integer PostData );
// Set the time-out value for PIO completions
task setPioTimeOut( integer TimeOut );
// Should we expect a Config/IO write to block all PIO reqs until completed?
task stallNonpostedWrite( bit Enabled );
function bit nonpostedWriteStalled();
function integer getPerfCtr( string ctrType );
task setActivityTimeout(integer timeout);
//N2 task enableEstar( bit Enabled );
//N2 function bit isEstarEnabled();
//N2 task enterEstar();
//N2 task exitEstar();
// Initialize the CSR in the LPU
task initLpuCSRs(integer numActiveLanes = 8,
integer mps = 128,
bit fastTrain = 1,
(bit enableL0s = 0),
(bit [63:0] retryBufSize = 64'h0));
task sendAck(integer seqNum);
task sendNak(integer seqNum);
task disableDenaliAcks();
task enableDenaliAcks();
#ifdef LPUXTR_INCLUDE_PCIE
task enterTxL0s(integer a_cycles);
task enterRecovery();
function bit [11:0] corruptNextXmtSeqNum(bit [11:0] a_increment);
function bit [11:0] corruptNextXmtLCRC(bit [31:0] a_mask);
function bit [11:0] corruptNextXmtSTP(bit [8:0] a_symbol);
function bit [11:0] corruptNextXmtENDTLP(bit [8:0] a_symbol);
function bit [11:0] corruptNextXmt10bTLP(bit [9:0] a_frameMask,
integer a_frameCorruptOffset,
integer a_frameCorruptFreq,
integer a_frameCorruptMax);
task corruptNextXmtCRC(bit [15:0] a_mask);
task corruptNextXmtSDP(bit [8:0] a_symbol);
task corruptNextXmtENDDLLP(bit [8:0] a_symbol);
task corruptNextXmt10bDLLP(bit [9:0] a_frameMask,
integer a_frameCorruptOffset,
integer a_frameCorruptFreq,
integer a_frameCorruptMax);
#endif
//N2 tasks
task ConvertHdr2PcieTlp( bit[PEC_PCI__HDR] tlpHdr,
bit[63:0] _DataSpec,
var FNXPCIEXactorTransaction PCIETlpTrans,
(integer LenAdjust=0),
(bit isDmaReq=0),
(integer dma_ptr=0 ) );
task setDWBE( var bit[PEC_PCI__HDR] TlpHdr );
task returnAllEgressCredits( (integer timerVal = 15) );
function bit[4:0] getLtssmState();
function integer getNmbrTlpsReplayBuffer();
task stayDetectQuiet();
task exitDetectQuiet();
task PeuHotReset();
task toLtssmState( bit [4:0] ltssmState,
(integer timer=2000),
(integer accessMethod=FIRE_PIO_SLOW) );
function string ltssmStateToString( bit [4:0] ltssmState );
task removePcie();
// task and function to detect Denali Endpoint LTSSM states for PM
task to_endpoint_LtssmState( bit [15:0] ep_ltssmState,
(integer timer=2000) );
function string ep_ltssmStateToString( bit [15:0] ep_ltssmState );
// added for N2_FC
// used by all SATs, but enabled only for N2_FC.
//
task N2fcWrMem (bit [63:0] addr, bit [31:0] din, bit [7:0] be);
function bit [31:0] N2fcRdMem (bit [63:0] addr);
// added by AC
task SetPEU_ASPM_enable( bit[1:0] value);
task EndpointExpectDLLP(bit [FNX_PCIE_XTR_DLLP_TYPE_WIDTH-1:0] DllpType);
task disableDenaliFC();
task enableDenaliFC();
task Change_soma_parameters_ac(string _str1);
task driveUnsupportDLLP();
task driveBadCRCDLLP();
task driveduplicateSeqNmbrReq( // Use FNXPcieXtr to drive a packet
bit[PEC_PCI__HDR] PktHdr,
bit [63:0] DataSpec,
(integer LenAdjust=0),
(integer BadParity=0),
(bit Priority=0),
(bit Abort=0),
(bit CfgRdCpl=0),
(bit isDmaReq=0) );
task Endpoint_send_FC_update(bit [8-1:0] DLLPtype, bit [8-1:0] HdrFC, bit [12-1:0] DataFC);
task Monitor_Endpoint_Sent_DLLP(bit [FNX_PCIE_XTR_DLLP_TYPE_WIDTH-1:0] DllpType);
function string dllptypeToString( bit [FNX_PCIE_XTR_DLLP_TYPE_WIDTH-1:0] DllpType );
task dmu_expect_msg( bit [7:0] f_msg, bit [2:0] f_rc );
task setDenaliLaneSkew( integer lane,
integer total_skew,
integer bit_skew,
integer bit_delay,
integer symbol_delay );
task Trigger_link_Up();
task skewRxClockMax(bit enabled);
task skewRxClockMin(bit enabled);
task driftRxClock(bit enabled);
task start_Denali_DTM();
} /* end "PEUTestEnv" */
/*
* new - Construct an environment for execution of PEC testcases
*
* Parameters:
* DMUxactor - An initialized transactor for the DMU-ILU interface
* CSRcollection - An initialized transactor for the (ILU) CSR ring
* LPUxactor - An initialized transactor for the LPU-TLU/serdes interface
* RetryCredits - The number of initial retry credits given to the TLU
*/
task PEUTestEnv::new( ilupeuPodClass _Pod,
ilupeuScenario _Scenario,
integer RetryCredits = 4096,
(integer RetryWidth = 16) )
{
reg [31:0] seedingtmpseed = 1;
// seed the RNG for this object to tg_seed, so that it is the same
// for rtl and gatesim, or different versions of vera.
mGetPlusargDec(tg_seed=, seedingtmpseed);
srandom( seedingtmpseed );
printf ("%0d- PEUTestEnv::new first random # = %0h\n", get_time(LO), random() );
Pod = _Pod;
#ifndef N2_FC
f_DMUXtr = _Pod.DMUXtr;
PiuCsrs = new();
#else
MMU = new();
#endif
f_CSR = _Pod.CSRXtr;
Scenario = _Scenario;
egressRetryInit = RetryCredits;
egressDataWidth = RetryWidth;
ingressDataWidth = RetryWidth;
f_ID = new(1,1,1);
Report = _Pod.Report;
//The egress sequence number should always start at 0
egressNextTransmitSeqNum = 0;
AckdSeqNum = 4095;
// Set the initial weights for the updating of egress credits.
// When we return credits, it's for as many as four TLPs at a time.
egressIdleWeight = 50;
egressInitPostWeight = 0;
egressInitNonpostWeight = 0;
egressInitCompletionWeight = 0;
egressUpdtPostWeight = 10;
egressUpdtNonpostWeight = 10;
egressUpdtCompletionWeight = 10;
egressInitPostVCNZWeight = 0;
egressInitNonpostVCNZWeight = 0;
egressInitCompletionVCNZWeight = 0;
egressUpdtPostVCNZWeight = 0;
egressUpdtNonpostVCNZWeight = 0;
egressUpdtCompletionVCNZWeight = 0;
egressUpdtPostNZAftInfWeight = 0;
egressUpdtNonpostNZAftInfWeight = 0;
egressUpdtCompletionNZAftInfWeight = 0;
egressUpdtPostOverflowWeight = 0;
egressUpdtNonpostOverflowWeight = 0;
egressUpdtCompletionOverflowWeight = 0;
egressRetryWeight = 30;
mb_egressPostHdrAvail = alloc(MAILBOX, 0, 1);
mb_egressPostDataAvail = alloc(MAILBOX, 0, 1);
mb_egressNonpostHdrAvail = alloc(MAILBOX, 0, 1);
mb_egressNonpostDataAvail = alloc(MAILBOX, 0, 1);
mb_egressCompletionHdrAvail = alloc(MAILBOX, 0, 1);
mb_egressCompletionDataAvail = alloc(MAILBOX, 0, 1);
egressPostHdrAllowed = 1;
egressPostDataAllowed = 1;
egressNonpostHdrAllowed = 1;
egressNonpostDataAllowed = 1;
egressCompletionHdrAllowed = 1;
egressCompletionDataAllowed = 1;
egressRetryAllowed = 1;
trigger(ON, egressPostHdrStopFlag);
trigger(ON, egressPostDataStopFlag);
trigger(ON, egressNonpostHdrStopFlag);
trigger(ON, egressNonpostDataStopFlag);
trigger(ON, egressCompletionHdrStopFlag);
trigger(ON, egressCompletionDataStopFlag);
egressPostHdrStopValue = 0;
egressPostDataStopValue = 0;
egressNonpostHdrStopValue = 0;
egressNonpostDataStopValue = 0;
egressCompletionHdrStopValue = 0;
egressCompletionDataStopValue = 0;
egressPostStarved = 0;
egressNonpostStarved = 0;
egressCompletionStarved = 0;
onlyHiIngressUpdates = 0; // Do not ignore low-priority updates
// Initially, the typical TLP is
// half 3DW hdrs and half 4DW hdrs.
gen4DWratio = 50;
gen1Weight = 2;
genPartialWeight = 6;
gen16Weight = 2;
genBulkWeight = 0;
genMemWeight = 20;
genConfigWeight = 0;
genIoWeight = 0;
minIngressGap = 2; // At least 2DW from EOP to next SOP
maxIngressGap = 2; // No need for more than 2DW after EOP
maxRequestSize = 4096; // Any size DMA read-request is OK
maxPayloadSize = 128;
ingressThrottleRandom = 0;
ingressThrottle = 0;
ingressAbortRate = 0;
egressThrottleRandom = 0; // Let "diddleDack" control everything
egressThrottle = 0; // For now, leave "dack" asserted...
egressPipelinePlugged = 0;
interruptExpected = 0; // We don't expect interrupts usually
interruptUnchecked = 0;
intMonitorActive = 0;
nakExpected = 0; // To keep track if A NAK was already sent
localRandomSeed = urandom() + 1; // We generate our own random numbers
ingressLatency = 40;
egressLatency = 20;
peuExpectTlp = 0;
peuExpectComplete = 0;
peuExpectReq = 0;
peuExpectCpl = 0;
peuExpectMsg = 0;
iluExpectReq = 0;
iluExpectComplete = 0;
// We're not asking the top-level
// VERILOG to inject an EHB/IBH error.
// Flip the "errReq" to do so.
#ifndef N2_FC
EHB.errReq <= 0;
IHB.errReq <= 0;
#endif
ehbErrorReq = 0;
ihbErrorReq = 0;
// There aren't any nonposted PIO
// requests waiting for completion,
// and nobody has called "expectTimeout"
// to say that the ILU might generate
// a time-out completion. Note that
// it's an error if timeout[i] and not
// pending[i].
// A non-posted request is "in limbo" if
// it's somewhere within the egress
// pipeline during transition into the
// "drain state".
nonpostReqPending = 32'b0;
nonpostReqTimeout = 32'b0;
nonpostReqInLimbo = 32'b0;
rsbEmpty = 1'b1;
// We aren't in the "drainState".
drainState = 0;
drainStateActive = 0;
drainStateSignaled = 0;
trigger( OFF, ev_drainStateEnd );
trigger( OFF, ev_removePcie );
// We aren't in the middle of a "soft reset"
softResetPending = 0;
trigger( OFF, ev_softReset );
trigger( OFF, ev_softResetEnd );
softResetOccurred = 0;
// Our pipes are open!
trigger( ON, ev_ingressUnblocked );
trigger( ON, ev_egressUnblocked );
ingressSuspenders = 0;
egressSuspenders = 0;
// No ASPM requests are expected from the TLU
monitorPMreq = 3'b000;
monitorPMstate = 3'b001;
trigger( OFF, ev_monitorPMreq );
// The "stall for non-posted PIO writes" feature is disabled
stallNpstWr = 0;
stallNpstWrPending = 0;
// We don't allow entry into Estar mode (ILU clock slowed by 32 times)
// unless someone calls "estarEnabled" to set the ILU's CSR bit
//N2 estarEnabled = 0;
// Reset all of our counters
perfCtr_dmaRead = 0;
perfCtr_dmaWrite = 0;
perfCtr_recvDWs = 0;
perfCtr_xmitDWs = 0;
perfCtr_pioCpl = 0;
coverageVector = 64'b0;
//Parms for Receiver Errors
enableRcvrErrInjection = 0;
nmbrRcvrErrsToInject = 0;
nmbrRcvrErrsInjected = 0;
nmbrRcvrErrsDriven = 0;
rcvrErrPct = 0;
rcvrErr8b10bWeight = 10;
rcvrErrFramingWeight = 10;
rcvrErrDisparityWeight = 10;
rcvrErrFlipBitWeight = 10;
rcvrErrLcrcWeight = 10;
rcvrErrDupSeqNmbrWeight = 0;
rcvrErrOutOfSeqNmbrWeight = 0;
rcvrErrBadSeqNmbrWeight = 0;
InvertLCRCErrWeight = 0;
EDBErrWeight = 0;
InvertLCRCAndEDBErrWeight = 0;
rcvrErr8b10bInjected = 0;
rcvrErrFramingInjected = 0;
rcvrErrDisparityInjected = 0;
rcvrErrFlipBitInjected = 0;
rcvrErrLcrcInjected = 0;
rcvrErrDupSeqNmbrInjected = 0;
rcvrErrOutOfSeqNmbrInjected = 0;
rcvrErrBadSeqNmbrInjected = 0;
invertLCRC32ErrInjected = 0 ;
EDBErrInjected = 0;
InvertLCRCAndEDBErrInjected = 0;
InvertLCRCAndEDBErr = 0;
nakExpected = 0;
trigger( ON, ev_StallPioCpl); // default: no one will wait
} /* end "new" */
/*
* localRandom - Generate a random number within some bounds
*
* Parameters:
* Limit - One greater than the max returned value, or zero if a 32-bit
* random number is desired.
*/
function bit[31:0] PEUTestEnv::localRandom( (integer Limit=0) )
{
localRandomSeed = urandom(localRandomSeed);
if ( Limit <= 0 )
localRandom = localRandomSeed;
else
localRandom = localRandomSeed % Limit;
} /* end localRandom */
/*
* localRandomRange - Generate a random number within some bounds
*
* Parameters:
* Hi - A possible value at one end of the range
* Lo - A possible value at the other end of the range
*/
function integer PEUTestEnv::localRandomRange( integer Hi, integer Lo )
{
if ( Hi == Lo )
localRandomRange = Hi;
else if ( Hi < Lo )
localRandomRange = localRandom(Lo-Hi) + Hi;
else
localRandomRange = localRandom(Hi-Lo) + Lo;
} /* end localRandomRange */
/*
* enableEnv - Get things moving within the PEC test environment
*
* Parameters:
* enableInt - Should interrupts be enabled an monitored? (default = true)
*/
task PEUTestEnv::enableEnv( (bit enableInt = 1) )
{
// Some things need to wait for the
// PEU to say it's ready to go...
trigger( OFF, ev_linkUp );
// A simple mutex used by all...
sm_mutex = alloc( SEMAPHORE, 0, 1, 1 );
// The resources required to build a
// packet are tags for PIO requests,
// tags for DMA requests, and DOU
// addresses for completions.
// DMA tags do not include 0-31, which
// are used by PIO requests. It doesn't
// have to be this way, but it makes
// some things a bit easier.
sm_PioTags = alloc( SEMAPHORE, 0, 1, 16 );
pioTagsUsed = 16'b0;
sm_DmaTags = alloc( SEMAPHORE, 0, 1, 224 ); // 256-32 = 224
dmaTagsUsed = 256'h0ffffffff;
trigger( OFF, ev_douBlkFreed );
sm_DouMutex = alloc( SEMAPHORE, 0, 1, 1 );
douBlksUsed = 31'b0;
douBlksRequest = 0;
infiniteCredits = 2000000000;
ingressExpectCount = 0;
//N2-review ENV_Control.reset = 0;
//N2-review TLU_EgressTLP.disconreq = 0;
// The reservation of credits for
// ingress packets is a critical section
// for the different TLP classes.
sm_consumePost = alloc( SEMAPHORE, 0, 1, 1 );
sm_consumeNonpost = alloc( SEMAPHORE, 0, 1, 1 );
sm_consumeCompletion = alloc( SEMAPHORE, 0, 1, 1 );
// A mailbox is used by the DMUXtr to
// tell us about unsuccessful completion
// TLPs which weren't expected.
mb_unexpectedCpls = alloc( MAILBOX, 0, 1 );
#ifndef N2_FC
f_DMUXtr.setCplMailbox( mb_unexpectedCpls );
#endif
// Simple FIFOs keep track of the order
// in which TLPs are expected from the
// TLU (egress). The DMU transactor
// makes sure that order is preserved
// for ingress TLPs.
mb_egressReqOrder = alloc( MAILBOX, 0, 1 );
mb_egressReqSeq = alloc( MAILBOX, 0, 1 );
mb_egressCplOrder = alloc( MAILBOX, 0, 1 );
mb_egressCplSeq = alloc( MAILBOX, 0, 1 );
egressLastSeq = 0;
egressReqOK = 1;
egressCplOK = 1;
egressBadCount = 0;
// Fire up ILU queues used by...
mb_ILUrelRecds = alloc( MAILBOX, 0, 1 );
mb_egressRetry = alloc( MAILBOX, 0, 1 );
mb_egressSeqNum = alloc( MAILBOX, 0, 1 );
intMonitorActive = enableInt;
// UD : enableEnv is called by ilupeuBootstr
// instead of removing the call from ilupeuBootstr, dont turn on
// the monitors in this routine. this way all the maiboxes and vairables
// are initialized which should prevent hung threads.
//
#ifndef N2_FC
fork
// ...a thread which catches ILU release
// records...
{ expectILUrel(); }
// ...and another thread to provide
// updates to egress credits...
{ updateEgressCredits(); }
// ...and another that just monitors
// ingress credit updates from the TLU.
{ updateIngressCredits(); }
// ...and another that watches the
// "activityCounter" reports an error
// if it doesn't move.
{ hangDetect(); }
// ...and another that plays around
// with the egress data-ACK signal.
//N2 Since this is not needed don't even call it { diddleDack(); }
// ...and another to enable interrupts
// and make sure that an interrupt only
// occurs when one is expected.
{ if ( enableInt ) { repeat(10) @(posedge CLOCK); monitorInt(1); } }
// ...and another which reads CSRs to
// keep track of the device's status.
{ monitorStatusCSRs( 1 ); }
// ...and another which watches the
// "unexpected CPL" mailbox.
{ monitorCplMailbox(); }
// ...and another for LPU CSR requests.
//N2 Since this is not needed don't even call it { if ( !f_LPUXtr.usePCIE ) monitorAHB(); }
// ...and another for the ASPM goo.
//N2 Since this is not needed don't even call it { if ( !f_LPUXtr.usePCIE ) monitorPM(); }
join none
#endif
} /* end enableEnv */
/*
* wait - Wait a given number of cycles without the hang detect
* timing out.
*
* Parameters:
* Cycles - the number of cycles to wait.
*/
task PEUTestEnv::wait( integer Cycles , bit start = 0) {
#ifdef N2_IOS
if (start) {
this.activityStalled += 1;
} else {
this.activityStalled -= 1;
}
#else
this.activityStalled += 1;
repeat(Cycles) @(posedge CLOCK);
this.activityStalled -= 1;
#endif
}
/*
* softReset - Perform a "soft reset" of the device
*
* Parameters: None
*/
task PEUTestEnv::softReset((bit noReset = 0))
{
bit[127:0] pktHdr;
bit [8:0] clearRelRecd;
integer clearMB;
activityStalled += 1;
softResetPending = 1;
_INFO_MSG( "Prepare for soft reset" );
#ifndef N2_FC
#ifndef N2_IOS
trigger( ON, ev_CSRupdateReq );
sync( ANY, ev_CSRupdateComplete );
trigger( OFF, ev_CSRupdateReq );
#endif
#endif
trigger( ON, ev_softReset );
//N2-review f_LPUXtr.linkDown();
//N2-review f_LPUXtr.reset();
//Remove any outstanding PCIE expects
removePcie();
//N2 - Reset Denali - which will bring the link down
if(!noReset){
Pod.FNXPCIEEnableTrans.SetDenaliReset( 1'b1 );
trigger( OFF, ev_linkUp );
}
egressPipelinePlugged = 0;
stallNpstWr = 0;
stallNpstWrPending = 0;
#ifndef N2_FC
#ifndef N2_IOS
if(!noReset){
f_DMUXtr.reset();
//N2 @(posedge CLOCK);
//N2-review ENV_Control.reset = 1;
//N2 warm reset driven active
Pod.DMUXtr.miscPort.$resetN = 1'b0;
_INFO_MSG( "Request soft reset" );
}else{
//Just clear the DMUXtr expects
Pod.DMUXtr.clear( 1 );
}
#endif
#endif
while( mailbox_get( NO_WAIT, mb_egressCplOrder ) > 0 )
void = mailbox_get( NO_WAIT, mb_egressCplOrder, pktHdr );
while( mailbox_get( NO_WAIT, mb_egressCplSeq ) > 0 )
void = mailbox_get( NO_WAIT, mb_egressCplSeq, pktHdr );
while( mailbox_get( NO_WAIT, mb_egressReqOrder ) > 0 )
void = mailbox_get( NO_WAIT, mb_egressReqOrder, pktHdr );
while( mailbox_get( NO_WAIT, mb_egressReqSeq ) > 0 )
void = mailbox_get( NO_WAIT, mb_egressReqSeq, pktHdr );
while( mailbox_get( NO_WAIT, mb_ILUrelRecds ) > 0 )
void = mailbox_get( NO_WAIT, mb_ILUrelRecds, clearRelRecd );
while( mailbox_get( NO_WAIT, mb_egressRetry ) > 0 )
void = mailbox_get( NO_WAIT, mb_egressRetry, clearMB );
while( mailbox_get( NO_WAIT, mb_egressSeqNum ) > 0 )
void = mailbox_get( NO_WAIT, mb_egressSeqNum, clearMB );
repeat(12) @(posedge CLOCK);
//N2-review TLU_EgressTLP.disconreq <= 0;
//N2-review ENV_Control.reset = 0;
//N2 warm reset driven active
#ifndef N2_FC
#ifndef N2_IOS
if(!noReset){
Pod.DMUXtr.miscPort.$resetN = 1'b0;
}
#endif
#endif
//Take Denali out of reset or else the linkup returns positive because
// its in an unknown state
if(!noReset){
Pod.FNXPCIEEnableTrans.SetDenaliReset( 1'b0 );
}
repeat(2) @(posedge CLOCK);
//Reset the Replay Monitor in the PCIEXtr
Pod.FNXPCIEEnableTrans.ResetReplayMonitor();
if(!noReset){
_INFO_MSG( "Soft reset complete" );
}else{
_INFO_MSG( "Soft reset complete with NO reset" );
}
//pioTagsUsed = 16'b0;
//dmaTagsUsed = 256'h0ffffffff;
//trigger( OFF, ev_douBlkFreed );
//douBlksUsed = 31'b0;
//douBlksRequest = 0;
ingressExpectCount = 0;
interruptExpected = 0;
interruptUnchecked = 0;
nonpostReqPending = 32'b0;
nonpostReqTimeout = 32'b0;
nonpostReqInLimbo = 32'b0;
rsbEmpty = 1'b1;
nakExpected = 0;
drainState = 0;
drainStateActive = 0;
drainStateSignaled = 0;
trigger( OFF, ev_drainStateEnd );
trigger( OFF, ev_removePcie );
trigger( OFF, ev_softReset );
softResetPending = 0;
//N2-review f_LPUXtr.linkInit();
trigger( ONE_SHOT, ev_softResetEnd );
softResetOccurred = 1;
#ifndef N2_FC
#ifndef N2_IOS
if(!noReset){
f_DMUXtr.enableXtr();
}
#endif
#endif
egressReqOK = 1;
egressCplOK = 1;
egressBadCount = 0;
egressPostStarved[31] = 1;
egressNonpostStarved[31] = 1;
egressCompletionStarved[31] = 1;
//Sequence number should always reset to 0
egressNextTransmitSeqNum = 0;
AckdSeqNum = 4095;
//Parms for Receiver Errors
enableRcvrErrInjection = 0;
nmbrRcvrErrsToInject = 0;
nmbrRcvrErrsInjected = 0;
nmbrRcvrErrsDriven = 0;
rcvrErrPct = 0;
rcvrErr8b10bWeight = 10;
rcvrErrFramingWeight = 10;
rcvrErrDisparityWeight = 10;
rcvrErrFlipBitWeight = 10;
rcvrErrLcrcWeight = 10;
rcvrErrDupSeqNmbrWeight = 0;
rcvrErrOutOfSeqNmbrWeight = 0;
rcvrErrBadSeqNmbrWeight = 0;
InvertLCRCErrWeight = 0;
EDBErrWeight = 0;
InvertLCRCAndEDBErrWeight = 0;
rcvrErr8b10bInjected = 0;
rcvrErrFramingInjected = 0;
rcvrErrDisparityInjected = 0;
rcvrErrFlipBitInjected = 0;
rcvrErrLcrcInjected = 0;
rcvrErrDupSeqNmbrInjected = 0;
rcvrErrOutOfSeqNmbrInjected = 0;
rcvrErrBadSeqNmbrInjected = 0;
invertLCRC32ErrInjected = 0 ;
EDBErrInjected = 0;
InvertLCRCAndEDBErrInjected = 0;
InvertLCRCAndEDBErr = 0;
nakExpected = 0;
// Restore threads killed by "softResetPending"
#ifndef N2_FC
fork
updateEgressCredits();
updateIngressCredits();
monitorStatusCSRs( 0 );
join none
#endif
activityStalled -= 1;
} /* end softReset */
/*
* linkUp - Go through the process of presenting "link up" to the TLU after
* a specified delay
*
* Parameters:
* Delay - The number of cycles to wait before asserting "link up"
* txBadInit -
*
* NOTE: The caller is suspended until the "link up" process (and delay) has
* completed.
*/
task PEUTestEnv::linkUp( integer Delay,
(integer txBadInit = 0),
(bit expectSetSlot = 0) )
{
ilupeuLinkTrainingStrategy LinkTrainingStrategy;
FNXPCIEXactorTransaction PCIETrans;
bit [63:0] csr;
// First wait for a while so that the enableAllErrors
// CSR write can take effect
if (txBadInit) this.wait(29);
// Disable the flow control protocol interrupt
if (txBadInit) this.setErrorIntEnable( e_ERR_ue_fcp, 0, 0 );
// Bring the link up.
//N2 f_LPUXtr.linkUp( Delay , txBadInit );
//Create the Link Training Strategy
LinkTrainingStrategy = new ( Report,
f_CSR.CSR,
Pod,
Scenario );
PCIETrans = new( Pod.FNXPCIEBldr );
fork
{
// Link Train the ILUPEU - Fork this off so we don't miss the Set Slot Power Msg
LinkTrainingStrategy.Execute();
// Get the initial credit allocations
// If LinkTrainingStrategy.Check_Flow_Control_Init passes then Scenario will hold
// all the correct Initial Flow Control values
//Denali stores infinite credits as all 1's instead of 0
ingressNonpostHdrInit = (Scenario.ilupeuInitialNonPostedHeaderCredit == 8'hff)? 0 : Scenario.ilupeuInitialNonPostedHeaderCredit;
ingressPostHdrInit = (Scenario.ilupeuInitialPostedHeaderCredit == 8'hff)? 0 : Scenario.ilupeuInitialPostedHeaderCredit;
ingressPostDataInit = (Scenario.ilupeuInitialPostedDataCredit == 12'hfff)? 0 : Scenario.ilupeuInitialPostedDataCredit;
//These should be hardwired to infinite
ingressNonpostDataInit = 0;
ingressCompletionHdrInit = 0;
ingressCompletionDataInit = 0;
// A number of threads are waiting
// for us to say "Giddyap!"
trigger( ON, ev_linkUp );
Report.report(RTYP_INFO,"Env:linkUp ilupeu linkup \n");
}
{
//Wait for the FNCPCIEXtr to assert link up and then move on
// so the Set Slot power message isn't missed
PCIETrans.WaitLinkUp();
// Get the initial credit allocations
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denali_FC_NPH_infinite = %d \n", Scenario.denali_FC_NPH_infinite);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denali_FC_NPD_infinite = %d \n", Scenario.denali_FC_NPD_infinite);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denali_FC_PH_infinite = %d \n", Scenario.denali_FC_PH_infinite);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denali_FC_PD_infinite = %d \n", Scenario.denali_FC_PD_infinite);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denali_FC_CPLH_infinite = %d \n", Scenario.denali_FC_CPLH_infinite);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denali_FC_CPLD_infinite = %d \n", Scenario.denali_FC_CPLD_infinite);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denaliInitialNonPostedHeaderCredit = %x \n", Scenario.denaliInitialNonPostedHeaderCredit);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denaliInitialNonPostedDataCredit = %x \n",Scenario.denaliInitialNonPostedDataCredit );
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denaliInitialPostedHeaderCredit = %x \n", Scenario.denaliInitialPostedHeaderCredit);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denaliInitialPostedDataCredit = %x \n", Scenario.denaliInitialPostedDataCredit);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denaliInitialCompletionHeaderCredit = %x \n", Scenario.denaliInitialCompletionHeaderCredit);
Report.report(RTYP_DEBUG_3,"PEUTestEnv::linkUp: Scenario.denaliInitialCompletionDataCredit = %x \n", Scenario.denaliInitialCompletionDataCredit);
egressNonpostHdrInit = (Scenario.denali_FC_NPH_infinite == 1)? 0 : Scenario.denaliInitialNonPostedHeaderCredit;
egressNonpostDataInit = (Scenario.denali_FC_NPD_infinite == 1)? 0 : Scenario.denaliInitialNonPostedDataCredit;
egressPostHdrInit = (Scenario.denali_FC_PH_infinite == 1)? 0 : Scenario.denaliInitialPostedHeaderCredit;
egressPostDataInit = (Scenario.denali_FC_PD_infinite == 1)? 0 : Scenario.denaliInitialPostedDataCredit;
egressCompletionHdrInit = (Scenario.denali_FC_CPLH_infinite == 1)? 0: Scenario.denaliInitialCompletionHeaderCredit;
egressCompletionDataInit = (Scenario.denali_FC_CPLD_infinite == 1)? 0 : Scenario.denaliInitialCompletionDataCredit;
Report.report(RTYP_DEBUG_3," PEUTestEnv::linkUp: egressNonpostHdrInit = %d \n", egressNonpostHdrInit);
Report.report(RTYP_DEBUG_3," PEUTestEnv::linkUp: egressNonpostDataInit = %d \n", egressNonpostDataInit);
Report.report(RTYP_DEBUG_3," PEUTestEnv::linkUp: egressPostHdrInit = %d \n",egressPostHdrInit );
Report.report(RTYP_DEBUG_3," PEUTestEnv::linkUp: egressPostDataInit = %d \n", egressPostDataInit);
Report.report(RTYP_DEBUG_3," PEUTestEnv::linkUp: egressCompletionHdrInit = %d \n",egressCompletionHdrInit );
Report.report(RTYP_DEBUG_3," PEUTestEnv::linkUp: egressCompletionDataInit = %d \n", egressCompletionDataInit);
Report.report(RTYP_INFO,"Env:linkUp Denali linkup \n");
}
join any
fork
{
// Need to fork off the flow control protocol interrupt checking
// so that it doesn't get in the way of the expect egress message
// Check for the flow control protocol error.
if (txBadInit) this.expectError( e_ERR_ue_fcp, 1, 1 );
// Re-enable the flow control protocol interrupt.
if (txBadInit) this.setErrorIntEnable( e_ERR_ue_fcp, 1, 1 );
}
join none
// We used to expect a "set slot power limit" message right away...
//RFE 1987
if( Scenario.ilupeuSetPowerLimitValue || Scenario.ilupeuSetPowerLimitScale ){
expectSetSlot = 1;
}
fork
{
if( expectSetSlot )
expectEgressMsg( PEC_PCI__MSG_CODE_SET_SLOT_POWER_LIMIT );
}
{
//Guarantee LinkTrainingStrategy completed
sync( ANY, ev_linkUp );
}
join
} /* end linkUp */
/*
* linkDown - Forces the RX lanes to electrical idle
*/
task PEUTestEnv::linkDown()
{
//N2 f_LPUXtr.linkDown();
//N2 - Reset Denali - which will bring the link down
//Pod.FNXPCIEEnableTrans.SetDenaliReset( 1'b1 );
Pod.FNXPCIEEnableTrans.SetElecIdleLanes( 8'hff );
} /* end linkDown */
/*
* plugIngressPipeline - Prevent TLPs from exiting the ingress pipeline by
* denying header credits to the ILU
*/
task PEUTestEnv::plugIngressPipeline() {
#ifndef N2_FC
f_DMUXtr.disableIngressDequeue();
#endif
}
/*
* unplugIngressPipeline - Resume returning credits to the ILU, allowing TLPs
* to be presented to the DMU
*/
task PEUTestEnv::unplugIngressPipeline() {
#ifndef N2_FC
f_DMUXtr.enableIngressDequeue();
#endif
}
/*
* plugEgressPipeline - Prevent TLPs from exiting the egress pipeline by
* deasserting "l2t_etp_dack"
*/
task PEUTestEnv::plugEgressPipeline()
{
/*N2-Not needed since testing ilu-peu
if ( egressPipelinePlugged == 0 )
_INFO_MSG( "Egress pipeline is plugged... DACK is deasserted" );
egressPipelinePlugged = egressPipelinePlugged + 1;
f_LPUXtr.assertDataAck(0);
*/
} /* end plugEgressPipeline */
/*
* unplugEgressPipeline - Resume asserting "data ack" to the TLU, allowing TLPs
* to be presented to the LPU
*/
task PEUTestEnv::unplugEgressPipeline()
{
if ( egressPipelinePlugged > 0 )
egressPipelinePlugged = egressPipelinePlugged - 1;
if ( egressPipelinePlugged == 0 )
_INFO_MSG( "Egress pipeline is unplugged... DACK can be asserted" );
} /* end unplugEgressPipeline */
/*
* disconnectEgressPipeline - Force the output of the egress pipeline to "idle"
*
* NOTE: The caller is suspended until no further egress TLPs will be presented
* to the transactor
*/
task PEUTestEnv::disconnectEgressPipeline()
{
_INFO_MSG( "Disconnecting the egress pipeline..." );
//N2-review TLU_EgressTLP.disconreq = 1;
//N2-review @( TLU_EgressTLP.disconack );
_INFO_MSG( "The egress pipeline is disconnected from the xactor" );
}
/*
* suspendIngressPipeline - Stop presenting TLPs to the ILU (see "driveILU")
*/
task PEUTestEnv::suspendIngressPipeline()
{
trigger( OFF, ev_ingressUnblocked );
ingressSuspenders = ingressSuspenders + 1;
} /* end suspendIngressPipeline */
/*
* resumeIngressPipeline - Allow TLPs to enter the ILU (see "driveILU")
*/
task PEUTestEnv::resumeIngressPipeline()
{
if ( ingressSuspenders > 0 )
{
ingressSuspenders = ingressSuspenders - 1;
if ( ingressSuspenders == 0 )
trigger( ON, ev_ingressUnblocked );
}
} /* end resumeIngressPipeline */
/*
* quiesceIngressPipeline - Wait for the ingress pipeline to become empty
*
* NOTE: The pipeline must be "suspended" before it can be quiesced!
*/
task PEUTestEnv::quiesceIngressPipeline()
{
while( this.iluExpectReq > this.iluExpectComplete ) @(posedge CLOCK);
} /* end quiesceIngressPipeline */
/*
* suspendEgressPipeline - Stop presenting TLPs to the TLU (see "driveTLU")
*/
task PEUTestEnv::suspendEgressPipeline()
{
trigger( OFF, ev_egressUnblocked );
egressSuspenders = egressSuspenders + 1;
} /* end suspendEgressPipeline */
/*
* resumeEgressPipeline - Allow TLPs to enter the TLU (see "driveTLU")
*
* Parameters:
* Done - An optional event to be triggered when the pipeline delivers a TLP
*/
task PEUTestEnv::resumeEgressPipeline( (event Done=null) )
{
if ( egressSuspenders > 0 )
egressSuspenders = egressSuspenders - 1;
if ( egressSuspenders == 0 )
trigger( ON, ev_egressUnblocked );
if ( Done != null )
{
//N2-review @( TLU_EgressTLP.cmd );
trigger( ON, Done );
}
} /* end resumeEgressPipeline */
/*
* quiesceEgressPipeline - Wait for the egress pipeline to become empty
*
* NOTE: The pipeline must be "suspended" before it can be quiesced!
*/
task PEUTestEnv::quiesceEgressPipeline()
{
while( this.peuExpectTlp > this.peuExpectComplete ) @(posedge CLOCK);
} /* end quiesceEgressPipeline */
/*
* suspendCreditUpdates - Stop returning credits of a given type to the TLU
*
* Parameters:
* CreditType - The sort of credit to be denied, as in "l2t_efc_type"
* Hdr - Should header credits be denied?
*/
task PEUTestEnv::suspendCreditUpdates( integer CreditType, bit Hdr ) {
if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_1))
this.egressPostHdrAllowed = 0;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_0))
this.egressPostDataAllowed = 0;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_1))
this.egressNonpostHdrAllowed = 0;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_0))
this.egressNonpostDataAllowed = 0;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_1))
this.egressCompletionHdrAllowed = 0;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_0))
this.egressCompletionDataAllowed = 0;
else
_REPORT_ERROR( psprintf("PEUTestEnv::suspendCreditUpdates Bad CreditType %0d / Hdr %1b", CreditType, Hdr) );
}
/*
* resumeCreditUpdates - Resume returning credits of a given type to the TLU
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
*/
task PEUTestEnv::resumeCreditUpdates( integer CreditType, bit Hdr ) {
if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_1))
this.egressPostHdrAllowed = 1;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_0))
this.egressPostDataAllowed = 1;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_1))
this.egressNonpostHdrAllowed = 1;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_0))
this.egressNonpostDataAllowed = 1;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_1))
this.egressCompletionHdrAllowed = 1;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_0))
this.egressCompletionDataAllowed = 1;
else
_REPORT_ERROR(
psprintf("PEUTestEnv::resumeCreditUpdates Bad CreditType %0d / Hdr %1b", CreditType, Hdr));
}
/*
* ignoreNormalUpdates - Should only high-priority ingress credit updates
* be considered?
*
* Parameters:
* Ignore - If non-zero, any non-high-priority credit update is ignored
*/
task PEUTestEnv::ignoreNormalUpdates( bit Ignore )
{
onlyHiIngressUpdates = Ignore;
} /* end ignoreNormalUpdates */
/*
* setEgressCreditWeight - Set the relative frequency of Egress Posted Flow
* Control Updates.
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type" +
* some other verification defined types.
* Weight - The relative frequency of Egress Posted Flow Control Updates.
*/
task PEUTestEnv::setEgressCreditWeight(integer CreditType, integer Weight) {
if (CreditType === PEC_CREDIT_TYPE__IDLE)
egressIdleWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__INIT_COMP)
egressInitCompletionWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__INIT_NONPOST)
egressInitNonpostWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__INIT_POST)
egressInitPostWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_COMP)
egressUpdtCompletionWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST)
egressUpdtNonpostWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_POST)
egressUpdtPostWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__INIT_COMP_VCNZ)
egressInitCompletionVCNZWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__INIT_NONPOST_VCNZ)
egressInitNonpostVCNZWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__INIT_POST_VCNZ)
egressInitPostVCNZWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_COMP_VCNZ)
egressUpdtCompletionVCNZWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST_VCNZ)
egressUpdtNonpostVCNZWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_POST_VCNZ)
egressUpdtPostVCNZWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_COMP_NZ_AFT_INF)
egressUpdtCompletionNZAftInfWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST_NZ_AFT_INF)
egressUpdtNonpostNZAftInfWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_POST_NZ_AFT_INF)
egressUpdtPostNZAftInfWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_COMP_OVERFLOW)
egressUpdtCompletionOverflowWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST_OVERFLOW)
egressUpdtNonpostOverflowWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__UPDT_POST_OVERFLOW)
egressUpdtPostOverflowWeight = Weight;
else if (CreditType === PEC_CREDIT_TYPE__RETRY)
egressRetryWeight = Weight;
else
_REPORT_ERROR(
psprintf("PEUTestEnv::setEgressCreditWeight Bad CreditType %0d", CreditType));
}
/*
* getEgressCreditAvail - Return number of egress flow control credits available
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
*/
function integer PEUTestEnv::getEgressCreditAvail(integer CreditType, bit Hdr) {
if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_1))
getEgressCreditAvail = egressPostHdrAvail;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_0))
getEgressCreditAvail = egressPostDataAvail;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_1))
getEgressCreditAvail = egressNonpostHdrAvail;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_0))
getEgressCreditAvail = egressNonpostDataAvail;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_1))
getEgressCreditAvail = egressCompletionHdrAvail;
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_0))
getEgressCreditAvail = egressCompletionDataAvail;
else
_REPORT_ERROR(
psprintf("PEUTestEnv::getEgressCreditAvail Bad CreditType %0d / Hdr %1b", CreditType, Hdr));
}
/*
* areEgressCreditsExhausted - determine wether the egress credits have
* been exhausted for a particular type.
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
*/
function integer PEUTestEnv::areEgressCreditsExhausted(integer CreditType,
bit Hdr) {
if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_1))
areEgressCreditsExhausted =
!(egressPostHdrAvail - egressPostHdrConsumed);
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_0))
areEgressCreditsExhausted =
((egressPostDataAvail - egressPostDataConsumed) < 4);
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_1))
areEgressCreditsExhausted =
!(egressNonpostHdrAvail - egressNonpostHdrConsumed);
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_0))
areEgressCreditsExhausted =
!(egressNonpostDataAvail - egressNonpostDataConsumed);
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_1))
areEgressCreditsExhausted =
!(egressCompletionHdrAvail - egressCompletionHdrConsumed);
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_0))
areEgressCreditsExhausted =
((egressCompletionDataAvail - egressCompletionDataConsumed) < (this.getMaxPayloadSize() / 16));
else
_REPORT_ERROR(
psprintf("PEUTestEnv::areEgressCreditsExhausted Bad CreditType %0d / Hdr %1b", CreditType, Hdr));
}
/*
* waitEgressCreditsExhausted - wait until the egress credits have
* been exhausted for a particular type.
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
*/
task PEUTestEnv::waitEgressCreditsExhausted(integer CreditType, bit Hdr) {
while (!this.areEgressCreditsExhausted(CreditType, Hdr))
@(posedge CLOCK);
}
/*
* waitEgressCreditRollover - Wait for the egress credit counter to roll over
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
*/
task PEUTestEnv::waitEgressCreditRollAround(integer CreditType, bit Hdr) {
integer initial;
if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_1)) {
initial = this.egressPostHdrAvail;
while (((this.egressPostHdrAvail - initial) <= 257) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Egress Posted Header Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_0)) {
initial = this.egressPostDataAvail;
while (((this.egressPostDataAvail - initial) <= 4097) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Egress Posted Data Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_1)) {
initial = this.egressNonpostHdrAvail;
while (((this.egressNonpostHdrAvail - initial) <= 257) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Egress Non-Posted Header Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_0)) {
initial = this.egressNonpostDataAvail;
while (((this.egressNonpostDataAvail - initial) <= 4097) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Egress Non-Posted Data Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_1)) {
initial = this.egressCompletionHdrAvail;
while (((this.egressCompletionHdrAvail - initial) <= 257) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Egress Completion Header Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_0)) {
initial = this.egressCompletionDataAvail;
while (((this.egressCompletionDataAvail - initial) <= 4097) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Egress Completion Data Credits Rolled Over **\n");
}
else
_REPORT_ERROR(
psprintf("PEUTestEnv::waitEgressCreditRollAround Bad CreditType %0d / Hdr %1b", CreditType, Hdr));
}
/*
* waitEgressCredit - Wait for the given egress credit type to reach
* the given value.
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
* Value - The credit value that we are waiting to reach.
*/
task PEUTestEnv::waitEgressCredit(integer CreditType, bit Hdr, integer Value) {
if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_1)) {
egressPostHdrStopValue = Value;
trigger(OFF, egressPostHdrStopFlag);
sync(ALL, egressPostHdrStopFlag);
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_0)) {
egressPostDataStopValue = Value;
trigger(OFF, egressPostDataStopFlag);
sync(ALL, egressPostDataStopFlag);
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_1)) {
egressNonpostHdrStopValue = Value;
trigger(OFF, egressNonpostHdrStopFlag);
sync(ALL, egressNonpostHdrStopFlag);
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_0)) {
egressNonpostDataStopValue = Value;
trigger(OFF, egressNonpostDataStopFlag);
sync(ALL, egressNonpostDataStopFlag);
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_1)) {
egressCompletionHdrStopValue = Value;
trigger(OFF, egressCompletionHdrStopFlag);
sync(ALL, egressCompletionHdrStopFlag);
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_0)) {
egressCompletionDataStopValue = Value;
trigger(OFF, egressCompletionDataStopFlag);
sync(ALL, egressCompletionDataStopFlag);
}
else
_REPORT_ERROR(
psprintf("PEUTestEnv::waitEgressCredit Bad CreditType %0d / Hdr %1b", CreditType, Hdr));
}
/*
* verifyEgressCreditStatus - Monitor the egress credit allocation in
* the device, and make sure it matches.
*/
function integer PEUTestEnv::verifyEgressCreditStatus() {
integer tluEgrPostHdr;
integer tluEgrPostData;
integer tluEgrNpstHdr;
integer tluEgrNpstData;
integer tluEgrCmplHdr;
integer tluEgrCmplData;
integer tluEgrRetry;
integer envEgrPostHdr;
integer envEgrPostData;
integer envEgrNpstHdr;
integer envEgrNpstData;
integer envEgrCmplHdr;
integer envEgrCmplData;
integer envEgrRetry;
this.activityStalled += 1;
egressCreditAvailCSR = readCSR( getCSRaddr( e_CSR_ecrdt_avail ) );
egressCreditUsedCSR = readCSR( getCSRaddr( e_CSR_ecrdt_used ) );
egressRetryCSR = readCSR( getCSRaddr( e_CSR_retry_crdt ) );
tluEgrPostHdr = (egressCreditUsedCSR[60] == 1'b1) ?
infiniteCredits : egressCreditAvailCSR[19:12];
tluEgrPostData = (egressCreditAvailCSR[60] == 1'b1) ?
infiniteCredits : egressCreditAvailCSR[11:0];
tluEgrNpstHdr = (egressCreditUsedCSR[61] == 1'b1) ?
infiniteCredits : egressCreditAvailCSR[39:32];
tluEgrNpstData = (egressCreditAvailCSR[61] == 1'b1) ?
infiniteCredits : egressCreditAvailCSR[31:20];
tluEgrCmplHdr = (egressCreditUsedCSR[62] == 1'b1) ?
infiniteCredits : egressCreditAvailCSR[59:52];
tluEgrCmplData = (egressCreditAvailCSR[62] == 1'b1) ?
infiniteCredits : egressCreditAvailCSR[51:40];
tluEgrRetry = egressRetryCSR[15:0];
envEgrPostHdr = (egressPostHdrAvail == infiniteCredits) ?
infiniteCredits : egressPostHdrAvail % 256;
envEgrPostData = (egressPostDataAvail == infiniteCredits) ?
infiniteCredits : egressPostDataAvail % 4096;
envEgrNpstHdr = (egressNonpostHdrAvail == infiniteCredits) ?
infiniteCredits : egressNonpostHdrAvail % 256;
envEgrNpstData = (egressNonpostDataAvail == infiniteCredits) ?
infiniteCredits : egressNonpostDataAvail % 4096;
envEgrCmplHdr = (egressCompletionHdrAvail == infiniteCredits) ?
infiniteCredits : egressCompletionHdrAvail % 256;
envEgrCmplData = (egressCompletionDataAvail == infiniteCredits) ?
infiniteCredits : egressCompletionDataAvail % 4096;
envEgrRetry = egressRetryAvail % 65536;
verifyEgressCreditStatus = ((tluEgrPostHdr == envEgrPostHdr) &&
(tluEgrPostData == envEgrPostData) &&
(tluEgrNpstHdr == envEgrNpstHdr) &&
(tluEgrNpstData == envEgrNpstData) &&
(tluEgrCmplHdr == envEgrCmplHdr) &&
(tluEgrCmplData == envEgrCmplData) &&
(tluEgrRetry == envEgrRetry));
if (!verifyEgressCreditStatus)
dumpCreditStatus();
this.activityStalled -= 1;
}
/*
* areIngressCreditsExhausted - determine wether the ingress credits have
* been exhausted for a particular type.
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
*/
function integer PEUTestEnv::areIngressCreditsExhausted(integer CreditType, bit Hdr) {
if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_1))
areIngressCreditsExhausted =
!(ingressPostHdrAvail - ingressPostHdrConsumed);
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_0))
areIngressCreditsExhausted =
((ingressPostDataAvail - ingressPostDataConsumed) < (this.getMaxPayloadSize() / 16));
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_1))
areIngressCreditsExhausted =
!(ingressNonpostHdrAvail - ingressNonpostHdrConsumed);
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_0))
areIngressCreditsExhausted =
((ingressNonpostDataAvail - ingressNonpostDataConsumed) < (this.getMaxPayloadSize() / 16));
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_1))
areIngressCreditsExhausted =
!(ingressCompletionHdrAvail - ingressCompletionHdrConsumed);
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_0))
areIngressCreditsExhausted =
((ingressCompletionDataAvail - ingressCompletionDataConsumed) < (this.getMaxPayloadSize() / 16));
else
_REPORT_ERROR(
psprintf("PEUTestEnv::areIngressCreditsExhausted Bad CreditType %0d / Hdr %1b", CreditType, Hdr));
}
/*
* waitIngressCreditsExhausted - wait until the egress credits have
* been exhausted for a particular type.
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
*/
task PEUTestEnv::waitIngressCreditsExhausted(integer CreditType, bit Hdr) {
while (!this.areIngressCreditsExhausted(CreditType, Hdr))
@(posedge CLOCK);
}
/*
* waitIngressCreditRollAround - Wait for the ingress credit counter to roll over
*
* Parameters:
* CreditType - The sort of credit to be returned, as in "l2t_efc_type"
* Hdr - Should header credits be returned?
*/
task PEUTestEnv::waitIngressCreditRollAround(integer CreditType, bit Hdr) {
integer initial;
if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_1)) {
initial = this.ingressPostHdrAvail;
while (((this.ingressPostHdrAvail - initial) <= 257) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Ingress Posted Header Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_POST) && (Hdr === 1'b_0)) {
initial = this.ingressPostDataAvail;
while (((this.ingressPostDataAvail - initial) <= 4097) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Ingress Posted Data Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_1)) {
initial = this.ingressNonpostHdrAvail;
while (((this.ingressNonpostHdrAvail - initial) <= 257) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Ingress Non-Posted Header Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_NONPOST) && (Hdr === 1'b_0)) {
initial = this.ingressNonpostDataAvail;
while (((this.ingressNonpostDataAvail - initial) <= 4097) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Ingress Non-Posted Data Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_1)) {
initial = this.ingressCompletionHdrAvail;
while (((this.ingressCompletionHdrAvail - initial) <= 257) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Ingress Completion Header Credits Rolled Over **\n");
}
else if ((CreditType === PEC_CREDIT_TYPE__UPDT_COMP) && (Hdr === 1'b_0)) {
initial = this.ingressCompletionDataAvail;
while (((this.ingressCompletionDataAvail - initial) <= 4097) &&
(initial !== infiniteCredits))
@(posedge CLOCK);
printf("** Ingress Completion Data Credits Rolled Over **\n");
}
else
_REPORT_ERROR(
psprintf("PEUTestEnv::waitIngressCreditRollAround Bad CreditType %0d / Hdr %1b", CreditType, Hdr));
}
/*
* suspendRetryUpdates - Stop returning retry credits to the TLU
*/
task PEUTestEnv::suspendRetryUpdates() {
this.egressRetryAllowed = 0;
}
/*
* resumeRetryUpdates - Resume returning retry credits to the TLU
*/
task PEUTestEnv::resumeRetryUpdates() {
this.egressRetryAllowed = 1;
}
/*
* areRetryCreditsExhausted - determine wether the retry credits
* have been exhausted.
*/
function integer PEUTestEnv::areRetryCreditsExhausted() {
integer maxRetryCredits;
// maxRetryCredits = egressDataWidth + this.getMaxPayloadSize();
//N2 review - Cascade calculates the maxRetryCredits based on the
// max supported packet size of 512. This is max_packet_entries
// in xdlh_tlp_gen and can also not transit the last packet that
// credits got allocated for so we'll compensate for that
maxRetryCredits = egressDataWidth + 512 + 32;
areRetryCreditsExhausted =
(egressRetryAvail - egressRetryConsumed) <= maxRetryCredits;
}
/*
* waitRetryCreditsExhausted - wait until the retry credits have
* been exhausted.
*/
task PEUTestEnv::waitRetryCreditsExhausted() {
while (!this.areRetryCreditsExhausted())
@(posedge CLOCK);
}
/*
* setEgressThrottle - Set the % of time that the TLU is preventing from
* delivering egress traffic
*
* Parameters:
* Ratio - The % of time that "l2t_etp_dack" is deasserted
*/
task PEUTestEnv::setEgressThrottle( integer Ratio )
{
string msg;
if ( Ratio < 0 || Ratio > 100 )
egressThrottleRandom = 1;
else
{
sprintf( msg, "Egress throttle (dack deassertion ratio) = %0d", Ratio );
_INFO_MSG( msg );
egressThrottle = Ratio;
egressThrottleRandom = 0;
}
} /* end setEgressThrottle */
/*
* setIngressThrottle - Set the % of time that the LPU sends nothing to the TLU.
*
* Parameters:
* Ratio - The % of time that "l2t_itp_cmd" is IDLE
*/
task PEUTestEnv::setIngressThrottle( integer Ratio )
{
string msg;
if ( Ratio < 0 || Ratio > 100 )
ingressThrottleRandom = 1;
else
{
ingressThrottle = Ratio;
ingressThrottleRandom = 0;
sprintf( msg, "Ingress throttle (idle TLP ratio) = %0d", Ratio );
_INFO_MSG( msg );
}
} /* end setIngressThrottle */
/*
* setIngressAbortRate - Set the % of time that the LPU aborts an ingress TLP
*
* Parameters:
* Ratio - The % of time that a TLP is sent to the TLU with bad CRC (i.e.
* aborted by the LPU) before being sent (again) correctly.
*/
task PEUTestEnv::setIngressAbortRate( integer Ratio )
{
if ( Ratio < 0 || Ratio > 100 )
ingressAbortRate = 0;
else
ingressAbortRate = Ratio;
} /* end setIngressAbortRate */
/*
* setIngressGap - Set the min/max # of DWs from end of one TLP to start of next
*
* Parameters:
* MinGap - The minimum number of DWs from EOP to SOP
* MaxGap - The maximum number of DWs from EOP to SOP
*/
task PEUTestEnv::setIngressGap( integer MinGap, integer MaxGap )
{
_DEBUG_MSG( "PEUTestEnv: Setting min/max ingress gap to %0d/%0d DWs...\n",
MinGap, MaxGap );
minIngressGap = MinGap;
maxIngressGap = MaxGap;
} /* end setIngressGap */
/*
* setIngressDequeueDelay - Set bounds for the number of cycles between
* assertion of "OK to push another ingress Hdr"
*
* Parameters:
* MinDelay - The minimum number of cycles from one assertion of 'k2y_rcd_deq'
* MaxDelay - The maximum number of cycles...
*/
task PEUTestEnv::setIngressDequeueDelay( integer MinDelay, integer MaxDelay )
{
#ifndef N2_FC
_INFO_MSG( psprintf( "Setting k2y_rcd_deq delay to [%0d:%0d]",
MinDelay, MaxDelay ) );
f_DMUXtr.setIngressDequeueDelay( MinDelay, MaxDelay );
#endif
} /* end setIngressDequeueDelay */
/*
* expectIdleState - Make sure that the device is in the "idle state"
*
* Parameters: None
*
* An error is reported if the device is not in the "idle state"
*/
task PEUTestEnv::expectIdleState()
{
bit[7:0] hdrCredit;
bit[11:0] dataCredit;
bit isIdle;
string msg;
_DEBUG_MSG( "Enter 'expectIdleState' at cycle #%0d\n", get_cycle() );
repeat(10) @(posedge CLOCK); //N2 review
_DEBUG_MSG( "Enter 'expectIdleState' at cycle #%0d after 10 cycle delay\n", get_cycle() );
// If we're in the drain state, then
// our only expectation is that there
// are no pending non-posted requests.
// We have to make sure that anyone
// waiting for a TLP is freed up.
if ( drainState )
{
if ( !sync( CHECK, ev_drainStateEnd ) )
{
_DEBUG_MSG( " ...and releasing any pending traffic strategy\n" );
trigger( ON, ev_drainStateEnd );
}
else if ( nonpostReqPending != 0 )
{
_REPORT_ERROR( "Nonposted PIO requests not completed?!!?" );
sprintf( msg, "Pending nonposted request tags: %b", nonpostReqPending );
_ERROR_INFO( msg );
}
return;
}
// There should be nothing expected
// from the ingress or egress pipes.
if ( peuExpectTlp != peuExpectComplete )
{
_INFO_MSG( psprintf( "#req=%0d #cpl=%0d #msg=%0d",
peuExpectReq, peuExpectCpl, peuExpectMsg ) );
_REPORT_ERROR( "'expectIdleState' called with TLPs expected from PEU!?!" );
}
if ( iluExpectReq != iluExpectComplete )
{
_REPORT_ERROR( "'expectIdleState' called with TLPs expected from ILU!?!" );
sprintf( msg, "iluExpectReq=%0d iluExpectComplete=%0d", iluExpectReq,iluExpectComplete );
_ERROR_INFO( msg );
}
// Make sure that all credits have been
// returned to the TLU.
returnAllEgressCredits();
// waitEgressLatency( 128'bx );
repeat(50) @(posedge CLOCK); //N2 review - FC Update timer + Ingress latency
_DEBUG_MSG( "expectIdleState: Egress credits returned at cycle #%0d\n",
get_cycle() );
activityCounter += 1;
// Tell the monitor to read the CSRs
// which record the ILU/TLU's status.
trigger( ON, ev_CSRupdateReq );
sync( ANY, ev_CSRupdateComplete );
_DEBUG_MSG( "expectIdleState: Request status CSR values at cycle #%0d\n",
get_cycle() );
activityCounter += 1;
@( posedge CLOCK );
sync( ANY, ev_CSRupdateComplete );
trigger( OFF, ev_CSRupdateReq );
// If a soft reset had happened,
// then the reserved credits are
// totally out of whack.
if ( softResetOccurred )
{
ingressNonpostHdrRsvd = 0;
ingressPostHdrRsvd = 0;
ingressPostDataRsvd = 0;
}
isIdle = 1;
if ( !rsbEmpty )
{
isIdle = 0;
_DEBUG_MSG( "device status indicates TLU scoreboard is not empty\n" );
}
hdrCredit = ingressCreditAvailCSR[39:32] - ingressCreditUsedCSR[39:32];
if ( hdrCredit != ingressNonpostHdrInit - ingressNonpostHdrRsvd )
{
isIdle = 0;
_DEBUG_MSG( "ingress non-posted hdr mismatch\n" );
}
hdrCredit = ingressCreditAvailCSR[19:12] - ingressCreditUsedCSR[19:12];
if ( hdrCredit != ingressPostHdrInit - ingressPostHdrRsvd )
{
isIdle = 0;
_DEBUG_MSG( "ingress posted hdr mismatch\n" );
}
dataCredit = ingressCreditAvailCSR[11:0] - ingressCreditUsedCSR[11:0];
if ( dataCredit != ingressPostDataInit - ingressPostDataRsvd )
{
isIdle = 0;
_DEBUG_MSG( "ingress posted data mismatch\n" );
}
if ( ingressCreditUsedCSR[39:32] !=
((ingressNonpostHdrConsumed+ingressNonpostHdrRsvd) % 256)
|| ingressCreditUsedCSR[19:12] !=
((ingressPostHdrConsumed+ingressPostHdrRsvd) % 256)
|| ingressCreditUsedCSR[11:00] !=
((ingressPostDataConsumed+ingressPostDataRsvd) % 4096) )
{
//N2 if ( !drainState && !f_LPUXtr.usePCIE ) isIdle = 0;
_DEBUG_MSG( "ingress credits used do not match total consumed by test\n" );
}
if ( egressPostHdrInit != 0 )
{
hdrCredit = egressCreditAvailCSR[19:12] - egressCreditUsedCSR[19:12];
if ( hdrCredit != egressPostHdrInit )
{
isIdle = 0;
_DEBUG_MSG( "egress posted hdr mismatch hdrCredit=%d AvailCSR=%0d UsedCSR=%0d egressPostHdrInit=%0d egressPostHdrConsumed=%0d egressPostHdrAvail=%0d\n",hdrCredit,egressCreditAvailCSR[19:12],egressCreditUsedCSR[19:12],egressPostHdrInit,egressPostHdrConsumed,egressPostHdrAvail );
}
}
if ( egressPostDataInit != 0 )
{
dataCredit = egressCreditAvailCSR[11:0] - egressCreditUsedCSR[11:0];
if ( dataCredit != egressPostDataInit )
{
isIdle = 0;
_DEBUG_MSG( "egress posted data mismatch dataCredit=%d AvailCSR=%0d UsedCSR=%0d egressPostDataInit=%0d egressPostDataConsumed=%0d egressPostDataAvail=%0d\n",dataCredit,egressCreditAvailCSR[11:0],egressCreditUsedCSR[11:0],egressPostDataInit,egressPostDataConsumed,egressPostDataAvail );
}
}
if ( egressNonpostHdrInit != 0 )
{
hdrCredit = egressCreditAvailCSR[39:32] - egressCreditUsedCSR[39:32];
if ( hdrCredit != egressNonpostHdrInit )
{
isIdle = 0;
_DEBUG_MSG( "egress nonposted hdr mismatch hdrCredit=%d AvailCSR=%0d UsedCSR=%0d egressNonpostHdrInit=%0d egressNonpostHdrConsumed=%0d egressNonpostHdrAvail=%0d\n",hdrCredit,egressCreditAvailCSR[39:32],egressCreditUsedCSR[39:32],egressNonpostHdrInit,egressNonpostHdrConsumed,egressNonpostHdrAvail );
}
}
if ( egressNonpostDataInit != 0 )
{
dataCredit = egressCreditAvailCSR[31:20] - egressCreditUsedCSR[31:20];
if ( dataCredit != egressNonpostDataInit )
{
isIdle = 0;
_DEBUG_MSG( "egress nonposted data mismatch dataCredit=%d AvailCSR=%0d UsedCSR=%0d egressNonpostDataInit=%0d egressNonpostDataConsumed=%0d egressNonpostDataAvail=%0d\n",dataCredit,egressCreditAvailCSR[31:20],egressCreditUsedCSR[31:20],egressNonpostDataInit,egressNonpostDataConsumed,egressNonpostDataAvail );
}
}
if ( egressCompletionHdrInit != 0 )
{
hdrCredit = egressCreditAvailCSR[59:52] - egressCreditUsedCSR[59:52];
if ( hdrCredit != egressCompletionHdrInit )
{
isIdle = 0;
_DEBUG_MSG( "egress completion hdr mismatch hdrCredit=%0d AvailCSR=%0d UsedCSR=%0d egressCompletionHdrInit=%0d \n",hdrCredit,egressCreditAvailCSR[59:52],egressCreditUsedCSR[59:52],egressCompletionHdrInit );
}
}
if ( egressCompletionDataInit != 0 )
{
dataCredit = egressCreditAvailCSR[51:40] - egressCreditUsedCSR[51:40];
if ( dataCredit != egressCompletionDataInit )
{
isIdle = 0;
_DEBUG_MSG( "egress completion data mismatch dataCredit=%0d AvailCSR=%0d UsedCSR=%0d egressCompletionDataInit=%0d \n",dataCredit,egressCreditAvailCSR[51:40],egressCreditUsedCSR[51:40],egressCompletionDataInit );
}
}
if ( ( egressCreditUsedCSR[59:52] != (egressCompletionHdrConsumed % 256)
&& (egressCompletionHdrAvail != infiniteCredits) )
|| ( egressCreditUsedCSR[51:40] != (egressCompletionDataConsumed % 4096)
&& (egressCompletionDataAvail != infiniteCredits) )
|| ( egressCreditUsedCSR[39:32] != (egressNonpostHdrConsumed % 256)
&& egressNonpostHdrAvail != infiniteCredits )
|| ( egressCreditUsedCSR[31:20] != (egressNonpostDataConsumed % 4096)
&& egressNonpostDataAvail != infiniteCredits )
|| ( egressCreditUsedCSR[19:12] != (egressPostHdrConsumed % 256)
&& egressPostHdrAvail != infiniteCredits )
|| ( egressCreditUsedCSR[11:00] != (egressPostDataConsumed % 4096)
&& egressPostDataAvail != infiniteCredits ) )
{
if ( !drainState && !egressUpdateError ) isIdle = 0;
_DEBUG_MSG( "egress credits used do not match total consumed by test\n" );
}
if ( egressRetryCSR[15:0] != (egressRetryAvail % 65536)
|| egressRetryCSR[47:32] != (egressRetryConsumed % 65536) )
{
if ( !drainState ) isIdle = 0;
_DEBUG_MSG( "egress retry credits used do not match environment totals egressRetryCSR[15:0]=%0d egressRetryAvail=%0d %0d ||| egressRetryCSR[47:32]=%0d egressRetryConsumed=%0d %0d\n",egressRetryCSR[15:0],egressRetryAvail,egressRetryAvail % 65536,egressRetryCSR[47:32],egressRetryConsumed,egressRetryConsumed % 65536 );
}
// If we're not in the idle state, then
// complain vigorously.
if ( !isIdle )
{
_REPORT_ERROR( "Device not in 'idle' state!" );
getIntStatus();
dumpIntStatus();
dumpCreditStatus();
repeat(20) @(posedge CLOCK);
}
else
_INFO_MSG( "expectIdleState: Device is IDLE\n" );
_INFO_MSG( psprintf( "Coverage = %h_%h_%h_%h\n",
coverageVector[63:48], coverageVector[47:32],
coverageVector[31:16], coverageVector[15:0] ) );
} /* end expectIdleState */
/*
* getMaxPayloadSize - Obtain the maximum payload size (not including ECRC) as
* recorded in the PCI-E Device Control register.
*
* NOTE: The returned value is in bytes
*/
function integer PEUTestEnv::getMaxPayloadSize()
{
#ifdef N2_FC
getMaxPayloadSize = PiuCsrs.piuMaxPayloadSize;
#else
getMaxPayloadSize = maxPayloadSize;
#endif
} /* end getMaxPayloadSize */
/*
* setMaxPayloadSize - Set the maximum payload size by writing (directly) to
* the device-status register.
*
* Parameters:
* MaxSize - The (new?) maximum payload size in bytes
*/
task PEUTestEnv::setMaxPayloadSize( integer MaxSize )
{
integer oldMax;
bit [63:0] csr;
string msg;
oldMax = this.maxPayloadSize;
sprintf( msg, "Max payload size = %0d", MaxSize );
_INFO_MSG( msg );
// Start obeying the new limit
// immediately if we're reducing it.
if ( MaxSize < oldMax )
this.maxPayloadSize = MaxSize;
#ifndef N2_FC
// Modify the TLU's "device control".
csr = readCSRdirect( getCSRaddr( e_CSR_dev_ctl ) );
case( MaxSize )
{
256: csr[FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_MPS_SLC] = 3'b001;
512: csr[FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_MPS_SLC] = 3'b010;
default: csr[FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_MPS_SLC] = 3'b000;
}
#ifdef N2_IOS
writeCSRdirect( getCSRaddr( e_CSR_dev_ctl ), csr );
#else
writeCSR( getCSRaddr( e_CSR_dev_ctl ), csr );
#endif
#endif
// We can now generate bigger requests
// if we increased the limit.
if ( MaxSize > oldMax )
this.maxPayloadSize = MaxSize;
} /* end setMaxPayloadSize */
/*
* getMaxRequestSize - Obtain the maximum DMA (memory) read-request size
*
* NOTE: The returned value is in bytes
*/
function integer PEUTestEnv::getMaxRequestSize()
{
getMaxRequestSize = maxRequestSize;
} /* end getMaxRequestSize */
/*
* setMaxRequestSize - Record the maximum DMA (memory) read-request size
* for TLPs generated by "genIngressRdReq"
*
* Parameters:
* MaxSize - The (new) maximum read-request size in bytes
*/
task PEUTestEnv::setMaxRequestSize( integer MaxSize )
{
maxRequestSize = MaxSize;
} /* end setMaxRequestSize */
/*
* genIngressWrReq - Generate a correct write request for submission to the
* ingress pipeline.
*
* Parameters:
* TlpTag - The tag to be used in the request
* TlpHdr - The resulting TLP header
* TlpPayload - The resulting TLP payload descriptor
* TlpLen - The TLP request/payload length in DWs (optional)
*
* NOTE: Only memory-write requests are valid
*/
task PEUTestEnv::genIngressWrReq( bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0) )
{
/* A valid ingress write-request must
be a memory-write, with a 32-bit or
64-bit address. */
TlpHdr = 128'b0;
TlpHdr[PEC_PCI__FMT_4DW] = localRandom(100) < gen4DWratio;
TlpHdr[PEC_PCI__FMT_DATA] = 1'b1;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MEM;
/* We must use the caller's tag. */
TlpHdr[PEC_PCI__TLP_TAG] = TlpTag;
/* ...but the rest is done generically*/
genReqHdr( TlpHdr, 0, TlpLen );
Report.report(RTYP_DEBUG_3,"genIngressWrReq TlpHdr[PEC_PCI__TYPE]=%0h TlpHdr=%0h \n",TlpHdr[PEC_PCI__TYPE],TlpHdr );
/* The payload is a byte-sequence with
a random starting byte. */
TlpPayload = localRandom(256);
} /* end genIngressWrReq */
/*
* genIngressRdReq - Generate an ingress (DMA memory) read request
*
* Parameters:
* TlpTag - The tag to be used in the request
* TlpHdr - The resulting TLP header
* TlpPayload - The resulting TLP payload descriptor
* TlpLen - The TLP request/payload length in DWs (optional)
*/
task PEUTestEnv::genIngressRdReq(
bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0) )
{
/* A valid ingress read-request must
be a memory-read, with a 32-bit or
64-bit address. */
TlpHdr = 128'b0;
TlpHdr[PEC_PCI__FMT_4DW] = localRandom(100) < gen4DWratio;
TlpHdr[PEC_PCI__FMT_DATA] = 1'b0;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MEM;
/* We must use the caller's tag. */
TlpHdr[PEC_PCI__TLP_TAG] = TlpTag;
/* ...but the rest is done generically*/
genReqHdr( TlpHdr, 0, TlpLen );
/* The payload is a byte-sequence with
a random starting byte. */
TlpPayload = localRandom(256);
} /* end genIngressRdReq */
/*
* genIngressCpl - Generate a completion to a valid egress (PIO) request
*
* Parameters:
* NpstReq - The original non-posted request requiring a completion
* TlpHdr - The header for a successful completion to that request
* TlpPayload - A payload descriptor
*/
task PEUTestEnv::genIngressCpl(
bit[127:0] NpstReq,
var bit[127:0] TlpHdr,
var integer TlpPayload )
{
genCplHdr( NpstReq, 1, TlpHdr, 0 );
TlpPayload = localRandom(256);
} /* end genIngressCpl */
/*
* genIngressMsg - Generate a valid (expected) DMA message
*
* Parameters:
* TlpTag - The tag to be used
* TlpHdr - The resulting message header
* TlpPayload - A payload descriptor
* TlpLen - The length of the message's payload in DWs (zero => no payload)
*/
task PEUTestEnv::genIngressMsg(
bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0) )
{
/* A message with/without payload is
very much like a memory write/read
request with a 4DW header and a
random tag. The "address" is a
random value which is then used as
embedded payload. */
TlpHdr = 128'b0;
TlpHdr[PEC_PCI__FMT_4DW] = 1'b1;
TlpHdr[PEC_PCI__FMT_DATA] = 1'b0;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MEM;
TlpHdr[PEC_PCI__TLP_TAG] = TlpTag;
genReqHdr( TlpHdr, 0, TlpLen );
if ( TlpLen == 0 ) TlpHdr[PEC_PCI__LEN] = 0;
/* Set the TLP type to a message with
a random routing code. */
//N2 Each message has only 1 valid routing code so use the right one
//N2 TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG
//N2 + (localRandom() & PEC_PCI__TYPE_MSG_RC_MASK);
//The attribute is always 0 except for vendor defined messages
TlpHdr[PEC_PCI__ATTR] = 0;
/* Pick a message code from among those
which are passed on by the TLU. */
randcase
{
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_ASSERT_INTA;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_100;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_ASSERT_INTB;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_100;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_ASSERT_INTC;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_100;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_ASSERT_INTD;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_100;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_DEASSERT_INTA;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_100;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_DEASSERT_INTB;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_100;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_DEASSERT_INTC;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_100;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_DEASSERT_INTD;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_100;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_PM_PME;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_000;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_PM_TO_ACK;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_101;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_ERR_COR;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_000;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_ERR_NONFATAL;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_000;
TlpHdr[PEC_PCI__TC] = 0;
}
1: {
TlpHdr[PEC_PCI__MSG_CODE] = PEC_PCI__MSG_CODE_ERR_FATAL;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG + 3'b_000;
TlpHdr[PEC_PCI__TC] = 0;
}
}
/* The payload is a byte-sequence with
a random starting byte. */
TlpPayload = localRandom(256);
} /* end genIngressMsg */ /* No message with data or VD-1 messages */ /*???*/
/*
* genEgressWrReq - Generate a correct write request for submission to the
* egress pipeline.
*
* Parameters:
* TlpTag - The tag to be used in the request
* TlpHdr - The resulting TLP header
* TlpPayload - The resulting TLP payload descriptor
* TlpLen - The TLP request/payload length in DWs (optional)
* TlpType - The TLP's type (optional)
*/
task PEUTestEnv::genEgressWrReq( bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0),
(bit[4:0] TlpType=5'bx) )
{
integer pickit;
/* A valid egress write-request can
be a memory-write, with a 32-bit or
64-bit address, or a non-posted
(config or I/O) request. */
TlpHdr = 128'b0;
pickit = localRandom(genMemWeight + genConfigWeight + genIoWeight);
if ( TlpType !== 5'bx )
{
TlpHdr[PEC_PCI__TYPE] = TlpType;
}
else if ( pickit < genMemWeight || TlpLen > 1 )
{
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MEM;
}
else if ( pickit < genMemWeight + genConfigWeight )
{
if ( localRandom(2) )
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_CFG1;
else
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_CFG0;
}
else
{
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_IO;
}
if ( TlpHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM )
TlpHdr[PEC_PCI__FMT_4DW] = localRandom(100) < gen4DWratio;
TlpHdr[PEC_PCI__FMT_DATA] = 1'b1;
/* We must use the caller's tag. */
TlpHdr[PEC_PCI__TLP_TAG] = TlpTag;
//If a length wasn't passed in for a PIO Memory write then set it here
if ( (TlpHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM) && TlpLen === 0 )
TlpLen = urandom_range( 2, 1 );
/* ...but the rest is done generically*/
if ( TlpHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM )
genReqHdr( TlpHdr, 1, TlpLen );
else
genReqHdr( TlpHdr, 1, 1 );
/* The payload is a byte-sequence with
a random starting byte. */
TlpPayload = localRandom(256);
} /* end genEgressWrReq */
/*
* genEgressRdReq - Generate a valid PIO read request
*
* Parameters:
* TlpTag - The tag to be used for this request
* TlpHdr - The resulting TLP header
* TlpPayload - The resulting TLP payload descriptor
* TlpLen - The length of the request in DWs (optional)
*/
task PEUTestEnv::genEgressRdReq(
bit[7:0] TlpTag,
var bit[127:0] TlpHdr,
var integer TlpPayload,
(integer TlpLen=0),
(bit[4:0] TlpType=5'bx) )
{
integer pickit;
/* A valid egress read-request can
be a memory-read, with a 32-bit or
64-bit address, or a config/IO
request with a 32-bit address. */
TlpHdr = 128'b0;
pickit = localRandom(genMemWeight + genConfigWeight + genIoWeight);
if ( TlpType !== 5'bx )
{
TlpHdr[PEC_PCI__TYPE] = TlpType;
}
else if ( pickit < genMemWeight || TlpLen > 1 )
{
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MEM;
}
else if ( pickit < genMemWeight + genConfigWeight )
{
if ( localRandom(2) )
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_CFG1;
else
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_CFG0;
}
else
{
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_IO;
}
if ( TlpHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM )
TlpHdr[PEC_PCI__FMT_4DW] = localRandom(100) < gen4DWratio;
TlpHdr[PEC_PCI__FMT_DATA] = 1'b0;
/* We must use the caller's tag. */
TlpHdr[PEC_PCI__TLP_TAG] = TlpTag;
/* ...but the rest is done generically*/
if ( TlpHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM )
genReqHdr( TlpHdr, 1, TlpLen );
else
genReqHdr( TlpHdr, 1, 1 );
TlpPayload = 0;
} /* end genEgressRdReq */
/*
* genEgressCpl - Generate an egress completion corresponding to an ingress
* (DMA) memory-read request
*
* Parameters:
* ReadReq - The header for the memory-read request
* TlpHdr - A valid header for a completion to the request
* TlpPayload - A payload spec'n for the request
*/
task PEUTestEnv::genEgressCpl(
bit[127:0] ReadReq,
var bit[127:0] TlpHdr,
var integer TlpPayload )
{
genCplHdr( ReadReq, 0, TlpHdr, 0 );
TlpPayload = localRandom(256);
} /* end genEgressCpl */
/*
* genEgressPartialCpl - Generate one of the multiple egress completions required
* to service a bulk (DMA) memory-read request
*
* Parameters:
* ReadReq - The header for the memory-read request
* TlpHdr - A valid header for a completion to the request
* TlpPayload - A payload spec'n for the request
* Cpl - The number of DWs of data already completed
*/
task PEUTestEnv::genEgressPartialCpl(
bit[127:0] ReadReq,
var bit[127:0] TlpHdr,
var integer TlpPayload,
integer DWremaining )
{
integer dwsRemaining;
dwsRemaining = ReadReq[PEC_PCI__LEN];
if ( dwsRemaining == 0 ) dwsRemaining = 1024;
dwsRemaining = dwsRemaining - DWremaining;
if ( dwsRemaining <= 0 )
_REPORT_ERROR("TEST BUG! 'genEgressPartialCpl' called with bogus DW count");
genCplHdr( ReadReq, 0, TlpHdr, dwsRemaining );
TlpPayload = localRandom(256);
} /* end genEgressCpl */
/*
* expectEgressMsg - Expect a power-management/set-slot message from the TLU
*
* Parameters:
* MsgCode - The sort of message expected (e.g. PEC_PCI__MSG_CODE_PM_TURN_OFF)
* MsgData - Expected data (for messages with data)
* StimulusDone - An event posted when the stimulus has completed
* Lazy - Should we wait forever for the messsage?
*/
task PEUTestEnv::expectEgressMsg( bit[7:0] MsgCode,
(bit[31:0] MsgData = 0),
(event StimulusDone = null),
(bit Lazy = 0) )
{
bit [127:0] tlpHdr;
FNXPCIEXactorTransaction PCIEMsgTrans;
bit setSlot;
bit [2:0] routingCode;
//N2 PECXtrDataTLP tlpPkt;
integer postHdrLimit;
string msg;
integer expectTO;
bit [7:0] pyldByteAry[*];
integer msgDLen = 0;
integer j;
tlpHdr = 128'b0;
setSlot = ( MsgCode == PEC_PCI__MSG_CODE_SET_SLOT_POWER_LIMIT );
case ( MsgCode )
{
PEC_PCI__MSG_CODE_PM_TURN_OFF:
routingCode = 3'b011;
PEC_PCI__MSG_CODE_PM_ACTIVE_STATE_NAK:
routingCode = 3'b100;
default:
routingCode = 3'b100;
}
tlpHdr[PEC_PCI__FMT_DATA] = setSlot;
tlpHdr[PEC_PCI__FMT_4DW] = 1'b1;
tlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG | routingCode;
tlpHdr[PEC_PCI__LEN] = setSlot;
tlpHdr[PEC_PCI__MSG_CODE] = MsgCode;
//
// have Z's.
#ifndef N2_FC
// assign `CPU.dmu.d2p_req_id = 16'h0100 ; Hardwired in ilu_peu_top.v
tlpHdr[ILUPEU_TLP_HDR_REQ_BUS_NUM_BITS] = 8'h01;
tlpHdr[ILUPEU_TLP_HDR_REQ_DEV_NUM_BITS] = 5'h00;
tlpHdr[ILUPEU_TLP_HDR_REQ_FUNC_NUM_BITS] = 3'h0;
#else
// value taken from pio write probe (N2fcXactionProbe.vr)
tlpHdr[ILUPEU_TLP_HDR_REQ_BUS_NUM_BITS] = PiuCsrs.piuREQ_ID[15:8];
tlpHdr[ILUPEU_TLP_HDR_REQ_DEV_NUM_BITS] = PiuCsrs.piuREQ_ID[7:3];
tlpHdr[ILUPEU_TLP_HDR_REQ_FUNC_NUM_BITS] = PiuCsrs.piuREQ_ID[2:0];
#endif
// Get a PCIE Transaction to give to the xactor.
PCIEMsgTrans = new( Pod.FNXPCIEBldr );
PCIEMsgTrans.SetID( f_ID.NextTransID() );
// ...and shove in the header data,
// ...and whatever payload is expected.
ConvertHdr2PcieTlp( tlpHdr,
0,
PCIEMsgTrans );
// ...and whatever payload is expected.
if ( setSlot )
{
//Delete the data generated in ConvertHdr2PcieTlp
PCIEMsgTrans.MyPacket.Pyld.delete();
//and put in the right payload
msgDLen = 1;
pyldByteAry = new[msgDLen*4];
for(j=0; j < (msgDLen*4); j++){
pyldByteAry[j] = MsgData[j*8+7:j*8];
}
PCIEMsgTrans.MyPacket.SetPyld( pyldByteAry );
}
// The xactor returns when it has seen
// the TLP.
if ( !Lazy ) this.peuExpectTlp = this.peuExpectTlp + 1;
if ( !Lazy ) this.peuExpectMsg = this.peuExpectMsg + 1;
PCIEMsgTrans.MyPacket.PktDisplay( RTYP_DEBUG_3, "Env::expectEgressMsg " );
#ifdef N2_FC
expectTO = 5000;
#else
expectTO = 1500;
#endif
fork
{
//#ifndef N2_FC
//review - UDAY Needs to troubleshoot for FC
void = PCIEMsgTrans.Expect( expectTO );
//return the credits consumed by the message!
//#endif
consumeEgressCredits( tlpHdr );
}
{
sync( ANY, ev_drainStateEnd );
printf("Env::expectEgressMsg ev_drainStateEnd hit \n");
}
{
postHdrLimit = 1;
while( postHdrLimit > 0
&& !sync( CHECK, StimulusDone ) ) @(posedge CLOCK);
if ( postHdrLimit > 0 ) postHdrLimit = egressPostHdrConsumed + 4;
while( postHdrLimit > 0
&& egressPostHdrConsumed < postHdrLimit ) @(posedge CLOCK);
while( Lazy && postHdrLimit > 0 ) @(posedge CLOCK);
if ( postHdrLimit > 0 )
{
_REPORT_ERROR("Egress message not received after 4 posted TLPs\n");
_ERROR_INFO( msg );
}
printf("Env::expectEgressMsg postHdrLimit=%0d hit \n",postHdrLimit);
}
join any
if ( !Lazy ) this.peuExpectComplete = this.peuExpectComplete + 1;
if ( !Lazy ) this.peuExpectMsg = this.peuExpectMsg - 1;
activityCounter = activityCounter + 1;
// For round-robin's sake, expect anything after the message
egressCplOK = 1;
egressReqOK = 1;
egressBadCount = 0;
// Break the "...message not received..." loop
postHdrLimit = 0;
} /* end expectEgressMsg */
/*
* expectTimeoutCpl - Expect a timed-out completion to a given non-posted request
*
* Parameters:
* ReqHdr - The TLP header for the request which we expect to time-out
*/
task PEUTestEnv::expectTimeoutCpl( bit[127:0] ReqHdr )
{
bit[7:0] tag;
// First, make sure that there's a
// pending non-posted request with the
// given tag.
tag = ReqHdr[PEC_PCI__TLP_TAG];
if ( tag > 31 || nonpostReqPending[tag] == 1'b0 )
{
_REPORT_ERROR("Internal error: Invalid tag supplied for nonposted PIO req");
}
else
{
if ( stallNpstWrPending && tag == stallNpstWrTag )
{
_INFO_MSG( "Time-out for prior non-posted write request expected" );
stallNpstWrPending = 0;
}
_DEBUG_MSG( "PEUTestEnv %s: PIO request tag=%h at cycle %0d\n",
"expectTimeoutCpl", tag, get_cycle() );
nonpostReqTimeout[tag] = 1'b1;
sync( ANY, nonpostReqComplete[tag] );
_DEBUG_MSG( "PEUTestEnv %s: Time-out for tag=%h at cycle %0d\n",
"expectTimeoutCpl", tag, get_cycle() );
}
} /* end expectTimeoutCpl */
/*
* isNonpostReq - Is a request non-posted?
*
* Parameters:
* PktHdr - The header of interest
*
* Returned value: Non-zero if the request is non-posted (i.e. requires a reply)
*/
function bit PEUTestEnv::isNonpostReq( bit[127:0] PktHdr )
{
if ( PktHdr[PEC_PCI__TYPE]==PEC_PCI__TYPE_CFG0
|| PktHdr[PEC_PCI__TYPE]==PEC_PCI__TYPE_CFG1
|| PktHdr[PEC_PCI__TYPE]==PEC_PCI__TYPE_IO
|| (PktHdr[PEC_PCI__TYPE]==PEC_PCI__TYPE_MEM && !PktHdr[PEC_PCI__FMT_DATA]))
isNonpostReq = 1;
else
isNonpostReq = 0;
}
/*
* recordNonpostReq - Look at the header of a TLP just submitted to the
* ILU and record it as a non-posted PIO request, if it is.
*
* Parameters:
* PktHdr - The header of a TLP just presented to the ILU
*/
task PEUTestEnv::recordNonpostReq( bit[127:0] PktHdr )
{
integer tag;
// If the TLP was a non-posted request,
// then record the tag.
if ( isNonpostReq(PktHdr) )
{
tag = PktHdr[PEC_PCI__TLP_TAG];
nonpostReqPending[tag] = 1'b1;
nonpostReqDispatch[tag] = 0;
trigger( OFF, nonpostReqComplete[tag] );
// If we're entering the "drain state",
// then we don't know whether or not to
// expect the request from the TLU.
if ( drainState && !drainStateActive ) nonpostReqInLimbo[tag] = 1'b1;
}
} /* end recordNonpostReq */
/*
* dispatchNonpostReq - Take note of the fact that a nonposted PIO request
* has just be sent by the TLU
*
* Parameters:
* PktHdr - The header of a TLP just presented by the TLU
*/
task PEUTestEnv::dispatchNonpostReq( bit[127:0] PktHdr )
{
integer tag;
// If the TLP was a non-posted request,
// then get the tag...
if ( PktHdr[PEC_PCI__TYPE]==PEC_PCI__TYPE_CFG0
|| PktHdr[PEC_PCI__TYPE]==PEC_PCI__TYPE_CFG1
|| PktHdr[PEC_PCI__TYPE]==PEC_PCI__TYPE_IO
|| (PktHdr[PEC_PCI__TYPE]==PEC_PCI__TYPE_MEM && !PktHdr[PEC_PCI__FMT_DATA]))
{
tag = PktHdr[PEC_PCI__TLP_TAG];
// ...and make sure that it's still
// a "pending" request...
if ( !nonpostReqPending[tag]
&& !sync( CHECK, ev_drainStateEnd ) )
{
if ( nonpostReqInLimbo[tag] )
nonpostReqInLimbo[tag] = 1'b0;
else
_REPORT_ERROR( "PIO request from TLU is not pending?!?" );
}
// ...before recording the cycle when
// the request left the TLU.
else
{
nonpostReqDispatch[tag] = get_cycle();
nonpostReqInLimbo[tag] = 1'b0;
}
}
} /* end dispatchNonpostReq */
/*
* completeNonpostReq - Look at the header of a TLP submitted by the ILU, and
* take note of a completion to a non-posted PIO request
*
* Parameters:
* PktHdr - The header of a TLP just submitted by the ILU
*/
task PEUTestEnv::completeNonpostReq( bit [127:0] PktHdr )
{
integer tag;
// If the TLP was a completion, then
// get the tag.
if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL )
{
tag = PktHdr[PEC_PCI__CPL_TAG];
// completeNonpostReq nonpostReqPending=%0h tag=%0h\n",nonpostReqPending,tag );
// ...and clear our records that the
// corresponding requst is pending.
nonpostReqPending[tag] = 1'b0;
nonpostReqTimeout[tag] = 1'b0;
trigger( ON, nonpostReqComplete[tag] );
}
} /* end completeNonpostReq */
/*
* genReqHdr - Generate a valid request TLP header
*
* Parameters:
* TlpHdr - The header to be filled in (format, type and tag already exist)
* IsPioReq - Is this a PIO (egress) request?
* TlpLen - The length of the request in DWs (zero=>random)
*/
task PEUTestEnv::genReqHdr(
var bit[127:0] TlpHdr,
bit IsPioReq,
integer TlpLen )
{
integer pickit;
bit [63:0] tlpAddr;
integer maxLen;
integer bulkReq;
integer len;
/* We'll always leave the EP (poisoned)
bit off, but we can set the TD (ECRC)
bit if this is a DMA request. */
TlpHdr[PEC_PCI__EP] = 1'b0;
if ( IsPioReq )
TlpHdr[PEC_PCI__TD] = 1'b0;
else if ( TlpHdr[PEC_PCI__FMT_DATA] )
TlpHdr[PEC_PCI__TD] = localRandom(2); /*???*/
else
TlpHdr[PEC_PCI__TD] = 1'b0;
/* For egress/PIO requests, the traffic
class and attributes are zero.
They're random in ingress requests.*/
if ( IsPioReq )
{
TlpHdr[PEC_PCI__REQ_ID] = localRandom();
TlpHdr[PEC_PCI__TC] = 0;
TlpHdr[PEC_PCI__ATTR] = 0;
}
else
{
TlpHdr[PEC_PCI__REQ_ID] = localRandom();
TlpHdr[PEC_PCI__TC] = localRandom();
TlpHdr[PEC_PCI__ATTR] = localRandom();
}
//Denali can hold a TLP from being transmitted if a previous TLP
// with the same tag and Request ID has not completed yet. This only
// should happen with error TLPs. To help with this make all good REQs
// PEC_PCI__REQ_ID[0] = 0
TlpHdr[80] = 1'b0;
/* If the caller gave us a length,
then use it. Otherwise, use the
controlling parameters. */
if ( IsPioReq )
pickit = localRandom( gen1Weight + genPartialWeight + gen16Weight );
else
pickit = localRandom( gen1Weight + genPartialWeight + gen16Weight
+ genBulkWeight );
bulkReq = pickit >= (gen1Weight + genPartialWeight + gen16Weight);
if ( TlpLen < 0 || TlpLen > 1024 )
TlpHdr[PEC_PCI__LEN] = 16;
else if ( TlpLen == 1024 )
TlpHdr[PEC_PCI__LEN] = 0;
else if ( TlpLen > 0 )
TlpHdr[PEC_PCI__LEN] = TlpLen;
else
{
if ( pickit < gen1Weight )
TlpHdr[PEC_PCI__LEN] = 1;
else if ( pickit < gen1Weight + genPartialWeight )
TlpHdr[PEC_PCI__LEN] = 2 + localRandom(14);
else if ( pickit < gen1Weight + genPartialWeight + gen16Weight )
TlpHdr[PEC_PCI__LEN] = 16;
else
{
if ( TlpHdr[PEC_PCI__FMT_DATA] )
maxLen = getMaxPayloadSize() / 4;
else
maxLen = maxRequestSize / 4;
TlpHdr[PEC_PCI__LEN] = 2 + localRandom(maxLen-1);
}
}
/* The address is random*/
tlpAddr = {localRandom(),localRandom()};
tlpAddr[1:0] = 2'b0;
//Allign 8 byte PIO writes
if( IsPioReq && TlpHdr[PEC_PCI__FMT_DATA] && (TlpHdr[PEC_PCI__LEN] == 2) )
tlpAddr[2] = 1'b0;
/* A "bulk" request must cross a
block boundary, or RCB (16DWs). */
/* A "non-bulk" request must not. */
if ( bulkReq )
{
if ( TlpHdr[PEC_PCI__LEN] + tlpAddr[5:2] <= 16 )
tlpAddr[5:2] = 17 - TlpHdr[PEC_PCI__LEN];
}
else
{
if ( TlpHdr[PEC_PCI__LEN] + tlpAddr[5:2] > 16 )
tlpAddr[5:2] = 16 - TlpHdr[PEC_PCI__LEN];
}
/* The request cannot cross a 4KB bndy*/
len = TlpHdr[PEC_PCI__LEN];
if ( len == 0 ) len = 1024;
if ( len + tlpAddr[11:2] > 1024 )
{
if ( len > 16 )
tlpAddr[11:2] = 1024 - TlpHdr[PEC_PCI__LEN];
else
tlpAddr[6] = 1'b0;
}
/* Finally, we can set the address. */
if ( TlpHdr[PEC_PCI__FMT_4DW] )
TlpHdr[PEC_PCI__ADDR] = tlpAddr;
else
TlpHdr[PEC_PCI__ADDR32] = tlpAddr[31:0];
//If this is a cfg type then set the reserved bits to 0
//this is called from TimeOutPEUStr
if( TlpHdr[ PEC_PCI__TYPE ] === PEC_PCI__TYPE_CFG0 ||
TlpHdr[ PEC_PCI__TYPE ] === PEC_PCI__TYPE_CFG1 ){
TlpHdr[ 47:44 ] = 4'h0;
TlpHdr[ 33:32 ] = 2'h0;
}
/* DWBEs are random, but their validity
depends on the length and boundary.*/
setDWBE( TlpHdr );
if ( TlpHdr[PEC_PCI__LEN] == 1 )
{
TlpHdr[PEC_PCI__FIRST_DWBE] = localRandom(16);
TlpHdr[PEC_PCI__LAST_DWBE] = 0;
}
/* N2 review
//If QW aligned First and Last can be non-contiguous
else if ( TlpHdr[PEC_PCI__LEN] == 2 && tlpAddr[3] == 1'b0 )
{
TlpHdr[PEC_PCI__FIRST_DWBE] = 1 + localRandom(15);
TlpHdr[PEC_PCI__LAST_DWBE] = 1 + localRandom(15);
}
*/
else
{
TlpHdr[PEC_PCI__FIRST_DWBE] = 8'h78 >> localRandom(4);
TlpHdr[PEC_PCI__LAST_DWBE] = 8'h0f >> localRandom(4);
}
Report.report(RTYP_DEBUG_3,"PEUTestEnv::genReqHdr() QW aligned Len=%0d tlpAddr=%0h FIRST_DWBE=%0h LAST_DWBE=%0h \n",TlpHdr[PEC_PCI__LEN],tlpAddr,TlpHdr[PEC_PCI__FIRST_DWBE],TlpHdr[PEC_PCI__LAST_DWBE] );
} /* end genReqHdr */
/*
* genCplHdr - Generate a completion TLP header corresponding to a request
*
* Parameters:
* NpstReq - The header for the original non-posted request
* IsPioReq - Is this to be a completion to a PIO request?
* TlpHdr - A valid header for a completion to the request
* DWremaining - The number of DWs which remain to be completed, or zero
* if the entire request is to be completed
*/
task PEUTestEnv::genCplHdr(
bit[127:0] NpstReq,
bit IsPioReq,
var bit[127:0] TlpHdr,
integer DWremaining )
{
bit [63:0] addr;
integer reqDWs;
/* Reserved fields in an egress header
must be zero. Ditto for TD and BCM*/
if ( IsPioReq )
TlpHdr = 128'b0;
// TlpHdr = { localRandom(), localRandom(), localRandom(), localRandom() };
//N2 review - Need to update Denali to handle reserved fields != 0
else
TlpHdr = 128'b0;
/* A completion always uses a 3DW hdr.*/
if ( NpstReq[PEC_PCI__FMT_DATA] )
TlpHdr[PEC_PCI__FMT_DATA] = 1'b0;
else
TlpHdr[PEC_PCI__FMT_DATA] = 1'b1;
TlpHdr[PEC_PCI__FMT_4DW] = 1'b0;
TlpHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_CPL;
/* The completion is not poisoned. */
TlpHdr[PEC_PCI__EP] = 1'b0;
/* The completion is successful. */
TlpHdr[PEC_PCI__CPL_STATUS] = 3'b000;
/* Many values are taken from the req.*/
TlpHdr[PEC_PCI__TC] = NpstReq[PEC_PCI__TC];
TlpHdr[PEC_PCI__ATTR] = NpstReq[PEC_PCI__ATTR];
TlpHdr[PEC_PCI__CPL_REQ_ID] = NpstReq[PEC_PCI__REQ_ID];
TlpHdr[PEC_PCI__CPL_TAG] = NpstReq[PEC_PCI__TLP_TAG];
/* The length is easy if we're handling
request with a single completion. */
if ( DWremaining <= 0 ){
TlpHdr[PEC_PCI__LEN] = NpstReq[PEC_PCI__LEN];
//If this is a Cpl not a CplD then set the LEN = 0
if( TlpHdr[PEC_PCI__FMT_DATA] === 1'b0 ){
TlpHdr[PEC_PCI__LEN] = 0;
}
}
/* Otherwise, determine the number of
RCB blocks required by the request,
and return as many blocks as are in
the "maximum payload size". */
else
{
if ( NpstReq[PEC_PCI__FMT_4DW] )
addr = NpstReq[PEC_PCI__ADDR];
else
addr = NpstReq[PEC_PCI__ADDR32];
reqDWs = NpstReq[PEC_PCI__LEN];
if ( reqDWs == 0 ) reqDWs = 1024;
/* If this is the first completion... */
if ( DWremaining == reqDWs )
{
/* ...then the number of DWs in the
payload depends on how far we start
into a block. */
if ( (reqDWs + addr[5:2]) < getMaxPayloadSize() / 4 ) // Assuming a 64B RCB...
TlpHdr[PEC_PCI__LEN] = DWremaining;
else
TlpHdr[PEC_PCI__LEN] = (getMaxPayloadSize() / 4) - addr[5:2];
}
/* Otherwise, handle whatever's left in
one completion, if we can... */
else if ( DWremaining < getMaxPayloadSize() / 4 )
{
TlpHdr[PEC_PCI__LEN] = DWremaining;
}
/* ...or hand off a "maxPayload" if
we're in the middle of the request.*/
else
{
TlpHdr[PEC_PCI__LEN] = getMaxPayloadSize() / 4;
}
}
/* The completer-ID is a don't-care. */
TlpHdr[PEC_PCI__CPL_ID] = localRandom();
if ( NpstReq[PEC_PCI__FMT_4DW] )
TlpHdr[PEC_PCI__LOWADDR] = NpstReq[PEC_PCI__ADDR] & ~(64'h03);
else
TlpHdr[PEC_PCI__LOWADDR] = NpstReq[PEC_PCI__ADDR32] & ~(32'h03);
//BYTECOUNT should hold the number of remaining bytes including this Cpl
if( DWremaining === 0 ){
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__LEN] * 4;
}else{
TlpHdr[PEC_PCI__BYTECOUNT] = DWremaining * 4;
}
//N2 TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__LEN] * 4;
/* Modify the byte-count and low-addr
as required by the DWBEs. */
if ( NpstReq[PEC_PCI__TYPE] != PEC_PCI__TYPE_MEM )
{
TlpHdr[PEC_PCI__BYTECOUNT] = 4;
TlpHdr[PEC_PCI__LOWADDR] = 0;
}
else if( DWremaining > 0 && DWremaining < reqDWs ) // For other than the 1st of many Cpls.
{
//N2 - Set bit 6 of the LowerAddress according to the alignment of 64-Byte data
// according to PCIE spec 1.0a pg.87 sec. 2.3.1.1
TlpHdr[PEC_PCI__LOWADDR] = {addr[6],6'h0};
//The byte count needs to be adjusted for last Cpls byte enables
if ( !(NpstReq[PEC_PCI__LAST_DWBE] & 4'b1000) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__LAST_DWBE] & 4'b0100) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__LAST_DWBE] & 4'b0010) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
}
}
}
}
else if ( NpstReq[PEC_PCI__FIRST_DWBE] == 0 )
{
TlpHdr[PEC_PCI__BYTECOUNT] = 1;
}
else if ( NpstReq[PEC_PCI__LEN] == 1 )
{
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b0001) )
{
TlpHdr[PEC_PCI__LOWADDR] = TlpHdr[PEC_PCI__LOWADDR] + 1;
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b0010) )
{
TlpHdr[PEC_PCI__LOWADDR] = TlpHdr[PEC_PCI__LOWADDR] + 1;
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b0100) )
{
TlpHdr[PEC_PCI__LOWADDR] = TlpHdr[PEC_PCI__LOWADDR] + 1;
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
}
}
}
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b1000) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b0100) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b0010) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
}
}
}
}
else
{
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b0001) )
{
TlpHdr[PEC_PCI__LOWADDR] = TlpHdr[PEC_PCI__LOWADDR] + 1;
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b0010) )
{
TlpHdr[PEC_PCI__LOWADDR] = TlpHdr[PEC_PCI__LOWADDR] + 1;
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__FIRST_DWBE] & 4'b0100) )
{
TlpHdr[PEC_PCI__LOWADDR] = TlpHdr[PEC_PCI__LOWADDR] + 1;
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
}
}
}
if ( !(NpstReq[PEC_PCI__LAST_DWBE] & 4'b1000) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__LAST_DWBE] & 4'b0100) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
if ( !(NpstReq[PEC_PCI__LAST_DWBE] & 4'b0010) )
{
TlpHdr[PEC_PCI__BYTECOUNT] = TlpHdr[PEC_PCI__BYTECOUNT] - 1;
}
}
}
}
} /* end genCplHdr */ /* LOWADDR & BYTECOUNT crap for bulk */ /*???*/
/*
* setAddrBndy - Set the boundary for a TLP address.
*
* Parameters:
* TlpHdr - The packet-header to be modified
* AddrBndy - The requested address boundary (in bytes)
* BlkSize - The block size for that boundary (in bytes, a power of two)
*
* For example, setting "AddrBndy" to 4 and "BlkSize" to 16 means that the
* resulting address is four bytes into a block of 16... the low-order hex
* digit for the address is "4".
*/
task PEUTestEnv::setAddrBndy( var bit[127:0] TlpHdr,
integer AddrBndy,
integer BlkSize )
{
bit[63:0] addrMask;
addrMask = 64'hffffffff00000000 | ~(BlkSize-1);
if ( TlpHdr[PEC_PCI__FMT_4DW] )
TlpHdr[PEC_PCI__ADDR] = (TlpHdr[PEC_PCI__ADDR] & addrMask) + AddrBndy;
else
TlpHdr[PEC_PCI__ADDR32] = (TlpHdr[PEC_PCI__ADDR32] & addrMask) + AddrBndy;
//Adjust the DWBE since address changed - especially needed for len=2
setDWBE( TlpHdr );
} /* end setAddrBndy */
/*
* setLenWeights - Set the relative frequency of lengths used for (memory)
* read/write requests
*
* Parameters:
* SingleWeight - The relative number of single DW requests
* PartialWeight - The relative number of requests from 2 to 15 DWs
* LineWeight - The relative number of full cache-line (16 DW) requests
* BulkWeight - The relative number of requests spanning the cache-line
* boundary (or RCB) up to the "maxPayload/RequestSize"
*
* NOTE: If a given "...Weight" is negative, then the corresponding value is
* not set.
*/
task PEUTestEnv::setLenWeights( integer SingleWeight, integer PartialWeight,
integer LineWeight, integer BulkWeight )
{
string msg;
if ( SingleWeight >= 0 ) gen1Weight = SingleWeight;
if ( PartialWeight >= 0 ) genPartialWeight = PartialWeight;
if ( LineWeight >= 0 ) gen16Weight = LineWeight;
if ( BulkWeight >= 0 ) genBulkWeight = BulkWeight;
sprintf( msg, "Payload weights: 1DW=%0d 2-15DW=%0d 16DW=%0d >16DW=%0d",
SingleWeight, PartialWeight, LineWeight, BulkWeight );
_INFO_MSG( msg );
} /* end setLenWeights */
/*
* setReqWeights - Set the relative frequency of memory, config, and I/O
* PIO (egress) requests
*
* Parameters:
* MemoryWeight - The relative number of memory requests
* ConfigWeight - The relative number of configuration requests
* IoWeight - The relative number of I/O requests
*
* NOTE: If a given "...Weight" is negative, then the corresponding value is
* not set.
*/
task PEUTestEnv::setReqWeights( integer MemoryWeight,
integer ConfigWeight,
integer IoWeight )
{
string msg;
if ( MemoryWeight >= 0 ) genMemWeight = MemoryWeight;
if ( ConfigWeight >= 0 ) genConfigWeight = ConfigWeight;
if ( IoWeight >= 0 ) genIoWeight = IoWeight;
sprintf( msg, "PIO request weights: Memory=%0d Config=%0d IO=%0d",
genMemWeight, genConfigWeight, genIoWeight );
_INFO_MSG( msg );
} /* end setReqWeights */
/*
* isBulkReq - Is a given TLP (header) a "bulk" memory request crossing the RCB?
*
* Parameters:
* TlpHdr - The header of the TLP in question
*
* Returned value: Non-zero if the header represents a memory read/write request
* which crosses the RCB/cache-line boundary (64B in our case)
*/
function bit PEUTestEnv::isBulkReq( bit[127:0] TlpHdr )
{
bit [63:0] addr;
if ( TlpHdr[PEC_PCI__TYPE] != PEC_PCI__TYPE_MEM )
isBulkReq = 0;
else if ( TlpHdr[PEC_PCI__LEN] == 0 )
isBulkReq = 1;
else if ( TlpHdr[PEC_PCI__LEN] > 16 )
isBulkReq = 1;
else
{
if ( TlpHdr[PEC_PCI__FMT_4DW] )
addr = TlpHdr[PEC_PCI__ADDR];
else
addr = TlpHdr[PEC_PCI__ADDR32];
isBulkReq = (TlpHdr[PEC_PCI__LEN] + addr[5:2]) > 16;
}
} /* end isBulkReq */
/*
* payloadFill - Mark a TLP's payload as being filled with a given byte
*
* Parameters:
* TlpPayload - The payload descriptor of interest
*/
task PEUTestEnv::payloadFill( var integer TlpPayload )
{
TlpPayload = TlpPayload | 32'h00002000;
}
/*
* isPayloadFill - Is a payload just the same byte over and over?
*
* Parameters:
* TlpPayload - The payload descriptor of interest
*/
function bit PEUTestEnv::isPayloadFill( integer TlpPayload )
{
isPayloadFill = ( TlpPayload & 32'h00002000 ) != 0;
}
/*
* poisonPayload - Mark a TLP's payload as being "poisoned"
*
* Parameters:
* TlpPayload - The payload descriptor of interest
*/
task PEUTestEnv::poisonPayload( var integer TlpPayload )
{
TlpPayload = TlpPayload | 32'h00001000;
}
/*
* isPayloadPoisoned - Is a TLP's payload poisoned?
*
* Parameters:
* TlpPayload - The payload descriptor of interest
*/
function bit PEUTestEnv::isPayloadPoisoned( integer TlpPayload )
{
isPayloadPoisoned = ( TlpPayload & 32'h00001000 ) != 0;
}
/*
* errorPayload - Mark a TLP's payload as having a parity error
*
* Parameters:
* TlpPayload - The payload descriptor of interest
* ErrorMask - Which (of up to eight) parity bits are in error?
*/
task PEUTestEnv::errorPayload( var integer TlpPayload,
(bit[7:0] ErrorMask = 8'b0) )
{
TlpPayload = TlpPayload | { ErrorMask, 24'h004000 };
}
/*
* isPayloadErroneous - Is a TLP's payload hampered by parity errors?
*
* Parameters:
* TlpPayload - The payload descriptor of interest
*/
function bit PEUTestEnv::isPayloadErroneous( integer TlpPayload )
{
isPayloadErroneous = ( TlpPayload & 32'h00004000 ) != 0;
}
function bit[7:0] PEUTestEnv::getPayloadErrorMask( integer TlpPayload )
{
bit[31:0] payloadDesc;
payloadDesc = TlpPayload;
getPayloadErrorMask = payloadDesc[31:24];
}
/*
* driveILU - Drive a packet into the egress port of the ILU
*
* Parameters:
* PktHdr - The packet's header in PCI-Express format
* DataAddr - The starting DOU address of the packet's payload
* DataSpec - A description of the payload
*/
task PEUTestEnv::driveILU(
bit[PEC_PCI__HDR] PktHdr,
bit[7:0] DataAddr,
integer DataSpec,
(bit Priority=0) )
{
#ifndef N2_FC
bit [7:0] poison;
bit [7:0] payloadByte;
bit payloadFill;
bit payloadErr;
bit [7:0] errMask;
integer blkCount;
integer badBlk;
string msg;
// Hold off any new request if we're in the
// middle of a soft-reset sequence.
if ( softResetPending && PktHdr[PEC_PCI__TYPE] != PEC_PCI__TYPE_CPL )
{
sync( ANY, ev_softResetEnd );
sync( ANY, ev_linkUp );
}
// Wait for the egress pipeline to
// resume if it's currently blocked.
if ( !Priority && !sync( CHECK, ev_egressUnblocked ) )
{
sync( ANY, ev_egressUnblocked );
}
/* The payload is based on the low-order
byte of the "DataSpec". */
payloadByte = DataSpec;
/* If the data is supposed to be
poisoned, then figure out which
blocks should have errors. */
poison = 0;
if ( isPayloadPoisoned(DataSpec) )
{
/* How many blocks are there? */
blkCount = (PktHdr[PEC_PCI__LEN] + 15) / 16;
/* Use the (random) "payloadByte" to
help us figure which block is
poisoned. */
badBlk = payloadByte % blkCount;
poison = 1 << badBlk;
/* ...and maybe a second block is also
very bad... */
badBlk = (payloadByte*3) % blkCount;
poison = poison | ( 1 << badBlk );
/* Is that enough? */ /*???*/
}
payloadByte = DataSpec; // The low-order byte
payloadFill = isPayloadFill( DataSpec );
payloadErr = isPayloadErroneous( DataSpec );
errMask = getPayloadErrorMask( DataSpec );
if ( payloadErr )
{
sprintf( msg, "Send TLP to ILU with incorrect data parity (tag=%h errMask=%0h payloadByte=%0h DataAddr=%0h)",
PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL ?
PktHdr[PEC_PCI__CPL_TAG] : PktHdr[PEC_PCI__TLP_TAG],
errMask, payloadByte, DataAddr );
_INFO_MSG(msg);
}
fork
f_DMUXtr.send( PktHdr,
{errMask,payloadErr,payloadFill,poison,payloadByte},
DataAddr );
sync( ANY, ev_softReset );
join any
recordNonpostReq( PktHdr );
activityCounter = activityCounter + 1;
#endif
} /* end "driveILU" */
/*
* expectILUrel - Catch release records from the ILU
*
* Parameters: None
*
* Note: "mb_ILUrelRecds" has ILU release records from the transactor
*/
task PEUTestEnv::expectILUrel()
{
#ifndef N2_FC
bit [8:0] relRecd;
// Tell the DMU xactor about the
// mailbox to be used for release recds!
f_DMUXtr.setRelMailbox( mb_ILUrelRecds );
// ...and then wait for a release
// record in the mailbox.
while( mb_ILUrelRecds != 0 )
{
void = mailbox_get( WAIT, mb_ILUrelRecds, relRecd );
activityCounter = activityCounter + 1;
//If we release the Tag too soon then there is a race condition
// when injecting parity errors
repeat(2) @(posedge CLOCK);
// Either a DOU block was released...
if ( relRecd[8] )
{
if ( !relRecd[7] ) freeCplData( relRecd[7:0] );
}
// ...or a PIO tag.
else
{
freePioTag( relRecd[7:0] );
}
}
#endif
} /* end "expectILUrel" */
/*
* expectILU - A TLP is expected from the ILU
*
* Parameters:
* PktHdr - The packet header (in PCI-Express format)
* DataSpec - An integer describing the payload (for now, the origin for an
* incrementing byte string)
*/
task PEUTestEnv::expectILU(
bit[PEC_PCI__HDR] PktHdr,
integer DataSpec,
(bit Optional=0) )
{
#ifndef N2_FC
integer tag;
// If this is a completion and if
// we're in the "drain state", then
// wait for the ILU to drain it.
//N2 - Only need 1 ReportClass static ReportClass report = new;
if (Report.get_global_print_threshold() < RPRT_DEBUG_1) {
printf("PEUTestEnv::expectILU(PktHdr=128'h%0h, DataSpec=%0d)\n", PktHdr, DataSpec);
}
tag = PktHdr[PEC_PCI__CPL_TAG];
if ( drainStateActive && PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL )
{
// Wait for the "we're done" event so that the strategy doesn't return early
if ( tag >= 0 && tag <= 31 )
sync( ANY, nonpostReqComplete[tag] );
}
else if ( !sync( CHECK, ev_drainStateEnd ) )
{
iluExpectReq = iluExpectReq + 1;
fork
f_DMUXtr.recv( PktHdr, DataSpec, Optional );
sync( ANY, ev_drainStateEnd, ev_softReset );
join any
/*
//For corner case in testbench where the UR hasn't come out and expectIdle was
// called
//If this is a completion and its still not been cleared in drain state then wait
// until the UR completion comes out and clears the nonpostReqComplete[tag]
if ( sync( CHECK, ev_drainStateEnd ) && (PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL) && (tag >= 0 && tag <= 31) ){
sync( ANY, nonpostReqComplete[tag] );
}else{
completeNonpostReq( PktHdr );
}
*/
completeNonpostReq( PktHdr );
iluExpectComplete = iluExpectComplete + 1;
activityCounter = activityCounter + 1;
}
#endif
} /* end "expectILU" */
/* N2
* drivePCIE - Tell the FNXPcieXtr to send a TLP to the PEU
*
* Parameters:
* PktHdr - The TLP's header, in PCI-Express format
* DataSpec - A specification of the packet payload
* LenAdjust - An adjustment to the number of DWs presented to the transactor
* BadParity - Where should bad parity be inserted (zero=>no bad parity)
* Priority - Should the TLP be presented even if the ingress pipe is plugged?
* Abort - Should the TLP be aborted (only) before returning?
*
* NOTE: The caller is suspended until the TLP is on its way to the PEU.
*/
task PEUTestEnv::drivePCIE(
bit[PEC_PCI__HDR] PktHdr,
bit [63:0] DataSpec,
(integer LenAdjust=0),
(integer BadParity=0),
(bit Priority=0),
(bit Abort=0),
(bit CfgRdCpl=0),
(bit isDmaReq=0),
(bit null_tlp=0) )
{
//N2 PECXtrDataTLP tlpPkt;
//N2 PECXtrDataTLP badPkt;
FNXPCIEXactorTransaction PCIETlpTrans;
FNXPCIEXactorTransaction PCIEDllpTrans;
FNXPCIEXactorTransaction PCIEDllpTrans2;
integer status1, status2;
integer hdrLen;
integer dataLen;
integer xtrLen;
integer tlpGap;
integer pickit;
integer idleChance;
integer badPtyDW;
integer i;
bit [7:0] pyldByteAry[*];
bit [11:0] NakSeqNmbr1 = 0;
bit [11:0] NakSeqNmbr2 = 0;
bit [11:0] nakSent = 0;
integer RcvrErrInjected = 0;
bit donot_increment_nmbrRcvrErrsInjected = 0; // indicator to not increment total rcv error number if
// not injecting rcvrduplicateseqnumber when it's selected in randcase
// for random injection of ECRC
bit inject_ECRC = 0;
// ECRC related
randcase {
inject_ECRC_weight : inject_ECRC = 1;
10 : inject_ECRC = 0;
}
// end ECRC related
Report.report(RTYP_DEBUG_3,"PEUTestEnv::drivePCIE(PktHdr=128'h%0h, DataSpec=%0d, LenAdjust=%0d, BadParity=%0d)\n", PktHdr, DataSpec, LenAdjust, BadParity);
// If this is a completion to a
// non-posted PIO request and if we're
// in the "drain state", then don't
// present it to the PEU... it might be
// flagged as an unsolicited completion
// since the PEU never saw the request.
//N2-review Check This
if ( (drainStateActive && PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL) ||
sync( CHECK, ev_removePcie) )
{
return;
}
// If the ingress pipeline is suspended,
// then wait for someone to unblock it.
// Don't block a "priority" TLP
if ( !Priority && !sync( CHECK, ev_ingressUnblocked ) )
{
sync( ANY, ev_drainStateEnd, ev_softReset, ev_ingressUnblocked );
}
if ( Priority ){
printf( "Sending priority TLP (tag=%h)\n", PktHdr[PEC_PCI__CPL_TAG] );
}
// Bail out if we've been in the "drain state" or if a soft reset is underway.
// Any strategy trying to send a request is held
// in "reserveIngressCredits".
if ( sync( CHECK, ev_drainStateEnd ) || softResetPending ||
sync( CHECK, ev_removePcie) )
{
return;
}
// How big is the header and payload?
hdrLen = 3 + PktHdr[PEC_PCI__FMT_4DW];
if ( PktHdr[PEC_PCI__FMT_DATA] )
{
dataLen = PktHdr[PEC_PCI__LEN];
if ( dataLen == 0 ) dataLen = 1024;
}
else
dataLen = 0;
if ( PktHdr[PEC_PCI__TD] ) dataLen = dataLen + 1;
// And how big is the TLP that we'll
// give to the transactor?
xtrLen = hdrLen + dataLen + LenAdjust;
if ( xtrLen < 1 ) xtrLen = 2;
// Get a PCIE Transaction to give to the xactor.
PCIETlpTrans = new( Pod.FNXPCIEBldr );
PCIETlpTrans.SetID( f_ID.NextTransID() );
// ...and shove in the header data,
// ...and whatever payload is expected.
ConvertHdr2PcieTlp( PktHdr,
DataSpec,
PCIETlpTrans,
LenAdjust,
isDmaReq);
//Don't adjust the payload if this is a length error being sent
if ( CfgRdCpl && (PktHdr[PEC_PCI__LEN] == 1) ) //DANGER IOS FC - Do NOT execute this
{
#ifndef N2_FC
//If this is a completion for a config read
//Delete the data generated in ConvertHdr2PcieTlp
PCIETlpTrans.MyPacket.Pyld.delete();
pyldByteAry = new[4];
//and put in the right byte swapped payload
for(i=0; i < 4 ; i++){
pyldByteAry[3-i] = DataSpec + i;
}
PCIETlpTrans.MyPacket.SetPyld( pyldByteAry );
#else
bit [7:0] tmpByteAry[*];
tmpByteAry = new[4];
//Get the data generated in ConvertHdr2PcieTlp
PCIETlpTrans.MyPacket.GetPyld( pyldByteAry );
//and put it in the right byte swapped order
for(i=0; i < 4 ; i++){
tmpByteAry[3-i] = pyldByteAry[i];
}
PCIETlpTrans.MyPacket.Pyld.delete();
PCIETlpTrans.MyPacket.SetPyld( tmpByteAry );
#endif
}
/* N2 review Test this
// increase the payload length of the packet by LenAdjust if needed
for ( i=hdrLen+dataLen; i<xtrLen; i++ )
{
tlpPkt._TLP[i] = nextPayloadDW( DataSpec );
}
*/
/* N2 - review- Need to test this
// Specify a LPU parity error, if requested
// A negative "BadParity" means "from the end of the packet"
for ( i=0; i<xtrLen; i++ ) tlpPkt._badParity[i] = 4'b0000;
if ( BadParity > 0 && BadParity <= xtrLen*4 )
{
badPtyDW = (BadParity-1)/4;
tlpPkt._badParity[badPtyDW] = 4'b1000 >> ((BadParity-1)%4);
}
else if ( BadParity < 0 && BadParity >= -(xtrLen*4) )
{
badPtyDW = xtrLen + (BadParity+1)/4 - 1;
tlpPkt._badParity[badPtyDW] = 4'b0001 << (((-BadParity)-1)%4);
}
else if ( BadParity != 0 )
{
badPtyDW = localRandom( xtrLen );
tlpPkt._badParity[badPtyDW] = localRandomRange(1,15);
}
*/
//N2 ingressThrottle - no control over idles between PEU and PTL(TLU)
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// Add some gas to the end of the TLP.
// N2 - Delay is before PCIETlpTrans gets driven
tlpGap = localRandomRange(minIngressGap,maxIngressGap);
// If we're really lucky, send a aborted
// copy of this packet to the TLU.
// But don't play games if this is a completion and we're expecting a time-out
//N2 Abort & ingressAbortRate should always be 0
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//If this is a completion then put it in the front of the Denali User Queue
// so an unexpected completion timeout doesn't happen
if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL ){
PCIETlpTrans.MyPacket.DriveImmediately = 1;
}
// The PCIETlpTrans returns when the packet is
// completely driven on serial links
// Don't submit the TLP if we're about to reset.
// And if there is a reset pending, hang out until it happens.
if ( Priority )
printf( "Calling xtr for TLP (tag=%h)\n", PktHdr[PEC_PCI__CPL_TAG] );
fork
{
// if null tlp, then set denaliErr
if (null_tlp) {
PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_TLP_NULL;
InvertLCRCAndEDBErr = 1;
Report.report(RTYP_DEBUG_3,"PEUTestEnv.drivePCIE is called with null_tlp = %d", null_tlp);
}
// do not inject error in cpl package. bench/denali drops package then
if ( PktHdr[PEC_PCI__TYPE] !== PEC_PCI__TYPE_CPL ) {
// if inject ECRC and TD = 1, then set denali to generate ECRC
if (inject_ECRC && (PktHdr[PEC_PCI__TD] == 1)) {
PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_TLP_ENABLE_ECRC;
Report.report(RTYP_DEBUG_3,"PEUTestEnv.drivePCIE is called with TD =1 and ECRC inject at time %d \n", get_time(LO));
}
}
//If enabled then drive packet with a physical error
// after a NAK is sent the packet will be retried by Denali without the error
if( enableRcvrErrInjection && (nmbrRcvrErrsToInject > nmbrRcvrErrsInjected) ){
//Not every packet gets an error
if( urandom()%100 < rcvrErrPct ){
randcase{
rcvrErr8b10bWeight: { PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_8B10B;
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_8B10B );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_DATA0 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_RSV_KC );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_TLP_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_SDP1 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_DLLP_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_PAD );
rcvrErr8b10bInjected += 1;
}
rcvrErrFramingWeight: { PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_FRAME;
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_DATA0 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_RSV_KC );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_TLP_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_SDP1 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_DLLP_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_PAD );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_MOS_FTS_NC );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_EDB );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_MOS_SKP_NC );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_LIDLE );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_MOS_IDL_NC );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_STP1 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_SDP1 );
rcvrErrFramingInjected += 1;
}
rcvrErrDisparityWeight: { PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_DISPARITY;
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_DISP );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_TLP_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_DATA0 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_PAD );
rcvrErrDisparityInjected += 1;
}
rcvrErrFlipBitWeight: { PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_FLIP_1BIT;
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_8B10B );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_DATA0 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_RSV_KC );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_TLP_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_SDP1 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_DLLP_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_PAD );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_DISP );
rcvrErrFlipBitInjected += 1;
}
rcvrErrLcrcWeight: { PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_LCRC;
rcvrErrLcrcInjected += 1;
}
// do not want to inject DupSeqNmbr error in two consecutive packages so
// use this scheme
// Since completions get added to the front of the Denali user queue then that
// was allowing 2 packets in a row to get the error injected so just
// don't let the error be injected in completions
rcvrErrDupSeqNmbrWeight: {
if ( PktHdr[PEC_PCI__TYPE] !== PEC_PCI__TYPE_CPL ){
donot_increment_nmbrRcvrErrsInjected = 0;
if (rcvrErrSeqNmbrErr_toinject == 0 &&
rcvrErrSeqNmbrErr_justinjected == 0) {
rcvrErrSeqNmbrErr_toinject = 1;
PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_DL_SEQ_DUP;
rcvrErrDupSeqNmbrInjected += 1;
}
// else inidcates no error inject so don't increment nmbrRcvrErrsInjected
else {
donot_increment_nmbrRcvrErrsInjected = 1;
if (rcvrErrSeqNmbrErr_justinjected == 1) {
rcvrErrSeqNmbrErr_justinjected = 0;
}
}
}else{
//If its a compleiton then don't inject the error
donot_increment_nmbrRcvrErrsInjected = 1;
}
}
rcvrErrOutOfSeqNmbrWeight: {
if ( PktHdr[PEC_PCI__TYPE] !== PEC_PCI__TYPE_CPL ){
donot_increment_nmbrRcvrErrsInjected = 0;
if( rcvrErrSeqNmbrErr_toinject == 0 &&
rcvrErrSeqNmbrErr_justinjected == 0) {
rcvrErrSeqNmbrErr_toinject = 1;
PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_DL_SEQ_INCR;
rcvrErrOutOfSeqNmbrInjected += 1;
}
// else indicates no error inject so don't increment nmbrRcvrErrsInjected
else {
donot_increment_nmbrRcvrErrsInjected = 1;
if (rcvrErrSeqNmbrErr_justinjected == 1) {
rcvrErrSeqNmbrErr_justinjected = 0;
}
}
}else{
//If its a compleiton then don't inject the error
donot_increment_nmbrRcvrErrsInjected = 1;
}
}
rcvrErrBadSeqNmbrWeight: {
if ( PktHdr[PEC_PCI__TYPE] !== PEC_PCI__TYPE_CPL ){
donot_increment_nmbrRcvrErrsInjected = 0;
if( rcvrErrSeqNmbrErr_toinject == 0 &&
rcvrErrSeqNmbrErr_justinjected == 0) {
rcvrErrSeqNmbrErr_toinject = 1;
PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_DL_SEQ_RNDM;
rcvrErrBadSeqNmbrInjected += 1;
}
// else indicates no error inject so don't increment nmbrRcvrErrsInjected
else {
donot_increment_nmbrRcvrErrsInjected = 1;
if (rcvrErrSeqNmbrErr_justinjected == 1) {
rcvrErrSeqNmbrErr_justinjected = 0;
}
}
}else{
//If its a compleiton then don't inject the error
donot_increment_nmbrRcvrErrsInjected = 1;
}
}
InvertLCRCErrWeight : {invertLCRC32 = 1;
PCIETlpTrans.MyPacket.invertLCRC32 = 1;
invertLCRC32ErrInjected +=1;
}
EDBErrWeight : {set_endsymbol_EDB = 1 ;
PCIETlpTrans.MyPacket.set_endsymbol_EDB = 1;
EDBErrInjected +=1;
PCIETlpTrans.tempSuppressDenaliErr(PCIE_PL_NONFATAL_FRAME_NULL_TLP );
}
// note: this mode is not used in receiver error strategy, been move to null strategy
InvertLCRCAndEDBErrWeight: { // invertLCRC32 = 1; set_endsymbol_EDB = 1;
// PCIETlpTrans.MyPacket.invertLCRC32 = 1;
// PCIETlpTrans.MyPacket.set_endsymbol_EDB = 1;
// PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_TLP_NULL;
// InvertLCRCAndEDBErr = 1;
// PCIETlpTrans.tempSuppressDenaliErr(PCIE_PL_NONFATAL_FRAME_NULL_TLP );
}
}
if (donot_increment_nmbrRcvrErrsInjected == 0 ) {
nmbrRcvrErrsInjected += 1;
RcvrErrInjected = 1;
}
}
}
if( !softResetPending ){
PCIETlpTrans.Drive( tlpGap );
// Check for a NAK
fork
if( (RcvrErrInjected == 1) ){
nmbrRcvrErrsDriven +=1;
Report.report(RTYP_DEBUG_3,"PEUTestEnv::drivePCIE Env Receiver Error injected nmbrRcvrErrsToInject=%0d nmbrRcvrErrsInjected=%0d nmbrRcvrErrsDriven=%0d\n",nmbrRcvrErrsToInject,nmbrRcvrErrsInjected,nmbrRcvrErrsDriven );
//Signal that the last error was injected
if( nmbrRcvrErrsToInject == nmbrRcvrErrsDriven ){
trigger( ONE_SHOT, ev_rcvrErrsDriven );
}
case( PCIETlpTrans.MyPacket.DenaliErr ){
/* Moved unSuppressDenaliErr to ilupeuIngressRcvrErr
PCIE_EI_8B10B: PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_8B10B );
PCIE_EI_FRAME: {PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_END );
PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_DATA0 );
PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_RSV_KC );
PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_TLP_END );
PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_SDP1 );
PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_DLLP_END );
}
PCIE_EI_DISPARITY:{ PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_SYM_DISP );
PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_TLP_END );
PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_END );
PCIETlpTrans.unSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_DATA0 );
}
PCIE_EI_FLIP_1BIT:{PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_DATA0 );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_BAD_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_TLP_END );
PCIETlpTrans.tempSuppressDenaliErr( PCIE_PL_NONFATAL_FRAME_PAD );
}
*/
PCIE_EI_DL_SEQ_DUP:{
if (rcvrErrSeqNmbrErr_toinject == 1) {
rcvrErrSeqNmbrErr_toinject = 0;
rcvrErrSeqNmbrErr_justinjected = 1;
}
}
PCIE_EI_DL_SEQ_INCR:{
if (rcvrErrSeqNmbrErr_toinject == 1) {
rcvrErrSeqNmbrErr_toinject = 0;
rcvrErrSeqNmbrErr_justinjected = 1;
}
}
PCIE_EI_DL_SEQ_RNDM:{
if (rcvrErrSeqNmbrErr_toinject == 1) {
rcvrErrSeqNmbrErr_toinject = 0;
rcvrErrSeqNmbrErr_justinjected = 1;
}
}
}
// no NAK for invertLCRC & EDB case, all others, expect NAK
if (!(InvertLCRCAndEDBErr)) {
if( nakExpected == 0 ){
nakExpected += 1;
//and check for a NAK being sent
//Get the sequence number from transmitted packet
NakSeqNmbr1 = PCIETlpTrans.MyPacket.DLLFrmSeqNum - 1;
NakSeqNmbr2 = PCIETlpTrans.MyPacket.DLLFrmSeqNum;
//Since disparity errors can occur on the next transmitted packet
// then set another NAK expect for the next sequence number
fork
{
PCIEDllpTrans = new( Pod.FNXPCIEBldr );
PCIEDllpTrans.SetID( f_ID.NextTransID() );
PCIEDllpTrans.MyPacket.PktType = FNX_PCIE_XTR_PKT_TYPE_DLLP;
PCIEDllpTrans.MyPacket.DllpType = FNX_PCIE_XTR_DLLP_TYPE_NAK;
PCIEDllpTrans.MyPacket.AckNakSeqNum = NakSeqNmbr1;
// time = %0d, fork off wait for Nak of seqNum = %0d", get_time(LO), NakSeqNmbr1);
status1 = PCIEDllpTrans.ExpectExpire( 200 );
if( status1 ){ //If transactin was not removed or didn't fail
nakSent = NakSeqNmbr1;
}
}
{
PCIEDllpTrans2 = new( Pod.FNXPCIEBldr );
PCIEDllpTrans2.SetID( f_ID.NextTransID() );
PCIEDllpTrans2.MyPacket.PktType = FNX_PCIE_XTR_PKT_TYPE_DLLP;
PCIEDllpTrans2.MyPacket.DllpType = FNX_PCIE_XTR_DLLP_TYPE_NAK;
PCIEDllpTrans2.MyPacket.AckNakSeqNum = NakSeqNmbr2;
// time = %0d, fork off wait for 2nd Nak of seqNum = %0d", get_time(LO), NakSeqNmbr2);
status2 = PCIEDllpTrans2.ExpectExpire( 200 );
if( status2 ){ //If transactin was not removed or didn't fail
nakSent = NakSeqNmbr2;
}
}
join any
if( nakSent == NakSeqNmbr1 ){
void = PCIEDllpTrans2.Remove();
//Wait until replayed packet has been transmitted
PCIETlpTrans.MyPacket.SyncReplayEnd();
}
if( nakSent == NakSeqNmbr2 ){
void = PCIEDllpTrans.Remove();
//Wait until the current transmitted seq number retry packet
while( Pod.FNXPCIEBldr.SignalInterface.currentSeqNum !== NakSeqNmbr2 ){
@( posedge CLOCK );
}
}
nakExpected -= 1;
}
}
}
join none
}else{
sync( ANY, ev_softReset );
}
}
{
sync( ANY, ev_softReset, ev_removePcie );
}
{
sync( ANY, ev_removePcie );
//Mark packets still stuck in the Denali User Queue to be Discarded
//PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_DISCARD;
}
join any
activityCounter = activityCounter + 1;
if ( Priority )
printf( "Xtr has sent priority TLP (tag=%h)\n", PktHdr[PEC_PCI__CPL_TAG] );
/* N2 - review- Need to test this
// If we just inserted bad parity into a TLP header, then the bad DW
// might also appear as padding for the prior TLP.
if ( BadParity != 0 && !softResetPending )
{
_DEBUG_MSG( "PEUTestEnv (cycle %0d) %s (offset=%0d)\n", get_cycle(),
"Inject bad ingress TLP parity",
BadParity > 0 ? (BadParity-1) : (xtrLen*4 + BadParity + 1) );
if ( badPtyDW < 3 )
this.f_DMUXtr.ignoreUnusedParity();
}
*/
//Good from here down
if ( LenAdjust != 0 )
_INFO_MSG( psprintf("TLP length adjusted by %0d DWs", LenAdjust) );
// Bump ingress performance counters...
if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM )
{
if ( PktHdr[PEC_PCI__FMT_DATA] )
perfCtr_dmaWrite = perfCtr_dmaWrite + 1;
else
perfCtr_dmaRead = perfCtr_dmaRead + 1;
}
if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL )
perfCtr_pioCpl = perfCtr_pioCpl + 1;
//2.0 PRM spec needs to be updated since PEU counter is only counting incoming DMAs data
// and not PIO completions
if ( PktHdr[PEC_PCI__FMT_DATA] && PktHdr[PEC_PCI__TYPE] !== PEC_PCI__TYPE_CPL )
perfCtr_recvDWs = perfCtr_recvDWs + PktHdr[PEC_PCI__LEN];
if ( (PktHdr[PEC_PCI__TYPE]& ~PEC_PCI__TYPE_MSG_RC_MASK) == PEC_PCI__TYPE_MSG)
{
if ( PktHdr[PEC_PCI__MSG_CODE] == PEC_PCI__MSG_CODE_VENDOR_TYPE_0 )
{
if ( !PktHdr[PEC_PCI__FMT_DATA] ) coverageVector[0] = 1;
if ( PktHdr[PEC_PCI__FMT_DATA] ) coverageVector[1] = 1;
}
if ( PktHdr[PEC_PCI__MSG_CODE] == PEC_PCI__MSG_CODE_VENDOR_TYPE_1 )
{
if ( !PktHdr[PEC_PCI__FMT_DATA] ) coverageVector[2] = 1;
if ( PktHdr[PEC_PCI__FMT_DATA] ) coverageVector[3] = 1;
}
if ( PktHdr[PEC_PCI__EP] ) coverageVector[4] = 1;
if ( !PktHdr[PEC_PCI__FMT_4DW] ) coverageVector[12] = 1;
}
else if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM )
{
if ( PktHdr[PEC_PCI__EP] )
{
if ( !PktHdr[PEC_PCI__FMT_DATA] ) coverageVector[5] = 1;
if ( PktHdr[PEC_PCI__FMT_DATA] ) coverageVector[6] = 1;
}
}
else if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL )
{
if ( PktHdr[PEC_PCI__EP] )
{
if ( !PktHdr[PEC_PCI__FMT_DATA] ) coverageVector[7] = 1;
if ( PktHdr[PEC_PCI__FMT_DATA] ) coverageVector[8] = 1;
}
}
else
{
if ( PktHdr[PEC_PCI__EP] ) coverageVector[9] = 1;
}
if ( xtrLen == 1 ) coverageVector[10] = 1;
if ( xtrLen == 2 ) coverageVector[11] = 1;
// If we just completed our "stalling"
// Config/IO write, then we're free!!
if ( stallNpstWrPending
&& PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL
&& PktHdr[PEC_PCI__CPL_TAG] == stallNpstWrTag )
{
stallNpstWrPending = 0;
_INFO_MSG( "Completion for non-posted PIO write request submitted" );
}
} /* end "drivePCIE" */
/* N2
* expectPCIE - Tell the FNXPcieXtr to expect a TLP
*
* Parameters:
* PktHdr - The TLP's header, in PCI-Express format
* DataSpec - A specification of the packet payload
*/
task PEUTestEnv::expectPCIE(
bit[PEC_PCI__HDR] PktHdr,
bit [63:0] DataSpec,
bit IgnoreTlpReqTag = 0,
(bit isDmaReq=0),
(integer dma_ptr=0) )
{
//N2 PECXtrDataTLP tlpPkt;
FNXPCIEXactorTransaction PCIETlpTrans;
bit[127:0] nextPktHdr;
integer nextCplSeq;
integer nextReqSeq;
integer hdrLen;
integer dataLen;
integer i;
// integer expectCompleteTO;
string msg;
bit[4:0] tag;
event never;
event reqComplete = null;
bit [7:0] ExpectedReqTag;
// If we're in the drain state, then
// this baby will never come out (or
// at least it shouldn't).
if ( drainStateActive || softResetPending ) return;
// The transmitter's ID used to be always zero when simulating gates...
// if ( get_plus_arg(CHECK, "sim_type=gates") )
// PktHdr[ PEC_PCI__REQ_ID ] = 0;
// Add this TLP to the queue of
// requests/completions expected from
// the PEU.
void = semaphore_get( WAIT, sm_mutex, 1 );
egressLastSeq = egressLastSeq + 1;
if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL
|| PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL_LK )
{
//printf( "PEUTestEnv::expectPCIE - putting %h into mb_egressCplOrder mailbox\n", PktHdr );
mailbox_put( mb_egressCplOrder, PktHdr );
mailbox_put( mb_egressCplSeq, egressLastSeq );
}
else
{
mailbox_put( mb_egressReqOrder, PktHdr );
mailbox_put( mb_egressReqSeq, egressLastSeq );
}
semaphore_put( sm_mutex, 1 );
// How big is the header and payload?
hdrLen = 3 + PktHdr[PEC_PCI__FMT_4DW];
if ( PktHdr[PEC_PCI__FMT_DATA] )
dataLen = PktHdr[PEC_PCI__LEN];
else
dataLen = 0;
// Get a PCIE Transaction to give to the xactor.
PCIETlpTrans = new( Pod.FNXPCIEBldr );
PCIETlpTrans.SetID( f_ID.NextTransID() );
// ...and shove in the header data,
// ...and whatever payload is expected.
ConvertHdr2PcieTlp( PktHdr,
DataSpec,
PCIETlpTrans,
*,
isDmaReq,
dma_ptr );
PCIETlpTrans.MyPacket.IgnoreTlpReqTag = IgnoreTlpReqTag;
/* N2 review Test this later
// Expect a parity error if one was inserted.
tlpPkt._abort = 1'b0;
if ( isPayloadErroneous(DataSpec) )
tlpPkt._status = PC_TLP_STATUS_DATA_PARITY_ERROR;
else
tlpPkt._status = PC_TLP_STATUS_NO_ERROR;
*/
// The xactor returns when it has seen
// the TLP. And force an exit if we receive
// a "reqComplete" for a nonposted request.
tag = PktHdr[PEC_PCI__TLP_TAG];
trigger( OFF, never );
if ( isNonpostReq(PktHdr) ) {
reqComplete = nonpostReqComplete[ tag ];
}
else
reqComplete = never;
this.peuExpectTlp = this.peuExpectTlp + 1;
if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL )
this.peuExpectCpl = this.peuExpectCpl + 1;
else
this.peuExpectReq = this.peuExpectReq + 1;
//N2 Big fork-join here since I can't stop the egress pipeline
// allow the expects to finish even if in drain state
fork
{
void = PCIETlpTrans.Expect( expectCompleteTO );
if( !sync( CHECK, ev_removePcie ) ){ //Order doesnt matter if expect packets are removed
// Make sure that this TLP is the one
// we expected next from the PEU!
if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL
|| PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL_LK )
{
nextPktHdr = 128'b0;
void = mailbox_get( NO_WAIT, mb_egressCplOrder, nextPktHdr );
//printf( "PEUTestEnv::expectPCIE - got %h out of mb_egressCplOrder mailbox\n", nextPktHdr );
void = mailbox_get( NO_WAIT, mb_egressCplSeq, nextCplSeq );
if ( mailbox_get( NO_WAIT, mb_egressReqSeq ) )
void = mailbox_get( COPY_NO_WAIT, mb_egressReqSeq, nextReqSeq );
else
nextReqSeq = nextCplSeq;
if ( nextPktHdr != PktHdr )
{
#ifndef N2_FC
#ifndef N2_IOS
_REPORT_ERROR( "CRAMP! Out-of-order completion received from PEU!" );
sprintf( msg,"Expect: %h\n", nextPktHdr );
_ERROR_INFO( msg );
sprintf( msg,"Actual: %h\n", PktHdr );
_ERROR_INFO( msg );
#endif
#endif
}
else if ( !egressCplOK && nextReqSeq < nextCplSeq
&& !stallNpstWr
&& !egressPostStarved && !egressNonpostStarved )
{
egressReqOK = 1;
egressBadCount = egressBadCount + 1;
printf( "egressBadCount = %0d\n", egressBadCount );
if ( egressBadCount > 4 )
_REPORT_ERROR( "CRAMP! Completion violates round-robin arbitration!" );
}
else
{
egressReqOK = 1;
egressCplOK = 1;
//N2 || stallNpstWr
//N2 || egressPostStarved
//N2 || egressNonpostStarved;
egressBadCount = 0;
}
}
else
{
void = mailbox_get( NO_WAIT, mb_egressReqOrder, nextPktHdr );
void = mailbox_get( NO_WAIT, mb_egressReqSeq, nextReqSeq );
if ( mailbox_get( NO_WAIT, mb_egressCplSeq ) )
void = mailbox_get( COPY_NO_WAIT, mb_egressCplSeq, nextCplSeq );
else
nextCplSeq = nextReqSeq;
if ( nextPktHdr != PktHdr )
{
#ifndef N2_FC
_REPORT_ERROR( "CRAMP! Out-of-order request received from PEU!" );
sprintf( msg,"Expect: %h\n", nextPktHdr );
_ERROR_INFO( msg );
sprintf( msg,"Actual: %h\n", PktHdr );
_ERROR_INFO( msg );
#endif
}
else if ( !egressReqOK && nextCplSeq < nextReqSeq
&& !egressCompletionStarved )
{
egressCplOK = 1;
egressBadCount = egressBadCount + 1;
printf( "egressBadCount = %0d\n", egressBadCount );
if ( egressBadCount > 4 )
_REPORT_ERROR( "CRAMP! PIO request violates round-robin arbitration!" );
}
else
{
egressCplOK = 1;
egressReqOK = 1;
//N2 || egressCompletionStarved;
egressBadCount = 0;
}
}
// Make sure that the PEU didn't violate
// credit restrictions, and make
// arrangements for those credits to be
// returned (eventually).
// No credits are consumed if the TLP
// was aborted due to a parity error.
//N2 if ( !PktHdr[PEC_PCI__FMT_DATA] || !isPayloadErroneous(DataSpec) )
//N2 if ( !f_LPUXtr.usePCIE )
if ( !sync( CHECK, ev_removePcie ) ){
consumeEgressCredits( PktHdr );
}
// If we're waiting for a non-posted write
// to complete, then there shouldn't be any
// other request! Cplns are OK...
if ( stallNpstWrPending
&& PktHdr[PEC_PCI__TYPE] != PEC_PCI__TYPE_CPL
&& PktHdr[PEC_PCI__TYPE] != PEC_PCI__TYPE_CPL_LK )
{
_REPORT_ERROR( "PIO request dispatched when nonposted write is pending" );
}
if ( stallNpstWr
&& PktHdr[PEC_PCI__FMT_DATA]
&& ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CFG0
|| PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CFG1
|| PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_IO ) )
{
stallNpstWrPending = 1;
stallNpstWrTag = PktHdr[PEC_PCI__TLP_TAG];
_INFO_MSG( psprintf( "Non-posted PIO write request dispatched... tag=%h",
stallNpstWrTag ) );
}
}//End if ( !sync( CHECK, ev_removePcie )
}
{
sync( ANY, ev_softReset, ev_removePcie );
//Since soft reset means no more transactions will be sent
// remove any outstanding expects that would timeout later
void = PCIETlpTrans.Remove();
}
{
sync( ANY, reqComplete, ev_drainStateEnd );
}
join any
//End N2 Big fork-join
#ifdef N2_FC
//Added in v 1.155 but it causes some tests to fail
// in PEU. The ilupeuLnkTrnFstx8x8LinkDownRetrainLink fails after the
// 1st warm reset because CSR daemon access quit working. ifdef around
// for right now.
// kill the other threads
terminate;
#endif
// Grab ReqTag so we can send completion with it
ReceivedReqTag = PCIETlpTrans.MyPacket.ReceivedReqTag;
#ifdef N2_FC
if ( (PCIETlpTrans.MyPacket.CmnType == FNX_PCIE_XTR_TYPE_IOWR ||
PCIETlpTrans.MyPacket.CmnType == FNX_PCIE_XTR_TYPE_CFGWR0 ||
PCIETlpTrans.MyPacket.CmnType == FNX_PCIE_XTR_TYPE_CFGWR1 ||
PCIETlpTrans.MyPacket.CmnType == FNX_PCIE_XTR_TYPE_MWR) &&
PCIETlpTrans.MyPacket.CmnFmt[FNX_PCIE_XTR_FMT_DATA_SLC])
{
bit [4:0] CmdType = PCIETlpTrans.MyPacket.CmnType;
bit [63:0] fcaddr = 0;
bit [63:0] piodata = 0;
if( PCIETlpTrans.MyPacket.CmnFmt[FNX_PCIE_XTR_FMT_64BIT_SLC] ){
fcaddr = {PCIETlpTrans.MyPacket.AddrUpper, PCIETlpTrans.MyPacket.AddrLower, 2'b0};
}
else {
fcaddr = {32'b0, PCIETlpTrans.MyPacket.AddrLower, 2'b0};
}
if (CmdType == FNX_PCIE_XTR_TYPE_IORD) {
fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_IOCFG_FLD] | 32'h10000000;
}
else if (CmdType == FNX_PCIE_XTR_TYPE_CFGRD0 ||
CmdType == FNX_PCIE_XTR_TYPE_CFGRD1) {
fcaddr = {PCIETlpTrans.MyPacket.CfgBusNum,
PCIETlpTrans.MyPacket.CfgDeviceNum,
PCIETlpTrans.MyPacket.CfgFuncNum,
PCIETlpTrans.MyPacket.CfgExtRegNum,
PCIETlpTrans.MyPacket.CfgRegNum, 2'b0};
fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_IOCFG_FLD];
}
else if( PCIETlpTrans.MyPacket.CmnFmt[FNX_PCIE_XTR_FMT_64BIT_SLC] ) {
//fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_MEM64_FLD];
}
else {
fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_MEM32_FLD];
}
for(i=0; i < PCIETlpTrans.MyPacket.Pyld.size() ; i++){
piodata[63-(i*8):64-((i+1)*8)] = PCIETlpTrans.MyPacket.Pyld[i];
}
// in order to not violate ordering rules, store data to sparce mem
// now rather then when the pio is detected at the ncu
QuickReport( Report, RTYP_DEBUG_1,
"UDEBUG PEUTestEnv::expectPCIE PIO Write : addr %0h, pyldsize %d data %0h\n",
fcaddr, PCIETlpTrans.MyPacket.Pyld.size(),
(PCIETlpTrans.MyPacket.Pyld.size() < 8) ? piodata[63:32] : piodata
);
N2fcWrMem (fcAddrMsk | fcaddr, piodata[63:32], PCIETlpTrans.MyPacket.BEFirstDW);
if (PCIETlpTrans.MyPacket.Pyld.size() == 8)
N2fcWrMem (fcAddrMsk | fcaddr + 4, piodata[31:0], PCIETlpTrans.MyPacket.BELastDW );
}
else {
if ( !(PCIETlpTrans.MyPacket.CmnType >= FNX_PCIE_XTR_TYPE_CPL &&
PCIETlpTrans.MyPacket.CmnType <= FNX_PCIE_XTR_TYPE_CPLDLK) ) {
bit [4:0] CmdType = PCIETlpTrans.MyPacket.CmnType;
bit [63:0] fcaddr = 0;
if( PCIETlpTrans.MyPacket.CmnFmt[FNX_PCIE_XTR_FMT_64BIT_SLC] ){
fcaddr = {PCIETlpTrans.MyPacket.AddrUpper, PCIETlpTrans.MyPacket.AddrLower, 2'b0};
}
else {
fcaddr = {32'b0, PCIETlpTrans.MyPacket.AddrLower, 2'b0};
}
if (CmdType == FNX_PCIE_XTR_TYPE_IORD) {
fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_IOCFG_FLD] | 32'h10000000;
}
else if (CmdType == FNX_PCIE_XTR_TYPE_CFGRD0 ||
CmdType == FNX_PCIE_XTR_TYPE_CFGRD1) {
fcaddr = {PCIETlpTrans.MyPacket.CfgBusNum,
PCIETlpTrans.MyPacket.CfgDeviceNum,
PCIETlpTrans.MyPacket.CfgFuncNum,
PCIETlpTrans.MyPacket.CfgExtRegNum,
PCIETlpTrans.MyPacket.CfgRegNum, 2'b0};
fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_IOCFG_FLD];
}
else if( PCIETlpTrans.MyPacket.CmnFmt[FNX_PCIE_XTR_FMT_64BIT_SLC] ) {
//fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_MEM64_FLD];
}
else {
fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_MEM32_FLD];
}
fcAddrArray[ReceivedReqTag] = fcaddr;
QuickReport( Report, RTYP_INFO,"UDEBUG PEUTestEnv::expectPCIE save completion Addr = %0h Tag = %0h\n",
fcAddrArray[ReceivedReqTag], ReceivedReqTag);
}
}
#endif
// if ( PktHdr[PEC_PCI__FMT_DATA] )
if ( PktHdr[PEC_PCI__FMT_DATA] && PktHdr[PEC_PCI__TYPE] === PEC_PCI__TYPE_CPL )
perfCtr_xmitDWs = perfCtr_xmitDWs + PktHdr[PEC_PCI__LEN];
this.peuExpectComplete = this.peuExpectComplete + 1;
if ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL )
this.peuExpectCpl = this.peuExpectCpl - 1;
else
this.peuExpectReq = this.peuExpectReq - 1;
activityCounter = activityCounter + 1;
// If this was a nonposted PIO request,
// then remember that we've sent it.
#ifndef N2_FC
dispatchNonpostReq( PktHdr );
#endif
// Don't worry about violating
// credit restrictions if we're in the
// "drain state"... we're just faking
// out the strategy anyway.
if ( sync( CHECK, ev_drainStateEnd ) ) return;
if ( sync( CHECK, reqComplete ) ) return;
// If we're in the middle of a soft reset,
// then free the DOU blocks associated with
// a DMA completion. Since we don't know
// which ones are involved, free them all.
if ( sync( CHECK, ev_softReset ) )
{
for ( i=0; i<32; i++ )
if ( douBlksUsed[i] ) freeCplData( i*4 );
trigger( ON, ev_douBlkFreed );
return;
}
} /* end "expectPCIE" */
/*
* nextPayloadDW - Obtain the next DW of payload, given a "spec"
*
* Parameters:
* DataSpec - A specification of the packet payload
*/
function bit[31:0] PEUTestEnv::nextPayloadDW(
var integer DataSpec )
{
bit [7:0] dataByte;
bit [31:0] dataDW;
integer j;
if ( isPayloadPoisoned(DataSpec) || isPayloadErroneous(DataSpec) )
dataDW = 32'hXXXXXXXX;
else
{
dataByte = DataSpec;
dataDW = 32'b0;
for ( j=0; j<4; j++ )
{
dataDW = { dataDW[23:0], dataByte };
if ( !isPayloadFill( DataSpec ) ) dataByte = dataByte + 1;
}
if ( !isPayloadFill( DataSpec ) ) DataSpec = dataByte;
}
nextPayloadDW = dataDW;
} /* end "nextPayloadDW" */
/*
* allocWrTag - Allocate a tag (and starting DOU address) for a PIO write request
*
* Parameters:
* TlpTag - The allocated tag
* DataAddr - The allocated DOU address (for up to 16DW of payload)
*/
task PEUTestEnv::allocWrTag( // Obtain a PIOWr tag & DOU addr
var bit[7:0] TlpTag,
var bit[7:0] DataAddr )
{
bit [3:0] tag;
#ifndef N2_FC
// Wait 'til a tag is available
void = semaphore_get( WAIT, sm_PioTags, 1 );
#endif
// Then pick one at random
tag = localRandom();
while ( pioTagsUsed[tag] ) tag = tag + 5;
pioTagsUsed[tag] = 1'b1;
TlpTag = { 4'b0001, tag };
// There's a DOU block tied
// to every tag.
// DataAddr = { 2'b10, tag, 2'b00 };
DataAddr = { 4'b1000, tag };
Report.report(RTYP_DEBUG_3,"PEUTestEnv::allocWrTag TlpTag=%0h pioTagsUsed=%0h \n",TlpTag,pioTagsUsed);
} /* end "allocWrTag" */
/*
* allocRdTag - Allocate a tag for a PIO read request
*
* Parameters:
* TlpTag - The allocated tag
*/
task PEUTestEnv::allocRdTag(
var bit[7:0] TlpTag )
{
bit [3:0] tag = 4'b0;
#ifndef N2_FC
// Wait 'til a tag is available
void = semaphore_get( WAIT, sm_PioTags, 1 );
#endif
// Then pick one at random
tag = localRandom();
while ( pioTagsUsed[tag] ) tag = tag + 7;
pioTagsUsed[tag] = 1'b1;
TlpTag = { 4'b0000, tag };
Report.report(RTYP_DEBUG_3,"PEUTestEnv::allocRdTag TlpTag=%0h pioTagsUsed=%0h \n",TlpTag,pioTagsUsed);
} /* end "allocRdTag" */
/*
* freePioTag - Deallocate a tag for a non-posted PIO request
*
* Parameters:
* TlpTag - The tag to be freed
*/
task PEUTestEnv::freePioTag( // Release a PIO tag
bit[7:0] TlpTag )
{
integer tag;
string errMsg;
tag = TlpTag[3:0];
if ( TlpTag[4] )
{
if ( pioTagsUsed[tag] )
{
pioTagsUsed[tag] = 1'b0;
#ifndef N2_FC
semaphore_put( sm_PioTags, 1 );
}
// When a strategy frees a tag while in drain-state, it might
// have already been freed when the ILU presents the completion.
else if ( !sync( CHECK, ev_drainStateEnd ) )
{
sprintf( errMsg, "PIO-Write tag '%x' erroneously released", tag );
_REPORT_ERROR( errMsg );
#endif
}
}
else
{
if ( pioTagsUsed[tag] )
{
pioTagsUsed[tag] = 1'b0;
#ifndef N2_FC
semaphore_put( sm_PioTags, 1 );
}
else if ( !sync( CHECK, ev_drainStateEnd ) )
{
sprintf( errMsg, "PIO-Read tag '%x' erroneously released", tag );
_REPORT_ERROR( errMsg );
#endif
}
}
Report.report(RTYP_DEBUG_3,"PEUTestEnv::freePioTag called with TlpTag=%0h pioTagsUsed=%0h \n",TlpTag,pioTagsUsed);
} /* end "freePioTag" */
/*
* allocDmaTag - Allocate a tag for a DMA (ingress) request
*
* Parameters:
* TlpTag - The reserved DMA-request tag
*
* NOTE: The caller is suspended if there are no available DMA tags
*/
task PEUTestEnv::allocDmaTag( // Obtain a DMA tag
var bit[7:0] TlpTag )
{
bit [7:0] tag;
// Wait 'til a tag is available
void = semaphore_get( WAIT, sm_DmaTags, 1 );
// Then pick one at random
tag = localRandom();
while ( dmaTagsUsed[tag] ) tag = tag + 13;
dmaTagsUsed[tag] = 1'b1;
TlpTag = tag;
} /* end "allocDmaTag" */
/*
* freeDmaTag - De-allocate a tag for a DMA (ingress) request
*
* Parameters:
* TlpTag - The DMA-request tag to be freed
*/
task PEUTestEnv::freeDmaTag( // Release a DMA tag
bit[7:0] TlpTag )
{
dmaTagsUsed[TlpTag] = 1'b0;
semaphore_put( sm_DmaTags, 1 );
} /* end "freeDmaTag" */
/*
* allocCplData - Allocate a number of (contiguous DMA read) DOU blocks
*
* Parameters:
* Len - The number of DWs to be stored
* LowAddr - The low-address bits from the completion header
* DouAddr - The full address of the first DOU block
*
* NOTE: This caller is suspended if insufficient DOU blocks are available
*/
task PEUTestEnv::allocCplData( // Allocate some DOU blocks
integer Len,
bit[6:0] LowAddr,
var bit[7:0] DouAddr )
{
bit [4:0] firstBlk;
bit [4:0] thisBlk;
integer blkCount;
integer unusedBlks;
integer i;
// How many blocks are req'd?
blkCount = ( Len + LowAddr[5:2] + 15 ) / 16;
if ( blkCount > 32 || Len == 0 )
_REPORT_ERROR( "TEST BUG! Excessive length given to allocCplData" );
// Only one customer at a time
void = semaphore_get( WAIT, sm_DouMutex, 1 );
douBlksRequest = blkCount;
// Look for "blkCount" consecutive
// blocks, and wait for them to show
// up if they aren't there.
while( blkCount > 0 )
{
trigger( OFF, ev_douBlkFreed );
thisBlk = localRandom();
unusedBlks = 0;
for ( i=0; i<64 && unusedBlks<blkCount; i++ )
{
if ( douBlksUsed[thisBlk] )
unusedBlks = 0;
else
{
if ( unusedBlks == 0 ) firstBlk = thisBlk;
unusedBlks = unusedBlks + 1;
}
thisBlk = thisBlk + 1;
}
// If we've found "blkCount" consecutive
// blocks, then we're done.
if ( unusedBlks == blkCount ) break;
// If we didn't find free blocks, we
// have to wait for a block to free up.
sync( ANY, ev_douBlkFreed );
}
// Mark the reserved blocks as "used"
thisBlk = firstBlk;
for ( i=0; i<blkCount; i++ )
{
douBlksUsed[thisBlk] = 1'b1;
thisBlk = thisBlk + 1;
}
// Let someone else get a block
douBlksRequest = 0;
semaphore_put( sm_DouMutex, 1 );
DouAddr = { 1'b0, firstBlk, 2'b00 };
} /* end "allocCplData" */
/*
* freeCplData - Free a DOU block allocated by "allocCplData"
*
* Parameters:
* DouAddr - The full address of the DOU block to be deallocated
*/
task PEUTestEnv::freeCplData(
bit[7:0] DouAddr )
{
integer blk;
string errMsg;
blk = DouAddr[6:2];
if ( DouAddr[7] || (!douBlksUsed[blk] && !softResetPending) )
{
sprintf( errMsg, "DOU block '%x' erroneously released", DouAddr );
_REPORT_ERROR( errMsg );
}
else
{
douBlksUsed[blk] = 1'b0;
trigger( ON, ev_douBlkFreed );
}
} /* end "freeCplData" */
/*
* set4DWratio - Set the ratio of generated TLPs with 4DW headers
*
* Parameters:
* ratio - The desired percentage of TLPs with 4DW headers (from zero to 100)
*/
task PEUTestEnv::set4DWratio( integer ratio )
{
if ( ratio >= 0 && ratio <= 100 )
gen4DWratio = ratio;
}
/*
* reserveIngressCredits - Reserve ingress credits required to send a given TLP.
* If the credits are not available, then the caller is
* suspended until they are.
*
* Parameters:
* PktHdr - The header of the TLP in question
*/
//Default switched to bypass_FC_credit since Denali will control credits and pacing of
// tlps
task PEUTestEnv::reserveIngressCredits( bit[PEC_PCI__HDR] PktHdr, bit bypass_FC_credit_checking=1 )
{
integer isCpl; // Is the "PktHdr" a completion?
integer isPost; // Is the "PktHdr" a posted request?
integer dataCredits; // # of data credits required
integer hdrAvail; // Total header credits available
integer dataAvail; // Total data credits available
Report.report(RTYP_DEBUG_3,"reserveIngressCredits called reserveIngressCreditsCntr=%0d \n",reserveIngressCreditsCntr);
// A completion?
isCpl = (PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL)
|| (PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL_LK);
if ( !isCpl && softResetPending )
{
sync( ANY, ev_softResetEnd );
}
// If this is a DMA request, then wait
// until the link is up.
if ( !isCpl && !sync( CHECK, ev_linkUp ) )
{
sync( ANY, ev_linkUp );
}
// A posted request? (Msg or MemWrite)
isPost = ( (PktHdr[PEC_PCI__TYPE] & ~PEC_PCI__TYPE_MSG_RC_MASK)
== PEC_PCI__TYPE_MSG )
|| ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM
&& PktHdr[PEC_PCI__FMT_DATA] );
// How many data credits are required?
dataCredits = 0;
if ( PktHdr[PEC_PCI__FMT_DATA] )
dataCredits = (PktHdr[PEC_PCI__LEN] + 3) / 4;
// Get in line for credits!
if ( isCpl )
void = semaphore_get( WAIT, sm_consumeCompletion, 1 );
else if ( isPost )
void = semaphore_get( WAIT, sm_consumePost, 1 );
else
void = semaphore_get( WAIT, sm_consumeNonpost, 1 );
// for FC overflow testing, then bypass the credit checking or else nothing proceeds
if ( (bypass_FC_credit_checking) == 0) {
QuickReport( Report, RTYP_INFO, "Env:: reserveIngressCredits: checking credits ");
// Wait for credits if necessary
if ( isCpl )
{
hdrAvail = ingressCompletionHdrAvail - ingressCompletionHdrRsvd;
dataAvail = ingressCompletionDataAvail - ingressCompletionDataRsvd;
while( !sync( CHECK, ev_drainStateEnd ) && !softResetPending
&& ( hdrAvail - ingressCompletionHdrConsumed < 1
|| dataAvail - ingressCompletionDataConsumed < dataCredits ) )
{
sync( ANY, ev_creditUpdateReceived, ev_drainStateEnd, ev_softReset );
hdrAvail = ingressCompletionHdrAvail - ingressCompletionHdrRsvd;
dataAvail = ingressCompletionDataAvail - ingressCompletionDataRsvd;
}
}
else if ( isPost )
{
hdrAvail = ingressPostHdrAvail - ingressPostHdrRsvd;
dataAvail = ingressPostDataAvail - ingressPostDataRsvd;
Report.report(RTYP_DEBUG_3,"reserveIngressCreditsCnt ingressPostHdrAvail=%0d ingressPostHdrRsvd=%0d ingressPostDataAvail=%0d ingressPostDataRsvd=%0d hdrAvail=%0d dataAvail=%0d ingressPostHdrConsumed=%0d ingressPostDataConsumed=%0d dataCredits=%0d \n",
ingressPostHdrAvail,ingressPostHdrRsvd,ingressPostDataAvail,ingressPostDataRsvd,hdrAvail,dataAvail,ingressPostHdrConsumed,ingressPostDataConsumed,dataCredits );
while( !sync( CHECK, ev_drainStateEnd ) && !softResetPending
&& ( hdrAvail - ingressPostHdrConsumed < 1
|| dataAvail - ingressPostDataConsumed < dataCredits ) )
{
sync( ANY, ev_creditUpdateReceived, ev_drainStateEnd, ev_softReset );
hdrAvail = ingressPostHdrAvail - ingressPostHdrRsvd;
dataAvail = ingressPostDataAvail - ingressPostDataRsvd;
}
}
else
{
hdrAvail = ingressNonpostHdrAvail - ingressNonpostHdrRsvd;
dataAvail = ingressNonpostDataAvail - ingressNonpostDataRsvd;
while( !sync( CHECK, ev_drainStateEnd ) && !softResetPending
&& ( hdrAvail - ingressNonpostHdrConsumed < 1
|| dataAvail - ingressNonpostDataConsumed < dataCredits ) )
{
sync( ANY, ev_creditUpdateReceived, ev_drainStateEnd, ev_softReset );
hdrAvail = ingressNonpostHdrAvail - ingressNonpostHdrRsvd;
dataAvail = ingressNonpostDataAvail - ingressNonpostDataRsvd;
}
}
} // end bypass
// Add the credits required for this
// TLP to the total reserved so far.
if ( sync( CHECK, ev_drainStateEnd ) || softResetPending )
{
// Do nothing
}
else if ( isCpl )
{
ingressCompletionHdrRsvd = ingressCompletionHdrRsvd + 1;
ingressCompletionDataRsvd = ingressCompletionDataRsvd + dataCredits;
}
else if ( isPost )
{
ingressPostHdrRsvd = ingressPostHdrRsvd + 1;
ingressPostDataRsvd = ingressPostDataRsvd + dataCredits;
}
else
{
ingressNonpostHdrRsvd = ingressNonpostHdrRsvd + 1;
ingressNonpostDataRsvd = ingressNonpostDataRsvd + dataCredits;
}
// Give someone else a chance to
// reserve necesary credits.
if ( isCpl )
semaphore_put( sm_consumeCompletion, 1 );
else if ( isPost )
semaphore_put( sm_consumePost, 1 );
else
semaphore_put( sm_consumeNonpost, 1 );
reserveIngressCreditsCntr += 1;
} /* end "reserveIngressCredits" */
/*
* consumeIngressCredits - Return the credits for an ingress TLP to the pool
* of credits to (eventually) be returned by the TLU.
*
* Parameters:
* PktHdr - The header of the TLP whose credits might be returned by the TLU.
*/
task PEUTestEnv::consumeIngressCredits( bit[PEC_PCI__HDR] PktHdr )
{
integer isCpl; // Is the "PktHdr" a completion?
integer isPost; // Is the "PktHdr" a posted request?
integer dataCredits; // # of data credits required
integer hdrAvail; // Total header credits available
integer dataAvail; // Total data credits available
// If the link isn't up, then this is bogus
if ( !sync( CHECK, ev_linkUp ) ) return;
// A completion?
isCpl = (PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL)
|| (PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL_LK);
// A posted request? (Msg or MemWrite)
isPost = ( (PktHdr[PEC_PCI__TYPE] & ~PEC_PCI__TYPE_MSG_RC_MASK)
== PEC_PCI__TYPE_MSG )
|| ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM
&& PktHdr[PEC_PCI__FMT_DATA] );
// How many data credits are required?
dataCredits = 0;
if ( PktHdr[PEC_PCI__FMT_DATA] )
dataCredits = (PktHdr[PEC_PCI__LEN] + 3) / 4;
// Credits are no longer reserved,
// they are now officially consumed.
if ( isCpl )
{
ingressCompletionHdrRsvd = ingressCompletionHdrRsvd - 1;
ingressCompletionDataRsvd = ingressCompletionDataRsvd - dataCredits;
ingressCompletionHdrConsumed = ingressCompletionHdrConsumed + 1;
ingressCompletionDataConsumed = ingressCompletionDataConsumed + dataCredits;
}
else if ( isPost )
{
ingressPostHdrRsvd = ingressPostHdrRsvd - 1;
ingressPostDataRsvd = ingressPostDataRsvd - dataCredits;
ingressPostHdrConsumed = ingressPostHdrConsumed + 1;
ingressPostDataConsumed = ingressPostDataConsumed + dataCredits;
}
else
{
ingressNonpostHdrRsvd = ingressNonpostHdrRsvd - 1;
ingressNonpostDataRsvd = ingressNonpostDataRsvd - dataCredits;
ingressNonpostHdrConsumed = ingressNonpostHdrConsumed + 1;
ingressNonpostDataConsumed = ingressNonpostDataConsumed + dataCredits;
}
} /* end "consumeIngressCredits" */
/*
* consumeEgressCredits - Add the credits required for a TLP sent by the
* TLU to the total consumed so far, and put a token
* in the appropriate mailbox so that the credits are
* restored by "updateEgressCredits" at a later time.
*
* Parameters:
* PktHdr - The header of the TLP presented by the TLU
*/
task PEUTestEnv::consumeEgressCredits( bit[PEC_PCI__HDR] PktHdr )
{
integer isCpl; // Is the "PktHdr" a completion?
integer isPost; // Is the "PktHdr" a posted request?
integer dataCredits; // # of associated data credits
integer retryCredits; // # of retry credits consumed
string msg;
bit[63:0] RetryCSR;
//Since ev_drainStateEnd means we will reset the PEU don't worry about the
// credits anymore
if( sync( CHECK, ev_drainStateEnd )){
return;
}
// A completion?
isCpl = (PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL)
|| (PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_CPL_LK);
// A posted request? (Msg or MemWrite)
isPost = ( (PktHdr[PEC_PCI__TYPE] & ~PEC_PCI__TYPE_MSG_RC_MASK)
== PEC_PCI__TYPE_MSG )
|| ( PktHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM
&& PktHdr[PEC_PCI__FMT_DATA] );
Report.report(RTYP_DEBUG_3,"PEUTestEnv::consumeEgressCredits isPost=%0d PktHdr[PEC_PCI__TYPE=%0h PEC_PCI__TYPE_MSG_RC_MASK=%0h PEC_PCI__TYPE_MSG=%0h result=%0h" , isPost,PktHdr[PEC_PCI__TYPE],PEC_PCI__TYPE_MSG_RC_MASK, (PktHdr[PEC_PCI__TYPE] & ~PEC_PCI__TYPE_MSG_RC_MASK) );
// How many data credits are involved?
dataCredits = 0;
if ( PktHdr[PEC_PCI__FMT_DATA] )
dataCredits = (PktHdr[PEC_PCI__LEN] + 3) / 4;
// Add the credits required by the
// given "PktHdr" to the total consumed
// by the TLU. Complain vigorously if
// the TLU has exceeded its budget.
if ( isPost )
{
egressPostHdrConsumed = egressPostHdrConsumed + 1;
egressPostDataConsumed = egressPostDataConsumed + dataCredits;
if ( egressPostHdrConsumed > egressPostHdrAvail
|| egressPostDataConsumed > egressPostDataAvail )
{
_REPORT_ERROR( "BLAST! Egress posted credit allowance exceeded!" );
sprintf( msg ,"egressPostHdrConsumed=%0d > egressPostHdrAvail%0d || egressPostDataConsumed=%0d > egressPostDataAvail=%0d",egressPostHdrConsumed,egressPostHdrAvail,egressPostDataConsumed,egressPostDataAvail);
_ERROR_INFO(msg);
}
// Add the credits associated with this
// TLP to the appropriate bin...
this.egressPostHdrToReturn += 1;
this.egressPostDataToReturn += dataCredits;
}
else if ( isCpl )
{
egressCompletionHdrConsumed = egressCompletionHdrConsumed + 1;
egressCompletionDataConsumed = egressCompletionDataConsumed + dataCredits;
if ( egressCompletionHdrConsumed > egressCompletionHdrAvail
|| egressCompletionDataConsumed > egressCompletionDataAvail )
{
_REPORT_ERROR( "BLAST! Egress compl'n credit allowance exceeded!" );
}
// Add the credits associated with this
// TLP to the appropriate bin...
this.egressCompletionHdrToReturn += 1;
this.egressCompletionDataToReturn += dataCredits;
}
else
{
egressNonpostHdrConsumed = egressNonpostHdrConsumed + 1;
egressNonpostDataConsumed = egressNonpostDataConsumed + dataCredits;
if ( egressNonpostHdrConsumed > egressNonpostHdrAvail
|| egressNonpostDataConsumed > egressNonpostDataAvail )
{
_REPORT_ERROR( "BLAST! Egress non-posted credit allowance exceeded!" );
}
// Add the credits associated with this
// TLP to the appropriate bin...
this.egressNonpostHdrToReturn += 1;
this.egressNonpostDataToReturn += dataCredits;
}
// We have to do the same for retry
// credits...
retryCredits = 12;
if ( PktHdr[PEC_PCI__FMT_4DW] ) retryCredits = retryCredits + 4;
if ( PktHdr[PEC_PCI__TD] ) retryCredits = retryCredits + 4;
if ( PktHdr[PEC_PCI__FMT_DATA] ) retryCredits = retryCredits +
4*PktHdr[PEC_PCI__LEN];
// Retry credits are consumed in
// N-byte blocks, where N is the
// number of lanes in the link.
//N2-review - Is this the same for Cascade
if ( (retryCredits % egressDataWidth) > 0 ){
retryCredits = retryCredits + egressDataWidth
- (retryCredits % egressDataWidth);
}
egressRetryConsumed = egressRetryConsumed + retryCredits;
if ( egressRetryConsumed > egressRetryAvail )
{
_REPORT_ERROR( "ZUT! The TLU has exceeded its retry credit allowance!" );
}
#ifdef N2_FC
#else
fork
{
RetryCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_erb.read(CSRT_DAEMON);
// mb_egressRetry retryCredits=%0d egressRetryConsumed=%0d RetryCSR[15:0]=%0h RetryCSR[47:32]=%0h \n",retryCredits,egressRetryConsumed,RetryCSR[15:0],RetryCSR[47:32] );
}
join none
#endif
mailbox_put( mb_egressRetry, retryCredits );
//Put a sequence number that corresponds to the credits so they can be restored when
// a ACK or NAK is received
// mb_egressSeqNum egressNextTransmitSeqNum=%0d \n",egressNextTransmitSeqNum );
mailbox_put( mb_egressSeqNum, egressNextTransmitSeqNum );
//Increment the Egress sequence number each time a TLP is sent
egressNextTransmitSeqNum = egressNextTransmitSeqNum + 1;
// consumeEgressCredits isCpl=%0d isPost=%0d egressPostHdrToReturn=%0d egressNonpostHdrToReturn=%0d egressCompletionHdrToReturn=%0d \n",isCpl,isPost,egressPostHdrToReturn,egressNonpostHdrToReturn,egressCompletionHdrToReturn);
} /* end "consumeEgressCredits" */
/*
* updateIngressCredits - A perpetual thread which records updated ingress
* credit totals from the TLU
*/
task PEUTestEnv::updateIngressCredits()
{
FNXPCIEXactorTransaction PCIEDllpTrans;
PEC_FCtype fcType;
integer fcHdr;
integer fcData;
bit fcHP;
integer changed;
integer rxLastPostHdr;
integer rxLastPostData;
integer rxLastNonpostHdr;
integer rxLastNonpostData;
integer rxLastCompletionHdr;
integer rxLastCompletionData;
integer rxTimeOut;
integer oldPostDataConsumed;
// Wait for "link up"
sync( ANY, ev_linkUp, ev_softReset );
if ( sync( CHECK, ev_softReset ) ) return;
// We start with the initial credit totals
ingressPostHdrAvail = ingressPostHdrInit;
ingressPostDataAvail = ingressPostDataInit;
ingressNonpostHdrAvail = ingressNonpostHdrInit;
ingressNonpostDataAvail = ingressNonpostDataInit;
ingressCompletionHdrAvail = ingressCompletionHdrInit;
ingressCompletionDataAvail = ingressCompletionDataInit;
if ( ingressPostHdrAvail == 0 )
ingressPostHdrAvail = infiniteCredits;
if ( ingressPostDataAvail == 0 )
ingressPostDataAvail = infiniteCredits;
if ( ingressNonpostHdrAvail == 0 )
ingressNonpostHdrAvail = infiniteCredits;
if ( ingressNonpostDataAvail == 0 )
ingressNonpostDataAvail = infiniteCredits;
if ( ingressCompletionHdrAvail == 0 )
ingressCompletionHdrAvail = infiniteCredits;
if ( ingressCompletionDataAvail == 0 )
ingressCompletionDataAvail = infiniteCredits;
// We haven't reserved or consumed any
// credits yet.
ingressPostHdrRsvd = 0;
ingressPostDataRsvd = 0;
ingressNonpostHdrRsvd = 0;
ingressNonpostDataRsvd = 0;
ingressCompletionHdrRsvd = 0;
ingressCompletionDataRsvd = 0;
ingressPostHdrConsumed = 0;
ingressPostDataConsumed = 0;
ingressNonpostHdrConsumed = 0;
ingressNonpostDataConsumed = 0;
ingressCompletionHdrConsumed = 0;
ingressCompletionDataConsumed = 0;
// Set the rxLast* to the current cycle time.
rxLastPostHdr = get_cycle();
rxLastPostData = get_cycle();
rxLastNonpostHdr = get_cycle();
rxLastNonpostData = get_cycle();
rxLastCompletionHdr = get_cycle();
rxLastCompletionData = get_cycle();
rxTimeOut = 25;
oldPostDataConsumed = 0;
PCIEDllpTrans = new( Pod.FNXPCIEBldr );
//Set up the CTTransactionID
PCIEDllpTrans.SetID( f_ID.NextTransID() );
// Respond to every credit update from
// the device by reflecting the new
// credit totals locally.
while( 1 )
{
//Start with a clean packet each time
PCIEDllpTrans.MyPacket.PktReset();
//The SampleDllp will return a copy of each DLLP packets that the FNXPCIEXtr recieves so
// determine if this is a Flow Control Update and then update the environment variables
fork
PCIEDllpTrans.SampleDllp( PCIEDllpTrans.MyPacket , 50000 );
sync( ANY, ev_softReset );
join any
if ( softResetPending ) return;
//Check to make sure DLLP is a Flow Control update before proceeding since ACKs, NAKs,
// and power management dllps can be returned from SampleDllp
if( PCIEDllpTrans.MyPacket.isDllpFCUpdate() ){
case( PCIEDllpTrans.MyPacket.DllpType[FNX_PCIE_XTR_DLLP_FC_TYPE_TYPE_INT_SLC] ){
FNX_PCIE_XTR_FC_DLLP_TYPE_UPDATE_FC_P: fcType = e_FC_posted;
FNX_PCIE_XTR_FC_DLLP_TYPE_UPDATE_FC_NP: fcType = e_FC_nonposted;
FNX_PCIE_XTR_FC_DLLP_TYPE_UPDATE_FC_CPL: fcType = e_FC_completion;
default: PCIEDllpTrans.MyPacket.PktDisplay( RTYP_TEST_ERROR, "Env.updateIngressCredits PCIEDllpTrans.MyPacket.isDllpFCUpdate() is not a flow control update packet" );
}
fcHdr = PCIEDllpTrans.MyPacket.DllpFCHdrFC;
fcData = PCIEDllpTrans.MyPacket.DllpFCDataFC;
changed =
( ingressPostHdrAvail != infiniteCredits
&& fcType == e_FC_posted
&& ingressPostHdrAvail%256 != fcHdr )
|| ( ingressPostDataAvail != infiniteCredits
&& fcType == e_FC_posted
&& ingressPostDataAvail%4096 != fcData )
|| ( ingressNonpostHdrAvail != infiniteCredits
&& fcType == e_FC_nonposted
&& ingressNonpostHdrAvail%256 != fcHdr )
|| ( ingressNonpostDataAvail != infiniteCredits
&& fcType == e_FC_nonposted
&& ingressNonpostDataAvail%4096 != fcData )
|| ( ingressCompletionHdrAvail != infiniteCredits
&& fcType == e_FC_completion
&& ingressCompletionHdrAvail%256 != fcHdr )
|| ( ingressCompletionDataAvail != infiniteCredits
&& fcType == e_FC_completion
&& ingressCompletionDataAvail%4096 != fcData );
if ( changed ) activityCounter = activityCounter + 1;
// Now check the high priority status
// N2 - Cascade deosn't use high priority so ignore it coming out of PTL
if ( fcType == e_FC_posted ) {
// We need to delay checking the posted data since there's
// latency between the times that "consumeIngressCredits" is called
// (i.e. when the header enters the TLU) and when the data credits are
// recognized by the TLU (i.e. a cycle or two after the end of the TLP).
oldPostDataConsumed = ingressPostDataConsumed;
}
// Now update the necessary timers
if ((ingressPostHdrAvail != infiniteCredits) &&
(fcType == e_FC_posted) &&
(ingressPostHdrAvail%256 != fcHdr))
rxLastPostHdr= get_cycle();
if ((ingressPostDataAvail != infiniteCredits) &&
(fcType == e_FC_posted) &&
(ingressPostDataAvail%4096 != fcData))
rxLastPostData = get_cycle();
if ((ingressNonpostHdrAvail != infiniteCredits) &&
(fcType == e_FC_nonposted) &&
(ingressNonpostHdrAvail%256 != fcHdr))
rxLastNonpostHdr = get_cycle();
if ((ingressNonpostDataAvail != infiniteCredits) &&
(fcType == e_FC_nonposted) &&
(ingressNonpostDataAvail%4096 != fcData))
rxLastNonpostData = get_cycle();
if ((ingressCompletionHdrAvail != infiniteCredits) &&
(fcType == e_FC_completion) &&
(ingressCompletionHdrAvail%256 != fcHdr))
rxLastCompletionHdr = get_cycle();
if ((ingressCompletionDataAvail != infiniteCredits) &&
(fcType == e_FC_completion) &&
(ingressCompletionDataAvail%4096 != fcData))
rxLastCompletionData = get_cycle();
// Update credit totals.
//N2 - Cascade doesn't have a High Priority Flow Control update
//N2 so get rid of fcHP & onlyHiIngressUpdates
if ( fcType == e_FC_posted )
{
Report.report(RTYP_DEBUG_3,"updateIngressCredits1 ingressPostHdrAvail=%0d ingressPostDataAvail=%0d fcHdr=%0d fcData=%0d \n",ingressPostHdrAvail,ingressPostDataAvail,fcHdr,fcData );
if ( ingressPostHdrAvail != infiniteCredits )
ingressPostHdrAvail = ((fcHdr - (ingressPostHdrAvail%256)) >= 0) ?
ingressPostHdrAvail + ( fcHdr - (ingressPostHdrAvail%256)) :
ingressPostHdrAvail + ( (256+fcHdr) - (ingressPostHdrAvail%256));
if ( ingressPostDataAvail != infiniteCredits )
ingressPostDataAvail =((fcData - (ingressPostDataAvail%4096)) >= 0) ?
ingressPostDataAvail + ( fcData - (ingressPostDataAvail%4096)) :
ingressPostDataAvail + ( (4096+fcData) - (ingressPostDataAvail%4096));
Report.report(RTYP_DEBUG_3,"updateIngressCredits2 ingressPostHdrAvail=%0d ingressPostDataAvail=%0d fcHdr=%0d fcData=%0d \n",ingressPostHdrAvail,ingressPostDataAvail,fcHdr,fcData);
}
if ( fcType == e_FC_nonposted )
{
if ( ingressNonpostHdrAvail != infiniteCredits )
ingressNonpostHdrAvail = ((fcHdr - (ingressNonpostHdrAvail%256)) >= 0) ?
ingressNonpostHdrAvail + ( fcHdr - (ingressNonpostHdrAvail%256)) :
ingressNonpostHdrAvail + ( (256+fcHdr) - (ingressNonpostHdrAvail%256));
if ( ingressNonpostDataAvail != infiniteCredits )
ingressNonpostDataAvail = ((fcData - (ingressNonpostDataAvail%4096)) >= 0) ?
ingressNonpostDataAvail + ( fcData - (ingressNonpostDataAvail%4096)) :
ingressNonpostDataAvail + ( (4096+fcData) - (ingressNonpostDataAvail%4096));
}
if ( fcType == e_FC_completion )
{
if ( ingressCompletionHdrAvail != infiniteCredits )
ingressCompletionHdrAvail = ((fcHdr - (ingressCompletionHdrAvail%256)) >= 0) ?
ingressCompletionHdrAvail + ( fcHdr - (ingressCompletionHdrAvail%256)) :
ingressCompletionHdrAvail + ( (256+fcHdr) - (ingressCompletionHdrAvail%256));
if ( ingressCompletionDataAvail != infiniteCredits )
ingressCompletionDataAvail = ((fcData - (ingressCompletionDataAvail%4096)) >= 0) ?
ingressCompletionDataAvail + ( fcData - (ingressCompletionDataAvail%4096)) :
ingressCompletionDataAvail + ( (4096+fcData) - (ingressCompletionDataAvail%4096));
}
// If someone is waiting for credits,
// then tell them to try again.
trigger( ONE_SHOT, ev_creditUpdateReceived );
trigger( ONE_SHOT, ev_CSRupdateReq );
} //End if( PCIEDllpTrans.MyPacket.isDllpFC() )
//Delay a cycle to allow time to progress
@( posedge if_ILU_PEU_PCIE_RX.refclk );
} //End while( 1 )
} /* end "updateIngressCredits" */
/*
* updateEgressCredits - Monitors Ingress DLLPs from PCIEXtr to update Egress
* Flow Control values based on update flow control packets
* and retry credits based on ACK/NAKs
*/
task PEUTestEnv::updateEgressCredits() {
FNXPCIEXactorTransaction PCIEIngressDllpTrans;
PEC_FCtype fcType;
integer egressSeqNum; // Sequence # put in mailbox for egress TLPs
integer retryPending; // Credits not yet returned to the TLU
integer hdrCredits;
integer dataCredits;
integer i;
integer seqDif; // Used to temporarily hold difference between 2 sequence numbers
integer egressTransmitSeqNum; // The current highest transmitted sequence number
integer AckNakSeqNum; // Sequence number of the Ingress DLLPs ACK/NAK
// A reset chip starts at 4095 since the first
// real ack sequence will be 0
bit discardDllp;
integer fcHdr;
integer fcData;
integer creditDifHdr;
integer creditDifData;
// FNXPCIEXactorTransaction PCIETrans;
// PCIETrans = new( Pod.FNXPCIEBldr );
PCIEIngressDllpTrans = new( Pod.FNXPCIEBldr );
//Wait for the Denali link to come up
PCIEIngressDllpTrans.WaitLinkUp();
// We start with the initial credit allocation
egressPostHdrAvail = egressPostHdrInit;
egressPostDataAvail = egressPostDataInit;
egressNonpostHdrAvail = egressNonpostHdrInit;
egressNonpostDataAvail = egressNonpostDataInit;
egressCompletionHdrAvail = egressCompletionHdrInit;
egressCompletionDataAvail = egressCompletionDataInit;
if ( egressPostHdrAvail == 0 )
egressPostHdrAvail = infiniteCredits;
if ( egressPostDataAvail == 0 )
egressPostDataAvail = infiniteCredits;
if ( egressNonpostHdrAvail == 0 )
egressNonpostHdrAvail = infiniteCredits;
if ( egressNonpostDataAvail == 0 )
egressNonpostDataAvail = infiniteCredits;
if ( egressCompletionHdrAvail == 0 )
egressCompletionHdrAvail = infiniteCredits;
if ( egressCompletionDataAvail == 0 )
egressCompletionDataAvail = infiniteCredits;
mailbox_put(mb_egressPostHdrAvail, egressPostHdrAvail);
mailbox_put(mb_egressPostDataAvail, egressPostDataAvail);
mailbox_put(mb_egressNonpostHdrAvail, egressNonpostHdrAvail);
mailbox_put(mb_egressNonpostDataAvail, egressNonpostDataAvail);
mailbox_put(mb_egressCompletionHdrAvail, egressCompletionHdrAvail);
mailbox_put(mb_egressCompletionDataAvail, egressCompletionDataAvail);
// The TLU hasn't eaten any credits yet.
egressPostHdrConsumed = 0;
egressPostDataConsumed = 0;
egressNonpostHdrConsumed = 0;
egressNonpostDataConsumed = 0;
egressCompletionHdrConsumed = 0;
egressCompletionDataConsumed = 0;
egressPostHdrToReturn = 0;
egressPostDataToReturn = 0;
egressNonpostHdrToReturn = 0;
egressNonpostDataToReturn = 0;
egressCompletionHdrToReturn = 0;
egressCompletionDataToReturn = 0;
// returnAllEgressCredits = 0;
egressUpdateError = 0; // We need to know if a FC error occurred
// Let's begin by setting the total
// number of "retry" credits available
// to the TLU.
retryPending = 0;
egressRetryAvail = egressRetryInit;
egressRetryConsumed = 0;
//N2-Not needed since testing ilu-peu f_LPUXtr.advertiseRetryCredit( egressRetryAvail );
// Now, wait for "link up" to be
// asserted...
//N2-review Might miss Set Slot Power sync( ANY, ev_linkUp );
// Update credit values as they are returned...
// Enable the Sampling of Ingress DLLPs
// PCIEIngressDllpTrans = new( Pod.FNXPCIEBldr );
PCIEIngressDllpTrans.EnableSampleIngressDllp();
//N2 DMT Bypass Link Train PCIEIngressDllpTrans.EnableSampleIngressDllp();
while( 1 ) {
//Start with a clean packet each time
PCIEIngressDllpTrans.MyPacket.PktReset();
//The SampleIngressDllp will return a copy of each DLLP packet that the FNXPCIEXtr transmits
// so determine if this is a Flow Control Update or an ACK/NAK and then update
// the correct environment variables
fork
PCIEIngressDllpTrans.SampleIngressDllp( PCIEIngressDllpTrans.MyPacket , 50000 );
sync( ANY, ev_softReset );
join any
if( softResetPending || (sync( CHECK, ev_drainStateEnd )) ){
PCIEIngressDllpTrans.DisableSampleIngressDllp();
terminate; //kill the SampleIngressDllp process
break;
}
//Delay here since Denali is returning ACK/NAK the same cycle as matching TLPs
@( posedge if_ILU_PEU_PCIE_RX.refclk );
//Check to make sure DLLP is a Flow Control update before proceeding since ACKs, NAKs,
// and power management dllps can be returned from SampleDllp
if( PCIEIngressDllpTrans.MyPacket.isDllpFCUpdate() ){
case( PCIEIngressDllpTrans.MyPacket.DllpType[FNX_PCIE_XTR_DLLP_FC_TYPE_TYPE_INT_SLC] ){
FNX_PCIE_XTR_FC_DLLP_TYPE_UPDATE_FC_P: fcType = e_FC_posted;
FNX_PCIE_XTR_FC_DLLP_TYPE_UPDATE_FC_NP: fcType = e_FC_nonposted;
FNX_PCIE_XTR_FC_DLLP_TYPE_UPDATE_FC_CPL: fcType = e_FC_completion;
default: PCIEIngressDllpTrans.MyPacket.PktDisplay( RTYP_TEST_ERROR, "Env.updateEgressCredits PCIEIngressDllpTrans.MyPacket.isDllpFCUpdate() is not a flow control update packet" );
}
fcHdr = PCIEIngressDllpTrans.MyPacket.DllpFCHdrFC;
fcData = PCIEIngressDllpTrans.MyPacket.DllpFCDataFC;
//
case( fcType ){
e_FC_posted: { //Flag an error for bad update from testbench unless expected
if (FCP_inject == 0 && FCP_P_inject == 0 ) {
if( egressPostHdrAvail == infiniteCredits && fcHdr != 0 ){ //N2 review Error Case Allowed to test dut
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() egressPostHdrAvail == infiniteCredits but received update Flow Control Hdr Credit=$0d",
fcHdr);
}
//Flag an error for bad update from testbench unless expected
if( egressPostDataAvail == infiniteCredits && fcData != 0 ){ //N2 review Error Case Allowed to test dut
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() egressPostDataAvail == infiniteCredits but received update Flow Control data Credit=$0d",
fcData);
}
//Determine difference between the last updates
if( (fcHdr - (egressPostHdrAvail%256)) >= 0 ){
creditDifHdr = fcHdr - (egressPostHdrAvail%256);
}else{
creditDifHdr = (fcHdr+256) - (egressPostHdrAvail%256);
}
if( (fcData - (egressPostDataAvail%4096)) >= 0 ){
creditDifData = fcData - (egressPostDataAvail%4096);
}else{
creditDifData = (fcData+4096) - (egressPostDataAvail%4096);
}
//Flag an error if Update is greater than # of outstanding credits
if( creditDifHdr > egressPostHdrToReturn ){ //N2 review Error Case
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() More Posted Header Credits returned than were outstanding fcHdr=%0d egressPostHdrToReturn=%0d creditDifHdr=%0d egressPostHdrAvail=%0d",
fcHdr,egressPostHdrToReturn,creditDifHdr,egressPostHdrAvail );
}
//Flag an error if Update is greater than # of outstanding credits
if( creditDifData > egressPostDataToReturn ){ //N2 review Error Case
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() More Posted Data Credits returned than were outstanding fcData=%0d egressPostDataToReturn=%0d creditDifData=%0d egressPostDataAvail=%0d",
fcHdr,egressPostDataToReturn,creditDifData,egressPostDataAvail );
}
//N2 - May not need these
if( egressPostHdrAvail == infiniteCredits && fcHdr == 0 ){
egressPostHdrToReturn = 0;
egressPostDataToReturn = 0;
}
//Keep the running total of Egress avail credits
egressPostHdrAvail = egressPostHdrAvail + creditDifHdr;
egressPostDataAvail = egressPostDataAvail + creditDifData;
//Keep track of outstanding credits that need to be returned
egressPostHdrToReturn = egressPostHdrToReturn - creditDifHdr;
egressPostDataToReturn = egressPostDataToReturn - creditDifData;
} // if FCP_inject
} //End e_FC_posted
e_FC_nonposted: { //Flag an error for bad update from testbench unless expected
if (FCP_inject == 0 && FCP_NP_inject == 0 ) {
if( egressNonpostHdrAvail == infiniteCredits && fcHdr != 0 ){ //N2 review Error Case Allowed to test dut
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() egressNonpostHdrAvail == infiniteCredits but received update Flow Control Hdr Credit=$0d",
fcHdr);
}
//Flag an error for bad update from testbench unless expected
if( egressNonpostDataAvail == infiniteCredits && fcHdr != 0 ){ //N2 review Error Case Allowed to test dut
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() egressNonpostDataAvail == infiniteCredits but received update Flow Control data Credit=$0d",
fcData);
}
//Determine difference between the last updates
if( (fcHdr - (egressNonpostHdrAvail%256)) >= 0 ){
creditDifHdr = fcHdr - (egressNonpostHdrAvail%256);
}else{
creditDifHdr = (fcHdr+256) - (egressNonpostHdrAvail%256);
}
if( (fcData - (egressNonpostDataAvail%4096)) >= 0 ){
creditDifData = fcData - (egressNonpostDataAvail%4096);
}else{
creditDifData = (fcData+4096) - (egressNonpostDataAvail%4096);
}
//Flag an error if Update is greater than # of outstanding credits
if( creditDifHdr > egressNonpostHdrToReturn ){ //N2 review Error Case
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() More Non Posted Header Credits returned than were outstanding fcHdr=%0d egressNonpostHdrToReturn=%0d creditDifHdr=%0d",
fcHdr,egressNonpostHdrToReturn,creditDifHdr );
}
//Flag an error if Update is greater than # of outstanding credits
if( creditDifData > egressNonpostDataToReturn ){ //N2 review Error Case
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() More Non Posted Data Credits returned than were outstanding fcData=%0d egressNonPostDataToReturn=%0d creditDifData=%0d",
fcHdr,egressNonpostDataToReturn,creditDifData );
}
//N2 - May not need these
if( egressNonpostHdrAvail == infiniteCredits && fcHdr == 0 ){
egressNonpostHdrToReturn = 0;
egressNonpostDataToReturn = 0;
}
//Keep the running total of Egress avail credits
egressNonpostHdrAvail = egressNonpostHdrAvail + creditDifHdr;
egressNonpostDataAvail = egressNonpostDataAvail + creditDifData;
//Keep track of outstanding credits that need to be returned
egressNonpostHdrToReturn = egressNonpostHdrToReturn - creditDifHdr;
egressNonpostDataToReturn = egressNonpostDataToReturn - creditDifData;
} // FCP_inject
} //End e_FC_nonposted
e_FC_completion: { //Flag an error for bad update from testbench unless expected
if (FCP_inject == 0 && FCP_CPL_inject == 0 ) {
if( egressCompletionHdrAvail == infiniteCredits && fcHdr != 0 ){ //N2 review Error Case Allowed to test dut
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() egressCompletionHdrAvail == infiniteCredits but received update Flow Control Hdr Credit=$0d",
fcHdr);
}
//Flag an error for bad update from testbench unless expected
if( egressCompletionDataAvail == infiniteCredits && fcData != 0 ){ //N2 review Error Case Allowed to test dut
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() egressCompletionDataAvaie == infiniteCredits but received update Flow Control data Credit=$0d",
fcHdr);
}
//Determine difference between the last updates
if( (fcHdr - (egressCompletionHdrAvail%256)) >= 0 ){
creditDifHdr = fcHdr - (egressCompletionHdrAvail%256);
}else{
creditDifHdr = (fcHdr+256) - (egressCompletionHdrAvail%256);
}
if( (fcData - (egressCompletionDataAvail%4096)) >= 0 ){
creditDifData = fcData - (egressCompletionDataAvail%4096);
}else{
creditDifData = (fcData+4096) - (egressCompletionDataAvail%4096);
}
//Flag an error if Update is greater than # of outstanding credits
if( (creditDifHdr > egressCompletionHdrToReturn) &&
(egressCompletionHdrAvail != infiniteCredits) ){ //N2 review Error Case
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() More Completion Header Credits returned than were outstanding fcHdr=%0d egressCompletionHdrToReturn=%0d creditDifHdr=%0d",
fcHdr,egressCompletionHdrToReturn,creditDifHdr );
}
//Flag an error if Update is greater than # of outstanding credits
if( (creditDifData > egressCompletionDataToReturn) &&
(egressCompletionDataAvail != infiniteCredits) ){ //N2 review Error Case
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() More Completion Data Credits returned than were outstanding fcData=%0d egressNonPostDataToReturn=%0d creditDifData=%0d",
fcHdr,egressNonpostDataToReturn,creditDifData );
}
//Keep the running total of Egress Header
if( (egressCompletionHdrAvail == infiniteCredits) && (fcHdr == 0) ){
egressCompletionHdrToReturn = 0;
egressCompletionHdrAvail = infiniteCredits;
}else{
egressCompletionHdrToReturn = egressCompletionHdrToReturn - creditDifHdr;
egressCompletionHdrAvail = egressCompletionHdrAvail + creditDifHdr;
}
//Keep the running total of Egress Data
if( (egressCompletionDataAvail == infiniteCredits) && (fcData == 0) ){
egressCompletionDataToReturn = 0;
egressCompletionDataAvail = infiniteCredits;
}else{
egressCompletionDataToReturn = egressCompletionDataToReturn - creditDifData;
egressCompletionDataAvail = egressCompletionDataAvail + creditDifData;
}
} // FCP_inject
} //End e_FC_completion
} //End case( fcType )
} //End if FCUpdate
//RETRY CREDITS
//If an ACK/NAK has been received and there are credits to restore in the
// egrressRetry mailbox then the retry credits can be restored
if( PCIEIngressDllpTrans.MyPacket.isDllpAckNak() ){
discardDllp = 0;
AckNakSeqNum = PCIEIngressDllpTrans.MyPacket.AckNakSeqNum;
//Make sure difference between NextTransmitSeqNum and AckNakSeqNum <= 2048
// since the dllp should be dropped and no credits returned
//review - This should also cause a DL layer error
egressTransmitSeqNum = ( (egressNextTransmitSeqNum%4096) == 0 ? 4095 : egressNextTransmitSeqNum - 1 );
if( (egressTransmitSeqNum%4096 - AckNakSeqNum) >= 0 ){
seqDif = (egressTransmitSeqNum%4096) - AckNakSeqNum;
}else{
seqDif = (egressTransmitSeqNum%4096)+4096 - AckNakSeqNum;
}
if( seqDif >= 2048 ){
discardDllp = 1;
//review - Error
}
//Keep track of the number of Tlps in the replay buffer
nmbrTlpsReplayBuffer = seqDif;
//1 review AckNakSeqNum=%0d egressTransmitSeqNum=%0d seqDif=%0d AckdSeqNum=%0d discardDllp=%0d\n",AckNakSeqNum,egressTransmitSeqNum,seqDif,AckdSeqNum,discardDllp );
if( (AckNakSeqNum - AckdSeqNum) >= 0 ){
seqDif = AckNakSeqNum - AckdSeqNum;
}else{
seqDif = (AckNakSeqNum+4096) - AckdSeqNum;
}
if( seqDif >= 2048 ){
discardDllp = 1;
//review - Error
}
//2 review AckNakSeqNum=%0d egressTransmitSeqNum=%0d seqDif=%0d AckdSeqNum=%0d discardDllp=%0d\n",AckNakSeqNum,egressTransmitSeqNum,seqDif,AckdSeqNum,discardDllp );
if( AckNakSeqNum == AckdSeqNum ){
//Not an error - Its legal to send an already sent seq # in a ack/nak
discardDllp = 1;
}
//3 review AckNakSeqNum=%0d egressTransmitSeqNum=%0d seqDif=%0d AckdSeqNum=%0d discardDllp=%0d\n",AckNakSeqNum,egressTransmitSeqNum,seqDif,AckdSeqNum,discardDllp );
//review - add check for AckNakSeqNum being less then AckdSeqNum - old AckNakSeqNum
//If we made it this far there should be something in mb_egressSeqNum
if( !(mailbox_get( NO_WAIT, mb_egressSeqNum )) && !discardDllp ){
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() nothing in mb_egressSeqNum #Entries=%0d when expected AckNakSeqNum=%0d AckdSeqNum=%0d egressTransmitSeqNum=%0d %4096=%0d ",(mailbox_get( NO_WAIT, mb_egressSeqNum )),AckNakSeqNum,AckdSeqNum,egressTransmitSeqNum,egressTransmitSeqNum%4096 );
}
//Check to see if the ACK/NAK sequence number is >= the oldest transmitted tlp
// sequence number
mailbox_get( COPY_NO_WAIT, mb_egressSeqNum, egressSeqNum );
//Get the difference between the lastAckd seq and the current Acks seq
if( (AckNakSeqNum - egressSeqNum%4096) >= 0 ){
seqDif = AckNakSeqNum - (egressSeqNum%4096);
}else{
seqDif = (AckNakSeqNum+4096) - (egressSeqNum%4096);
}
//4 review AckNakSeqNum=%0d egressTransmitSeqNum=%0d seqDif=%0d AckdSeqNum=%0d discardDllp=%0d\n",AckNakSeqNum,egressTransmitSeqNum,seqDif,AckdSeqNum,discardDllp );
for( i = 0; (i <= seqDif) && !discardDllp; i++ ){
//Pop the oldest unacknowledged tlp sequence number
mailbox_get( NO_WAIT, mb_egressSeqNum, egressSeqNum );
//Its an error if there aren't any credits to go with the sequence number
if( !mailbox_get( NO_WAIT, mb_egressRetry )){
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() mb_egressSeqNum had entry but mb_egressRetry didn't");
}
//... pull the credits returned for the TLP that goes with the egressSeqNum
mailbox_get( NO_WAIT, mb_egressRetry, dataCredits );
//Keep the running total of available retry credits
// the dut wil be several cycles behind in updating its credits
egressRetryAvail = egressRetryAvail + dataCredits;
//Make AckdSeqNum modulo to track with the incoming AckNakSeqNum
AckdSeqNum = egressSeqNum%4096;
}
//At this point its an error if the AckNakSeqNum != the last popped egressSeqNum
if( (AckNakSeqNum != egressSeqNum%4096) && !discardDllp ){
QuickReport( Report, RTYP_TEST_ERROR,
"Env::updateEgressCredits() AckNakSeqNum=%0d is not equal to egressSeqNum=%0d %4096=%0d after processing ACK/NAK ",AckNakSeqNum,egressSeqNum,egressSeqNum%4096 );
}
} //End //If an ACK or NAK has been received and there are credits
/*N2 review Comment out until fixed
randcase {
egressIdleWeight : {
// Do nothing this cycle
// Nothing to see here ...
}
egressInitPostWeight : {
f_LPUXtr.sendCreditInit(e_FC_posted, 0,
egressPostHdrInit,
egressPostDataInit);
}
egressInitNonpostWeight : {
f_LPUXtr.sendCreditInit(e_FC_nonposted, 0,
egressNonpostHdrInit,
egressNonpostDataInit);
}
egressInitCompletionWeight : {
f_LPUXtr.sendCreditInit(e_FC_completion, 0,
egressCompletionHdrInit,
egressCompletionDataInit);
}
egressUpdtPostWeight : {
//N2 review If Infinite credits send infinite update
if ( egressPostHdrAvail == infiniteCredits
&& egressPostDataAvail == infiniteCredits ) {
egressPostHdrToReturn = 0;
egressPostDataToReturn = 0;
f_LPUXtr.sendCreditUpdate( e_FC_posted, 0, 0, 0 );
}else {
if (( egressPostHdrAvail != infiniteCredits ) &&
( egressPostHdrAllowed == 1)) {
if (!sync(CHECK, egressPostHdrStopFlag)) {
integer distance =
((egressPostHdrStopValue % 256) - (egressPostHdrAvail % 256) + 256) % 256;
if (distance == 0) {
egressPostHdrAvail = egressPostHdrAvail;
trigger(ON, egressPostHdrStopFlag);
}else if (distance >= 4) {
egressPostHdrAvail +=
(egressPostHdrToReturn < 4) ? egressPostHdrToReturn : 4;
egressPostHdrToReturn =
(egressPostHdrToReturn < 4) ? 0 : egressPostHdrToReturn - 4;
}else {
egressPostHdrAvail +=
(egressPostHdrToReturn < distance) ? egressPostHdrToReturn : distance;
egressPostHdrToReturn =
(egressPostHdrToReturn < distance) ? 0 : egressPostHdrToReturn - distance;
}
}else {
egressPostHdrAvail +=
(egressPostHdrToReturn < 4) ? egressPostHdrToReturn : 4;
egressPostHdrToReturn =
(egressPostHdrToReturn < 4) ? 0 : egressPostHdrToReturn - 4;
}
}
if (( egressPostDataAvail != infiniteCredits ) &&
( egressPostDataAllowed == 1)) {
if (!sync(CHECK, egressPostDataStopFlag)) {
integer distance =
((egressPostDataStopValue % 4096) - (egressPostDataAvail % 4096) + 4096) % 4096;
if (distance == 0) {
egressPostDataAvail = egressPostDataAvail;
trigger(ON, egressPostDataStopFlag);
}else if (distance >= 16) {
egressPostDataAvail +=
(egressPostDataToReturn < 16) ? egressPostDataToReturn : 16;
egressPostDataToReturn =
(egressPostDataToReturn < 16) ? 0 : egressPostDataToReturn - 16;
}else {
egressPostDataAvail +=
(egressPostDataToReturn < distance) ? egressPostDataToReturn : distance;
egressPostDataToReturn =
(egressPostDataToReturn < distance) ? 0 : egressPostDataToReturn - distance;
}
}else {
egressPostDataAvail +=
(egressPostDataToReturn < 16) ? egressPostDataToReturn : 16;
egressPostDataToReturn =
(egressPostDataToReturn < 16) ? 0 : egressPostDataToReturn - 16;
}
}
f_LPUXtr.sendCreditUpdate( e_FC_posted, 0,
egressPostHdrAvail==infiniteCredits ? 0
: egressPostHdrAvail,
egressPostDataAvail==infiniteCredits ? 0
: egressPostDataAvail );
}//End else ! hdr & data infinite credits
}
egressUpdtNonpostWeight : {
if ( egressNonpostHdrAvail == infiniteCredits
&& egressNonpostDataAvail == infiniteCredits ) {
egressNonpostHdrToReturn = 0;
egressNonpostDataToReturn = 0;
f_LPUXtr.sendCreditUpdate( e_FC_nonposted, 0, 0, 0 );
}
else {
if (( egressNonpostHdrAvail != infiniteCredits ) &&
( egressNonpostHdrAllowed == 1)) {
if (!sync(CHECK, egressNonpostHdrStopFlag)) {
integer distance =
((egressNonpostHdrStopValue % 256) - (egressNonpostHdrAvail % 256) + 256) % 256;
if (distance == 0) {
egressNonpostHdrAvail = egressNonpostHdrAvail;
trigger(ON, egressNonpostHdrStopFlag);
}
else if (distance >= 4) {
egressNonpostHdrAvail +=
(egressNonpostHdrToReturn < 4) ? egressNonpostHdrToReturn : 4;
egressNonpostHdrToReturn =
(egressNonpostHdrToReturn < 4) ? 0 : egressNonpostHdrToReturn - 4;
}
else {
egressNonpostHdrAvail +=
(egressNonpostHdrToReturn < distance) ? egressNonpostHdrToReturn : distance;
egressNonpostHdrToReturn =
(egressNonpostHdrToReturn < distance) ? 0 : egressNonpostHdrToReturn - distance;
}
}
else {
egressNonpostHdrAvail +=
(egressNonpostHdrToReturn < 4) ? egressNonpostHdrToReturn : 4;
egressNonpostHdrToReturn =
(egressNonpostHdrToReturn < 4) ? 0 : egressNonpostHdrToReturn - 4;
}
}
if (( egressNonpostDataAvail != infiniteCredits ) &&
( egressNonpostDataAllowed == 1)) {
if (!sync(CHECK, egressNonpostDataStopFlag)) {
integer distance =
((egressNonpostDataStopValue % 4096) - (egressNonpostDataAvail % 4096) + 4096) % 4096;
if (distance == 0) {
egressNonpostDataAvail = egressNonpostDataAvail;
trigger(ON, egressNonpostDataStopFlag);
}
else if (distance >= 16) {
egressNonpostDataAvail +=
(egressNonpostDataToReturn < 16) ? egressNonpostDataToReturn : 16;
egressNonpostDataToReturn =
(egressNonpostDataToReturn < 16) ? 0 : egressNonpostDataToReturn - 16;
}
else {
egressNonpostDataAvail +=
(egressNonpostDataToReturn < distance) ? egressNonpostDataToReturn : distance;
egressNonpostDataToReturn =
(egressNonpostDataToReturn < distance) ? 0 : egressNonpostDataToReturn - distance;
}
}
else {
egressNonpostDataAvail +=
(egressNonpostDataToReturn < 16) ? egressNonpostDataToReturn : 16;
egressNonpostDataToReturn =
(egressNonpostDataToReturn < 16) ? 0 : egressNonpostDataToReturn - 16;
}
}
f_LPUXtr.sendCreditUpdate( e_FC_nonposted, 0,
egressNonpostHdrAvail==infiniteCredits ? 0
: egressNonpostHdrAvail,
egressNonpostDataAvail==infiniteCredits ? 0
: egressNonpostDataAvail );
}
}
egressUpdtCompletionWeight : {
if ( egressCompletionHdrAvail == infiniteCredits
&& egressCompletionDataAvail == infiniteCredits ) {
egressCompletionHdrToReturn = 0;
egressCompletionDataToReturn = 0;
f_LPUXtr.sendCreditUpdate( e_FC_completion, 0, 0, 0 );
}
else {
if (( egressCompletionHdrAvail != infiniteCredits ) &&
( egressCompletionHdrAllowed == 1)) {
if (!sync(CHECK, egressCompletionHdrStopFlag)) {
integer distance =
((egressCompletionHdrStopValue % 256) - (egressCompletionHdrAvail % 256) + 256) % 256;
if (distance == 0) {
egressCompletionHdrAvail = egressCompletionHdrAvail;
trigger(ON, egressCompletionHdrStopFlag);
}
else if (distance >= 4) {
egressCompletionHdrAvail +=
(egressCompletionHdrToReturn < 4) ? egressCompletionHdrToReturn : 4;
egressCompletionHdrToReturn =
(egressCompletionHdrToReturn < 4) ? 0 : egressCompletionHdrToReturn - 4;
}
else {
egressCompletionHdrAvail +=
(egressCompletionHdrToReturn < distance) ? egressCompletionHdrToReturn : distance;
egressCompletionHdrToReturn =
(egressCompletionHdrToReturn < distance) ? 0 : egressCompletionHdrToReturn - distance;
}
}
else {
egressCompletionHdrAvail +=
(egressCompletionHdrToReturn < 4) ? egressCompletionHdrToReturn : 4;
egressCompletionHdrToReturn =
(egressCompletionHdrToReturn < 4) ? 0 : egressCompletionHdrToReturn - 4;
}
}
if (( egressCompletionDataAvail != infiniteCredits ) &&
( egressCompletionDataAllowed == 1)) {
if (!sync(CHECK, egressCompletionDataStopFlag)) {
integer distance =
((egressCompletionDataStopValue % 4096) - (egressCompletionDataAvail % 4096) + 4096) % 4096;
if (distance == 0) {
egressCompletionDataAvail = egressCompletionDataAvail;
trigger(ON, egressCompletionDataStopFlag);
}
else if (distance >= 16) {
egressCompletionDataAvail +=
(egressCompletionDataToReturn < 16) ? egressCompletionDataToReturn : 16;
egressCompletionDataToReturn =
(egressCompletionDataToReturn < 16) ? 0 : egressCompletionDataToReturn - 16;
}
else {
egressCompletionDataAvail +=
(egressCompletionDataToReturn < distance) ? egressCompletionDataToReturn : distance;
egressCompletionDataToReturn =
(egressCompletionDataToReturn < distance) ? 0 : egressCompletionDataToReturn - distance;
}
}
else {
egressCompletionDataAvail +=
(egressCompletionDataToReturn < 16) ? egressCompletionDataToReturn : 16;
egressCompletionDataToReturn =
(egressCompletionDataToReturn < 16) ? 0 : egressCompletionDataToReturn - 16;
}
}
f_LPUXtr.sendCreditUpdate( e_FC_completion, 0,
egressCompletionHdrAvail==infiniteCredits ? 0
: egressCompletionHdrAvail,
egressCompletionDataAvail==infiniteCredits ? 0
: egressCompletionDataAvail );
}
}
egressInitPostVCNZWeight : {
f_LPUXtr.sendCreditInit( e_FC_posted, localRandomRange(7, 1),
localRandom(), localRandom());
}
egressInitNonpostVCNZWeight : {
f_LPUXtr.sendCreditInit( e_FC_nonposted, localRandomRange(7, 1),
localRandom(), localRandom());
}
egressInitCompletionVCNZWeight : {
f_LPUXtr.sendCreditInit( e_FC_completion, localRandomRange(7, 1),
localRandom(), localRandom());
}
egressUpdtPostVCNZWeight : {
f_LPUXtr.sendCreditUpdate( e_FC_posted, localRandomRange(7, 1),
localRandom(), localRandom());
}
egressUpdtNonpostVCNZWeight : {
f_LPUXtr.sendCreditUpdate( e_FC_nonposted, localRandomRange(7, 1),
localRandom(), localRandom());
}
egressUpdtCompletionVCNZWeight : {
f_LPUXtr.sendCreditUpdate( e_FC_completion, localRandomRange(7, 1),
localRandom(), localRandom());
}
egressUpdtPostNZAftInfWeight : {
_INFO_MSG( "Sending finite posted credit update" );
f_LPUXtr.sendCreditUpdate(e_FC_posted, 0,
(egressPostHdrAvail == infiniteCredits) ?
localRandom() : egressPostHdrAvail,
(egressPostDataAvail == infiniteCredits) ?
localRandom() : egressPostDataAvail
);
egressUpdateError = 1;
}
egressUpdtNonpostNZAftInfWeight : {
_INFO_MSG( "Sending finite non-posted credit update" );
f_LPUXtr.sendCreditUpdate(e_FC_nonposted, 0,
(egressNonpostHdrAvail == infiniteCredits) ?
localRandom() : egressNonpostHdrAvail,
(egressNonpostDataAvail == infiniteCredits) ?
localRandom() : egressNonpostDataAvail
);
egressUpdateError = 1;
}
egressUpdtCompletionNZAftInfWeight : {
_INFO_MSG( "Sending finite completion credit update" );
f_LPUXtr.sendCreditUpdate(e_FC_completion, 0,
(egressCompletionHdrAvail == infiniteCredits) ?
localRandom() : egressCompletionHdrAvail,
(egressCompletionDataAvail == infiniteCredits) ?
localRandom() : egressCompletionDataAvail
);
egressUpdateError = 1;
}
egressUpdtPostOverflowWeight : {
_INFO_MSG( "Sending overflow posted credit update" );
f_LPUXtr.sendCreditUpdate(e_FC_posted, 0,
(egressPostHdrAvail == infiniteCredits) ?
0 : egressPostHdrConsumed + localRandomRange(255, 138),
(egressPostDataAvail == infiniteCredits) ?
0 : egressPostDataConsumed + localRandomRange(4095, 2058)
);
egressUpdateError = 1;
}
egressUpdtNonpostOverflowWeight : {
_INFO_MSG( "Sending overflow non-posted credit update" );
f_LPUXtr.sendCreditUpdate(e_FC_nonposted, 0,
(egressNonpostHdrAvail == infiniteCredits) ?
0 : egressNonpostHdrConsumed + localRandomRange(255, 138),
(egressNonpostDataAvail == infiniteCredits) ?
0 : egressNonpostDataConsumed + localRandomRange(4095, 2058)
);
egressUpdateError = 1;
}
egressUpdtCompletionOverflowWeight : {
_INFO_MSG( "Sending overflow completion credit update" );
f_LPUXtr.sendCreditUpdate(e_FC_completion, 0,
(egressCompletionHdrAvail == infiniteCredits) ?
0 : egressCompletionHdrConsumed + localRandomRange(255, 138),
(egressCompletionDataAvail == infiniteCredits) ?
egressUpdateError = 1;
}
egressRetryWeight : {
if (( egressRetryAllowed == 1 ) &&
( mailbox_get( NO_WAIT, mb_egressRetry ) > 0 )) {
mailbox_get( NO_WAIT, mb_egressRetry, dataCredits );
egressRetryAvail = egressRetryAvail + dataCredits;
}
f_LPUXtr.advertiseRetryCredit( egressRetryAvail );
}
}
End N2 */
// @( posedge CLOCK );
if ( softResetPending ) return;
/* N2 moved below to returnEgressCredits()
// If we've been told to restore all
// credits, then let's do so.
if( returnAllEgressCredits ){
QuickReport( Report, RTYP_INFO,
"Env::updateEgressCredits() returnAllEgressCredits called N2- ");
}
*/
/*N2 review
if ( returnAllEgressCredits )
{
while ( mailbox_get( NO_WAIT, mb_egressRetry ) > 0 )
{
mailbox_get( NO_WAIT, mb_egressRetry, dataCredits );
egressRetryAvail = egressRetryAvail + dataCredits;
}
f_LPUXtr.advertiseRetryCredit( egressRetryAvail );
if ( ( egressPostHdrAvail != infiniteCredits
&& egressPostHdrToReturn > 0 )
|| ( egressPostDataAvail != infiniteCredits
&& egressPostDataToReturn > 0 ) )
{
if ( egressPostHdrAvail != infiniteCredits )
egressPostHdrAvail += egressPostHdrToReturn;
egressPostHdrToReturn = 0;
if ( egressPostDataAvail != infiniteCredits )
egressPostDataAvail += egressPostDataToReturn;
egressPostDataToReturn = 0;
f_LPUXtr.sendCreditUpdate(e_FC_posted, 0,
egressPostHdrAvail==infiniteCredits ? 0
: egressPostHdrAvail,
egressPostDataAvail==infiniteCredits ? 0
: egressPostDataAvail );
@( posedge CLOCK );
if ( softResetPending ) return;
}
if ( ( egressNonpostHdrAvail != infiniteCredits
&& egressNonpostHdrToReturn > 0 )
|| ( egressNonpostDataAvail != infiniteCredits
&& egressNonpostDataToReturn > 0 ) )
{
if ( egressNonpostHdrAvail != infiniteCredits )
egressNonpostHdrAvail += egressNonpostHdrToReturn;
egressNonpostHdrToReturn = 0;
if ( egressNonpostDataAvail != infiniteCredits )
egressNonpostDataAvail += egressNonpostDataToReturn;
egressNonpostDataToReturn = 0;
f_LPUXtr.sendCreditUpdate(e_FC_nonposted, 0,
egressNonpostHdrAvail==infiniteCredits ? 0
: egressNonpostHdrAvail,
egressNonpostDataAvail==infiniteCredits ? 0
: egressNonpostDataAvail );
@( posedge CLOCK );
if ( softResetPending ) return;
}
if ( ( egressCompletionHdrAvail != infiniteCredits
&& egressCompletionHdrToReturn > 0 )
|| ( egressCompletionDataAvail != infiniteCredits
&& egressCompletionDataToReturn > 0 ) )
{
if ( egressCompletionHdrAvail != infiniteCredits )
egressCompletionHdrAvail += egressCompletionHdrToReturn;
egressCompletionHdrToReturn = 0;
if ( egressCompletionDataAvail != infiniteCredits )
egressCompletionDataAvail += egressCompletionDataToReturn;
egressCompletionDataToReturn = 0;
f_LPUXtr.sendCreditUpdate(e_FC_completion, 0,
egressCompletionHdrAvail==infiniteCredits ? 0
: egressCompletionHdrAvail,
egressCompletionDataAvail==infiniteCredits ? 0
: egressCompletionDataAvail );
@( posedge CLOCK );
if ( softResetPending ) return;
}
returnAllEgressCredits = 0;
} // end "if (returnAllEgressCredits)..."
END N2 */
// Record whether we think the TLU is out of credits for each TLP type.
// The "round robin" checker in "expectTLU" uses this... it let's a violation
// get through if credits have been lean recently.
egressPostStarved[30:0] = egressPostStarved[31:1];
egressNonpostStarved[30:0] = egressNonpostStarved[31:1];
egressCompletionStarved[30:0] = egressCompletionStarved[31:1];
egressPostStarved[20] =
areEgressCreditsExhausted( PEC_CREDIT_TYPE__UPDT_POST, 0 )
|| areEgressCreditsExhausted( PEC_CREDIT_TYPE__UPDT_POST, 1 );
egressNonpostStarved[20] =
areEgressCreditsExhausted( PEC_CREDIT_TYPE__UPDT_NONPOST, 0 )
|| areEgressCreditsExhausted( PEC_CREDIT_TYPE__UPDT_NONPOST, 1 );
egressCompletionStarved[20] =
areEgressCreditsExhausted( PEC_CREDIT_TYPE__UPDT_COMP, 0 )
|| areEgressCreditsExhausted( PEC_CREDIT_TYPE__UPDT_COMP, 1 );
}
} /* end updateEgressCredits */
/*
* hangDetect - Watch the "activityCounter" and report an error if it doesn't
* move for a significant period of time
*/
task PEUTestEnv::hangDetect()
{
#ifndef N2_FC
integer lastCount;
integer quietTime;
string errMsg;
activityCounter = 0;
activityStalled = 0;
activityTimeout = 750;
lastCount = 0;
quietTime = 0;
while( lastCount >= 0 )
{
@( posedge CLOCK );
if( softResetPending ) break; // If something just happened, then
// reset our local counter and timer.
if ( lastCount != activityCounter || softResetPending )
{
lastCount = activityCounter;
quietTime = 0;
}
// If we aren't expecting any activity
// then (again) reset the timer so that
// it doesn't go off.
else if ( activityStalled )
{
quietTime = 0;
}
// Otherwise, bump the timer...
else if ( quietTime < activityTimeout )
{
quietTime = quietTime + 1;
}
// ...or blow up if we've been inactive
// for too long.
else if ( lastCount > 0 )
{
_REPORT_ERROR( "HANG DETECT\n" );
sprintf( errMsg, " activityStalled=%0d quietTime=%0d activityTimeout=%0d lastCount=%0d",
activityStalled,quietTime,activityTimeout,lastCount );
_ERROR_INFO( errMsg );
// Try to describe everything that might
// be in the way of making progress.
_ERROR_INFO( "Egress credits (hdr/data)..." );
sprintf( errMsg, " Post: %0d/%0d Npst: %0d/%0d Cpln: %0d/%0d",
egressPostHdrAvail == infiniteCredits ? 999
: egressPostHdrAvail - egressPostHdrConsumed,
egressPostDataAvail == infiniteCredits ? 999
: egressPostDataAvail - egressPostDataConsumed,
egressNonpostHdrAvail == infiniteCredits ? 999
: egressNonpostHdrAvail - egressNonpostHdrConsumed,
egressNonpostDataAvail == infiniteCredits ? 999
: egressNonpostDataAvail - egressNonpostDataConsumed,
egressCompletionHdrAvail == infiniteCredits ? 999
: egressCompletionHdrAvail - egressCompletionHdrConsumed,
egressCompletionDataAvail == infiniteCredits ? 999
: egressCompletionDataAvail - egressCompletionDataConsumed );
_ERROR_INFO( errMsg );
_ERROR_INFO( "Ingress credits (hdr/data)..." );
sprintf( errMsg, " Post: %0d/%0d Npst: %0d/%0d Cpln: %0d/%0d",
ingressPostHdrAvail == infiniteCredits ? 999
: ingressPostHdrAvail - ingressPostHdrConsumed,
ingressPostDataAvail == infiniteCredits ? 999
: ingressPostDataAvail - ingressPostDataConsumed,
ingressNonpostHdrAvail == infiniteCredits ? 999
: ingressNonpostHdrAvail - ingressNonpostHdrConsumed,
ingressNonpostDataAvail == infiniteCredits ? 999
: ingressNonpostDataAvail - ingressNonpostDataConsumed,
ingressCompletionHdrAvail == infiniteCredits ? 999
: ingressCompletionHdrAvail - ingressCompletionHdrConsumed,
ingressCompletionDataAvail == infiniteCredits ? 999
: ingressCompletionDataAvail-ingressCompletionDataConsumed );
_ERROR_INFO( errMsg );
sprintf( errMsg, "Retry credits = %0d (%0d avail, %0d consumed)",
egressRetryAvail - egressRetryConsumed,
egressRetryAvail, egressRetryConsumed );
_ERROR_INFO( errMsg );
sprintf( errMsg, "DMA DOU blocks reserved: %h", douBlksUsed );
_ERROR_INFO( errMsg );
if ( douBlksRequest > 0 )
{
sprintf( errMsg, "Outstanding request for %0d DOU blocks",
douBlksRequest );
_ERROR_INFO( errMsg );
}
sprintf( errMsg, "PIO tags reserved: %h", pioTagsUsed );
_ERROR_INFO( errMsg );
sprintf( errMsg, "Pending non-posted PIO tags: %h", nonpostReqPending );
_ERROR_INFO( errMsg );
sprintf( errMsg, "..and those held in the TLU: %h", nonpostReqInLimbo );
_ERROR_INFO( errMsg );
sprintf( errMsg, "%0d/%0d egress req/cpl TLPs expected from the PEU",
mailbox_get( NO_WAIT, mb_egressReqOrder ),
mailbox_get( NO_WAIT, mb_egressCplOrder ) );
_ERROR_INFO( errMsg );
sprintf( errMsg, "%0d ingress TLPs expected from the ILU",
iluExpectReq - iluExpectComplete );
_ERROR_INFO( errMsg );
sprintf( errMsg, "%0d egress TLPs expected from the PEU",
peuExpectTlp - peuExpectComplete );
_ERROR_INFO( errMsg );
sprintf( errMsg, "DMU credits: ingress=%0d egress=%0d",
f_DMUXtr.ingressCreditsAvailable(),
f_DMUXtr.egressCreditsAvailable() );
_ERROR_INFO( errMsg );
dumpCreditStatus();
getIntStatus();
dumpIntStatus();
}
}
#endif
} /* end hangDetect */
/* N2 - Not needed since we're testing ilu-peu
* diddleDack - Play around with the egress "data ack" signal.
*
* This is a permanent thread which asserts/deasserts "l2t_etp_dack"
* as directed by "egressThrottle" (set by the public method "setEgressThrottle")
* If "egressThrottleRandom" is specified, then we'll use a value from {0,20,50}
* with the value changing every thousand cycles (or so).
*/
task PEUTestEnv::diddleDack()
{
// N2 - Not needed
} /* end diddleDack */
/*
* monitorInt - Enable interrupts and make sure that we get only only when
* we expect one.
*
* Parameters:
* EnableErrs - Should we call "enableAllErrors"?
*/
task PEUTestEnv::monitorInt( bit EnableErrs )
{
#ifndef N2_FC
if ( EnableErrs ) enableAllErrors();
while( 1 )
{
@( posedge CLOCK );
//miscPort.$int is active low
if ( !Pod.DMUXtr.miscPort.$int && !interruptExpected && !softResetPending )
{
getIntStatus();
showUnexpectedInt();
dumpIntStatus();
dumpCreditStatus();
}
else if ( !Pod.DMUXtr.miscPort.$int && interruptExpected && !softResetPending )
{
if ( interruptUnchecked==0 ) interruptUnchecked = 1;
}
else if ( Pod.DMUXtr.miscPort.$int && interruptUnchecked==1 && !softResetPending )
{
_REPORT_ERROR( "Interrupt not caught by test" );
}
}
#endif
} /* end monitorInt */
/*
* disableInterrupt - A test/strategy/whatever is expecting an interrupt
*
* Parameters: None
*/
task PEUTestEnv::disableInterrupt()
{
interruptExpected = interruptExpected + 1;
} /* end disableInterrupt */
/*
* enableInterrupt - A test no longer expects an interrupt
*
* Parameters: None
*/
task PEUTestEnv::enableInterrupt()
{
if ( interruptExpected )
interruptExpected = interruptExpected - 1;
if ( interruptExpected == 0 ) interruptUnchecked = 0;
} /* end enableInterrupt */
/*
* expectInterrupt - A test either expects (or does not expect) an interrupt
*
* Parameters:
* Expected - Is an interrupt expected?
*/
function bit PEUTestEnv::expectInterrupt( bit Expected )
{
#ifndef N2_FC
//miscPort.$int is active low
if ( !Pod.DMUXtr.miscPort.$int && !Expected )
{
_REPORT_ERROR( "Interrupt from ILU when none expected by test" );
getIntStatus();
dumpIntStatus();
expectInterrupt = 1;
}
else if ( Pod.DMUXtr.miscPort.$int && Expected )
{
_REPORT_ERROR( "No interrupt from ILU when one is expected by test" );
getIntStatus();
dumpIntStatus();
expectInterrupt = 1;
}
else
{
expectInterrupt = 0;
Report.report(RTYP_DEBUG_3,"PEUTestEnv.expectInterrupt good Expected=%0b \n",Expected);
}
if ( interruptUnchecked==1 ) interruptUnchecked = 2;
#endif
} /* end expectInterrupt */
//Wait until an Interrupt is signaled
task PEUTestEnv::waitInterrupt()
{
//miscPort.$int is active low
while ( Pod.DMUXtr.miscPort.$int ){
@( posedge CLOCK );
}
} /* end waitInterrupt */
/*
* enableAllErrors - Set all interrupt-enable bits so that any error results
* in an interrupt, halting simulation if "disableInterrupt"
* has not been called.
*
* Parameters: None
*/
task PEUTestEnv::enableAllErrors()
{
#ifndef N2_FC
bit [63:0] ones;
integer lupIndex;
ones = ~ 64'b0;
_INFO_MSG( "Enable all errors (but not the 'link up' event)" );
// Enable all ILU + TLU(PEC) interrupts
#ifdef N2_IOS
f_CSR.CSR.fire_dlc_ilu_cib_csr_a_pec_int_en.write(ones,CSRT_OMNI);
#else
f_CSR.CSR.fire_dlc_ilu_cib_csr_a_pec_int_en.write(ones,FIRE_PIO_MED);
#endif
// Enable all ILU interrupts
f_CSR.CSR.fire_dlc_ilu_cib_csr_a_ilu_log_en.write(ones,CSRT_OMNI);
f_CSR.CSR.fire_dlc_ilu_cib_csr_a_ilu_int_en.write(ones,CSRT_OMNI);
// Enable all uncorrectable TLU(+LPU) interrupts
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ue_log.write(ones,CSRT_OMNI);
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ue_int_en.write(ones,CSRT_OMNI);
// Enable all correctable TLU(+LPU) interrupts
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ce_log.write(ones,CSRT_OMNI);
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ce_int_en.write(ones,CSRT_OMNI);
// Enable all other TLU(+LPU) interrupts
// EXCEPT "link up", which isn't an error at all!
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_oe_log.write(ones,CSRT_OMNI);
lupIndex = PEC_ERR_bitIndex( e_ERR_oe_lup );
ones[lupIndex] = 1'b0;
ones[lupIndex+32] = 1'b0;
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_oe_int_en.write(ones,CSRT_OMNI);
// Enable all DLPL error interrupts
//Don't enable the allignment error as there are deskew errors during link training
//LOS can occur in detect so disable it here and reenable in LinkTraining Strategy
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_event_err_int_en.write(63'h3bfff,CSRT_OMNI);
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_event_err_log_en.write(FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_INT_EN_EN_ERROR_FMASK&63'h3fffe,CSRT_OMNI);
// If the interrupt monitor isn't running, then start it up!
if ( !intMonitorActive )
{
intMonitorActive = 1;
fork
monitorInt(0);
join none
}
#endif
} /* end enableAllErrors */
/*
* getIntStatus - collect interrupt status
*
* Parameters: None
*/
task PEUTestEnv::getIntStatus()
{
intCSR[0] = readCSRdirect( getCSRaddr(e_CSR_pec_int_en) );
intCSR[1] = readCSR( getCSRaddr(e_CSR_pec_err) );
//intCSR[1] = 64'bx;
intCSR[2] = readCSRdirect( getCSRaddr(e_CSR_ilu_int_en) );
intCSR[3] = readCSRdirect( getCSRaddr(e_CSR_ilu_log_en) );
intCSR[4] = readCSRdirect( getCSRaddr(e_CSR_ilu_err) );
intCSR[5] = readCSRdirect( getCSRaddr(e_CSR_ue_int_en) );
intCSR[6] = readCSRdirect( getCSRaddr(e_CSR_ue_log_en) );
intCSR[7] = readCSRdirect( getCSRaddr(e_CSR_ue_err) );
intCSR[8] = readCSRdirect( getCSRaddr(e_CSR_ue_recv_hdr1) );
intCSR[9] = readCSRdirect( getCSRaddr(e_CSR_ue_recv_hdr2) );
intCSR[10] = readCSRdirect( getCSRaddr(e_CSR_ue_xmit_hdr1) );
intCSR[11] = readCSRdirect( getCSRaddr(e_CSR_ue_xmit_hdr2) );
intCSR[12] = readCSRdirect( getCSRaddr(e_CSR_ce_int_en) );
intCSR[13] = readCSRdirect( getCSRaddr(e_CSR_ce_log_en) );
intCSR[14] = readCSRdirect( getCSRaddr(e_CSR_ce_err) );
intCSR[15] = readCSRdirect( getCSRaddr(e_CSR_oe_int_en) );
intCSR[16] = readCSRdirect( getCSRaddr(e_CSR_oe_log_en) );
intCSR[17] = readCSRdirect( getCSRaddr(e_CSR_oe_err) );
intCSR[18] = readCSRdirect( getCSRaddr(e_CSR_oe_recv_hdr1) );
intCSR[19] = readCSRdirect( getCSRaddr(e_CSR_oe_recv_hdr2) );
intCSR[20] = readCSRdirect( getCSRaddr(e_CSR_oe_xmit_hdr1) );
intCSR[21] = readCSRdirect( getCSRaddr(e_CSR_oe_xmit_hdr2) );
intCSR[22] = readCSRdirect( getCSRaddr(e_CSR_dlpl_ee_int_en) );
intCSR[23] = readCSRdirect( getCSRaddr(e_CSR_dlpl_ee_log_en) );
intCSR[24] = readCSRdirect( getCSRaddr(e_CSR_dlpl_ee_err) );
} /* end getIntStatus */
/*
* dumpIntStatus - Write messages describing the state of the ILU/TLU error
* reporting (interrupt) mechanism
*
* Parameters: None
*/
task PEUTestEnv::dumpIntStatus()
{
string msg;
sprintf( msg, "PEC interrupt enable....... %h", intCSR[0] );
_ERROR_INFO(msg);
sprintf( msg, "PEC errors................. %h", intCSR[1] );
_ERROR_INFO(msg);
sprintf( msg, "ILU error log enable....... %h", intCSR[3] );
_ERROR_INFO(msg);
sprintf( msg, "ILU interrupt enable....... %h", intCSR[2] );
_ERROR_INFO(msg);
sprintf( msg, "ILU errors................. %h", intCSR[4] );
_ERROR_INFO(msg);
sprintf( msg, "TLU UE error log enable.... %h", intCSR[6] );
_ERROR_INFO(msg);
sprintf( msg, "TLU UE interrupt enable.... %h", intCSR[5] );
_ERROR_INFO(msg);
sprintf( msg, "TLU uncorrectable errors... %h", intCSR[7] );
_ERROR_INFO(msg);
sprintf( msg, "TLU UE logged 'R' header... %h %h", intCSR[8], intCSR[9] );
_ERROR_INFO(msg);
sprintf( msg, "TLU UE logged 'T' header... %h %h", intCSR[10], intCSR[11] );
_ERROR_INFO(msg);
sprintf( msg, "TLU CE error log enable.... %h", intCSR[13] );
_ERROR_INFO(msg);
sprintf( msg, "TLU CE interrupt enable.... %h", intCSR[12] );
_ERROR_INFO(msg);
sprintf( msg, "TLU correctable errors..... %h", intCSR[14] );
_ERROR_INFO(msg);
sprintf( msg, "TLU OE error log enable.... %h", intCSR[16] );
_ERROR_INFO(msg);
sprintf( msg, "TLU OE interrupt enable.... %h", intCSR[15] );
_ERROR_INFO(msg);
sprintf( msg, "TLU 'other' errors......... %h", intCSR[17] );
_ERROR_INFO(msg);
sprintf( msg, "TLU OE logged 'R' header... %h %h", intCSR[18], intCSR[19] );
_ERROR_INFO(msg);
sprintf( msg, "TLU OE logged 'T' header... %h %h", intCSR[20], intCSR[21] );
_ERROR_INFO(msg);
sprintf( msg, "DLPL error log enable....... %h", intCSR[23] );
_ERROR_INFO(msg);
sprintf( msg, "DLPL interrupt enable....... %h", intCSR[22] );
_ERROR_INFO(msg);
sprintf( msg, "DLPL errors................. %h", intCSR[24] );
_ERROR_INFO(msg);
} /* end dumpIntStatus */
/*
* showUnexpectedInt - shows BY NAME which unexpected interrupt(s) occurred
*
* Parameters: None
*/
task PEUTestEnv::showUnexpectedInt()
{
PEC_ERRtype err;
string msg;
integer lupIndex;
integer bitIndex;
/* Uncorrectable Errors */
bitIndex = 0;
while ( ( bitIndex < 64 ) && ( (intCSR[5][bitIndex] & intCSR[7][bitIndex]) != 1 ) )
bitIndex++;
if ( bitIndex < 64 ) {
err = e_ERR_ue_mfp;
while ( ( err <= e_ERR_ue_dlp ) && ( PEC_ERR_bitIndex( err ) != ( bitIndex % 32 ) ) )
err++;
if ( err <= e_ERR_ue_dlp ) {
case (err)
{
e_ERR_ue_mfp: _REPORT_ERROR( "Unexpected malformed packet error interrupt!" );
e_ERR_ue_rof: _REPORT_ERROR( "Unexpected Receiver overflow interrupt!" );
e_ERR_ue_ur: _REPORT_ERROR( "Unexpected Unsupported request interrupt!" );
e_ERR_ue_uc: _REPORT_ERROR( "Unexpected Unexpected completion interrupt!" );
e_ERR_ue_cto: _REPORT_ERROR( "Unexpected Completion time-out interrupt!" );
e_ERR_ue_fcp: _REPORT_ERROR( "Unexpected Flow-control protocol error interrupt!" );
e_ERR_ue_pp: _REPORT_ERROR( "Unexpected Poisoned TLP received interrupt!" );
e_ERR_ue_dlp: _REPORT_ERROR( "Unexpected Data-link protocol error (LPU) interrupt!" );
//N2 - removed .81 PRM e_ERR_ue_te: _REPORT_ERROR( "Unexpected Training error (LPU) interrupt!" );
default: { sprintf(msg, "case default Unexpected unknown (bit %0d) uncorrectable error interrupt!", bitIndex );
_REPORT_ERROR( msg );
}
}
} else {
sprintf(msg, "Unexpected unknown (bit %0d) uncorrectable error interrupt!", bitIndex );
_REPORT_ERROR( msg );
}
}
/* Correctable Errors */
bitIndex = 0;
while ( ( bitIndex < 64 ) && ( (intCSR[12][bitIndex] & intCSR[14][bitIndex]) != 1 ) )
bitIndex++;
if ( bitIndex < 64 ) {
err = e_ERR_ce_rto;
while ( ( err <= e_ERR_ce_re ) && ( PEC_ERR_bitIndex( err ) != ( bitIndex % 32 ) ) )
err++;
if ( err <= e_ERR_ce_re ) {
case (err)
{
e_ERR_ce_rto: _REPORT_ERROR( "Unexpected Replay time-out (PEU) interrupt!" );
e_ERR_ce_rnr: _REPORT_ERROR( "Unexpected Replay roll-over (PEU) interrupt!" );
e_ERR_ce_bdp: _REPORT_ERROR( "Unexpected Bad DLLP (PEU) interrupt!" );
e_ERR_ce_btp: _REPORT_ERROR( "Unexpected Bad TLP (PEU) interrupt!" );
e_ERR_ce_re: _REPORT_ERROR( "Unexpected Receiver error (PEU) interrupt!" );
default: { sprintf(msg, "case default Unexpected unknown (bit %0d) correctable error interrupt!", bitIndex );
_REPORT_ERROR( msg );
}
}
} else {
sprintf(msg, "Unexpected unknown (bit %0d) correctable error interrupt!", bitIndex );
_REPORT_ERROR( msg );
}
}
/* Other Errors */
bitIndex = 0;
while ( ( bitIndex < 64 ) && ( (intCSR[15][bitIndex] & intCSR[17][bitIndex]) != 1 ) )
bitIndex++;
if ( bitIndex < 64 ) {
err = e_ERR_oe_mrc;
while ( ( err <= e_ERR_oe_eip ) && ( PEC_ERR_bitIndex( err ) != ( bitIndex % 32 ) ) )
err++;
if ( err <= e_ERR_oe_eip ) {
case (err)
{
e_ERR_oe_mrc: _REPORT_ERROR( "Unexpected Memory read capture interrupt!" );
e_ERR_oe_cto: _REPORT_ERROR( "Unexpected Completion time-out (dup) interrupt!" );
e_ERR_oe_mfc: _REPORT_ERROR( "Unexpected Malformed completion interrupt!" );
e_ERR_oe_nfp: _REPORT_ERROR( "Unexpected No forward progress interrupt!" );
e_ERR_oe_lwc: _REPORT_ERROR( "Unexpected Link-width change interrupt!" );
e_ERR_oe_wuc: _REPORT_ERROR( "Unexpected Unsuccessful cpl to write interrupt!" );
e_ERR_oe_ruc: _REPORT_ERROR( "Unexpected Unsuccessful cpl to read interrupt!" );
e_ERR_oe_crs: _REPORT_ERROR( "Unexpected Cfg cpl'n with retry status interrupt!" );
e_ERR_oe_iip: _REPORT_ERROR( "Unexpected Ingress interface parity err interrupt!" );
e_ERR_oe_edp: _REPORT_ERROR( "Unexpected Egress data (EDB) parity err interrupt!" );
e_ERR_oe_ehp: _REPORT_ERROR( "Unexpected Egress hdr (EHB) parity err interrupt!" );
e_ERR_oe_lin: _REPORT_ERROR( "Unexpected Link interrupt interrupt!" );
e_ERR_oe_lrs: _REPORT_ERROR( "Unexpected Link reset interrupt!" );
e_ERR_oe_ldn: _REPORT_ERROR( "Unexpected Link down interrupt!" );
e_ERR_oe_lup: _REPORT_ERROR( "Unexpected Link up interrupt!" );
e_ERR_oe_eru: _REPORT_ERROR( "Unexpected Retry buffer underflow interrupt!" );
e_ERR_oe_ero: _REPORT_ERROR( "Unexpected Retry buffer overflow interrupt!" );
e_ERR_oe_emp: _REPORT_ERROR( "Unexpected Egress minimum pkt error interrupt!" );
e_ERR_oe_epe: _REPORT_ERROR( "Unexpected Egress protocol error interrupt!" );
e_ERR_oe_erp: _REPORT_ERROR( "Unexpected Egress retry parity error interrupt!" );
e_ERR_oe_eip: _REPORT_ERROR( "Unexpected Egress interface parity error interrupt!" );
default: { sprintf(msg, "case default Unexpected unknown (bit %0d) other error interrupt!", bitIndex );
_REPORT_ERROR( msg );
}
}
} else {
sprintf(msg, "Unexpected unknown (bit %0d) other error interrupt!", bitIndex );
_REPORT_ERROR( msg );
}
}
/* DLPL Errors */
bitIndex = 0;
while ( ( bitIndex < 64 ) && ( (intCSR[22][bitIndex] & intCSR[24][bitIndex]) != 1 ) )
bitIndex++;
if ( bitIndex < 64 ) {
err = e_ERR_dlpl_sds_los;
while ( ( err <= e_ERR_dlpl_out_skip ) && ( PEC_ERR_bitIndex( err ) != ( bitIndex % 32 ) ) )
err++;
if ( err <= e_ERR_dlpl_out_skip ) {
case (err)
{
e_ERR_dlpl_sds_los: _REPORT_ERROR( "Unexpected Serdes Loss Signal interrupt!" );
e_ERR_dlpl_src_tlp: _REPORT_ERROR( "Unexpected Ingress TLP w/ inverted CRC and EDB interrupt!" );
e_ERR_dlpl_unsup_dllp: _REPORT_ERROR( "Unexpected Ingress Unsupported DLLP interrupt!" );
e_ERR_dlpl_ill_stp_pos: _REPORT_ERROR( "Unexpected Ingress illegal STP position interrupt!" );
e_ERR_dlpl_ill_sdp_pos: _REPORT_ERROR( "Unexpected Ingress illegal SDP position interrupt!" );
e_ERR_dlpl_multi_stp: _REPORT_ERROR( "Ingress multiple stp without END/EDB interrupt!" );
e_ERR_dlpl_multi_sdp: _REPORT_ERROR( "Ingress multiple sdp without END/EDB interrupt!" );
e_ERR_dlpl_ill_pad_pos: _REPORT_ERROR( "Unexpected Ingress illegal pad position interrupt!" );
e_ERR_dlpl_stp_no_end_edb: _REPORT_ERROR( "Unexpected Ingress STP without END/EDB interrupt!" );
e_ERR_dlpl_sdp_no_end: _REPORT_ERROR( "Unexpected Ingress SDP without END interrupt!" );
e_ERR_dlpl_end_no_stp_sdp: _REPORT_ERROR( "Unexpected Ingress END without STP/SDP interrupt!" );
e_ERR_dlpl_sync: _REPORT_ERROR( "Unexpected Lost bit/byte sync interrupt!" );
e_ERR_dlpl_ill_end_pos: _REPORT_ERROR( "Unexpected Ingress illegal END position interrupt!" );
e_ERR_dlpl_kchar_dllp: _REPORT_ERROR( "Unexpected Ingress kchar in dllp interrupt!" );
e_ERR_dlpl_align: _REPORT_ERROR( "Unexpected Alignment error interrupt!" );
e_ERR_dlpl_elas_fifo_ovfl: _REPORT_ERROR( "Unexpected Elastic fifo overflow interrupt!" );
e_ERR_dlpl_elas_fifo_unfl: _REPORT_ERROR( "Unexpected Elastic fifo underflow interrupt!" );
e_ERR_dlpl_out_skip: _REPORT_ERROR( "Unexpected Number of outstanding SKIPs > 6 interrupt!" );
default: { sprintf(msg, "case default Unexpected unknown (bit %0d) DLPL error interrupt!", bitIndex );
_REPORT_ERROR( msg );
}
}
} else {
sprintf(msg, "Unexpected unknown (bit %0d) DLPL error interrupt!", bitIndex );
_REPORT_ERROR( msg );
}
}
} /* end showUnexpectedInt */
//N2-Not Needed
/*
* monitorAHB - A "transactor" for the TLU/LPU AHB port
*
* Parameters: None
*/
task PEUTestEnv::monitorAHB()
{
/* N2
bit [31:0] csrAddr;
bit [31:0] dataOut;
integer delay;
integer i;
bit retry;
// Initialize all LPU registers
for (i=0; i<PEC_LPU_CSR_MAX_COUNT; i++ ) lpuCsr[i] = 0;
// There is no pending AHB request
delay = 0;
// We haven't asked for a "retry"
retry = 0;
// Monitor the AHB interface
while( 1 )
{
if ( delay && TLU_AHB.Msel && TLU_AHB.Mready && TLU_AHB.Mtrans == 2'b10 )
{
_REPORT_ERROR( "TLU submits AHB request while another is in progress" );
}
// If the bus-master is asking us to
// perform a (nonsequential) transfer...
if ( !delay && TLU_AHB.Msel && TLU_AHB.Mready && TLU_AHB.Mtrans == 2'b10 )
{
// Make sure that a single-word
// read/write is requested.
if ( TLU_AHB.Msize != 3'b010 )
{
_REPORT_ERROR( "Invalid non-word AHB request from TLU!" );
}
if ( TLU_AHB.Mburst != 3'b000 )
{
_REPORT_ERROR( "Invalid 'burst' AHB request from TLU!" );
}
// Get the CSR's index from the address
csrAddr = TLU_AHB.Maddr[PEC_LPU_CSR_AHB_ADDR];
// Then either write it...
if ( TLU_AHB.Mwrite )
{
lpuCsr[ csrAddr ] = TLU_AHB.Mwdata;
dataOut = 32'bx;
retry = 0;
}
// ...or read it.
else
{
dataOut = lpuCsr[ csrAddr ];
if ( retry )
retry = 0;
else
retry = 0; // If we wanted to retry, we'd set it to one...
}
// We'll take the delay from the addr.
delay = csrAddr[2:0] + 1;
}
// All done!
@1 TLU_AHB.Sready = void;
if ( softResetPending )
{
if ( delay > 0 )
{
TLU_AHB.Srdata <= 32'b0;
TLU_AHB.Sready <= 1;
@1 TLU_AHB.Sready = void;
}
delay = 0;
TLU_AHB.Sready <= 0;
}
else if ( delay == 1 )
{
TLU_AHB.Srdata <= dataOut;
TLU_AHB.Sready <= 1;
if ( retry )
TLU_AHB.Sresp <= 2'b10;
else
TLU_AHB.Sresp <= 2'b00;
}
else
{
TLU_AHB.Srdata <= 32'bx;
TLU_AHB.Sready <= 0;
}
if ( delay > 0 ) delay = delay - 1;
}
END N2 */
} /* end monitorAHB */
/*
* getCSRaddr - Obtain the address of an ILU/TLU CSR
*
* Parameters:
* csr - An indication of the CSR of interest
*
* Returned value: The "csr's" address
*/
function integer PEUTestEnv::getCSRaddr( PEC_CSRtype csr )
{
integer addr;
case ( csr )
{
e_CSR_pec_int_en :
addr = FIRE_DLC_ILU_CIB_CSR_A_PEC_INT_EN_ADDR;
e_CSR_pec_err :
addr = FIRE_DLC_ILU_CIB_CSR_A_PEC_EN_ERR_ADDR;
e_CSR_ilu_int_en :
addr = FIRE_DLC_ILU_CIB_CSR_A_ILU_INT_EN_ADDR;
e_CSR_ilu_log_en :
addr = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_EN_ADDR;
e_CSR_ilu_en_err :
addr = FIRE_DLC_ILU_CIB_CSR_A_ILU_EN_ERR_ADDR;
e_CSR_ilu_err :
addr = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1C_ALIAS_ADDR;
e_CSR_ilu_err_diag :
addr = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_ADDR;
e_CSR_ilu_diagnos :
addr = FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_ADDR;
e_CSR_dev_cap :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CAP_ADDR;
e_CSR_dev_ctl :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_ADDR;
e_CSR_dev_status :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_STS_ADDR;
e_CSR_lnk_cap :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CAP_ADDR;
e_CSR_lnk_ctl :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_ADDR;
e_CSR_lnk_status :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_ADDR;
e_CSR_slot_cap :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_SLT_CAP_ADDR;
e_CSR_pme_ctl :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TRN_OFF_ADDR;
e_CSR_ue_int_en :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_INT_EN_ADDR;
e_CSR_ue_log_en :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_LOG_ADDR;
e_CSR_ue_en_err :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_EN_ERR_ADDR;
e_CSR_ue_err :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1C_ALIAS_ADDR;
e_CSR_ue_err_diag :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1S_ALIAS_ADDR;
e_CSR_ue_recv_hdr1 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR1_ADDR;
e_CSR_ue_recv_hdr2 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR2_ADDR;
e_CSR_ue_xmit_hdr1 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR1_ADDR;
e_CSR_ue_xmit_hdr2 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR2_ADDR;
e_CSR_ce_int_en :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_INT_EN_ADDR;
e_CSR_ce_log_en :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_LOG_ADDR;
e_CSR_ce_en_err :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_EN_ERR_ADDR;
e_CSR_ce_err :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1C_ALIAS_ADDR;
e_CSR_ce_err_diag :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1S_ALIAS_ADDR;
e_CSR_oe_int_en :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_INT_EN_ADDR;
e_CSR_oe_log_en :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_LOG_ADDR;
e_CSR_oe_en_err :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_EN_ERR_ADDR;
e_CSR_oe_err :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1C_ALIAS_ADDR;
e_CSR_oe_err_diag :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1S_ALIAS_ADDR;
e_CSR_oe_recv_hdr1 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR1_ADDR;
e_CSR_oe_recv_hdr2 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR2_ADDR;
e_CSR_oe_xmit_hdr1 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR1_ADDR;
e_CSR_oe_xmit_hdr2 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR2_ADDR;
e_CSR_tlu_ctl :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_ADDR;
e_CSR_tlu_stat :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_ADDR;
e_CSR_tlu_diag :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DIAG_ADDR;
e_CSR_tlu_debug_a :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_A_ADDR;
e_CSR_tlu_debug_b :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_B_ADDR;
e_CSR_ecrdt_avail :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECL_ADDR;
e_CSR_ecrdt_used :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECC_ADDR;
e_CSR_retry_crdt :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ERB_ADDR;
e_CSR_icrdt_init :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_ADDR;
e_CSR_icrdt_avail :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICA_ADDR;
e_CSR_icrdt_used :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICR_ADDR;
e_CSR_tlu_prfc :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRFC_ADDR;
e_CSR_tlu_prf0 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF0_ADDR;
e_CSR_tlu_prf1 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF1_ADDR;
e_CSR_tlu_prf2 :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF2_ADDR;
e_CSR_core_status :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_ADDR;
e_CSR_replay_tim_thresh :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_REPLAY_TIM_THRESH_ADDR;
e_CSR_replay_timer :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_REPLAY_TIMER_ADDR;
e_CSR_dlpl_ee_int_en :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_INT_EN_ADDR;
e_CSR_dlpl_ee_log_en :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_LOG_EN_ADDR;
e_CSR_dlpl_ee_int_sts :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_INT_STS_ADDR;
e_CSR_dlpl_ee_err :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_STS_CLR_RW1C_ALIAS_ADDR;
e_CSR_dlpl_ee_err_diag :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_STS_CLR_RW1S_ALIAS_ADDR;
e_CSR_dlpl_link_ctl :
addr = FIRE_PLC_TLU_CTB_TLR_CSR_A_LINK_CTL_ADDR;
/*
//N2 ILU Error injection
addr = FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_RW1S_ALIAS_ADDR;
addr = FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_RW1C_ALIAS_ADDR;
*/
}
getCSRaddr = addr;
} /* end getCSRaddr */
/*
* isCSRreset - Is a CSR reset during a "soft reset"?
*
* Parameters:
* csr - An indication of the CSR of interest
*
* Returned value: Non-zero if the CSR is reset during a soft reset
*/
function bit PEUTestEnv::isCSRreset( PEC_CSRtype csr )
{
case ( csr )
{
e_CSR_pec_int_en : isCSRreset = 1;
e_CSR_pec_err : isCSRreset = 1;
e_CSR_ilu_int_en : isCSRreset = 1;
e_CSR_ilu_log_en : isCSRreset = 0;
e_CSR_ilu_en_err : isCSRreset = 1;
e_CSR_dev_cap : isCSRreset = 1;
e_CSR_dev_ctl : isCSRreset = 1;
e_CSR_dev_status : isCSRreset = 1;
e_CSR_lnk_cap : isCSRreset = 1;
e_CSR_lnk_ctl : isCSRreset = 1;
e_CSR_lnk_status : isCSRreset = 1;
e_CSR_slot_cap : isCSRreset = 1;
e_CSR_pme_ctl : isCSRreset = 1;
e_CSR_ue_int_en : isCSRreset = 1;
e_CSR_ue_log_en : isCSRreset = 0;
e_CSR_ue_en_err : isCSRreset = 1;
e_CSR_ce_int_en : isCSRreset = 1;
e_CSR_ce_log_en : isCSRreset = 0;
e_CSR_ce_en_err : isCSRreset = 1;
e_CSR_oe_int_en : isCSRreset = 1;
e_CSR_oe_log_en : isCSRreset = 0;
e_CSR_oe_en_err : isCSRreset = 1;
e_CSR_tlu_ctl : isCSRreset = 0;
e_CSR_tlu_stat : isCSRreset = 1;
e_CSR_tlu_diag : isCSRreset = 1;
e_CSR_tlu_debug_a : isCSRreset = 1;
e_CSR_tlu_debug_b : isCSRreset = 1;
e_CSR_ecrdt_avail : isCSRreset = 1;
e_CSR_ecrdt_used : isCSRreset = 1;
e_CSR_retry_crdt : isCSRreset = 1;
e_CSR_icrdt_avail : isCSRreset = 1;
e_CSR_icrdt_used : isCSRreset = 1;
e_CSR_tlu_prfc : isCSRreset = 1;
e_CSR_tlu_prf0 : isCSRreset = 1;
e_CSR_tlu_prf1 : isCSRreset = 1;
e_CSR_tlu_prf2 : isCSRreset = 1;
e_CSR_core_status : isCSRreset = 1;
default: isCSRreset = 0;
}
} /* end isCSRreset */
/*
* getCSRreadMask - Which bits of a CSR are defined/readable?
*
* Parameters:
* csr - An indication of the CSR of interest
*
* Returned value: A bit-mask of defined CSR bits
*
* NOTE: The mask does NOT include "read as zero" bits
*/
function bit[63:0] PEUTestEnv::getCSRreadMask( PEC_CSRtype csr )
{
case ( csr )
{
e_CSR_pec_int_en :
getCSRreadMask = FIRE_DLC_ILU_CIB_CSR_A_PEC_INT_EN_READ_MASK;
e_CSR_pec_err :
getCSRreadMask = FIRE_DLC_ILU_CIB_CSR_A_PEC_EN_ERR_READ_MASK;
e_CSR_ilu_int_en :
getCSRreadMask = FIRE_DLC_ILU_CIB_CSR_A_ILU_INT_EN_READ_MASK;
e_CSR_ilu_log_en :
getCSRreadMask = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_EN_READ_MASK;
e_CSR_ilu_en_err :
getCSRreadMask = FIRE_DLC_ILU_CIB_CSR_A_ILU_EN_ERR_READ_MASK;
e_CSR_ilu_err :
getCSRreadMask = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1C_ALIAS_READ_MASK;
e_CSR_ilu_err_diag :
getCSRreadMask = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_READ_MASK;
e_CSR_ilu_diagnos :
getCSRreadMask = FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_READ_MASK;
e_CSR_dev_cap :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CAP_READ_MASK;
e_CSR_dev_ctl :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_READ_MASK;
e_CSR_dev_status :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_STS_READ_MASK;
e_CSR_lnk_cap :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CAP_READ_MASK;
e_CSR_lnk_ctl :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_READ_MASK
^ FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_HW_LD_MASK;
e_CSR_lnk_status :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_READ_MASK;
e_CSR_slot_cap :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_SLT_CAP_READ_MASK;
e_CSR_pme_ctl :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TRN_OFF_READ_MASK;
e_CSR_ue_int_en :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_INT_EN_READ_MASK;
e_CSR_ue_log_en :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_LOG_READ_MASK;
e_CSR_ue_en_err :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_EN_ERR_READ_MASK;
e_CSR_ue_err :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1C_ALIAS_READ_MASK;
e_CSR_ue_err_diag :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1S_ALIAS_READ_MASK;
e_CSR_ue_recv_hdr1 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR1_READ_MASK;
e_CSR_ue_recv_hdr2 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR2_READ_MASK;
e_CSR_ue_xmit_hdr1 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR1_READ_MASK;
e_CSR_ue_xmit_hdr2 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR2_READ_MASK;
e_CSR_ce_int_en :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_INT_EN_READ_MASK;
e_CSR_ce_log_en :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_LOG_READ_MASK;
e_CSR_ce_en_err :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_EN_ERR_READ_MASK;
e_CSR_ce_err :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1C_ALIAS_READ_MASK;
e_CSR_ce_err_diag :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1S_ALIAS_READ_MASK;
e_CSR_oe_int_en :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_INT_EN_READ_MASK;
e_CSR_oe_log_en :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_LOG_READ_MASK;
e_CSR_oe_en_err :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_EN_ERR_READ_MASK;
e_CSR_oe_err :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1C_ALIAS_READ_MASK;
e_CSR_oe_err_diag :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1S_ALIAS_READ_MASK;
e_CSR_oe_recv_hdr1 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR1_READ_MASK;
e_CSR_oe_recv_hdr2 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR2_READ_MASK;
e_CSR_oe_xmit_hdr1 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR1_READ_MASK;
e_CSR_oe_xmit_hdr2 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR2_READ_MASK;
e_CSR_tlu_ctl :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_READ_MASK;
e_CSR_tlu_stat :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_READ_MASK;
e_CSR_tlu_diag :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DIAG_READ_MASK;
e_CSR_tlu_debug_a :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_A_READ_MASK;
e_CSR_tlu_debug_b :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_B_READ_MASK;
e_CSR_ecrdt_avail :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECL_READ_MASK;
e_CSR_ecrdt_used :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECC_READ_MASK;
e_CSR_retry_crdt :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ERB_READ_MASK;
e_CSR_icrdt_init :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_READ_MASK;
e_CSR_icrdt_avail :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICA_READ_MASK;
e_CSR_icrdt_used :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICR_READ_MASK;
e_CSR_tlu_prfc :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRFC_READ_MASK;
e_CSR_tlu_prf0 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF0_READ_MASK;
e_CSR_tlu_prf1 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF1_READ_MASK;
e_CSR_tlu_prf2 :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF2_READ_MASK;
e_CSR_core_status :
getCSRreadMask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_READ_MASK;
default:
getCSRreadMask = 64'b0;
}
} /* end getCSRreadMask */
/*
* getCSRwriteMask - Which bits of a CSR are writable?
*
* Parameters:
* csr - An indication of the CSR of interest
*
* Returned value: A bit-mask of software-modifiable CSR bits
*/
function bit[63:0] PEUTestEnv::getCSRwriteMask( PEC_CSRtype csr )
{
bit[63:0] mask;
case ( csr )
{
e_CSR_pec_int_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_PEC_INT_EN_WRITE_MASK;
e_CSR_pec_err :
mask = FIRE_DLC_ILU_CIB_CSR_A_PEC_EN_ERR_WRITE_MASK;
e_CSR_ilu_int_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_INT_EN_WRITE_MASK;
e_CSR_ilu_log_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_EN_WRITE_MASK;
e_CSR_ilu_en_err :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_EN_ERR_WRITE_MASK;
e_CSR_ilu_err :
mask =FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1C_ALIAS_WRITE_MASK;
e_CSR_ilu_err_diag :
mask =FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_WRITE_MASK;
e_CSR_ilu_diagnos :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_WRITE_MASK;
e_CSR_dev_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CAP_WRITE_MASK;
e_CSR_dev_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_WRITE_MASK;
e_CSR_dev_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_STS_WRITE_MASK;
e_CSR_lnk_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CAP_WRITE_MASK;
e_CSR_lnk_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_WRITE_MASK;
e_CSR_lnk_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_WRITE_MASK;
e_CSR_slot_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_SLT_CAP_WRITE_MASK;
e_CSR_pme_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TRN_OFF_WRITE_MASK;
e_CSR_ue_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_INT_EN_WRITE_MASK;
e_CSR_ue_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_LOG_WRITE_MASK;
e_CSR_ue_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_EN_ERR_WRITE_MASK;
e_CSR_ue_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1C_ALIAS_WRITE_MASK;
e_CSR_ue_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1S_ALIAS_WRITE_MASK;
e_CSR_ue_recv_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR1_WRITE_MASK;
e_CSR_ue_recv_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR2_WRITE_MASK;
e_CSR_ue_xmit_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR1_WRITE_MASK;
e_CSR_ue_xmit_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR2_WRITE_MASK;
e_CSR_ce_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_INT_EN_WRITE_MASK;
e_CSR_ce_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_LOG_WRITE_MASK;
e_CSR_ce_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_EN_ERR_WRITE_MASK;
e_CSR_ce_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1C_ALIAS_WRITE_MASK;
e_CSR_ce_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1S_ALIAS_WRITE_MASK;
e_CSR_oe_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_INT_EN_WRITE_MASK;
e_CSR_oe_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_LOG_WRITE_MASK;
e_CSR_oe_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_EN_ERR_WRITE_MASK;
e_CSR_oe_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1C_ALIAS_WRITE_MASK;
e_CSR_oe_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1S_ALIAS_WRITE_MASK;
e_CSR_oe_recv_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR1_WRITE_MASK;
e_CSR_oe_recv_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR2_WRITE_MASK;
e_CSR_oe_xmit_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR1_WRITE_MASK;
e_CSR_oe_xmit_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR2_WRITE_MASK;
e_CSR_tlu_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_WRITE_MASK;
e_CSR_tlu_stat :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_WRITE_MASK;
e_CSR_tlu_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DIAG_WRITE_MASK;
e_CSR_tlu_debug_a :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_A_WRITE_MASK;
e_CSR_tlu_debug_b :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_B_WRITE_MASK;
e_CSR_ecrdt_avail :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECL_WRITE_MASK;
e_CSR_ecrdt_used :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECC_WRITE_MASK;
e_CSR_retry_crdt :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ERB_WRITE_MASK;
e_CSR_icrdt_init :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_WRITE_MASK;
e_CSR_icrdt_avail :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICA_WRITE_MASK;
e_CSR_icrdt_used :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICR_WRITE_MASK;
e_CSR_tlu_prfc :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRFC_WRITE_MASK;
e_CSR_tlu_prf0 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF0_WRITE_MASK;
e_CSR_tlu_prf1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF1_WRITE_MASK;
e_CSR_tlu_prf2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF2_WRITE_MASK;
e_CSR_core_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_WRITE_MASK;
default:
mask = 64'b0;
}
getCSRwriteMask = mask | getCSRsetMask(csr) | getCSRclearMask(csr);
} /* end getCSRwriteMask */
/*
* getCSRsetMask - Which bits of a CSR are write-1-to-set?
*
* Parameters:
* csr - An indication of the CSR of interest
*
* Returned value: A bit-mask of software-modifiable set-only CSR bits
*/
function bit[63:0] PEUTestEnv::getCSRsetMask( PEC_CSRtype csr )
{
bit[63:0] mask;
case ( csr )
{
e_CSR_pec_int_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_PEC_INT_EN_SET_MASK;
e_CSR_pec_err :
mask = FIRE_DLC_ILU_CIB_CSR_A_PEC_EN_ERR_SET_MASK;
e_CSR_ilu_int_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_INT_EN_SET_MASK;
e_CSR_ilu_log_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_EN_SET_MASK;
e_CSR_ilu_en_err :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_EN_ERR_SET_MASK;
e_CSR_ilu_err :
mask =FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1C_ALIAS_SET_MASK;
e_CSR_ilu_err_diag :
mask =FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_SET_MASK;
e_CSR_ilu_diagnos :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_SET_MASK;
e_CSR_dev_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CAP_SET_MASK;
e_CSR_dev_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_SET_MASK;
e_CSR_dev_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_STS_SET_MASK;
e_CSR_lnk_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CAP_SET_MASK;
e_CSR_lnk_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_SET_MASK;
e_CSR_lnk_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_SET_MASK;
e_CSR_slot_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_SLT_CAP_SET_MASK;
e_CSR_pme_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TRN_OFF_SET_MASK;
e_CSR_ue_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_INT_EN_SET_MASK;
e_CSR_ue_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_LOG_SET_MASK;
e_CSR_ue_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_EN_ERR_SET_MASK;
e_CSR_ue_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1C_ALIAS_SET_MASK;
e_CSR_ue_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1S_ALIAS_SET_MASK;
e_CSR_ue_recv_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR1_SET_MASK;
e_CSR_ue_recv_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR2_SET_MASK;
e_CSR_ue_xmit_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR1_SET_MASK;
e_CSR_ue_xmit_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR2_SET_MASK;
e_CSR_ce_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_INT_EN_SET_MASK;
e_CSR_ce_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_LOG_SET_MASK;
e_CSR_ce_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_EN_ERR_SET_MASK;
e_CSR_ce_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1C_ALIAS_SET_MASK;
e_CSR_ce_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1S_ALIAS_SET_MASK;
e_CSR_oe_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_INT_EN_SET_MASK;
e_CSR_oe_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_LOG_SET_MASK;
e_CSR_oe_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_EN_ERR_SET_MASK;
e_CSR_oe_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1C_ALIAS_SET_MASK;
e_CSR_oe_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1S_ALIAS_SET_MASK;
e_CSR_oe_recv_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR1_SET_MASK;
e_CSR_oe_recv_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR2_SET_MASK;
e_CSR_oe_xmit_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR1_SET_MASK;
e_CSR_oe_xmit_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR2_SET_MASK;
e_CSR_tlu_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_SET_MASK;
e_CSR_tlu_stat :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_SET_MASK;
e_CSR_tlu_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DIAG_SET_MASK;
e_CSR_tlu_debug_a :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_A_SET_MASK;
e_CSR_tlu_debug_b :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_B_SET_MASK;
e_CSR_ecrdt_avail :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECL_SET_MASK;
e_CSR_ecrdt_used :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECC_SET_MASK;
e_CSR_retry_crdt :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ERB_SET_MASK;
e_CSR_icrdt_init :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_SET_MASK;
e_CSR_icrdt_avail :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICA_SET_MASK;
e_CSR_icrdt_used :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICR_SET_MASK;
e_CSR_tlu_prfc :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRFC_SET_MASK;
e_CSR_tlu_prf0 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF0_SET_MASK;
e_CSR_tlu_prf1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF1_SET_MASK;
e_CSR_tlu_prf2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF2_SET_MASK;
e_CSR_core_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_SET_MASK;
default:
mask = 64'b0;
}
getCSRsetMask = mask;
} /* end getCSRsetMask */
/*
* getCSRclearMask - Which bits of a CSR are "write-1-to-clear"?
*
* Parameters:
* csr - An indication of the CSR of interest
*
* Returned value: A bit-mask of software-modifiable clear-only CSR bits
*/
function bit[63:0] PEUTestEnv::getCSRclearMask( PEC_CSRtype csr )
{
bit[63:0] mask;
case ( csr )
{
e_CSR_pec_int_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_PEC_INT_EN_CLEAR_MASK;
e_CSR_pec_err :
mask = FIRE_DLC_ILU_CIB_CSR_A_PEC_EN_ERR_CLEAR_MASK;
e_CSR_ilu_int_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_INT_EN_CLEAR_MASK;
e_CSR_ilu_log_en :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_EN_CLEAR_MASK;
e_CSR_ilu_en_err :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_EN_ERR_CLEAR_MASK;
e_CSR_ilu_err :
mask =FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1C_ALIAS_CLEAR_MASK;
e_CSR_ilu_err_diag :
mask =FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_CLEAR_MASK;
e_CSR_ilu_diagnos :
mask = FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_CLEAR_MASK;
e_CSR_dev_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CAP_CLEAR_MASK;
e_CSR_dev_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_CLEAR_MASK;
e_CSR_dev_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_STS_CLEAR_MASK;
e_CSR_lnk_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CAP_CLEAR_MASK;
e_CSR_lnk_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_CLEAR_MASK;
e_CSR_lnk_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_CLEAR_MASK;
e_CSR_slot_cap :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_SLT_CAP_CLEAR_MASK;
e_CSR_pme_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TRN_OFF_CLEAR_MASK;
e_CSR_ue_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_INT_EN_CLEAR_MASK;
e_CSR_ue_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_LOG_CLEAR_MASK;
e_CSR_ue_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_EN_ERR_CLEAR_MASK;
e_CSR_ue_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1C_ALIAS_CLEAR_MASK;
e_CSR_ue_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1S_ALIAS_CLEAR_MASK;
e_CSR_ue_recv_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR1_CLEAR_MASK;
e_CSR_ue_recv_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR2_CLEAR_MASK;
e_CSR_ue_xmit_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR1_CLEAR_MASK;
e_CSR_ue_xmit_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR2_CLEAR_MASK;
e_CSR_ce_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_INT_EN_CLEAR_MASK;
e_CSR_ce_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_LOG_CLEAR_MASK;
e_CSR_ce_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_EN_ERR_CLEAR_MASK;
e_CSR_ce_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1C_ALIAS_CLEAR_MASK;
e_CSR_ce_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1S_ALIAS_CLEAR_MASK;
e_CSR_oe_int_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_INT_EN_CLEAR_MASK;
e_CSR_oe_log_en :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_LOG_CLEAR_MASK;
e_CSR_oe_en_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_EN_ERR_CLEAR_MASK;
e_CSR_oe_err :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1C_ALIAS_CLEAR_MASK;
e_CSR_oe_err_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1S_ALIAS_CLEAR_MASK;
e_CSR_oe_recv_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR1_CLEAR_MASK;
e_CSR_oe_recv_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR2_CLEAR_MASK;
e_CSR_oe_xmit_hdr1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR1_CLEAR_MASK;
e_CSR_oe_xmit_hdr2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR2_CLEAR_MASK;
e_CSR_tlu_ctl :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_CLEAR_MASK;
e_CSR_tlu_stat :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_CLEAR_MASK;
e_CSR_tlu_diag :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DIAG_CLEAR_MASK;
e_CSR_tlu_debug_a :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_A_CLEAR_MASK;
e_CSR_tlu_debug_b :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_B_CLEAR_MASK;
e_CSR_ecrdt_avail :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECL_CLEAR_MASK;
e_CSR_ecrdt_used :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECC_CLEAR_MASK;
e_CSR_retry_crdt :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ERB_CLEAR_MASK;
e_CSR_icrdt_init :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_CLEAR_MASK;
e_CSR_icrdt_avail :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICA_CLEAR_MASK;
e_CSR_icrdt_used :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICR_CLEAR_MASK;
e_CSR_tlu_prfc :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRFC_CLEAR_MASK;
e_CSR_tlu_prf0 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF0_CLEAR_MASK;
e_CSR_tlu_prf1 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF1_CLEAR_MASK;
e_CSR_tlu_prf2 :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF2_CLEAR_MASK;
e_CSR_core_status :
mask = FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_CLEAR_MASK;
default:
mask = 64'b0;
}
getCSRclearMask = mask;
} /* end getCSRclearMask */
/*
* getCSRinit - What is the reset value for a CSR?
*
* Parameters:
* csr - An indication of the CSR of interest
*
* Returned value: The (hard/soft) reset value of the CSR
*/
function bit[63:0] PEUTestEnv::getCSRinit( PEC_CSRtype csr )
{
case ( csr )
{
e_CSR_pec_int_en :
getCSRinit = FIRE_DLC_ILU_CIB_CSR_A_PEC_INT_EN_POR_VALUE;
e_CSR_pec_err :
getCSRinit = FIRE_DLC_ILU_CIB_CSR_A_PEC_EN_ERR_POR_VALUE;
e_CSR_ilu_int_en :
getCSRinit = FIRE_DLC_ILU_CIB_CSR_A_ILU_INT_EN_POR_VALUE;
e_CSR_ilu_log_en :
getCSRinit = FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_EN_POR_VALUE;
e_CSR_ilu_en_err :
getCSRinit = FIRE_DLC_ILU_CIB_CSR_A_ILU_EN_ERR_POR_VALUE;
e_CSR_ilu_err :
getCSRinit =FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1C_ALIAS_POR_VALUE;
e_CSR_ilu_err_diag :
getCSRinit =FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_POR_VALUE;
e_CSR_ilu_diagnos :
getCSRinit = FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_POR_VALUE;
e_CSR_dev_cap :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CAP_POR_VALUE;
e_CSR_dev_ctl :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_POR_VALUE;
e_CSR_dev_status :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_STS_POR_VALUE;
e_CSR_lnk_cap :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CAP_POR_VALUE;
e_CSR_lnk_ctl :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_POR_VALUE;
e_CSR_lnk_status :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_POR_VALUE;
e_CSR_slot_cap :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_SLT_CAP_POR_VALUE;
e_CSR_pme_ctl :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TRN_OFF_POR_VALUE;
e_CSR_ue_int_en :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_INT_EN_POR_VALUE;
e_CSR_ue_log_en :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_LOG_POR_VALUE;
e_CSR_ue_en_err :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_EN_ERR_POR_VALUE;
e_CSR_ue_err :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1C_ALIAS_POR_VALUE;
e_CSR_ue_err_diag :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1S_ALIAS_POR_VALUE;
e_CSR_ue_recv_hdr1 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR1_POR_VALUE;
e_CSR_ue_recv_hdr2 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR2_POR_VALUE;
e_CSR_ue_xmit_hdr1 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR1_POR_VALUE;
e_CSR_ue_xmit_hdr2 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR2_POR_VALUE;
e_CSR_ce_int_en :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_INT_EN_POR_VALUE;
e_CSR_ce_log_en :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_LOG_POR_VALUE;
e_CSR_ce_en_err :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_EN_ERR_POR_VALUE;
e_CSR_ce_err :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1C_ALIAS_POR_VALUE;
e_CSR_ce_err_diag :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1S_ALIAS_POR_VALUE;
e_CSR_oe_int_en :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_INT_EN_POR_VALUE;
e_CSR_oe_log_en :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_LOG_POR_VALUE;
e_CSR_oe_en_err :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_EN_ERR_POR_VALUE;
e_CSR_oe_err :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1C_ALIAS_POR_VALUE;
e_CSR_oe_err_diag :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1S_ALIAS_POR_VALUE;
e_CSR_oe_recv_hdr1 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR1_POR_VALUE;
e_CSR_oe_recv_hdr2 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR2_POR_VALUE;
e_CSR_oe_xmit_hdr1 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR1_POR_VALUE;
e_CSR_oe_xmit_hdr2 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR2_POR_VALUE;
e_CSR_tlu_ctl :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_POR_VALUE;
e_CSR_tlu_stat :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_POR_VALUE;
e_CSR_tlu_diag :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DIAG_POR_VALUE;
e_CSR_tlu_debug_a :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_A_POR_VALUE;
e_CSR_tlu_debug_b :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_B_POR_VALUE;
e_CSR_ecrdt_avail :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECL_POR_VALUE;
e_CSR_ecrdt_used :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECC_POR_VALUE;
e_CSR_retry_crdt :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ERB_POR_VALUE;
e_CSR_icrdt_init :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_POR_VALUE;
e_CSR_icrdt_avail :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICA_POR_VALUE;
e_CSR_icrdt_used :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICR_POR_VALUE;
e_CSR_tlu_prfc :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRFC_POR_VALUE;
e_CSR_tlu_prf0 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF0_POR_VALUE;
e_CSR_tlu_prf1 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF1_POR_VALUE;
e_CSR_tlu_prf2 :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF2_POR_VALUE;
e_CSR_core_status :
getCSRinit = FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_POR_VALUE;
default:
getCSRinit = 64'b0;
}
} /* end getCSRinit */
/*
* getLPUaddr - Obtain the address of an LPU CSR given its index
*
* Parameters:
* csrIndex - The zero-origin index of the CSR of interest
*
* Returned value: The address of the corresponding LPU register
*/
function integer PEUTestEnv::getLPUaddr( integer csrIndex )
{
/*N2 - Since there are no LPU registers always return a -1 if this gets called
getLPUaddr = FIRE_PLC_TLU_CTB_LPR_CSR_A_AHB_ADDR + 8*csrIndex;
*/
getLPUaddr = -1;
} /* end getLPUaddr */
/*
* getLPUindex - Obtain the index of an LPU CSR given its address
*
* Parameters:
* addr - The address of interest
*
* Returned value: The index of the corresponding LPU register, or -1
*/
function integer PEUTestEnv::getLPUindex( integer addr )
{
/*N2 - Since there are no LPU registers always return a -1 if this gets called
if ( addr >= FIRE_PLC_TLU_CTB_LPR_CSR_A_AHB_ADDR
&& ( addr < FIRE_PLC_TLU_CTB_LPR_CSR_A_AHB_ADDR
+ FIRE_PLC_TLU_CTB_LPR_CSR_A_AHB_DEPTH * 8 ) )
{
getLPUindex = (addr - FIRE_PLC_TLU_CTB_LPR_CSR_A_AHB_ADDR) / 8;
}
else
*/
{
getLPUindex = -1;
}
} /* end getLPUindex */
/*
* getCSR - Given a CSR address, return the corresponding CSR object
*
* Parameters:
* addr - The address of the CSR of interest
*
* Returned value: The corresponding CSR, or "null"
*/
function CSRAccessor PEUTestEnv::getCSR( integer addr )
{
CSRAccessor thisCSR;
integer csrIndex;
string msg;
case( addr & 32'hfffffff8 )
{
FIRE_DLC_ILU_CIB_CSR_A_PEC_INT_EN_ADDR :
thisCSR = f_CSR.CSR.fire_dlc_ilu_cib_csr_a_pec_int_en;
FIRE_DLC_ILU_CIB_CSR_A_PEC_EN_ERR_ADDR :
thisCSR = f_CSR.CSR.fire_dlc_ilu_cib_csr_a_pec_en_err;
FIRE_DLC_ILU_CIB_CSR_A_ILU_INT_EN_ADDR :
thisCSR = f_CSR.CSR.fire_dlc_ilu_cib_csr_a_ilu_int_en;
FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_EN_ADDR :
thisCSR = f_CSR.CSR.fire_dlc_ilu_cib_csr_a_ilu_log_en;
FIRE_DLC_ILU_CIB_CSR_A_ILU_EN_ERR_ADDR :
thisCSR = f_CSR.CSR.fire_dlc_ilu_cib_csr_a_ilu_en_err;
FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1C_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_dlc_ilu_cib_csr_a_ilu_log_err_rw1c_alias;
FIRE_DLC_ILU_CIB_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_dlc_ilu_cib_csr_a_ilu_log_err_rw1s_alias;
FIRE_DLC_ILU_CIB_CSR_A_ILU_DIAGNOS_ADDR :
thisCSR = f_CSR.CSR.fire_dlc_ilu_cib_csr_a_ilu_diagnos;
FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CAP_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_dev_cap;
FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_dev_ctl;
FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_STS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_dev_sts;
FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CAP_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_lnk_cap;
FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_lnk_ctl;
FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_lnk_sts;
FIRE_PLC_TLU_CTB_TLR_CSR_A_SLT_CAP_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_slt_cap;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TRN_OFF_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_trn_off;
FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_INT_EN_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ue_int_en;
FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_LOG_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ue_log;
FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_EN_ERR_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ue_en_err;
FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1C_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ue_err_rw1c_alias;
FIRE_PLC_TLU_CTB_TLR_CSR_A_UE_ERR_RW1S_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ue_err_rw1s_alias;
FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR1_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_rue_hdr1;
FIRE_PLC_TLU_CTB_TLR_CSR_A_RUE_HDR2_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_rue_hdr2;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR1_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tue_hdr1;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TUE_HDR2_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tue_hdr2;
FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_INT_EN_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ce_int_en;
FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_LOG_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ce_log;
FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_EN_ERR_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ce_en_err;
FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1C_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ce_err_rw1c_alias;
FIRE_PLC_TLU_CTB_TLR_CSR_A_CE_ERR_RW1S_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_ce_err_rw1s_alias;
FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_INT_EN_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_oe_int_en;
FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_LOG_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_oe_log;
FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_EN_ERR_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_oe_en_err;
FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1C_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_oe_err_rw1c_alias;
FIRE_PLC_TLU_CTB_TLR_CSR_A_OE_ERR_RW1S_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_oe_err_rw1s_alias;
FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR1_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_roe_hdr1;
FIRE_PLC_TLU_CTB_TLR_CSR_A_ROE_HDR2_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_roe_hdr2;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR1_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_toe_hdr1;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TOE_HDR2_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_toe_hdr2;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ctl;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_sts;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DIAG_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_diag;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_A_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_dbg_sel_a;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_DBG_SEL_B_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_dbg_sel_b;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECL_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ecl;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ECC_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ecc;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ERB_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_erb;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ici;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICA_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ica;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICR_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_icr;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRFC_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_prfc;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF0_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_prf0;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF1_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_prf1;
FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_PRF2_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_prf2;
FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_core_status;
FIRE_PLC_TLU_CTB_TLR_CSR_A_REPLAY_TIMER_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_replay_timer;
FIRE_PLC_TLU_CTB_TLR_CSR_A_REPLAY_TIM_THRESH_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_replay_tim_thresh;
FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_LOG_EN_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_event_err_log_en;
FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_INT_EN_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_event_err_int_en;
FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_INT_STS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_event_err_int_sts;
FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_STS_CLR_RW1C_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_event_err_sts_clr_rw1c_alias;
FIRE_PLC_TLU_CTB_TLR_CSR_A_EVENT_ERR_STS_CLR_RW1S_ALIAS_ADDR :
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_event_err_sts_clr_rw1s_alias;
default:
{
sprintf( msg, "PEUTestEnv::getCSR( integer addr=%0h ) ", addr );
_REPORT_ERROR( msg );
/* ahb removed from N2
csrIndex = getLPUindex( addr );
if ( csrIndex >= 0 )
thisCSR = f_CSR.CSR.fire_plc_tlu_ctb_lpr_csr_a_ahb[csrIndex];
else
thisCSR = null;
*/
}
}
getCSR = thisCSR;
} /* end getCSR */
/*
* readCSR - Read a ILU/TLU/LPU CSR in the normal way
*
* Parameters:
* addr - The address of the register of interest
*
* Returned value: The value of the specified register
*/
function bit[63:0] PEUTestEnv::readCSR( integer addr )
{
#ifndef N2_FC
CSRAccessor csr;
csr = getCSR( addr );
if ( csr == null )
readCSR = 64'b0;
else if ( PEC_CSR__IS_PEC_ADDR(addr) )
readCSR = csr.read( FIRE_PIO_SLOW );
else
readCSR = csr.read( FIRE_PIO_MED );
#else
readCSR = readCSRdirect(addr);
#endif
} /* end readCSR */
/*
* readCSRdirect - Read a ILU/TLU/LPU CSR directly
*
* Parameters:
* addr - The address of the register of interest
*
* Returned value: The value of the specified register
*/
function bit[63:0] PEUTestEnv::readCSRdirect( integer addr )
{
CSRAccessor csr;
csr = getCSR( addr );
if ( csr == null )
readCSRdirect = 64'b0;
//N2 else if ( getLPUindex(addr) >= 0 )
//N2 readCSRdirect = lpuCsr[ getLPUindex(addr) ];
else
readCSRdirect = csr.read( CSRT_OMNI );
} /* end readCSRdirect */
/*
* writeCSR - Write a ILU/TLU/LPU CSR in the normal way
*
* Parameters:
* addr - The address of the register of interest
* data - The value to be written to the corresponding CSR
*/
task PEUTestEnv::writeCSR( integer addr, bit [63:0] data )
{
#ifndef N2_FC
CSRAccessor csr;
csr = getCSR( addr );
if ( csr == null )
csr = null;
else if ( PEC_CSR__IS_PEC_ADDR(addr) )
csr.write( data, FIRE_PIO_SLOW );
else
csr.write( data, FIRE_PIO_MED );
#else
writeCSRdirect (addr, data);
#endif
} /* end writeCSR */
/*
* writeCSRdirect - Write a ILU/TLU/LPU CSR directly (in zero simulation time)
*
* Parameters:
* addr - The address of the register of interest
* data - The value to be written to the corresponding CSR
*/
task PEUTestEnv::writeCSRdirect( integer addr, bit [63:0] data )
{
CSRAccessor csr;
csr = getCSR( addr );
if ( csr == null )
csr = null;
else if ( getLPUindex(addr) >= 0 )
lpuCsr[ getLPUindex(addr) ] = data;
else
csr.write( data, CSRT_OMNI );
} /* end writeCSRdirect */
/*
* expectCSR - Expect a ILU/TLU/LPU CSR value by reading it
*
* Parameters:
* addr - The address of the register of interest
* data - The expected value of the corresponding CSR
*/
task PEUTestEnv::expectCSR( integer addr, bit [63:0] data )
{
bit [63:0] actual;
string msg;
actual = readCSR( addr );
if ( actual != data )
{
sprintf( msg, "Incorrect CSR value (addr=%h)", addr );
_REPORT_ERROR( msg );
sprintf( msg, "Actual: %h", actual );
_ERROR_INFO( msg );
sprintf( msg, "Expect: %h", data );
_ERROR_INFO( msg );
}
} /* end expectCSR */
/*
* expectCSRdirect - Expect a ILU/TLU/LPU CSR value by directly looking at it
*
* Parameters:
* addr - The address of the register of interest
* data - The expected value of the corresponding CSR
*/
task PEUTestEnv::expectCSRdirect( integer addr, bit [63:0] data )
{
bit [63:0] actual;
string msg;
actual = readCSRdirect( addr );
if ( actual != data )
{
sprintf( msg, "Incorrect CSR value (addr=%h)", addr );
_REPORT_ERROR( msg );
sprintf( msg, "Actual: %h", actual );
_ERROR_INFO( msg );
sprintf( msg, "Expect: %h", data );
_ERROR_INFO( msg );
}
} /* end expectCSRdirect */
/*
* setTLUdebug - Set the debug port selects for the TLU
*
* Parameters:
* SelA - Select for debug port "A"
* SelB - Select for debug port "B"
*/
task PEUTestEnv::setTLUdebug( bit[8:0] SelA, bit[8:0] SelB )
{
/* N2 review
// Debug values from the LPU mimic the debug select...
TLU_Control.dbga = SelA;
TLU_Control.dbgb = SelB;
writeCSRdirect( getCSRaddr( e_CSR_tlu_debug_a ), { 55'b0, SelA } );
writeCSRdirect( getCSRaddr( e_CSR_tlu_debug_b ), { 55'b0, SelB } );
*/
} /* end setTLUdebug */
/*
* setILUdebug - Set the debug port selects for the ILU
*
* Parameters:
* SelA - Select for debug port "A"
* SelB - Select for debug port "B"
*/
task PEUTestEnv::setILUdebug( bit[5:0] SelA, bit[5:0] SelB )
{
//N2 review ILU_CSR.dbgSelA = SelA;
//N2 review ILU_CSR.dbgSelB = SelB;
} /* end setILUdebug */
/*
* expectTLUdebug - Start looking at the TLU debug ports
*
* Parameters:
* A - Expected behavior of debug port "A"
* B - Expected behavior of debug port "B"
*/
task PEUTestEnv::expectTLUdebug( integer A[8], integer B[8] )
{
/* N2 review
integer i;
for (i=0; i<8; i++)
{
tluDebugCtlA[i] = A[i];
tluDebugCtlB[i] = B[i];
}
tluDebugA0 = ~TLU_Control.dbgA;
tluDebugA1 = TLU_Control.dbgA;
tluDebugB0 = ~TLU_Control.dbgB;
tluDebugB1 = TLU_Control.dbgB;
monitorTLUend = 0;
fork
monitorTLUdebug();
join none
*/
} /* end expectTLUdebug */
/*
* expectILUdebug - Start looking at the ILU debug ports
*
* Parameters:
* A - Expected behavior of debug port "A"
* B - Expected behavior of debug port "B"
*/
task PEUTestEnv::expectILUdebug( integer A[8], integer B[8] )
{
} /* end expectILUdebug */
/*
* endTLUdebug - Stop looking at the TLU debug ports
*
* Parameters: None
*
* NOTE: The caller is suspended into debug-port monitoring completes.
* (Only a cycle.)
*/
task PEUTestEnv::endTLUdebug()
{
integer i;
string errMsg;
monitorTLUend = 1;
@( posedge CLOCK );
for ( i=0; i<8; i++ )
{
casez( { tluDebugA1[i], tluDebugA0[i], tluDebugCtlA[i] } )
{
4'b1z0z: errMsg = "One occurred, but not expected";
4'bz1z0: errMsg = "Zero occurred, but not expected";
4'b0z1z: errMsg = "Constant zero, but not expected";
4'bz0z1: errMsg = "Constant one, but not expected";
default: errMsg = "";
}
if ( errMsg != "" )
{
_REPORT_ERROR( psprintf("TLU debug port-A bit-%0d: %s", i, errMsg) );
}
}
for ( i=0; i<8; i++ )
{
casez( { tluDebugB1[i], tluDebugB0[i], tluDebugCtlB[i] } )
{
4'b1z0z: errMsg = "One occurred, but not expected";
4'bz1z0: errMsg = "Zero occurred, but not expected";
4'b0z1z: errMsg = "Constant zero, but not expected";
4'bz0z1: errMsg = "Constant one, but not expected";
default: errMsg = "";
}
if ( errMsg != "" )
{
_REPORT_ERROR( psprintf("TLU debug port-B bit-%0d: %s", i, errMsg) );
}
}
} /* end endTLUdebug */
/*
* endILUdebug - Stop looking at the ILU debug ports
*
* Parameters: None
*/
task PEUTestEnv::endILUdebug()
{
} /* end endILUdebug */
/*
* monitorTLUdebug - A thread which monitors the TLU's debug results
*
* NOTE: The thread ends when "monitorTLUend" is true
*/
task PEUTestEnv::monitorTLUdebug()
{
/* N2
fork
while( !monitorTLUend ) @(posedge CLOCK);
while( !monitorTLUend )
{
@( TLU_Control.dbgA );
tluDebugA0 = tluDebugA0 | ~TLU_Control.dbgA;
tluDebugA1 = tluDebugA1 | TLU_Control.dbgA;
}
while( !monitorTLUend )
{
@( TLU_Control.dbgB );
tluDebugB0 = tluDebugB0 | ~TLU_Control.dbgB;
tluDebugB1 = tluDebugB1 | TLU_Control.dbgB;
}
join any
terminate;
*/
}
/*
* monitorILUdebug - A thread which monitors the ILU's debug results
*
* NOTE: The thread ends when "monitorILUend" is true
*/
task PEUTestEnv::monitorILUdebug()
{
/* N2 review
fork
while( !monitorILUend ) @(posedge CLOCK);
while( !monitorILUend )
{
@( ILU_CSR.dbgA );
iluDebugA0 = iluDebugA0 | ~ILU_CSR.dbgA;
iluDebugA1 = iluDebugA1 | ILU_CSR.dbgA;
}
while( !monitorILUend )
{
@( ILU_CSR.dbgB );
iluDebugB0 = iluDebugB0 | ~ILU_CSR.dbgB;
iluDebugB1 = iluDebugB1 | ILU_CSR.dbgB;
}
join any
terminate;
*/
}
/*
* setIngressLatency - Set the number of cycles for a TLP to pass from TLU to ILU
*
* Parameters:
* Latency - The number of clocks for... you guessed it
*/
task PEUTestEnv::setIngressLatency( integer Latency ) {
ingressLatency = Latency;
}
/*
* setEgressLatency - Set the number of cycles for a TLP to pass from ILU to TLU
*
* Parameters:
* Latency - The number of clocks for... you guessed it
*/
task PEUTestEnv::setEgressLatency( integer Latency ) {
egressLatency = Latency;
}
/*
* getIngressLatency - Get the amount of time it should take for a TLP
* to pass from the TLU to ILU.
*
* Parameters:
* PktHdr - The TLP's header
*/
function integer PEUTestEnv::getIngressLatency( bit[127:0] PktHdr,
(integer ExtraPayload=0) ) {
getIngressLatency = ingressLatency; // User supplied latency.
if ( (^PktHdr[PEC_PCI__LEN]) !== 1'b_x || ExtraPayload != 0 ) {
if ( PktHdr[PEC_PCI__LEN] ) // Need to deliver payload
getIngressLatency += PktHdr[PEC_PCI__LEN]/(ingressDataWidth/4)
+ ExtraPayload;
else if ( PktHdr[PEC_PCI__LEN] == 0 )
getIngressLatency += 4096/ingressDataWidth + ExtraPayload;
else
getIngressLatency += ExtraPayload;
getIngressLatency += 2; // Add a fudge factor
getIngressLatency *= 10000; // Compensate for cycles in
getIngressLatency /= (10000 - 100*ingressThrottle + 1); // which idle is driven to TLU.
}
}
/*
* getEgressLatency - Get the amount of time it should take for a TLP
* to pass from the ILU to TLU.
*
* Parameters:
* PktHdr - The TLP's header
*/
function integer PEUTestEnv::getEgressLatency( bit [127:0] PktHdr ) {
getEgressLatency = egressLatency; // User supplied latency.
if ( (^PktHdr[PEC_PCI__LEN]) !== 1'b_x) {
getEgressLatency += PktHdr[PEC_PCI__LEN]/(egressDataWidth/4);
getEgressLatency += 2; // Add a fudge factor
getEgressLatency *= 10000; // Compensate for cycles in
getEgressLatency /= (10000 - 100*egressThrottle + 1); // which dack is asserted.
}
}
/*
* waitIngressLatency - Wait for a TLP to pass from TLU to ILU
*
* Parameters:
* PktHdr - The TLP's header
*
* NOTE: We aren't guaranteeing that the TLP has actually come out of the
* ILU... just that the header should have been presented by the ILU if
* the ingress pipeline was otherwise empty
*/
task PEUTestEnv::waitIngressLatency( bit[127:0] PktHdr,
(integer ExtraPayload=0) ) {
// We should wait for the TLP to be fed into the TLU, but we're lazy...
repeat( this.getIngressLatency(PktHdr,ExtraPayload) ) @(posedge CLOCK);
}
/*
* waitEgressLatency - Wait for a TLP to pass from ILU to TLU
*
* Parameters:
* PktHdr - The TLP's header
*
* NOTE: We aren't guaranteeing that the TLP has actually come out of the
* TLU... just that the header should have been presented by the TLU if
* the ingress pipeline was otherwise empty
*/
task PEUTestEnv::waitEgressLatency( bit[127:0] PktHdr ) {
// We should wait for the TLP to be fed into the ILU, but we're lazy...
repeat( this.getEgressLatency(PktHdr) ) @(posedge CLOCK);
}
/*
* waitEgressPipeFull - Wait for the Egress Pipeline to be full
*
* Parameters: None
*/
task PEUTestEnv::waitEgressPipeFull() {
#ifndef N2_FC
bit [127:0] PktHdr;
integer latency;
integer peuPktRcvd;
integer cycle;
// Generate a packet header with max length. Use the header to get the
// max egress latency.
PktHdr[PEC_PCI__LEN] = this.getMaxPayloadSize() / 4;
latency = this.getEgressLatency(PktHdr);
// Grab the current number of packets received by the TLU.
peuPktRcvd = this.peuExpectComplete;
// Need to have a number of cycles of fullness to advance.
for (cycle = 0; cycle < latency; cycle++) {
// If there are egress credits available, restart the counter.
if (f_DMUXtr.egressCreditsAvailable() != 0)
cycle = 0;
// If more packets have been received by the TLU, restart the counter.
if (peuPktRcvd != this.peuExpectComplete)
cycle = 0;
// Grab the current number of packets received by the TLU.
peuPktRcvd = this.peuExpectComplete;
// Advance the clock a cycle.
@(posedge CLOCK);
}
// Egress Pipe Is Full!!
#endif
}
/*
* expectEgressParityError - Expect a one-time parity error on the TLU->LPU
* interface, returning after the error has occurred
*
* Parameters:
* ErrMask - Which "t2l_etp_dpar" bits do we expect to be in error?
*/
task PEUTestEnv::expectEgressParityError( bit[15:0] ErrMask )
{
/* N2 review
TLU_Control.etperr = ErrMask;
@( TLU_Control.etperrack );
TLU_Control.etperr = 16'b0;
*/
} /* end expectEgressParityError */
/*
* monitorStatusCSRs - Continually read the TLU's credit status registers.
* If things don't look right, then scream and yell.
*
* Parameters:
* IngressCredits - Should we worry about ingress credits as we go?
*/
task PEUTestEnv::monitorStatusCSRs( bit ingressCredits )
{
bit [7:0] hdrCredit;
bit [11:0] dataCredit;
integer envNpstHdr;
integer envPostHdr;
integer envPostData;
string msg;
IngressCredits = ingressCredits;
repeat(10) @(posedge CLOCK);
while( !softResetPending )
{
sync( ANY, ev_CSRupdateReq );
if ( softResetPending ) break;
if( drainStateSignaled ){ IngressCredits = 0;
}
// The order is important...
// Read the TLU's idea of how many
// credits have been used...
ingressCreditUsedCSR = readCSR( getCSRaddr( e_CSR_icrdt_used ) );
if ( softResetPending ) break;
if( drainStateSignaled ){ IngressCredits = 0;
}
// ...then determine how many credits
// we think are available...
envNpstHdr = ingressNonpostHdrAvail - ingressNonpostHdrConsumed;
// Since Denali is allowed to control Ingress packets it could have
// many Q'd transactions with Reserved credits
// - ingressNonpostHdrRsvd;
envPostHdr = ingressPostHdrAvail - ingressPostHdrConsumed;
// - ingressPostHdrRsvd;
envPostData = ingressPostDataAvail - ingressPostDataConsumed;
// - ingressPostDataRsvd;
// ...and finally the number of credits
// that the TLU has given us (total).
ingressCreditAvailCSR = readCSR( getCSRaddr( e_CSR_icrdt_avail ) );
if ( softResetPending ) break;
if( drainStateSignaled ){ IngressCredits = 0;
}
// Check non-posted header credits...
hdrCredit = ingressCreditAvailCSR[39:32] - ingressCreditUsedCSR[39:32];
if ( IngressCredits && hdrCredit < envNpstHdr )
{
_REPORT_ERROR( "Ingress non-posted header credits are out of sync!?!" );
sprintf( msg, "TLU avail = %h env = %3h TLU used = %h",
ingressCreditAvailCSR[39:32], envNpstHdr,
ingressCreditUsedCSR[39:32] );
_ERROR_INFO( msg );
dumpCreditStatus();
}
// Check posted header credits...
hdrCredit = ingressCreditAvailCSR[19:12] - ingressCreditUsedCSR[19:12];
if ( IngressCredits && hdrCredit < envPostHdr )
{
_REPORT_ERROR( "Ingress posted header credits are out of sync!?!" );
sprintf( msg, "TLU avail = %h env = %3h TLU used = %h",
ingressCreditAvailCSR[19:12], envPostHdr,
ingressCreditUsedCSR[19:12] );
_ERROR_INFO( msg );
dumpCreditStatus();
}
// Check posted data credits...
dataCredit = ingressCreditAvailCSR[11:0] - ingressCreditUsedCSR[11:0];
if ( IngressCredits && dataCredit < envPostData )
{
_REPORT_ERROR( "Ingress posted data credits are out of sync!?!" );
sprintf( msg, "TLU avail = %h env = %3h TLU used = %h",
ingressCreditAvailCSR[11:0], envPostData,
ingressCreditUsedCSR[11:0] );
_ERROR_INFO( msg );
dumpCreditStatus();
}
// We aren't doing anything with the
// egress credits yet...
egressCreditAvailCSR = readCSR( getCSRaddr( e_CSR_ecrdt_avail ) );
if ( softResetPending ) break;
egressCreditUsedCSR = readCSR( getCSRaddr( e_CSR_ecrdt_used ) );
if ( softResetPending ) break;
egressRetryCSR = readCSR( getCSRaddr( e_CSR_retry_crdt ) );
if ( softResetPending ) break;
// Get the "transactions pending" bit from the TLU device status register
rsbEmpty = !( readCSR( getCSRaddr( e_CSR_dev_status ) )
& FIRE_PLC_TLU_CTB_TLR_CSR_A_DEV_STS_TP_FMASK );
// If anyone was waiting, then tell them
// that we've updated our vision of the
// device's status
trigger( ONE_SHOT, ev_CSRupdateComplete );
}
trigger( ONE_SHOT, ev_CSRupdateComplete );
} /* end monitorStatusCSRs */
/*
* dumpCreditStatus - Dump the environment's idea of what's going on and
* the TLU's idea of how many credits it has.
*/
task PEUTestEnv::dumpCreditStatus()
{
printf( "Environment ingress credit status...\n" );
printf( " npstHdr avail/rsvd/consumed = %6d (%2h) %3d %6d (%2h)\n",
ingressNonpostHdrAvail, ingressNonpostHdrAvail % 256,
ingressNonpostHdrRsvd,
ingressNonpostHdrConsumed, ingressNonpostHdrConsumed % 256 );
printf( " postHdr avail/rsvd/consumed = %6d (%2h) %3d %6d (%2h)\n",
ingressPostHdrAvail, ingressPostHdrAvail % 256,
ingressPostHdrRsvd,
ingressPostHdrConsumed, ingressPostHdrConsumed % 256 );
printf( " postData avail/rsvd/consumed = %6d (%3h) %3d %6d (%3h)\n",
ingressPostDataAvail, ingressPostDataAvail % 4096,
ingressPostDataRsvd,
ingressPostDataConsumed, ingressPostDataConsumed % 4096 );
printf( "TLU ingress credit status...\n" );
printf( " npstHdr avail / consumed = %2h %2h\n",
ingressCreditAvailCSR[39:32], ingressCreditUsedCSR[39:32] );
printf( " postHdr avail / consumed = %2h %2h\n",
ingressCreditAvailCSR[19:12], ingressCreditUsedCSR[19:12] );
printf( " postData avail / consumed = %3h %3h\n",
ingressCreditAvailCSR[11:0], ingressCreditUsedCSR[11:0] );
printf( "Environment egress credit status...\n" );
printf( " cplnHdr avail / consumed = %6d (%2h) %6d (%2h)\n",
egressCompletionHdrAvail, egressCompletionHdrAvail % 256,
egressCompletionHdrConsumed, egressCompletionHdrConsumed % 256 );
printf( " cplnData avail / consumed = %6d (%3h) %6d (%3h)\n",
egressCompletionDataAvail, egressCompletionDataAvail % 4096,
egressCompletionDataConsumed, egressCompletionDataConsumed % 4096 );
printf( " npstHdr avail / consumed = %6d (%2h) %6d (%2h)\n",
egressNonpostHdrAvail, egressNonpostHdrAvail % 256,
egressNonpostHdrConsumed, egressNonpostHdrConsumed % 256 );
printf( " npstData avail / consumed = %6d (%3h) %6d (%3h)\n",
egressNonpostDataAvail, egressNonpostDataAvail % 4096,
egressNonpostDataConsumed, egressNonpostDataConsumed % 4096 );
printf( " postHdr avail / consumed = %6d (%2h) %6d (%2h)\n",
egressPostHdrAvail, egressPostHdrAvail % 256,
egressPostHdrConsumed, egressPostHdrConsumed % 256 );
printf( " postData avail / consumed = %6d (%3h) %6d (%3h)\n",
egressPostDataAvail, egressPostDataAvail % 4096,
egressPostDataConsumed, egressPostDataConsumed % 4096 );
printf( " retry avail / consumed = %6d (%4h) %6d (%4h)\n",
egressRetryAvail, egressRetryAvail % 65536,
egressRetryConsumed, egressRetryConsumed % 65536 );
printf( "TLU egress credit status...\n" );
printf( " cplnHdr avail / consumed = %2h %2h\n",
egressCreditAvailCSR[59:52], egressCreditUsedCSR[59:52] );
printf( " cplnData avail / consumed = %3h %3h\n",
egressCreditAvailCSR[51:40], egressCreditUsedCSR[51:40] );
printf( " npstHdr avail / consumed = %2h %2h\n",
egressCreditAvailCSR[39:32], egressCreditUsedCSR[39:32] );
printf( " npstData avail / consumed = %3h %3h\n",
egressCreditAvailCSR[31:20], egressCreditUsedCSR[31:20] );
printf( " postHdr avail / consumed = %2h %2h\n",
egressCreditAvailCSR[19:12], egressCreditUsedCSR[19:12] );
printf( " postData avail / consumed = %3h %3h\n",
egressCreditAvailCSR[11:0], egressCreditUsedCSR[11:0] );
printf( " retry avail / consumed = %4h %4h\n",
egressRetryCSR[15:0], egressRetryCSR[47:32] );
} /* end dumpCreditStatus */
/*
* monitorCplMailbox - Watch the mailbox connected to the DMU-transactor and
* make sure that any CPL not expected by the transactor is
* expected by us
*
* Parameters: None
*/
task PEUTestEnv::monitorCplMailbox()
{
#ifndef N2_FC
bit[127:0] cplHdr;
bit[7:0] tag;
string msg;
integer i;
while( 1 )
{
mailbox_get( WAIT, mb_unexpectedCpls, cplHdr );
activityCounter = activityCounter + 1;
// Get the tag for the original
// nonposted PIO request.
tag = cplHdr[PEC_PCI__CPL_TAG];
// If the tag does not correspond to
// a pending request, then OOPS!
if ( !nonpostReqPending[tag] )
{
_REPORT_ERROR( "Completion forwarded from DMUXtr is truly unexpected" );
sprintf( msg, "ReqID=%h CplID=%h Tag=%h Status=%h",
cplHdr[PEC_PCI__CPL_ID], cplHdr[PEC_PCI__CPL_REQ_ID],
cplHdr[PEC_PCI__CPL_TAG], cplHdr[PEC_PCI__CPL_STATUS] );
_ERROR_INFO( msg );
}
// Otherwise, if we got a time-out
// completion, make sure that it was
// expected.
else if ( cplHdr[PEC_PCI__CPL_STATUS] == PEC_PCI__CPL_STATUS_TIMEOUT )
{
if ( !nonpostReqTimeout[tag] )
{
_REPORT_ERROR( "Time-out completion from DMUXtr is unexpected" );
sprintf( msg, "ReqID=%h CplID=%h Tag=%h Status=%h",
cplHdr[PEC_PCI__CPL_ID], cplHdr[PEC_PCI__CPL_REQ_ID],
cplHdr[PEC_PCI__CPL_TAG], cplHdr[PEC_PCI__CPL_STATUS] );
_ERROR_INFO( msg );
}
nonpostReqTimeout[tag] = 1'b0;
nonpostReqPending[tag] = 1'b0;
trigger( ON, nonpostReqComplete[tag] );
}
// Otherwise, if we got a UR completion,
// we had better be in the drain state.
else if ( cplHdr[PEC_PCI__CPL_STATUS] == PEC_PCI__CPL_STATUS_UR )
{
if ( !drainState )
{
_REPORT_ERROR( "UR completion from DMUXtr is unexpected" );
sprintf( msg, "ReqID=%h CplID=%h Tag=%h Status=%h",
cplHdr[PEC_PCI__CPL_ID], cplHdr[PEC_PCI__CPL_REQ_ID],
cplHdr[PEC_PCI__CPL_TAG], cplHdr[PEC_PCI__CPL_STATUS] );
}
// In response to the completion, we
// have to somehow free the tag.
// We'll do this by aborting the
// "expectTLU" (if the request hasn't
// been dispatched) and then forcing
// every non-error "expectILU" CPL'n
// to return immediately.
else
{
if ( !drainStateActive )
{
_INFO_MSG( "ILU is now in the 'drain state'... " );
plugEgressPipeline();
fork
{
//Delay for 4 PCI clocks and then check ilu.iil.xfrsfm.ihb_empty before clearing DMUXtr
repeat( 100 ) @(posedge CLOCK ); //N2 review
f_DMUXtr.clear(0);
}
join none
}
// if ( nonpostReqInLimbo[tag] ) freePioTag(tag);
// nonpostReqInLimbo[tag] = 1'b0;
drainStateActive = 1;
}
printf("PEUTestEnv UR completion from DMUXtr drainState=%0d drainStateActive=%0d tag=%h \n",drainState,drainStateActive,tag);
nonpostReqTimeout[tag] = 1'b0;
nonpostReqPending[tag] = 1'b0;
trigger( ON, nonpostReqComplete[tag] );
}
// Otherwise, the ILU has sent us a
// bizarre completion status
else
{
_REPORT_ERROR( "Completion from DMUXtr has unexpected status" );
sprintf( msg, "ReqID=%h CplID=%h Tag=%h Status=%h",
cplHdr[PEC_PCI__CPL_ID], cplHdr[PEC_PCI__CPL_REQ_ID],
cplHdr[PEC_PCI__CPL_TAG], cplHdr[PEC_PCI__CPL_STATUS] );
nonpostReqTimeout[tag] = 1'b0;
nonpostReqPending[tag] = 1'b0;
}
}
#endif
} /* end monitorCplMailbox */
/*
* injectEHBerror - Inject a parity error into the egress header buffer
*
* Parameters:
* TlpTag - The tag of the target TLP header to receive the parity error
* ErrMask - Which "dpar" bits are to be polluted?
*
* NOTE: Injecting an EHB parity error will cause the DUT to enter the "drain
* state". Call "enterDrainState" after supplying the target TLP to the
* ILU.
* NOTE: This procedure returns immediately.
*/
task PEUTestEnv::injectEHBerror( bit[7:0] TlpTag, bit[3:0] ErrMask )
{
string msg;
// Can't be injectin two errurs at once!
if ( EHB.errAck != ehbErrorReq )
_REPORT_ERROR( "'injectEHBerror' called while another error is pending!" );
// Tell the top-level VERILOG to flip
// some parity bits when the target TLP
// is written to the EHB.
else
{
sprintf( msg, "Inject EHB error: mask='b%b tag='h%h", ErrMask, TlpTag );
_INFO_MSG(msg);
ehbErrorReq = !ehbErrorReq;
EHB.errReq <= ehbErrorReq;
EHB.errTag <= TlpTag;
EHB.errSel <= ErrMask;
}
} /* end injectEHBerror */
/*
* injectIHBerror - Inject a parity error into the ingress header buffer
*
* Parameters:
* TlpTag - The tag of the target TLP header to receive the parity error
* ErrMask - Which "dpar" bits are to be polluted?
*
* NOTE: Injecting an IHB parity error will cause the DUT to enter the "drain
* state". Call "enterDrainState" after supplying the target TLP to the
* TLU.
* NOTE: This procedure returns immediately.
*/
task PEUTestEnv::injectIHBerror( bit[7:0] TlpTag, bit[3:0] ErrMask )
{
string msg;
// Can't be injectin two errurs at once!
if ( IHB.errAck != ihbErrorReq )
_REPORT_ERROR( "'injectIHBerror' called while another error is pending!" );
// Tell the top-level VERILOG to flip
// some parity bits when the target TLP
// is written to the EHB.
else
{
sprintf( msg, "Inject IHB error: mask='b%b tag='h%h", ErrMask, TlpTag );
_INFO_MSG(msg);
ihbErrorReq = !ihbErrorReq;
IHB.errReq <= ihbErrorReq;
IHB.errTag <= TlpTag;
IHB.errSel <= ErrMask;
}
} /* end injectIHBerror */
/*
* enterDrainState - We're goin' down! Man the life-craft!
* Pending non-posted PIO requests can be completed by a
* "UR" request from the ILU.
*
* Parameters:
* TlpHdr - The optional header from the TLP which caused the problem.
*/
task PEUTestEnv::enterDrainState( (bit[127:0] TlpHdr = 128'bx) )
{
integer tag;
// Setting "drainState" means that it's
// OK to get a UR completion from the
// ILU. We'll set "drainStateActive"
// when we get that first completion.
drainState = 1;
drainStateActive = 0;
_INFO_MSG( "Entering 'drain state'" );
// A pending non-posted request is in
// limbo if it's in between the ILU and
// TLU as we enter the drain state.
for ( tag=0; tag<32; tag++ )
nonpostReqInLimbo[tag] = nonpostReqPending[tag] && !nonpostReqDispatch[tag];
} /* end enterDrainState */
/*
* waitDrainState - Wait for the TLU to report a drain-state error to the ILU
*
* Parameters: None
*/
task PEUTestEnv::waitDrainState()
{
//N2 review - Do we need a timeout here?
if ( !Pod.DMUXtr.miscPort.$drain ) @(Pod.DMUXtr.miscPort.$drain);
drainStateSignaled = 1; //Used to turn off Ingress credit checking
_INFO_MSG( "Env::waitDrainState() 'drain state entered'" );
} /* end waitDrainState */
/*
* setLPUerror - Set an LPU error indicator for one cycle
*
* Parameters:
* LpuErr - The error to be presented to the TLU
*/
task PEUTestEnv::setLPUerror( PEC_ERRtype LpuErr )
{
/*N2 review
integer bitIndex;
if ( !PEC_ERR_isLPU(LpuErr) ) return;
bitIndex = PEC_ERR_LPUpos(LpuErr);
if ( bitIndex < 0 )
{
if ( LpuErr == e_ERR_oe_lin )
TLU_Control.int <= 1;
if ( LpuErr == e_ERR_oe_lrs )
TLU_Control.reset <= 1;
}
else if ( PEC_ERR_isUE(LpuErr) )
TLU_Control.ue[bitIndex] <= 1;
else if ( PEC_ERR_isCE(LpuErr) )
TLU_Control.ce[bitIndex] <= 1;
else if ( PEC_ERR_isOE(LpuErr) )
TLU_Control.oe[bitIndex] <= 1;
*/
} // end setLPUerror
/*
* setErrorLogEnable - Set the error log enable bit for a particular error
*
* Parameters:
* Err - The error of interest
* LogEnab - The log-enable bit for that error
*/
task PEUTestEnv::setErrorLogEnable( PEC_ERRtype Err, bit LogEnab )
{
integer indx;
integer addr;
bit [63:0] csr;
case ( 1 ) {
PEC_ERR_isUE(Err) : addr = getCSRaddr( e_CSR_ue_log_en );
PEC_ERR_isCE(Err) : addr = getCSRaddr( e_CSR_ce_log_en );
PEC_ERR_isOE(Err) : addr = getCSRaddr( e_CSR_oe_log_en );
PEC_ERR_isILU(Err) : addr = getCSRaddr( e_CSR_ilu_log_en );
PEC_ERR_isDLPL(Err): addr = getCSRaddr( e_CSR_dlpl_ee_log_en );
default : addr = 0;
}
if ( addr != 0 )
{
csr = readCSRdirect( addr );
indx = PEC_ERR_bitIndex( Err );
csr[indx] = LogEnab;
writeCSR( addr, csr );
}
} /* end setErrorLogEnable */
/*
* setErrorIntEnable - Set the primary and secondary interrupt-enables for
* a particular error
*
* Parameters:
* Err - The error of interest
* Primary - The primary interrupt enable
* Secondary - The secondary interrupt enable
*
* NOTE: If the "Secondary" enable is "1", then the "Primary" must be "1" also.
*/
task PEUTestEnv::setErrorIntEnable(PEC_ERRtype Err, bit Primary, bit Secondary)
{
integer indx;
integer addr;
bit [63:0] csr;
case ( 1 ) {
PEC_ERR_isUE(Err) : addr = getCSRaddr( e_CSR_ue_int_en );
PEC_ERR_isCE(Err) : addr = getCSRaddr( e_CSR_ce_int_en );
PEC_ERR_isOE(Err) : addr = getCSRaddr( e_CSR_oe_int_en );
PEC_ERR_isILU(Err) : addr = getCSRaddr( e_CSR_ilu_int_en );
PEC_ERR_isDLPL(Err): addr = getCSRaddr( e_CSR_dlpl_ee_int_en );
default : addr = 0;
}
if ( addr != 0 )
{
csr = readCSRdirect( addr );
indx = PEC_ERR_bitIndex( Err );
csr[indx] = Primary;
csr[indx + 32] = Secondary;
writeCSRdirect( addr, csr );
}
} /* end setErrorIntEnable */
/*
* expectError - Expect primary and/or secondary error-log bits to be set/clear
* for a particular error
*
* Parameters:
* Err - The error of interest
* Primary - The expected primary log bit
* Secondary - The expected secondary log bit
*
* NOTE: The error logs are cleared by this task
*/
task PEUTestEnv::expectError(PEC_ERRtype Err, bit Primary, bit Secondary)
{
#ifndef N2_FC
// UD : this part is temp...
// just need to get Linkn training to work... also check if this reg has OMNI access
//
integer indx;
integer addr;
bit [63:0] csr;
string msg;
case ( 1 ) {
PEC_ERR_isUE(Err) : addr = getCSRaddr( e_CSR_ue_err );
PEC_ERR_isCE(Err) : addr = getCSRaddr( e_CSR_ce_err );
PEC_ERR_isOE(Err) : addr = getCSRaddr( e_CSR_oe_err );
PEC_ERR_isILU(Err) : addr = getCSRaddr( e_CSR_ilu_err );
PEC_ERR_isDLPL(Err): addr = getCSRaddr( e_CSR_dlpl_ee_err );
default : addr = 0;
}
if ( addr != 0 )
{
csr = readCSRdirect( addr );
indx = PEC_ERR_bitIndex( Err );
if ( (csr[indx] != Primary && Primary !== 1'bx)
|| (csr[indx + 32] != Secondary && Secondary !== 1'bx) )
{
dumpIntStatus();
_REPORT_ERROR( "Incorrect error-log bit-values" );
sprintf( msg, " Actual: %b", csr );
_ERROR_INFO( msg );
csr[indx] = Primary;
csr[indx+32] = Secondary;
sprintf( msg, " Expect: %b", csr );
_ERROR_INFO( msg );
csr = 64'bx;
csr[indx] = 1'b1;
csr[indx+32] = 1'b1;
sprintf( msg, " Mask: %b", csr );
_ERROR_INFO( msg );
}
csr = 64'b0;
csr[indx] = 1'b1;
csr[indx+32] = 1'b1;
#ifdef N2_IOS
writeCSRdirect (addr, csr);
#else
writeCSR( addr, csr );
#endif
}
#endif
} /* end expectError */
/*
* enableOptionalCheck - (Re)enable optional error checking
*
* Parameter:
* OptCheck - A string describing the optional check, default is "all"
*/
task PEUTestEnv::enableOptionalCheck( (string OptCheck = "all") )
{
bit [31:0] diagAddr;
bit [63:0] diagCsr;
diagAddr = getCSRaddr( e_CSR_tlu_diag );
diagCsr = readCSR( diagAddr );
if ( OptCheck == "all" )
diagCsr[47:32] = diagCsr[47:32] & ~(16'h1f73);
if ( OptCheck == "DWBE" )
diagCsr[36] = 1'b0;
if ( OptCheck == "cross 4KB" )
diagCsr[37] = 1'b0;
if ( OptCheck == "receiver overflow" )
diagCsr[38] = 1'b0;
if ( OptCheck == "NonConfigCRS" )
diagCsr[40] = 1'b0;
if ( OptCheck == "completion TC" )
diagCsr[41] = 1'b0;
if ( OptCheck == "completion attr" )
diagCsr[42] = 1'b0;
if ( OptCheck == "completion count" )
diagCsr[43] = 1'b0;
if ( OptCheck == "completion address" )
diagCsr[44] = 1'b0;
writeCSR( diagAddr, diagCsr );
} /* end enableOptionalCheck */
/*
* disableOptionalCheck - Disable optional error checking
*
* Parameter:
* OptCheck - A string describing the optional check, default is "all"
*/
task PEUTestEnv::disableOptionalCheck( (string OptCheck = "all") )
{
bit [31:0] diagAddr;
bit [63:0] diagCsr;
diagAddr = getCSRaddr( e_CSR_tlu_diag );
diagCsr = readCSR( diagAddr );
if ( OptCheck == "all" )
diagCsr[47:32] = diagCsr[47:32] | 16'h1f73;
if ( OptCheck == "DWBE" )
diagCsr[36] = 1'b1;
if ( OptCheck == "cross 4KB" )
diagCsr[37] = 1'b1;
if ( OptCheck == "receiver overflow" )
diagCsr[38] = 1'b1;
if ( OptCheck == "NonConfigCRS" )
diagCsr[40] = 1'b1;
if ( OptCheck == "completion TC" )
diagCsr[41] = 1'b1;
if ( OptCheck == "completion attr" )
diagCsr[42] = 1'b1;
if ( OptCheck == "completion count" )
diagCsr[43] = 1'b1;
if ( OptCheck == "completion address" )
diagCsr[44] = 1'b1;
writeCSR( diagAddr, diagCsr );
} /* end disableOptionalCheck */
//N2-Not needed
/*
* monitorPM - Monitor the power-management port to the TLU
*
* Parameters: None
*/
task PEUTestEnv::monitorPM()
{
/* N2 review
bit [2:0] oldReq;
bit [2:0] newReq;
oldReq = 3'b000;
newReq = 3'b000;
while( 1 )
{
@( posedge TLU_PM.clk );
if ( TLU_PM.req == 3 || TLU_PM.req == 4 )
{
if ( TLU_PM.dllpreq != 3'b100 )
_REPORT_ERROR( "TLU requests entry to L1 but does not send ACK DLLPs" );
}
else if ( TLU_PM.req == 5 )
{
if ( TLU_PM.dllpreq != 3'b100 )
_REPORT_ERROR( "TLU requests entry to L2/3 without sending ACK DLLPs" );
}
else if ( oldReq >= 3 && oldReq <= 5 && TLU_PM.dllpreq == 3'b100 )
{
// TLU is a bit slow taking out the ACK-DLLP request
}
else if ( TLU_PM.dllpreq != 3'b000 )
_REPORT_ERROR( "Unexpected power-management DLLP request from TLU" );
if ( TLU_PM.req != oldReq && TLU_PM.req != 3'b000 )
{
_INFO_MSG( psprintf( "TLU requests transition to '%s'",
TLU_PM.req==1 ? "L0" : TLU_PM.req==2 ? "L0s" :
TLU_PM.req==3 ? "L1" : TLU_PM.req==4 ? "L1(PME)" :
TLU_PM.req==5 ? "L23" : "????" ) );
if ( newReq != 3'b000 )
_REPORT_ERROR( "Unexpected PM state request from TLU" );
newReq = 3'b000;
if ( oldReq != 3'b000 )
newReq = TLU_PM.req;
else if ( TLU_PM.req == monitorPMreq )
trigger( ON, ev_monitorPMreq );
else
_REPORT_ERROR( "Unexpected PM state request from TLU" );
}
else if ( newReq != 3'b000 )
{
if ( TLU_PM.req != newReq )
_REPORT_ERROR( "TLU withdraws PM state request after one cycle?" );
else if ( TLU_PM.req == monitorPMreq )
trigger( ON, ev_monitorPMreq );
else
_REPORT_ERROR( "Unexpected ASPM state request from TLU" );
newReq = 3'b000;
}
if ( TLU_PM.req[2:1] != 2'b00 && TLU_EgressTLP.cmd != 3'b000 )
_REPORT_ERROR( "TLU submits a TLP while requesting a low-power state" );
else if ( monitorPMstate != 3'b001 && TLU_EgressTLP.cmd != 3'b000 )
_REPORT_ERROR( "TLU submits a TLP while not in L0" );
oldReq = TLU_PM.req;
}
*/
} /* end monitorPM */
/*
* pmDllp - Pretend that the LPU has gotten a/some power-management DLLPs...
*
* Parameters:
* PmReq - The PM request received by the LPU
*/
task PEUTestEnv::pmDllp( PEC_PMtype PmReq )
{
//N2 review f_LPUXtr.pmDllp( PmReq );
} /* end pmDllp */
/*
* pmStatus - Tell the TLU what the LPU's doing
*
* Parameters:
* Status - Either "DLLP" if the LPU has a DLLP to send, or
* "TLP" if it has a (retry) TLP to send, or
* "BUSY" if both are true, or
* "IDLE" if there's nothing to send
*/
task PEUTestEnv::pmStatus( string Status )
{
//N2 review f_LPUXtr.pmStatus( Status );
} /* end pmStatus */
/*
* expectASPM - Expect an ASPM transition request from the TLU
*
* Parameters:
* StateReq - Either "L0", or "L0s", or "L1" as the requested ASPM state
* ReqTimeout - Within how many cycles do we expect this request?
* AckDelay - After how many cycles to we transition to that state?
* ReqAbort - If triggered, don't expect the request after all.
*/
task PEUTestEnv::expectASPM( string StateReq,
integer ReqTimeout,
integer AckDelay,
(event ReqAbort=null),
(integer IdleTimeout=10) )
{
/* N2 review
integer i;
event abortEvent=null;
_INFO_MSG( psprintf( "Expecting an ASPM transition to '%s'...", StateReq ) );
case ( StateReq ) {
"L0" : monitorPMreq = 3'b001;
"L0s" : monitorPMreq = 3'b010;
"L1" : monitorPMreq = 3'b011;
}
if ( ReqAbort == null )
abortEvent = ev_monitorPMreq;
else
abortEvent = ReqAbort;
fork
sync( ALL, ev_monitorPMreq );
repeat(ReqTimeout) @(posedge CLOCK);
sync( ALL, abortEvent );
join any
terminate;
if ( ReqAbort != null && sync( CHECK, ReqAbort ) )
{
if ( sync( CHECK, ev_monitorPMreq ) )
_REPORT_ERROR( "PM transition aborted, but occurred anyway" );
monitorPMreq = 3'b000;
return;
}
if ( !sync( CHECK, ev_monitorPMreq ) )
{
_REPORT_ERROR( psprintf( "No transition to '%s' within %0d cycles",
StateReq, ReqTimeout ) );
dumpCreditStatus();
return;
}
trigger( OFF, ev_monitorPMreq );
// Acknowledge the TLU's request
// to move to a new PM state after
// the specified delay.
if ( AckDelay > 0 )
{
repeat( AckDelay ) @(posedge CLOCK);
// If we're moving out of L0, shut off
// the egress pipeline. And turn it
// back on if we're re-entering L0.
if ( monitorPMreq == 3'b001 )
{
fork
unplugEgressPipeline();
join none
}
else if ( monitorPMstate == 3'b001 )
{
fork
plugEgressPipeline();
join none
}
// Move to the new PM state and wait
// for the TLU to remove its request.
fork
f_LPUXtr.pmState( StateReq );
join none
monitorPMstate = monitorPMreq;
if ( IdleTimeout <= 0 ) return;
for ( i=0; i<IdleTimeout; i++ )
{
@( posedge TLU_PM.clk );
if ( TLU_PM.req == 3'b000 ) return;
}
_REPORT_ERROR( "TLU does not deassert ASPM request after 10 cycles" );
}
monitorPMreq = 3'b000;
END N2 */
} /* end expectASPM */
/*
* expectPM - Expect a software-driven (PME) transition request from the TLU
*
* Parameters:
* StateReq - Either "L0", or "L0s", or "L1" as the requested ASPM state
* ReqTimeout - Within how many cycles do we expect this request?
* AckDelay - After how many cycles to we transition to that state?
* ReqAbort - If triggered, don't expect the request after all.
*/
task PEUTestEnv::expectPM(
string StateReq,
integer ReqTimeout,
integer AckDelay,
(event ReqAbort=null) ) {
/* N2 review
integer i;
event abortEvent=null;
_INFO_MSG( psprintf( "Expecting an PM transition to '%s'...", StateReq ) );
case ( StateReq ) {
"L0" : monitorPMreq = 3'b001;
"L1" : monitorPMreq = 3'b100;
"L2" : monitorPMreq = 3'b101;
}
if ( ReqAbort == null )
abortEvent = ev_monitorPMreq;
else
abortEvent = ReqAbort;
fork
sync( ALL, ev_monitorPMreq );
repeat(ReqTimeout) @(posedge CLOCK);
sync( ALL, abortEvent );
join any
terminate;
if ( ReqAbort != null && sync( CHECK, ReqAbort ) )
{
if ( sync( CHECK, ev_monitorPMreq ) )
_REPORT_ERROR( "PM transition aborted, but occurred anyway" );
monitorPMreq = 3'b000;
return;
}
if ( !sync( CHECK, ev_monitorPMreq ) )
{
_REPORT_ERROR( psprintf( "No transition to '%s' within %0d cycles",
StateReq, ReqTimeout ) );
return;
}
trigger( OFF, ev_monitorPMreq );
// Acknowledge the TLU's request
// to move to a new PM state after
// the specified delay.
if ( AckDelay > 0 )
{
repeat( AckDelay ) @(posedge CLOCK);
// If we're moving out of L0, shut off
// the egress pipeline. And turn it
// back on if we're re-entering L0.
if ( monitorPMreq == 3'b001 )
{
fork
unplugEgressPipeline();
join none
}
else if ( monitorPMstate == 3'b001 )
{
fork
plugEgressPipeline();
join none
}
// Move to the new PM state and wait
// for the TLU to remove its request.
fork
f_LPUXtr.pmState( StateReq );
join none
monitorPMstate = monitorPMreq;
for ( i=0; i<10; i++ )
{
@( posedge TLU_PM.clk );
if ( TLU_PM.req != monitorPMreq ) return;
}
_REPORT_ERROR( "TLU does not deassert PM request after 10 cycles" );
}
monitorPMreq = 3'b000;
END N2 */
} /* end expectPM */
/*
* L1toL0 - Transition from L1 to L0 as would happen if the remote device has
* something to send.
*
* Parameters: None
*/
task PEUTestEnv::L1toL0()
{
/* N2 review
if ( monitorPMstate != 3'b011 && monitorPMstate != 3'b100 )
_REPORT_ERROR( "L1toL0 called, but we're not in L1!" );
else
{
fork
unplugEgressPipeline();
f_LPUXtr.pmState( "L0" );
join none
monitorPMstate = 3'b001;
monitorPMreq = 3'b000;
}
END N2*/
} /* end L1toL0 */
/*
* setIngressCredits - Set the number of credits advertised by the TLU and
* expected (after soft reset) by the PCIE transactor
*
* Parameters:
* NpstHdr - The number of nonposted-header credits
* PostHdr - The number of posted-header credits
* PostData - The number of posted-data credits
*/
task PEUTestEnv::setIngressCredits( integer NpstHdr,
integer PostHdr,
integer PostData )
{
bit [63:0] csrData;
csrData = 64'b0;
csrData[ FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_NHC_SLC ] = NpstHdr;
csrData[ FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_PHC_SLC ] = PostHdr;
csrData[ FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_ICI_PDC_SLC ] = PostData;
writeCSR( getCSRaddr( e_CSR_icrdt_init ), csrData );
//N2 f_LPUXtr.setInitIngressCredits( e_FC_nonposted, NpstHdr, 0 );
//N2 f_LPUXtr.setInitIngressCredits( e_FC_posted, PostHdr, PostData );
//N2 - Change the Initial credits in Scenario so Init and LinkTraining can use them
Scenario.ilupeuInitialNonPostedHeaderCredit = NpstHdr;
Scenario.ilupeuInitialPostedHeaderCredit = PostHdr;
Scenario.ilupeuInitialPostedDataCredit = PostData;
_INFO_MSG( psprintf( "%s: npstHdr=%0d postHdr=%0d postData=%0d",
"Set ingress credits", NpstHdr, PostHdr, PostData ) );
} /* end setIngressCredits */
/*
* setPioTimeOut - Set the time-out value for PIO completions
*
* Parameters:
* TimeOut - An encoded time-out value: 0="no time-out", 1="sim", 2="normal"
*
* NOTE: If the "TimeOut" is negative, then it's set only if the current
* value is zero (i.e. no time-out).
*/
task PEUTestEnv::setPioTimeOut( integer TimeOut )
{
bit [63:0] tluCtl;
#ifdef N2_IOS
tluCtl = readCSRdirect( getCSRaddr(e_CSR_tlu_ctl) );
#else
tluCtl = readCSR( getCSRaddr(e_CSR_tlu_ctl) );
#endif
if ( tluCtl[18:16] == 3'b000 || TimeOut >= 0 )
{
if ( TimeOut == 0 )
tluCtl[18:16] = 3'b000;
if ( TimeOut == 1 || TimeOut == -1 )
tluCtl[18:16] = 3'b111;
if ( TimeOut == 2 || TimeOut == -2 )
tluCtl[18:16] = 3'b110;
#ifdef N2_IOS
writeCSRdirect( getCSRaddr(e_CSR_tlu_ctl), tluCtl );
#else
writeCSR( getCSRaddr(e_CSR_tlu_ctl), tluCtl );
#endif
}
} /* end setPioTimeOut */
/*
* stallNonpostedWrite - Should we expect an outstanding Config/IO-write
* request to prevent dispatch of other PIO requests
* until completed (or time-out)?
*
* Parameters:
* Enabled - "1" if the "stall" is on
*/
task PEUTestEnv::stallNonpostedWrite( bit Enabled )
{
bit[63:0] csr;
csr = readCSRdirect( getCSRaddr( e_CSR_tlu_ctl ) );
csr[ FIRE_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_NPWR_EN_POSITION ] = Enabled;
writeCSRdirect( getCSRaddr( e_CSR_tlu_ctl ), csr );
stallNpstWr = Enabled;
} /* end stallNonpostedWrite */
/*
* nonpostedWriteStalled - Did someone call "stallNonpostedWrite"?
*/
function bit PEUTestEnv::nonpostedWriteStalled()
{
nonpostedWriteStalled = stallNpstWr;
}
function integer PEUTestEnv::getPerfCtr( string ctrType )
{
case ( ctrType )
{
"dma read" : getPerfCtr = perfCtr_dmaRead;
"dma write" : getPerfCtr = perfCtr_dmaWrite;
"recv DWs" : getPerfCtr = perfCtr_recvDWs;
"xmit DWs" : getPerfCtr = perfCtr_xmitDWs;
"pio cpl" : getPerfCtr = perfCtr_pioCpl;
default : getPerfCtr = 0;
}
}
task PEUTestEnv::setActivityTimeout(integer timeout) {
activityTimeout = timeout;
}
/*
* enableEstar - Set the CSR bit which enables entry/exit into E-star mode
*
* Parameters:
* Enabled - Should Estar clocking be enabled?
*/
//N2 task PEUTestEnv::enableEstar( bit Enabled )
//N2 {
//N2 estarEnabled = Enabled;
//N2 } /* end enableEstar */
/*
* isEstarEnabled - Is Estar clocking enabled?
*
* Parameters: None
*
* Returned value: The value of the Estar-enable CSR bit
*/
//N2 function bit PEUTestEnv::isEstarEnabled()
//N2 {
//N2 isEstarEnabled = estarEnabled;
//N2 } /* end isEstarEnabled */
/*
* enterEstar - Enter Estar mode... the ILU clock is slowed by 32 times
*
* Parameters: None
*/
//N2 task PEUTestEnv::enterEstar()
//N2 {
//N2 if ( !estarEnabled )
//N2 _REPORT_ERROR( "'enterEstar' called, but Estar is not enabled!?!" );
//N2 else
//N2 ENV_Control.estar = 1;
//N2 } /* end enterEstar */
/*
* exitEstar - Leave Estar mode
*
* Parameters: None
*/
//N2 task PEUTestEnv::exitEstar()
//N2 {
//N2 ENV_Control.estar = 0;
//N2 } /* end exitEstar */
/*
* Initialize the timers in the LPU
*
* Parameters:
*
* numActiveLanes - number of active lanes, default = 8 lanes
* mps - max. payload size, default = 128 bytes
*
*/
task PEUTestEnv::initLpuCSRs(integer numActiveLanes = 8,
integer mps = 128,
bit fastTrain = 1,
(bit enableL0s = 0),
(bit [63:0] retryBufSize = 64'h0))
{
/*N2 review Need to write new TLU CSRs for PEU
#ifdef LPUXTR_INCLUDE_PCIE
integer replay;
integer acknak;
bit [63:0] csrdata;
// Simulation mode fast training setup that has to be
// done as early as possible in the sim.
if ( fastTrain )
{
// Set fast simulation mode
csrdata = readCSR ( 32'h006e_2600 );
csrdata[30] = 1'b1;
writeCSR( 32'h006e_2600, csrdata );
// Initialize LTSSM 12ms timer (WARNING: have to make sure we set it to a value
// greater than what it has already counted at this point in the sim)
csrdata = 63'h200;
writeCSR( 32'h006e_2788, csrdata );
// Reset the RX Phy to reinitialize timers to fast sim values
csrdata = 63'hff;
writeCSR( 32'h006e_2680, csrdata );
csrdata = 63'h00;
writeCSR( 32'h006e_2680, csrdata );
}
case( numActiveLanes )
{
1:
case( mps )
{
512: { replay = 1677; acknak = 559; }
256: { replay = 1248; acknak = 416; }
default: { replay = 711; acknak = 237; }
}
4:
case( mps )
{
512: { replay = 462; acknak = 154; }
256: { replay = 354; acknak = 118; }
default: { replay = 354; acknak = 118; } // LPU Spec replay = 264; PCIE Spec replay = 3(acknak);
}
8:
case( mps )
{
512: { replay = 318; acknak = 106; } // LPU Spec replay = 258; PCIE Spec replay = 3(acknak);
256: { replay = 321; acknak = 107; }
default: { replay = 336; acknak = 112; } // LPU Spec replay = 246; PCIE Spec replay = 3(acknak);
}
}
if (enableL0s) {
replay += 564;
acknak += 564;
}
printf("AckNak Latency Timer : %0d\n", acknak);
printf("Replay Timer : %0d\n", replay);
writeCSR( 32'h006e_2400, acknak );
writeCSR( 32'h006e_2410, replay );
if (retryBufSize) {
printf("Replay Buffer Size : %0x\n", retryBufSize);
writeCSR( 32'h006e_2428, retryBufSize );
}
// write the new values to the PCIEX transactor
f_LPUXtr.setLatencyTimer( acknak );
f_LPUXtr.setRetryTimer( replay );
#endif
END N2 */
} /* end initLpuCSRs */
task PEUTestEnv::sendAck(integer seqNum) {
FNXPCIEXactorTransaction PCIEDllpTrans;
PCIEDllpTrans = Pod.FNXPCIEEnableTrans;
PCIEDllpTrans.MyPacket.PktType = FNX_PCIE_XTR_PKT_TYPE_DLLP;
PCIEDllpTrans.MyPacket.DllpType = FNX_PCIE_XTR_DLLP_TYPE_ACK;
PCIEDllpTrans.MyPacket.AckNakSeqNum = seqNum;
PCIEDllpTrans.MyPacket.DriveImmediately = 1;
PCIEDllpTrans.Drive(0);
}
task PEUTestEnv::sendNak(integer seqNum) {
FNXPCIEXactorTransaction PCIEDllpTrans;
PCIEDllpTrans = Pod.FNXPCIEEnableTrans;
PCIEDllpTrans.MyPacket.PktType = FNX_PCIE_XTR_PKT_TYPE_DLLP;
PCIEDllpTrans.MyPacket.DllpType = FNX_PCIE_XTR_DLLP_TYPE_NAK;
PCIEDllpTrans.MyPacket.AckNakSeqNum = seqNum;
PCIEDllpTrans.MyPacket.DriveImmediately = 1;
PCIEDllpTrans.Drive(0);
}
task PEUTestEnv::disableDenaliAcks() {
FNXPCIEXactorTransaction PCIEDllpTrans;
PCIEDllpTrans = Pod.FNXPCIEEnableTrans;
PCIEDllpTrans.EnableAckDiscard();
}
task PEUTestEnv::enableDenaliAcks() {
FNXPCIEXactorTransaction PCIEDllpTrans;
PCIEDllpTrans = Pod.FNXPCIEEnableTrans;
PCIEDllpTrans.DisableAckDiscard();
}
#ifdef LPUXTR_INCLUDE_PCIE
task PEUTestEnv::enterTxL0s(integer a_cycles) {
f_LPUXtr.enterTxL0s(a_cycles);
}
task PEUTestEnv::enterRecovery() {
f_LPUXtr.enterRecovery();
}
function bit [11:0] PEUTestEnv::corruptNextXmtSeqNum(bit [11:0] a_increment) {
corruptNextXmtSeqNum = this.f_LPUXtr.corruptNextXmtSeqNum(a_increment);
}
function bit [11:0] PEUTestEnv::corruptNextXmtLCRC(bit [31:0] a_mask) {
corruptNextXmtLCRC = this.f_LPUXtr.corruptNextXmtLCRC(a_mask);
}
function bit [11:0] PEUTestEnv::corruptNextXmtSTP(bit [8:0] a_symbol) {
corruptNextXmtSTP = this.f_LPUXtr.corruptNextXmtSTP(a_symbol);
}
function bit [11:0] PEUTestEnv::corruptNextXmtENDTLP(bit [8:0] a_symbol) {
corruptNextXmtENDTLP = this.f_LPUXtr.corruptNextXmtENDTLP(a_symbol);
}
function bit [11:0] PEUTestEnv::corruptNextXmt10bTLP(bit [9:0] a_frameMask,
integer a_frameCorruptOffset,
integer a_frameCorruptFreq,
integer a_frameCorruptMax) {
corruptNextXmt10bTLP = this.f_LPUXtr.corruptNextXmt10bTLP(a_frameMask,
a_frameCorruptOffset,
a_frameCorruptFreq,
a_frameCorruptMax);
}
task PEUTestEnv::corruptNextXmtCRC(bit [15:0] a_mask) {
this.f_LPUXtr.corruptNextXmtCRC(a_mask);
}
task PEUTestEnv::corruptNextXmtSDP(bit [8:0] a_symbol) {
this.f_LPUXtr.corruptNextXmtSDP(a_symbol);
}
task PEUTestEnv::corruptNextXmtENDDLLP(bit [8:0] a_symbol) {
this.f_LPUXtr.corruptNextXmtENDDLLP(a_symbol);
}
task PEUTestEnv::corruptNextXmt10bDLLP(bit [9:0] a_frameMask,
integer a_frameCorruptOffset,
integer a_frameCorruptFreq,
integer a_frameCorruptMax) {
this.f_LPUXtr.corruptNextXmt10bDLLP(a_frameMask,
a_frameCorruptOffset,
a_frameCorruptFreq,
a_frameCorruptMax);
}
#endif
task PEUTestEnv::ConvertHdr2PcieTlp( bit[PEC_PCI__HDR] tlpHdr,
bit [63:0] _DataSpec,
var FNXPCIEXactorTransaction PCIETlpTrans,
(integer LenAdjust=0),
(bit isDmaReq=0),
(integer dma_ptr=0)) {
bit [31:0] dataDW;
bit [63:0] dataQW;
integer j;
integer i, length, pyldByteValue;
//Payload arrays
bit [7:0] pyldByteAry[*];
bit [63:0] fcaddr = 64'b0;
bit [39:0] pa = 40'b0;
bit [7:0] busid;
bit fcRdCmd = 1'b1;
bit fcEgressCmd = !isDmaReq;
bit zero_len_read = (tlpHdr[PEC_PCI__LEN] == 1) &&
(tlpHdr[PEC_PCI__FIRST_DWBE] == 0) &&
(tlpHdr[PEC_PCI__LAST_DWBE] == 0) ;
//PcieXtr Transaction Packet
FNXPCIEXactorPacket TlpPkt;
//Set the initial payload byte value
pyldByteValue = _DataSpec;
//Get the handle to the transaction packet
TlpPkt = PCIETlpTrans.MyPacket;
//Use the TlpPkt to build up a 3 or 4 DW header plus a payload if needed
//Handle all the common fields first
TlpPkt.CmnFmt = tlpHdr[ILUPEU_TLP_HDR_FMT_BITS];
TlpPkt.CmnType = tlpHdr[ILUPEU_TLP_HDR_TYPE_BITS];
TlpPkt.CmnTC = tlpHdr[ILUPEU_TLP_HDR_TC_BITS];
TlpPkt.CmnTD = tlpHdr[ILUPEU_TLP_HDR_TD_BITS];
TlpPkt.CmnEP = tlpHdr[ILUPEU_TLP_HDR_EP_BITS];
TlpPkt.CmnRO = tlpHdr[ILUPEU_TLP_HDR_RO_BITS];
TlpPkt.CmnSnoop = tlpHdr[ILUPEU_TLP_HDR_SNOOP_BITS];
TlpPkt.CmnLength = tlpHdr[ILUPEU_TLP_HDR_LEN_BITS];
//Set all header fields that are common to Memory, IO, and Cfg and Msg TLP's
if( TlpPkt.CmnType <= FNX_PCIE_XTR_TYPE_CFGWR1 ||
TlpPkt.CmnType[FNX_PCIE_XTR_TYPE_MSG_FIXED_SLC] === FNX_PCIE_XTR_TYPE_MSG_FIXED ){
TlpPkt.ReqBusNum = tlpHdr[ILUPEU_TLP_HDR_REQ_BUS_NUM_BITS];
TlpPkt.ReqDeviceNum = tlpHdr[ILUPEU_TLP_HDR_REQ_DEV_NUM_BITS];
TlpPkt.ReqFuncNum = tlpHdr[ILUPEU_TLP_HDR_REQ_FUNC_NUM_BITS];
TlpPkt.ReqTag = tlpHdr[ILUPEU_TLP_HDR_TAG_BITS];
if( TlpPkt.CmnType[FNX_PCIE_XTR_TYPE_MSG_FIXED_SLC] === FNX_PCIE_XTR_TYPE_MSG_FIXED ){
TlpPkt.MsgCode = tlpHdr[ILUPEU_TLP_HDR_MSG_CODE_BITS];
TlpPkt.MsgRouting = tlpHdr[ILUPEU_TLP_HDR_TYPE_BITS]; //Lower 3 bits of type
}
else{
TlpPkt.BELastDW = tlpHdr[ILUPEU_TLP_HDR_LAST_DWBE_BITS];
TlpPkt.BEFirstDW = tlpHdr[ILUPEU_TLP_HDR_FIRST_DWBE_BITS];
}
}
//Set address header fields for Memory, IO
//If this is a 64 bit address than assign both halves of the address
if( TlpPkt.CmnType <= FNX_PCIE_XTR_TYPE_IOWR ){
if( tlpHdr[ILUPEU_TLP_HDR_FMT_4DW_BITS] ){
TlpPkt.AddrUpper = tlpHdr[ILUPEU_TLP_HDR_ADDR64_UPPER_BITS];
TlpPkt.AddrLower = tlpHdr[ILUPEU_TLP_HDR_ADDR64_LOWER_BITS];
if (tlpHdr[ILUPEU_TLP_HDR_TYPE_BITS] === FNX_PCIE_XTR_TYPE_IOWR) {
fcaddr = ({TlpPkt.AddrUpper, TlpPkt.AddrLower, 2'b0} |
PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_IOCFG_FLD]);
QuickReport( Report, RTYP_INFO,"UDEBUG:PEUTestEnv IO 3DW fcaddr = %0h\n", fcaddr);
}
else {
fcaddr = {TlpPkt.AddrUpper, TlpPkt.AddrLower, 2'b0};
if (fcEgressCmd) {
//fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_MEM64_FLD];
QuickReport( Report, RTYP_INFO,"UDEBUG:PEUTestEnv Mrd64 fcaddr = %0h %0h %0h\n",
fcaddr, TlpPkt.AddrUpper, TlpPkt.AddrLower);
}
else {
QuickReport( Report, RTYP_INFO,"UDEBUG:PEUTestEnv Dma fcaddr = %0h %0h %0h\n",
fcaddr, TlpPkt.AddrUpper, TlpPkt.AddrLower);
}
}
}
else{
TlpPkt.AddrLower = tlpHdr[ILUPEU_TLP_HDR_ADDR32_BITS];
if (tlpHdr[ILUPEU_TLP_HDR_TYPE_BITS] === FNX_PCIE_XTR_TYPE_IOWR) {
fcaddr = {32'b0, TlpPkt.AddrLower, 2'b0} | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_IOCFG_FLD] | 32'h10000000;
QuickReport( Report, RTYP_INFO,"UDEBUG:PEUTestEnv IO 3DW Cmd fcaddr = %0h\n", fcaddr);
}
else {
fcaddr = {32'b0, TlpPkt.AddrLower, 2'b0};
if (fcEgressCmd) {
fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_MEM32_FLD];
QuickReport( Report, RTYP_INFO,"UDEBUG:PEUTestEnv Mrd32 fcaddr = %0h %0h, Tag = %0h\n",
fcaddr, TlpPkt.ReceivedReqTag, TlpPkt.AddrLower);
}
else {
QuickReport( Report, RTYP_INFO,"UDEBUG:PEUTestEnv Dma fcaddr = %0h %0h, Tag = %0h\n",
fcaddr, TlpPkt.ReceivedReqTag, TlpPkt.AddrLower);
}
}
}
}
//Set up DW3 header fields for Configuration Requests
if( TlpPkt.CmnType >= FNX_PCIE_XTR_TYPE_CFGRD0 && TlpPkt.CmnType <= FNX_PCIE_XTR_TYPE_CFGWR1 ){
TlpPkt.CfgBusNum = tlpHdr[ILUPEU_TLP_HDR_CFG_BUS_NUM_BITS];
TlpPkt.CfgDeviceNum = tlpHdr[ILUPEU_TLP_HDR_CFG_DEV_NUM_BITS];
TlpPkt.CfgFuncNum = tlpHdr[ILUPEU_TLP_HDR_CFG_FUNC_NUM_BITS];
TlpPkt.CfgExtRegNum = tlpHdr[ILUPEU_TLP_HDR_CFG_EXT_REG_NUM_BITS];
TlpPkt.CfgRegNum = tlpHdr[ILUPEU_TLP_HDR_CFG_REG_NUM_BITS];
// 2'b0 inserted in address below to properly align the address.
//
fcaddr = {TlpPkt.CfgBusNum, TlpPkt.CfgDeviceNum, TlpPkt.CfgFuncNum,
TlpPkt.CfgExtRegNum, TlpPkt.CfgRegNum, 2'b0};
fcaddr = fcaddr | PiuCsrs.ncuBaseAddr[NCU_BASE_ADDR_IOCFG_FLD];
QuickReport( Report, RTYP_INFO,"-%0d-UDEBUG:PEUTestEnv::ConvertHdr2PcieTlp : A = %0h - %0h %0h %0h %0h %0h - %0h \n",
get_time(LO), fcaddr, TlpPkt.CfgBusNum, TlpPkt.CfgDeviceNum, TlpPkt.CfgFuncNum,
TlpPkt.CfgExtRegNum, TlpPkt.CfgRegNum, tlpHdr);
}
//Set up DW3 & DW4 fields for Messages
if( TlpPkt.CmnType[FNX_PCIE_XTR_TYPE_MSG_FIXED_SLC] === FNX_PCIE_XTR_TYPE_MSG_FIXED ){
TlpPkt.MsgDW3 = tlpHdr[ILUPEU_TLP_HDR_MSG_DW3_BITS];
TlpPkt.MsgDW4 = tlpHdr[ILUPEU_TLP_HDR_MSG_DW4_BITS];
}
//Set up fields for Completions
if( TlpPkt.CmnType >= FNX_PCIE_XTR_TYPE_CPL && TlpPkt.CmnType <= FNX_PCIE_XTR_TYPE_CPLDLK ){
TlpPkt.CmplBusNum = tlpHdr[ILUPEU_TLP_HDR_CPL_CPL_BUS_NUM_BITS];
TlpPkt.CmplDeviceNum = tlpHdr[ILUPEU_TLP_HDR_CPL_CPL_DEV_NUM_BITS];
TlpPkt.CmplFuncNum = tlpHdr[ILUPEU_TLP_HDR_CPL_CPL_FUNC_NUM_BITS];
TlpPkt.CmplStatus = tlpHdr[ILUPEU_TLP_HDR_CPL_STATUS_BITS];
TlpPkt.CmplBCM = tlpHdr[ILUPEU_TLP_HDR_CPL_BCM_BITS];
TlpPkt.CmplByteCount = tlpHdr[ILUPEU_TLP_HDR_CPL_BYTECOUNT_BITS];
TlpPkt.ReqBusNum = tlpHdr[ILUPEU_TLP_HDR_CPL_REQ_BUS_NUM_BITS];
TlpPkt.ReqDeviceNum = tlpHdr[ILUPEU_TLP_HDR_CPL_REQ_DEV_NUM_BITS];
TlpPkt.ReqFuncNum = tlpHdr[ILUPEU_TLP_HDR_CPL_REQ_FUNC_NUM_BITS];
TlpPkt.ReqTag = tlpHdr[ILUPEU_TLP_HDR_CPL_TAG_BITS];
TlpPkt.CmplLowerAddr = tlpHdr[ILUPEU_TLP_HDR_CPL_LOWADDR_BITS];
//Set reserved fields for ingress completions
TlpPkt.CmnResv1 = tlpHdr[127];
TlpPkt.CmnResv2 = tlpHdr[119];
TlpPkt.CmnResv3 = tlpHdr[115:112];
TlpPkt.CmnResv4 = tlpHdr[107:106];
TlpPkt.CmplResv5 = tlpHdr[39];
fcaddr = fcAddrArray[TlpPkt.ReqTag];
QuickReport( Report, RTYP_INFO,"UDEBUG:PEUTestEnv Cpl fcaddr = %0h, Tag = %0h tlp@ %0h %0h \n",
fcaddr, TlpPkt.ReqTag,
tlpHdr[ILUPEU_TLP_HDR_ADDR64_UPPER_BITS],
tlpHdr[ILUPEU_TLP_HDR_ADDR64_LOWER_BITS]
);
if (isDmaReq) {
// review: temp hack for DMA RD completion ...
// fcaddr[63:39] = 0; // if so, clear those bits
//}
fcAddrArray[TlpPkt.ReqTag] = fcAddrArray[TlpPkt.ReqTag] + (4*TlpPkt.CmnLength);
QuickReport( Report, RTYP_INFO,"UDEBUG:PEUTestEnv fixed fcaddr for next DMA RD cmpl, fcaddr = %0h cnt = %d\n",
fcAddrArray[TlpPkt.ReqTag], TlpPkt.CmplByteCount );
}
}
if ( (TlpPkt.CmnType == FNX_PCIE_XTR_TYPE_IOWR ||
TlpPkt.CmnType == FNX_PCIE_XTR_TYPE_CFGWR0 ||
TlpPkt.CmnType == FNX_PCIE_XTR_TYPE_CFGWR1 ||
TlpPkt.CmnType == FNX_PCIE_XTR_TYPE_MWR) &&
TlpPkt.CmnFmt[FNX_PCIE_XTR_FMT_DATA_SLC]) {
fcRdCmd = 1'b0;
}
else {
fcRdCmd = 1'b1;
// save received req tag only if this is a read command
// and not for completions
//
if ( !(TlpPkt.CmnType >= FNX_PCIE_XTR_TYPE_CPL &&
TlpPkt.CmnType <= FNX_PCIE_XTR_TYPE_CPLDLK) ) {
if (isDmaReq) {
QuickReport( Report, RTYP_INFO,"UDEBUG .. DMA RD completion Addr = %0h Tag = %0h\n", fcaddr, tlpHdr[PEC_PCI__TLP_TAG] );
fcAddrArray[tlpHdr[PEC_PCI__TLP_TAG]] = fcaddr;
}
}
}
/*
DMUXtr payload specification
payloadByte = payload[7:0];
poisonedPayload = payload[15:8];
fillPayload = payload[16];
errPayload = payload[17];
errMask = payload[25:18];
*/
//Set up the random payload if needed
if( TlpPkt.CmnFmt[FNX_PCIE_XTR_FMT_DATA_SLC] ){
if( TlpPkt.CmnLength === 0 ){
length = 1024;
}
else{
length = TlpPkt.CmnLength;
}
//Adjust the length if test requests it
length += LenAdjust;
pyldByteAry = new[length*4];
if( length == 0 ){
pyldByteAry = new[1];
pyldByteAry.delete();
}
//In order to use the DMUXtr env code -get a DW and then
// put it into a byte array byte 0 = DW[31:24]
#ifdef N2_FC
if (~fcEgressCmd && fcRdCmd) {
if (TlpPkt.CmnType == FNX_PCIE_XTR_TYPE_CPL) {
busid = tlpHdr[ILUPEU_TLP_HDR_CPL_REQ_BUS_NUM_BITS];
} else {
busid = tlpHdr[ILUPEU_TLP_HDR_REQ_BUS_NUM_BITS];
}
if (!MMU.get_physical_address(fcaddr, pa, busid, 0)) {
printf("PEUTestEnv::ConvertHdr2PcieTlp translation error detected by MMU.get_physical_address for VA %0h busid %h\n", fcaddr, busid);
return;
}
fcaddr = pa; // from here on, use the physical address
fork
l2sio_stub.reassemble_dma_pkt("PEUTestEnv::ConvertHdr2PcieTlp", length, fcaddr, dma_ptr);
sync( ANY, ev_removePcie );
join any
terminate; // kill the other thread
if( sync( CHECK, ev_removePcie ) ){
l2sio_stub.free_data_semaphore("PEUTestEnv::ConvertHdr2PcieTlp", dma_ptr);
return;
}
}
#endif
for( i=0; i< length; i++){
#ifdef N2_FC
if (fcEgressCmd) {
if (fcRdCmd) {
// PIO read responce - read from gmem
dataDW = N2fcRdMem (fcAddrMsk | fcaddr);
for( j=0; j<4; j++)
pyldByteAry[(i*4)+j] = dataDW[31-(j*8):24-(j*8)];
printf("UDEBUG : PEUTestEnv::ConvertHdr2PcieTlp : Adr %0h, dataDW %0h, i %0d\n",
fcaddr, dataDW, i );
}
else {
bit [3:0] DWBE = i ? TlpPkt.BELastDW : TlpPkt.BEFirstDW;
dataDW = _DataSpec[63-(i*32):32-(i*32)];
// PIO write - leave Xs in the expected pkt for bytes w/ BM == 0
//N2fcWrMem (fcAddrMsk | fcaddr, dataDW, DWBE);
printf("UDEBUG : PEUTestEnv::ConvertHdr2PcieTlp : Adr %0h, data %0h, LBE %0h FBE %0h i %0d\n",
fcaddr, dataDW, TlpPkt.BELastDW, TlpPkt.BEFirstDW, i );
for( j=0; j<4; j++) {
if (DWBE & (1<<j))
pyldByteAry[(i*4)+j] = dataDW[31-(j*8):24-(j*8)];
}
}
}
// ingress command from endpoint
//
else {
if (fcRdCmd) {
// for DMA read, read from data captured at the L2-SIU interface
// to create expected TLP payload, 4 bytes at a time
if (!zero_len_read) {
l2sio_stub.read_mem ("PEUTestEnv::ConvertHdr2PcieTlp", fcaddr, dataDW, dma_ptr);
//printf("UDEBUG : PEUTestEnv::ConvertHdr2PcieTlp DMA read l2sio : Adr %0h, data %0h, i %0d dma_ptr %0d\n", fcaddr, dataDW, i, dma_ptr);
} else {
dataDW = 32'hxxxxxxxx; // make data unknown for 0 length reads
}
for( j=0; j<4; j++)
pyldByteAry[(i*4)+j] = dataDW[31-(j*8):24-(j*8)];
}
else {
// for DMA write, create the payload data, and
// let dma sync take care of writing data to gMem when it gets to the L2
dataDW = this.nextPayloadDW( pyldByteValue );
//printf("UDEBUG : PEUTestEnv::ConvertHdr2PcieTlp DMA wr : Adr %0h, data %0h, i %0d\n", fcaddr, dataDW, i );
for( j=0; j<4; j++)
pyldByteAry[(i*4)+j] = dataDW[31-(j*8):24-(j*8)];
}
}
fcaddr += 4;
#else
dataDW = this.nextPayloadDW( pyldByteValue );
for( j=0; j<4; j++){
pyldByteAry[(i*4)+j] = dataDW[31-(j*8):24-(j*8)];
}
fcaddr += 4;
#endif
}
TlpPkt.SetPyld( pyldByteAry );
}
//Add TLP Digest
if( TlpPkt.CmnTD ){
TlpPkt.ECRC = urandom();
}
//Turn off Denali automatic tag generation
TlpPkt.GenTag = 0;
TlpPkt.PktDisplay( RTYP_DEBUG_3, "::ConvertHdr2PcieTlp()" );
QuickReport( Report,
RTYP_DEBUG_3,
"ConvertHdr2PcieTlp() tlpHdr=%h ",tlpHdr );
} //End ConvertHdr2PcieTlp
task PEUTestEnv::setDWBE( var bit[PEC_PCI__HDR] TlpHdr ){
bit [63:0] tlpAddr;
if ( TlpHdr[PEC_PCI__FMT_4DW] )
tlpAddr = TlpHdr[PEC_PCI__ADDR];
else
tlpAddr[31:0] = TlpHdr[PEC_PCI__ADDR32];
/* DWBEs are random, but their validity
depends on the length and boundary.*/
if ( TlpHdr[PEC_PCI__LEN] == 1 )
{
TlpHdr[PEC_PCI__FIRST_DWBE] = localRandom(16);
TlpHdr[PEC_PCI__LAST_DWBE] = 0;
}
//If QW aligned First and Last can be non-contiguous
else if ( TlpHdr[PEC_PCI__LEN] == 2 && tlpAddr[3:0] == 4'b0000 )
{
TlpHdr[PEC_PCI__FIRST_DWBE] = 1 + localRandom(15);
TlpHdr[PEC_PCI__LAST_DWBE] = 1 + localRandom(15);
}
else
{
TlpHdr[PEC_PCI__FIRST_DWBE] = 8'h78 >> localRandom(4);
TlpHdr[PEC_PCI__LAST_DWBE] = 8'h0f >> localRandom(4);
}
}
task PEUTestEnv::returnAllEgressCredits( (integer timerVal = 15) ){
bit[ FNX_PCIE_XTR_REG_DEN_WIDTH-1:0 ] denRegTmpData;
FNXPCIEXactorTransaction PCIETrans;
PCIETrans = new( Pod.FNXPCIEBldr );
QuickReport( Report, RTYP_INFO,
"Env::returnAllEgressCredits() called ");
//Just set the Denali Flow Control timer values to 15 to force Denali
// to send any updates
denRegTmpData = 0;
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_FC_OP_SLC] = PCIE_FCCTRL_set_timer;
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_VC_SLC] = 0; //VC 0
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_FC_TYPE_SLC] = PCIE_FCTYPE_PH;
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_TIMER_VAL_SLC] = timerVal;
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL, denRegTmpData );
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_FC_TYPE_SLC] = PCIE_FCTYPE_PD;
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_TIMER_VAL_SLC] = timerVal;
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL, denRegTmpData );
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_FC_TYPE_SLC] = PCIE_FCTYPE_NPH;
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_TIMER_VAL_SLC] = timerVal;
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL, denRegTmpData );
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_FC_TYPE_SLC] = PCIE_FCTYPE_NPD;
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_TIMER_VAL_SLC] = timerVal;
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL, denRegTmpData );
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_FC_TYPE_SLC] = PCIE_FCTYPE_CPLH;
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_TIMER_VAL_SLC] = timerVal;
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL, denRegTmpData );
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_FC_TYPE_SLC] = PCIE_FCTYPE_CPLD;
denRegTmpData[FNX_PCIE_XTR_REG_DEN_FC_CTRL_TIMER_VAL_SLC] = timerVal;
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL, denRegTmpData );
}
//Read the DLPL Core status register and return the LTSSM state
function bit[4:0] PEUTestEnv::getLtssmState(){
bit [63:0] csr;
bit [4:0] ltssmState;
string msg;
csr = readCSRdirect( getCSRaddr( e_CSR_core_status ) );
ltssmState = csr[FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_LTSSM_STATE_SLC];
sprintf( msg, "PEUTestEnv::getLtssmState ltssmState = %0h %s", ltssmState,ltssmStateToString(ltssmState) );
_INFO_MSG( msg );
getLtssmState = ltssmState;
}
//Get the number of unACKd TLPs in the replay buffer
function integer PEUTestEnv::getNmbrTlpsReplayBuffer(){
integer nmbrTlpsReplayBuffer;
integer oldestTransmitSeqNum;
oldestTransmitSeqNum = ( (egressNextTransmitSeqNum%4096) == 0 ? 4095 : egressNextTransmitSeqNum - 1 );
if( (oldestTransmitSeqNum%4096 - AckdSeqNum) >= 0 ){
nmbrTlpsReplayBuffer = (oldestTransmitSeqNum%4096) - AckdSeqNum;
}else{
nmbrTlpsReplayBuffer = (oldestTransmitSeqNum%4096)+4096 - AckdSeqNum;
}
//Return the number of Tlps in the replay buffer
getNmbrTlpsReplayBuffer = nmbrTlpsReplayBuffer;
}
//------------------------------------------------------------------------------
// N2 FC. Write received data in gMem
//------------------------------------------------------------------------------
task PEUTestEnv::N2fcWrMem (bit [63:0] addr, bit [31:0] din, bit [7:0] be) {
#ifdef N2_FC
bit [63:0] rdat, wdat;
bit [63:0] memAddr = addr;
rdat = gMem.read_mem(memAddr);
// writeBM() will mask off addr bits 2:0. We need to pass the data in the
// right position within a 64 bit word
wdat = rdat;
if(memAddr[2]) {
wdat[31: 0] = din;
be[7:4] = 0;
be[3:0] = {be[0],be[1],be[2],be[3]};
}
else {
wdat[63:32] = din;
//be[7:4] = be[3:0];
be[7:4] = {be[0],be[1],be[2],be[3]};
be[3:0] = 0;
}
gMem.writeBM(memAddr, wdat, be);
wdat = gMem.read_mem(memAddr);
printf ("-%0d-UDEBUG:PEUTestEnv::N2fcWrMem: A= %0h, wdat= %0h, BE= %0h, gMem Dat Old = %0h New = %0h\n",
get_time(LO), addr, din, be, rdat, wdat);
#endif
}
//------------------------------------------------------------------------------
// N2 FC. Read data in gMem
//------------------------------------------------------------------------------
function bit [31:0] PEUTestEnv::N2fcRdMem (bit [63:0] addr) {
#ifdef N2_FC
bit [63:0] rdat;
bit [63:0] memAddr = addr;
rdat = gMem.read_mem(memAddr);
printf ("-%0d-UDEBUG:PEUTestEnv::N2fcRdMem : New Addr = %0h, Data = %0h - %0h %0h\n",
get_time(LO), memAddr, rdat, rdat[63:32], rdat[31:0]);
N2fcRdMem = (memAddr[2]==1'b0) ? rdat[63:32] : rdat[31:0];
#endif
}
//-------------------------------
//Set bit to stay in Detect.Quiet
//-------------------------------
task PEUTestEnv::stayDetectQuiet() {
bit [63:0] csrRegTmpData;
csrRegTmpData = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ctl.read(FIRE_PIO_SLOW);
csrRegTmpData[8] = 1; //Turn on remain in detect.quiet
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ctl.write(csrRegTmpData,FIRE_PIO_SLOW);
}
//-------------------------------
//Set bit to exit in Detect.Quiet
//-------------------------------
task PEUTestEnv::exitDetectQuiet() {
bit [63:0] csrRegTmpData;
csrRegTmpData = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ctl.read(FIRE_PIO_SLOW);
csrRegTmpData[8] = 0; //Turn off remain in detect.quiet
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_tlu_ctl.write(csrRegTmpData,FIRE_PIO_SLOW);
}
//---------------------------------------------------------------------
//set Assert Reset bit set which should cause transition to HOT RESET State
//---------------------------------------------------------------------
task PEUTestEnv::PeuHotReset() {
bit [63:0] csrRegTmpData;
csrRegTmpData = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_link_ctl.read(FIRE_PIO_SLOW);
csrRegTmpData[FIRE_PLC_TLU_CTB_TLR_CSR_A_LINK_CTL_RESET_ASSERT_SLC] = 1'b1;
f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_link_ctl.write(csrRegTmpData,FIRE_PIO_SLOW);
printf("\n ............Asserting Hot Reset csr bit............. \n");
}
//--------------------------------------------------------
//This task expects to enter specified LTSSM state or times out waiting
//--------------------------------------------------------
task PEUTestEnv::toLtssmState( bit [4:0] ltssmState,
(integer timer=2000),
(integer accessMethod=FIRE_PIO_SLOW) ){
bit [63:0] csrRegTmpData;
string msg;
csrRegTmpData = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_core_status.read(accessMethod);
fork
{
while( (csrRegTmpData[ FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_LTSSM_STATE_SLC ] !== ltssmState) && timer ){
csrRegTmpData = f_CSR.CSR.fire_plc_tlu_ctb_tlr_csr_a_core_status.read(accessMethod);
if( accessMethod === OMNI ) @(posedge CLOCK);
}
}
{
while( timer ){
@(posedge CLOCK);
timer--;
}
}
join any
if( !timer ){
sprintf(msg,"::toLtssmState timed out waiting to enter LTSSM_STATE -%s- ---Still in state -%s- (%0h) at time %d",ltssmStateToString(ltssmState), ltssmStateToString(csrRegTmpData[FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_LTSSM_STATE_SLC ]), csrRegTmpData[FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_LTSSM_STATE_SLC ], get_time(LO) );
_REPORT_ERROR("::toLtssmState timed out");
_ERROR_INFO(msg);
}else{
printf("\n=========== PEU Entered LTSSM_STATE -%s- (%h) ===========\n",ltssmStateToString(ltssmState), csrRegTmpData[ FIRE_PLC_TLU_CTB_TLR_CSR_A_CORE_STATUS_LTSSM_STATE_SLC ]);
}
}
function string PEUTestEnv::ltssmStateToString( bit [4:0] ltssmState ){
string msg;
//Get the values from ilupeu_defines.vri
case (ltssmState){
ILUPEU_LTSSM_PRE_DETECT_QUIET: sprintf(msg, "PreDetect.Quiet");
ILUPEU_LTSSM_DETECT_QUIET: sprintf(msg, "Detect.Quiet");
ILUPEU_LTSSM_DETECT_ACT: sprintf(msg, "Detect.Active");
ILUPEU_LTSSM_DETECT_WAIT: sprintf(msg, "Detect.Wait");
ILUPEU_LTSSM_POLL_ACTIVE: sprintf(msg, "Polling.Active");
ILUPEU_LTSSM_POLL_COMPLIANCE: sprintf(msg, "Polling.Compliance");
ILUPEU_LTSSM_POLL_CONFIG: sprintf(msg, "Polling.Configuration");
ILUPEU_LTSSM_CFG_LINKWD_START: sprintf(msg, "Configuration.Linkwidth.Start");
ILUPEU_LTSSM_CFG_LINKWD_ACEPT: sprintf(msg, "Configuration.Linkwidth.Accept");
ILUPEU_LTSSM_CFG_LANENUM_WAIT: sprintf(msg, "Configuration.Lanenum.Wait");
ILUPEU_LTSSM_CFG_LANENUM_ACEPT: sprintf(msg, "Configuration.Lanenum.Accept");
ILUPEU_LTSSM_CFG_COMPLETE: sprintf(msg, "Configuration.Complete");
ILUPEU_LTSSM_CFG_IDLE: sprintf(msg, "Configuration.Idle");
ILUPEU_LTSSM_RCVRY_RCVRLOCK: sprintf(msg, "Recovery.RcvrLock");
ILUPEU_LTSSM_RCVRY_RCVRCFG: sprintf(msg, "Recovery.RcvrCfg");
ILUPEU_LTSSM_RCVRY_IDLE: sprintf(msg, "Recovery.Idle");
ILUPEU_LTSSM_HOT_RESET_ENTRY: sprintf(msg, "HotReset.Entry");
ILUPEU_LTSSM_HOT_RESET: sprintf(msg, "HotReset");
ILUPEU_LTSSM_L0: sprintf(msg, "L0");
ILUPEU_LTSSM_L0S: sprintf(msg, "L0S");
ILUPEU_LTSSM_L123_SEND_EIDLE: sprintf(msg, "L123.SEND.EIDLE (ENTRY)");
ILUPEU_LTSSM_L1_IDLE: sprintf(msg, "L1.Idle");
ILUPEU_LTSSM_L2_IDLE: sprintf(msg, "L2.Idle");
ILUPEU_LTSSM_L2_WAKE: sprintf(msg, "L2.Wake");
ILUPEU_LTSSM_DISABLED_ENTRY: sprintf(msg, "Disabled.Entry");
ILUPEU_LTSSM_DISABLED_IDLE: sprintf(msg, "Disabled.Idle");
ILUPEU_LTSSM_DISABLED: sprintf(msg, "Disabled");
ILUPEU_LTSSM_LPBK_ENTRY: sprintf(msg, "Loopback.Entry");
ILUPEU_LTSSM_LPBK_ACTIVE: sprintf(msg, "Loopback.Active");
ILUPEU_LTSSM_LPBK_EXIT: sprintf(msg, "Loopback.Exit");
ILUPEU_LTSSM_LPBK_EXIT_TIMEOUT: sprintf(msg, "Loopback.Exit.Timeout");
default: sprintf(msg, "OUCH! ERROR! You Missed Try Again");
}
ltssmStateToString = msg;
}
task PEUTestEnv::removePcie(){
trigger( ON, ev_removePcie );
}
//--------------------------------------------------------
//This task expects Denali Endpoint to enter specified LTSSM state or times out waiting
//--------------------------------------------------------
task PEUTestEnv::to_endpoint_LtssmState( bit [15:0] ep_ltssmState,
(integer timer=2000) ){
bit [31:0] denali_ltssm_tempdata;
bit [15:0] denali_ltssm_new_state;
bit [15:0] denali_ltssm_old_state;
string msg;
denali_ltssm_tempdata = Pod.FNXPCIEEnableTrans.ReadDenaliReg(PCIE_REG_DEN_LTSSM_STATE );
denali_ltssm_new_state = denali_ltssm_tempdata[15:0];
denali_ltssm_old_state = denali_ltssm_tempdata[31:16];
fork
{
while( (denali_ltssm_new_state !== ep_ltssmState) && timer ){
denali_ltssm_tempdata = Pod.FNXPCIEEnableTrans.ReadDenaliReg(PCIE_REG_DEN_LTSSM_STATE );
denali_ltssm_new_state = denali_ltssm_tempdata[15:0];
denali_ltssm_old_state = denali_ltssm_tempdata[31:16];
@(posedge CLOCK);
}
}
{
while( timer ){
@(posedge CLOCK);
timer--;
}
}
join any
if( !timer ){
sprintf(msg,"PEUTestEnv::to_endpoint_LtssmState timed out waiting to enter LTSSM_STATE -%s- (new_state = %0h, old_state = %0h) \n",ep_ltssmStateToString(ep_ltssmState), denali_ltssm_new_state, denali_ltssm_old_state );
_REPORT_ERROR("::to_endpoint_LtssmState timed out");
_ERROR_INFO(msg);
}else{
printf("\n=========== Denali Endpoint Entered LTSSM_STATE -%s- (new_state = %h, old_state = %0h) ===========\n",ep_ltssmStateToString(ep_ltssmState), denali_ltssm_new_state, denali_ltssm_old_state);
}
}
task PEUTestEnv::SetPEU_ASPM_enable( bit[1:0] value=3) {
CSRCollection CSR;
bit[ ILUPEU_CSR_WIDTH-1:0 ] csrRegTmpData;
bit[ FNX_PCIE_XTR_REG_DEN_WIDTH-1:0 ] denRegTmpData;
CSR = Pod.CSRXtr.CSR;
// CSR = new(Pod.CSRXtr.CSR);
// Setting PEU Link control ASPM to value
csrRegTmpData = 0;
csrRegTmpData = CSR.fire_plc_tlu_ctb_tlr_csr_a_lnk_ctl.read();
csrRegTmpData[ FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_ASPM_SLC ] = value;
CSR.fire_plc_tlu_ctb_tlr_csr_a_lnk_ctl.write(csrRegTmpData,FIRE_PIO_SLOW);
// Set the same value to Denali root monitor link control register ASPM
denRegTmpData = Pod.denali_root_monitor_PCIEEnableTrans.ReadDenaliReg( PCIE_REG_EXP_LINK_CTRL );
denRegTmpData[FNX_PCIE_XTR_REG_DEN_EXP_LINK_CTRL_ASPM_CTRL_SLC] = value;
Pod.denali_root_monitor_PCIEEnableTrans.WriteDenaliReg(PCIE_REG_EXP_LINK_CTRL, denRegTmpData);
// report the value set
csrRegTmpData = CSR.fire_plc_tlu_ctb_tlr_csr_a_lnk_ctl.read();
denRegTmpData = Pod.FNXPCIEEnableTrans.ReadDenaliReg( PCIE_REG_EXP_LINK_CTRL );
// ilupeuLinkCtrlASPM = %h \n", csrRegTmpData[FIRE_PLC_TLU_CTB_TLR_CSR_A_LNK_CTL_ASPM_SLC]);
// denali root monitor LinkCtrlASPM = %h \n", denRegTmpData);
}
task PEUTestEnv::EndpointExpectDLLP(bit [FNX_PCIE_XTR_DLLP_TYPE_WIDTH-1:0] DllpType) {
FNXPCIEXactorTransaction PCIEDllpTrans;
PCIEDllpTrans = new( Pod.FNXPCIEBldr );
PCIEDllpTrans.MyPacket.PktType = FNX_PCIE_XTR_PKT_TYPE_DLLP;
PCIEDllpTrans.MyPacket.DllpType = DllpType;
void = PCIEDllpTrans.Expect( 7000 );
}
//These tasks will discard FC update from Denali
task PEUTestEnv::disableDenaliFC() {
FNXPCIEXactorTransaction PCIEDllpTrans;
PCIEDllpTrans = Pod.FNXPCIEEnableTrans;
PCIEDllpTrans.EnableFCDiscard();
}
task PEUTestEnv::enableDenaliFC() {
FNXPCIEXactorTransaction PCIEDllpTrans;
PCIEDllpTrans = Pod.FNXPCIEEnableTrans;
PCIEDllpTrans.DisableFCDiscard();
}
// task to change denali soma timing parameter
task PEUTestEnv::Change_soma_parameters_ac(string _str1) {
integer Err;
string str1;
// str1 = "mmsomaset tb_top.pcie_root_monitor ttoTLCpl 1 us ";
str1 = _str1;
Err = DenaliDDVTclEval(str1);
// bad status when = 1
if (Err == 1) {
printf("AC: Error: changing soma parameter: %s at time %d \n", str1, get_time(LO));
}
else {
printf("AC: changing soma parameter: %s at time %d \n", str1, get_time(LO));
}
}
function string PEUTestEnv::ep_ltssmStateToString( bit [15:0] ep_ltssmState ){
string msg;
//Get the values from ilupeu_defines.vri
case (ep_ltssmState){
PCIE_LTSSM_STATE_L0: sprintf(msg, "PCIE_LTSSM_STATE_L0");
PCIE_LTSSM_STATE_L1Idle: sprintf(msg, " PCIE_LTSSM_L1Idle");
PCIE_LTSSM_STATE_L2Idle: sprintf(msg, " PCIE_LTSSM_L2Idle");
PCIE_LTSSM_STATE_Rx_L0sIdle_Tx_L0 : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sIdle_Tx_L0 "); // x000000a0,
PCIE_LTSSM_STATE_Rx_L0sIdle_Tx_L0sIdle : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sIdle_Tx_L0sIdle "); // x00000022,
PCIE_LTSSM_STATE_Rx_L0_Tx_L0sIdle : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0_Tx_L0sIdle "); // x00000082,
PCIE_LTSSM_STATE_Rx_L0sEntry_Tx_L0 : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sEntry_Tx_L0 "); // x000000c0,
PCIE_LTSSM_STATE_Rx_L0sFTS_Tx_L0 : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sFTS_Tx_L0 "); // x00000090,
PCIE_LTSSM_STATE_Rx_L0sEntry_Tx_L0sEntry : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sEntry_Tx_L0sEntry "); // x00000044,
PCIE_LTSSM_STATE_Rx_L0sIdle_Tx_L0sEntry : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sIdle_Tx_L0sEntry "); // x00000024,
PCIE_LTSSM_STATE_Rx_L0sFTS_Tx_L0sEntry : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sFTS_Tx_L0sEntry "); // x00000014,
PCIE_LTSSM_STATE_Rx_L0sEntry_Tx_L0sIdle : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sEntry_Tx_L0sIdle "); // x00000042,
PCIE_LTSSM_STATE_Rx_L0sFTS_Tx_L0sIdle : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sFTS_Tx_L0sIdle "); // x00000012,
PCIE_LTSSM_STATE_Rx_L0sEntry_Tx_L0sFTS : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sEntry_Tx_L0sFTS "); // x00000041,
PCIE_LTSSM_STATE_Rx_L0sIdle_Tx_L0sFTS : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sIdle_Tx_L0sFTS "); // x00000021,
PCIE_LTSSM_STATE_Rx_L0sFTS_Tx_L0sFTS : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0sFTS_Tx_L0sFTS "); // x00000011,
PCIE_LTSSM_STATE_Rx_L0_Tx_L0sEntry : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0_Tx_L0sEntry "); // x00000084,
PCIE_LTSSM_STATE_Rx_L0_Tx_L0sFTS : sprintf(msg, " PCIE_LTSSM_STATE_Rx_L0_Tx_L0sFTS "); // x00000081
PCIE_LTSSM_STATE_ConfigurationIdle : sprintf(msg, " PCIE_LTSSM_STATE_ConfigurationIdle "); // x00003500
PCIE_LTSSM_STATE_ConfigurationLinkwidthStart : sprintf(msg, " PCIE_LTSSM_STATE_ConfigurationLinkwidthStart "); // x00000081
PCIE_LTSSM_STATE_ConfigurationLanenumAccept : sprintf(msg, "PCIE_LTSSM_STATE_ConfigurationLanenumAccept "); // 0x00003200,
PCIE_LTSSM_STATE_ConfigurationLanenumWait : sprintf(msg, "PCIE_LTSSM_STATE_ConfigurationLanenumWait "); // 0x00003300,
PCIE_LTSSM_STATE_ConfigurationComplete : sprintf(msg, "PCIE_LTSSM_STATE_ConfigurationComplete "); // 0x00003400,
PCIE_LTSSM_STATE_ConfigurationIdle : sprintf(msg, "PCIE_LTSSM_STATE_ConfigurationIdle "); // 0x00003500,
PCIE_LTSSM_STATE_LoopbackEntry_Master : sprintf(msg, "PCIE_LTSSM_STATE_LoopbackEntry_Master "); // 0x00007000,
PCIE_LTSSM_STATE_LoopbackActive_Master : sprintf(msg, "PCIE_LTSSM_STATE_LoopbackActive_Master "); // 0x00007100,
PCIE_LTSSM_STATE_LoopbackExit_Master : sprintf(msg, "PCIE_LTSSM_STATE_LoopbackExit_Master "); // 0x00007200,
PCIE_LTSSM_STATE_LoopbackEntry_Slave : sprintf(msg, "PCIE_LTSSM_STATE_LoopbackEntry_Slave "); // 0x00007400,
PCIE_LTSSM_STATE_LoopbackActive_Slave : sprintf(msg, "PCIE_LTSSM_STATE_LoopbackActive_Slave "); // 0x00007500,
PCIE_LTSSM_STATE_LoopbackExit_Slave : sprintf(msg, "PCIE_LTSSM_STATE_LoopbackExit_Slave "); // 0x00007600,
PCIE_LTSSM_STATE_LoopbackExit_Idle : sprintf(msg, "PCIE_LTSSM_STATE_LoopbackExit_Idle "); // 0x00007700,
PCIE_LTSSM_STATE_DetectEntry : sprintf(msg, "PCIE_LTSSM_STATE_DetectEntry "); // 0x00001000,
PCIE_LTSSM_STATE_DetectQuiet : sprintf(msg, "PCIE_LTSSM_STATE_DetectQuiet "); // 0x00001100,
PCIE_LTSSM_STATE_DisabledEntry : sprintf(msg, " PCIE_LTSSM_STATE_DisabledEntry "); // x00008000
PCIE_LTSSM_STATE_Disabled : sprintf(msg, " PCIE_LTSSM_STATE_Disabled "); // x00008100
PCIE_LTSSM_STATE_HotReset : sprintf(msg, " PCIE_LTSSM_STATE_HotReset "); // x0000f000
PCIE_LTSSM_STATE_RecoveryRcvrLock : sprintf(msg, " PCIE_LTSSM_STATE_RecoveryRcvrLock "); // x00004000
PCIE_LTSSM_STATE_RecoveryRcvrCfg : sprintf(msg, " PCIE_LTSSM_STATE_RecoveryRcvrCfg "); // x00004100
PCIE_LTSSM_STATE_RecoveryIdle : sprintf(msg, " PCIE_LTSSM_STATE_RecoveryIdle "); // x00004200
default: _REPORT_ERROR( psprintf("ep_ltssmStateToString ERROR! You Missed Try Again") );
}
ep_ltssmStateToString = msg;
}
task PEUTestEnv::driveUnsupportDLLP() {
FNXPCIEXactorTransaction PCIEDllpTrans;
bit [11:0] DLLPSeqNmbr = 0;
// create Nak with invalid large sequence number
PCIEDllpTrans = new(Pod.FNXPCIEBldr);
PCIEDllpTrans.MyPacket.PktType = FNX_PCIE_XTR_PKT_TYPE_DLLP;
PCIEDllpTrans.MyPacket.DllpType = FNX_PCIE_XTR_DLLP_TYPE_NAK;
DLLPSeqNmbr = PCIEDllpTrans.MyPacket.DLLFrmSeqNum - 1;
if (DLLPSeqNmbr < 12'hFEF) {
PCIEDllpTrans.MyPacket.AckNakSeqNum = DLLPSeqNmbr + 12'h10;
}
else {
PCIEDllpTrans.MyPacket.AckNakSeqNum = 12'hFFF;
}
// inject error into this packet
PCIEDllpTrans.MyPacket.DenaliErr = PCIE_EI_RSRVD_TYPE;
PCIEDllpTrans.MyPacket.inject_unsupport_dllp_type = 1;
// env.driveUnsupportDLLP: inject_unsupport_dllp_type = %d at time %d\n", PCIEDllpTrans.MyPacket.inject_unsupport_dllp_type, get_time(LO));
// drive it out
PCIEDllpTrans.MyPacket.DriveImmediately = 1;
PCIEDllpTrans.Drive(0);
activityCounter = activityCounter + 1;
printf("AC: Unsupported DLLP was injected \n");
}
task PEUTestEnv::driveBadCRCDLLP() {
FNXPCIEXactorTransaction PCIEDllpTrans;
bit [11:0] DLLPSeqNmbr = 0;
// create Nak with invalid large sequence number
PCIEDllpTrans = new(Pod.FNXPCIEBldr);
PCIEDllpTrans.MyPacket.PktType = FNX_PCIE_XTR_PKT_TYPE_DLLP;
PCIEDllpTrans.MyPacket.DllpType = FNX_PCIE_XTR_DLLP_TYPE_NAK;
DLLPSeqNmbr = PCIEDllpTrans.MyPacket.DLLFrmSeqNum - 1;
if (DLLPSeqNmbr < 12'hFEF) {
PCIEDllpTrans.MyPacket.AckNakSeqNum = DLLPSeqNmbr + 12'h10;
}
else {
PCIEDllpTrans.MyPacket.AckNakSeqNum = 12'hFFF;
}
// inject error into this packet
PCIEDllpTrans.MyPacket.DenaliErr = PCIE_EI_LCRC;
// drive it out
PCIEDllpTrans.MyPacket.DriveImmediately = 1;
PCIEDllpTrans.Drive(0);
activityCounter = activityCounter + 1;
printf("AC: Bad CRC DLLP was injected at time %d \n", get_time(LO));
}
/* N2
* driveduplicateSeqNmbrReq - Tell the FNXPcieXtr to send a duplicate sequence number TLP to the PEU
*
* Parameters:
* PktHdr - The TLP's header, in PCI-Express format
* DataSpec - A specification of the packet payload
* LenAdjust - An adjustment to the number of DWs presented to the transactor
* BadParity - Where should bad parity be inserted (zero=>no bad parity)
* Priority - Should the TLP be presented even if the ingress pipe is plugged?
* Abort - Should the TLP be aborted (only) before returning?
*
* NOTE: The caller is suspended until the TLP is on its way to the PEU.
*/
task PEUTestEnv::driveduplicateSeqNmbrReq(
bit[PEC_PCI__HDR] PktHdr,
bit [63:0] DataSpec,
(integer LenAdjust=0),
(integer BadParity=0),
(bit Priority=0),
(bit Abort=0),
(bit CfgRdCpl=0),
(bit isDmaReq=0) )
{
FNXPCIEXactorTransaction PCIETlpTrans;
FNXPCIEXactorTransaction PCIEDllpTrans;
integer hdrLen;
integer dataLen;
integer xtrLen;
integer tlpGap;
integer pickit;
integer idleChance;
integer badPtyDW;
integer i;
bit [7:0] pyldByteAry[*];
bit [11:0] SeqNmbr = 0;
//N2 - Only need 1 report class ReportClass report = new;
if (Report.get_global_print_threshold() < RPRT_DEBUG_1) {
printf("AC: PEUTestEnv::driveduplicateSeqNmbrReq(PktHdr=128'h%0h, DataSpec=%0d, LenAdjust=%0d, BadParity=%0d)\n",
PktHdr, DataSpec, LenAdjust, BadParity);
}
// If the ingress pipeline is suspended,
// then wait for someone to unblock it.
// Don't block a "priority" TLP
if ( !Priority && !sync( CHECK, ev_ingressUnblocked ) )
{
sync( ANY, ev_drainStateEnd, ev_softReset, ev_ingressUnblocked );
}
// How big is the header and payload?
hdrLen = 3 + PktHdr[PEC_PCI__FMT_4DW];
if ( PktHdr[PEC_PCI__FMT_DATA] )
{
dataLen = PktHdr[PEC_PCI__LEN];
if ( dataLen == 0 ) dataLen = 1024;
}
else
dataLen = 0;
if ( PktHdr[PEC_PCI__TD] ) dataLen = dataLen + 1;
// And how big is the TLP that we'll
// give to the transactor?
xtrLen = hdrLen + dataLen + LenAdjust;
if ( xtrLen < 1 ) xtrLen = 2;
// Get a PCIE Transaction to give to the xactor.
PCIETlpTrans = new( Pod.FNXPCIEBldr );
PCIEDllpTrans = new( Pod.FNXPCIEBldr );
PCIETlpTrans.SetID( f_ID.NextTransID() );
PCIEDllpTrans.SetID( f_ID.NextTransID() );
// ...and shove in the header data,
// ...and whatever payload is expected.
ConvertHdr2PcieTlp( PktHdr,
DataSpec,
PCIETlpTrans,
LenAdjust,
isDmaReq);
//Don't adjust the payload if this is a length error being sent
if ( CfgRdCpl && (PktHdr[PEC_PCI__LEN] == 1) ) //DANGER IOS FC - Do NOT execute this
{
//If this is a completion for a config read
//Delete the data generated in ConvertHdr2PcieTlp
PCIETlpTrans.MyPacket.Pyld.delete();
pyldByteAry = new[4];
//and put in the right byte swapped payload
for(i=0; i < 4 ; i++){
pyldByteAry[3-i] = DataSpec + i;
}
PCIETlpTrans.MyPacket.SetPyld( pyldByteAry );
}
//N2 ingressThrottle - no control over idles between PEU and PTL(TLU)
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// Add some gas to the end of the TLP.
// N2 - Delay is before PCIETlpTrans gets driven
tlpGap = localRandomRange(minIngressGap,maxIngressGap);
// The PCIETlpTrans returns when the packet is
// completely driven on serial links
// Don't submit the TLP if we're about to reset.
// And if there is a reset pending, hang out until it happens.
if ( Priority )
printf( "Calling xtr for TLP (tag=%h)\n", PktHdr[PEC_PCI__CPL_TAG] );
fork
{
if( !softResetPending ){
// modify PCIE_REG_DEN_NXT_TX_TLP_SEQ by 1
SeqNmbr = PCIETlpTrans.ReadDenaliReg(PCIE_REG_DEN_NXT_TX_TLP_SEQ);
SeqNmbr = SeqNmbr - 1;
PCIETlpTrans.WriteDenaliReg(PCIE_REG_DEN_NXT_TX_TLP_SEQ, SeqNmbr);
}else{
sync( ANY, ev_softReset );
}
}
{
sync( ANY, ev_softReset, ev_removePcie );
}
{
sync( ANY, ev_removePcie );
//Mark packets still stuck in the Denali User Queue to be Discarded
//PCIETlpTrans.MyPacket.DenaliErr = PCIE_EI_DISCARD;
}
join any
activityCounter = activityCounter + 1;
// if ( Priority )
// printf( "Xtr has sent priority TLP (tag=%h)\n", PktHdr[PEC_PCI__CPL_TAG] );
/* N2 - review- Need to test this
// If we just inserted bad parity into a TLP header, then the bad DW
// might also appear as padding for the prior TLP.
if ( BadParity != 0 && !softResetPending )
{
_DEBUG_MSG( "PEUTestEnv (cycle %0d) %s (offset=%0d)\n", get_cycle(),
"Inject bad ingress TLP parity",
BadParity > 0 ? (BadParity-1) : (xtrLen*4 + BadParity + 1) );
if ( badPtyDW < 3 )
this.f_DMUXtr.ignoreUnusedParity();
}
*/
} /* end "driveduplicateSeqNmbrReq" */
task PEUTestEnv::Endpoint_send_FC_update(bit [FNX_PCIE_XTR_DLLP_TYPE_WIDTH-1:0] DLLPtype, bit [FNX_PCIE_XTR_DLLP_FC_HDR_FC_WIDTH-1:0] HdrFC, bit [FNX_PCIE_XTR_DLLP_FC_DATA_FC_WIDTH-1:0] DataFC) {
FNXPCIEXactorTransaction PCIEDllpTrans;
bit [FNX_PCIE_XTR_DLLP_FC_VC_WIDTH-1:0] VC_no;
PCIEDllpTrans = Pod.FNXPCIEEnableTrans;
PCIEDllpTrans.MyPacket.PktType = FNX_PCIE_XTR_PKT_TYPE_DLLP;
VC_no = PCIEDllpTrans.MyPacket.GetDllpFCVC();
// PCIEDllpTrans.MyPacket.SetDllpFCVC(3'b000); // setting VC = 0
PCIEDllpTrans.MyPacket.SetDllpFCVC(0); // setting VC = 0
VC_no = PCIEDllpTrans.MyPacket.GetDllpFCVC();
PCIEDllpTrans.MyPacket.DllpType = DLLPtype;
PCIEDllpTrans.MyPacket.DllpFCHdrFC = HdrFC;
PCIEDllpTrans.MyPacket.DllpFCDataFC = DataFC;
printf("AC: PCIEDllpTrans.MyPacket.DllpType = %b, PCIEDllpTrans.MyPacket.DllpFCHdrFC = %x, PCIEDllpTrans.MyPacket.DllpFCDataFC = %x \n", PCIEDllpTrans.MyPacket.DllpType, PCIEDllpTrans.MyPacket.DllpFCHdrFC, PCIEDllpTrans.MyPacket.DllpFCDataFC);
PCIEDllpTrans.MyPacket.DriveImmediately = 1;
PCIEDllpTrans.Drive(0);
}
task PEUTestEnv::Monitor_Endpoint_Sent_DLLP(bit [FNX_PCIE_XTR_DLLP_TYPE_WIDTH-1:0] DllpType)
{
FNXPCIEXactorTransaction PCIEIngressDllpTrans;
PCIEIngressDllpTrans = new( Pod.FNXPCIEBldr );
PCIEIngressDllpTrans.EnableSampleIngressDllp();
//Start with a clean packet each time
PCIEIngressDllpTrans.MyPacket.PktReset();
//The SampleIngressDllp will return a copy of each DLLP packet that the FNXPCIEXtr transmits
// so determine if this is a Flow Control Update or an ACK/NAK and then update
// the correct environment variables
PCIEIngressDllpTrans.SampleIngressDllp( PCIEIngressDllpTrans.MyPacket , 5000 );
if( PCIEIngressDllpTrans.MyPacket.isDllpAckNak() || PCIEIngressDllpTrans.MyPacket.isDllpPM()){
if (DllpType == PCIEIngressDllpTrans.MyPacket.DllpType) {
_DEBUG_MSG( "AC: received expected endpoint sent DllpType of %s", dllptypeToString(PCIEIngressDllpTrans.MyPacket.DllpType) );
}
else {
_REPORT_ERROR( psprintf("PEUTestEnv::expected endpoint to send DllpType = %s, but receive DllpType = %s", dllptypeToString(DllpType), dllptypeToString(PCIEIngressDllpTrans.MyPacket.DllpType)));
}
// PCIEIngressDllpTrans.MyPacket.AckNakSeqNum
}
}
function string PEUTestEnv::dllptypeToString( bit [FNX_PCIE_XTR_DLLP_TYPE_WIDTH-1:0] DllpType ){
string msg;
case(DllpType) {
FNX_PCIE_XTR_DLLP_TYPE_ACK : sprintf(msg, "ACK ");
FNX_PCIE_XTR_DLLP_TYPE_NAK : sprintf(msg, "NAK ");
FNX_PCIE_XTR_DLLP_TYPE_PM_ENTER_L1 : sprintf(msg, "PM_ENTER_L1 ");
FNX_PCIE_XTR_DLLP_TYPE_PM_ENTER_L23 : sprintf(msg, "PM_ENTER_L23 ");
FNX_PCIE_XTR_DLLP_TYPE_PM_ACTIVE_ST_REQ_L1 : sprintf(msg, "PM_ACTIVE_ST_REQ_L1 ");
FNX_PCIE_XTR_DLLP_TYPE_PM_REQUEST_ACK : sprintf(msg, "PM_REQUEST_ACK ");
FNX_PCIE_XTR_DLLP_TYPE_VENDOR : sprintf(msg, "VENDOR ");
FNX_PCIE_XTR_DLLP_TYPE_INIT_FC1_P : sprintf(msg, "INIT_FC1_P ");
FNX_PCIE_XTR_DLLP_TYPE_INIT_FC1_NP : sprintf(msg, "INIT_FC1_NP ");
FNX_PCIE_XTR_DLLP_TYPE_INIT_FC1_CPL : sprintf(msg, "INIT_FC1_CPL ");
FNX_PCIE_XTR_DLLP_TYPE_INIT_FC2_P : sprintf(msg, "INIT_FC2_P ");
FNX_PCIE_XTR_DLLP_TYPE_INIT_FC2_NP : sprintf(msg, "INIT_FC2_NP ");
FNX_PCIE_XTR_DLLP_TYPE_INIT_FC2_CPL : sprintf(msg, "INIT_FC2_CPL ");
default: _INFO_MSG("DllpType of unknown type" );
}
dllptypeToString = msg;
}
/*
* dmu_expect_msg - dmu is expecting A msg TLP from the ILU
*
* Parameters:
* f_msg = 8 bit message code, ie. PEC_PCI__TYPE_MSG
*/
task PEUTestEnv::dmu_expect_msg(
bit [7:0] f_msg, // The requested message code
bit [2:0] f_rc)
{
bit[PEC_PCI__HDR] ingressHdr; // The ingress TLP's header
integer ingressData; // A payload descriptor
bit[7:0] ingressTag; // The tag for the TLP
// First, get in line for a DMA tag...
// f_env.allocDmaTag( ingressTag );
// Then build a TLP
genIngressMsg( ingressTag, ingressHdr, ingressData );
// ingressData = 0;
ingressHdr[PEC_PCI__MSG_CODE] = f_msg;
ingressHdr[PEC_PCI__FMT] = PEC_PCI__FMT_NO_DATA_4DW; // msg with no data
ingressHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG;
ingressHdr[PEC_PCI__TYPE] =
( ingressHdr[PEC_PCI__TYPE] & ~PEC_PCI__TYPE_MSG_RC_MASK )
| ( f_rc & PEC_PCI__TYPE_MSG_RC_MASK );
ingressHdr[PEC_PCI__TC] = 0;
ingressHdr[PEC_PCI__TD] = 0;
ingressHdr[PEC_PCI__EP] = 0;
ingressHdr[PEC_PCI__ATTR] = 0;
ingressHdr[PEC_PCI__LEN] = 0;
ingressHdr[PEC_PCI__REQ_ID] = 32;
ingressHdr[PEC_PCI__TLP_TAG] = 0;
ingressHdr[PEC_PCI__ADDR] = 0;
// ingressHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MSG;
printf("PEUTestEnv::dmu_expect_msg: ingressHdr[PEC_PCI__FMT] = %h, ingressHdr[PEC_PCI__TYPE] = %0h, ingressHdr[PEC_PCI__MSG_CODE] = %h \n", ingressHdr[PEC_PCI__FMT] , ingressHdr[PEC_PCI__TYPE], ingressHdr[PEC_PCI__MSG_CODE]);
reserveIngressCredits( ingressHdr );
expectILU( ingressHdr, ingressData );
consumeIngressCredits( ingressHdr );
// f_env.freeDmaTag( ingressTag );
} /* end "dmu_expect_msg" */
task PEUTestEnv::setDenaliLaneSkew( integer lane,
integer total_skew,
integer bit_skew,
integer bit_delay,
integer symbol_delay ){
bit[ 31:0 ] Val;
bit[ FNX_PCIE_XTR_REG_DEN_WIDTH-1:0 ] denRegTmpData;
FNXPCIEXactorTransaction PCIETrans;
PCIETrans = new( Pod.FNXPCIEBldr );
denRegTmpData = 0;
denRegTmpData[4:0] = lane; //Lane Number
denRegTmpData[6:5] = PCIE_LN_SKEW_OP_set_tx; //Operation get/set tx/rx
denRegTmpData[8:7] = PCIE_LN_SKEW_total_skew; //Parameter bit_skew/bit_delay/symbol_delay
denRegTmpData[31:9] = total_skew;
if( total_skew ){
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_LN_SKEW, denRegTmpData );
}
denRegTmpData[8:7] = PCIE_LN_SKEW_bit_skew; //Parameter bit_skew/bit_delay/symbol_delay
denRegTmpData[31:9] = bit_skew;
if( bit_skew ){
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_LN_SKEW, denRegTmpData );
}
denRegTmpData[8:7] = PCIE_LN_SKEW_bit_delay; //Parameter bit_skew/bit_delay/symbol_delay
denRegTmpData[31:9] = bit_delay;
if( bit_delay ){
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_LN_SKEW, denRegTmpData );
}
denRegTmpData[8:7] = PCIE_LN_SKEW_symbol_delay; //Parameter bit_skew/bit_delay/symbol_delay
denRegTmpData[31:9] = symbol_delay;
if( symbol_delay ){
PCIETrans.WriteDenaliReg( PCIE_REG_DEN_LN_SKEW, denRegTmpData );
}
QuickReport( Report, RTYP_INFO, "setDenaliLaneSkew lane=%0d total_skew=%0d bit_skew=%0d bit_delay=%0d symbol_delay=%0d\n",lane,total_skew,bit_skew,bit_delay,symbol_delay );
}
task PEUTestEnv::Trigger_link_Up()
{
// Get the initial credit allocations
// If LinkTrainingStrategy.Check_Flow_Control_Init passes then Scenario will hold
// all the correct Initial Flow Control values
//Denali stores infinite credits as all 1's instead of 0
ingressNonpostHdrInit = (Scenario.ilupeuInitialNonPostedHeaderCredit == 8'hff)? 0 : Scenario.ilupeuInitialNonPostedHeaderCredit;
ingressPostHdrInit = (Scenario.ilupeuInitialPostedHeaderCredit == 8'hff)? 0 : Scenario.ilupeuInitialPostedHeaderCredit;
ingressPostDataInit = (Scenario.ilupeuInitialPostedDataCredit == 12'hfff)? 0 : Scenario.ilupeuInitialPostedDataCredit;
//These should be hardwired to infinite
ingressNonpostDataInit = 0;
ingressCompletionHdrInit = 0;
ingressCompletionDataInit = 0;
egressNonpostHdrInit = (Scenario.denali_FC_NPH_infinite == 1)? 0 : Scenario.denaliInitialNonPostedHeaderCredit;
egressNonpostDataInit = (Scenario.denali_FC_NPD_infinite == 1)? 0 : Scenario.denaliInitialNonPostedDataCredit;
egressPostHdrInit = (Scenario.denali_FC_PH_infinite == 1)? 0 : Scenario.denaliInitialPostedHeaderCredit;
egressPostDataInit = (Scenario.denali_FC_PD_infinite == 1)? 0 : Scenario.denaliInitialPostedDataCredit;
egressCompletionHdrInit = (Scenario.denali_FC_CPLH_infinite == 1)? 0: Scenario.denaliInitialCompletionHeaderCredit;
egressCompletionDataInit = (Scenario.denali_FC_CPLD_infinite == 1)? 0 : Scenario.denaliInitialCompletionDataCredit;
Report.report(RTYP_DEBUG_3," AC: egressNonpostHdrInit = %d \n", egressNonpostHdrInit);
Report.report(RTYP_DEBUG_3," AC: egressNonpostDataInit = %d \n", egressNonpostDataInit);
Report.report(RTYP_DEBUG_3," AC: egressPostHdrInit = %d \n",egressPostHdrInit );
Report.report(RTYP_DEBUG_3," AC: egressPostDataInit = %d \n", egressPostDataInit);
Report.report(RTYP_DEBUG_3," AC: egressCompletionHdrInit = %d \n",egressCompletionHdrInit );
Report.report(RTYP_DEBUG_3," AC: egressCompletionDataInit = %d \n", egressCompletionDataInit);
trigger( ON, ev_linkUp );
Report.report(RTYP_INFO,"Env:linkUp ilupeu linkup \n");
}
task PEUTestEnv::skewRxClockMax( bit enabled )
{
//Symbol Parameter Min Nom Max Units Comments
//UI Unit Interval 399.88 400 400.12 ps Each UI is 400 ps +/-300 ppm.
if( enabled ){
//Set Denali clock to -600ppm
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 399.74 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 399.78 ps");
}else{
//Set back to default clock
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 399.99 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.01 ps");
}
}
task PEUTestEnv::skewRxClockMin( bit enabled )
{
//Symbol Parameter Min Nom Max Units Comments
//UI Unit Interval 399.88 400 400.12 ps Each UI is 400 ps +/-300 ppm.
if( enabled ){
//Set Denali clock to -600ppm
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 400.22 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.26 ps");
}else{
//Set back to default clock
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 399.99 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.01 ps");
}
}
task PEUTestEnv::driftRxClock( bit enabled )
{
//Since the PEU clock is stable we can drift the Denali clock +/-600ppm
//Symbol Parameter Min Nom Max Units Comments
//UI Unit Interval 399.88 400 400.12 ps Each UI is 400 ps +/-300 ppm.
driftRxClockEnabled = enabled;
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 400.10 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.14 ps");
fork
{
while( driftRxClockEnabled ){
if( driftRxClockEnabled ){
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 400.22 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.26 ps");
}
if( driftRxClockEnabled ){
repeat( urandom_range(250, 100) ) @(posedge CLOCK);
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 400.10 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.14 ps");
}
if( driftRxClockEnabled ){
repeat( urandom_range(250, 100) ) @(posedge CLOCK);
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 400.01 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.03 ps");
}
if( driftRxClockEnabled ){
repeat( urandom_range(250, 100) ) @(posedge CLOCK);
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 399.86 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 399.90 ps");
}
if( driftRxClockEnabled ){
repeat( urandom_range(250, 100) ) @(posedge CLOCK);
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 399.74 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 399.78 ps");
}
if( driftRxClockEnabled ){
repeat( urandom_range(250, 100) ) @(posedge CLOCK);
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 399.82 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 399.88 ps");
}
if( driftRxClockEnabled ){
repeat( urandom_range(250, 100) ) @(posedge CLOCK);
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 399.97 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 399.99 ps");
}
if( driftRxClockEnabled ){
repeat( urandom_range(250, 100) ) @(posedge CLOCK);
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 400.08 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.12 ps");
}
}
//Set back to default clock
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImin 399.99 ps");
void = DenaliDDVTclEval("mmsomaset tb_top.pcieA ttxUImax 400.01 ps");
}
join none
}
task PEUTestEnv::start_Denali_DTM()
{
integer ui_delay = 0;
integer nmbr_clk_symbls = 250;
integer nmbr_fts_symbls = 50;
// 10/17/06
// Needed to force Denali to stay in L0
FNXPCIEXactorTransaction PCIEXtrTrans;
PCIEXtrTrans = new( Pod.FNXPCIEBldr );
//Take Denali out of reset
Pod.FNXPCIEEnableTrans.SetDenaliReset( 1'b0 );
printf("After SetDenaliReset( 1'b0 )\n");
// 10/17/06
//Added so fullchip did not need to reprogram the PEU skip interval timer
fork
wait( 1800, 1); //Wait for 500 cycles and turn off Hang Detect
{
@(posedge CLOCK);
@(posedge CLOCK);
//Wait until LTSSM = L0
to_endpoint_LtssmState(PCIE_LTSSM_STATE_L0,100);
printf("Starting forcing to L0 until PEU sends 1st COM \n");
repeat(1800){
//Keep forcing to L0 until PEU sends 1st COM
PCIEXtrTrans.WriteDenaliReg( PCIE_REG_DEN_LINK_CTRL, 32'h800 );
@(posedge CLOCK);
}
printf("Finishing forcing Denali to L0 until after PEU sends 1st COM SKIP \n");
}
join none
//Disable all Denali Errors
Pod.FNXPCIEEnableTrans.SuppressDenaliErr( PCIE_NO_ERROR );
//Don't transmit a SKIP ordered set first
Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_TX_SKIP_SETS, 0 );
// AT+ DTM 104MHz, instead of 100MHz, copied from
// /import/n2-svl-localdir6/somePerson/work1/verif/diag/vera/ilu_peu/src/directed/ilupeux8x8DTM.vr
//Change Denalis Timing to be 9.6ns(104MHz) instead of 4ns(250MHz)
Change_soma_parameters_ac("mmsomaset tb_top.pcieA ttoPollSpeed 960.01 ps ");
Change_soma_parameters_ac("mmsomaset tb_top.pcieA ttxUImin 959.99 ps ");
Change_soma_parameters_ac("mmsomaset tb_top.pcieA ttxUImax 960.01 ps ");
Change_soma_parameters_ac("mmsomaset tb_top.pcieA ttxLaneSKEWmax 3000 ps ");
Change_soma_parameters_ac("mmsomaset tb_top.pcieA trxUImin 959.99 ps ");
Change_soma_parameters_ac("mmsomaset tb_top.pcieA trxUImax 960.01 ps ");
// AT- DTM 104: //Change Denalis Timing to be 10ns(100MHz) instead of 4ns(250MHz)
// AT- DTM 104: Change_soma_parameters_ac("mmsomaset tb_top.pcieA ttoPollSpeed 1000.01 ps ");
// AT- DTM 104: Change_soma_parameters_ac("mmsomaset tb_top.pcieA ttxUImin 999.99 ps ");
// AT- DTM 104: Change_soma_parameters_ac("mmsomaset tb_top.pcieA ttxUImax 1000.01 ps ");
// AT- DTM 104: Change_soma_parameters_ac("mmsomaset tb_top.pcieA ttxLaneSKEWmax 3000 ps ");
// AT- DTM 104: Change_soma_parameters_ac("mmsomaset tb_top.pcieA trxUImin 999.99 ps ");
// AT- DTM 104: Change_soma_parameters_ac("mmsomaset tb_top.pcieA trxUImax 1000.01 ps ");
printf("After Change_soma_parameters_ac \n");
// repeat( 10 ) @(posedge CLOCK);
if( get_plus_arg( CHECK, "PEU_DTM_PCIE_SKEW_LANE0_UI=" ) ){
ui_delay = get_plus_arg( NUM, "PEU_DTM_PCIE_SKEW_LANE0_UI=" );
printf(" XXXXXXXXXXX PEU_DTM_PCIE_SKEW_LANE0_UI ui_delay=%0d \n",ui_delay);
ui_delay = ui_delay + 1; //Denalis format?
//Set a 10ui delay for lane 0
setDenaliLaneSkew( 0, 960000, 000000, ui_delay, 0 ); // delay lane 0
}
//Set Denali replay timer really high so there are no Replays
Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_REPLAY_TIMER, 64'hffff );
//Set Denali replay buffer really big to hold all transactions set
Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_RETRY_SIZE, 64'hfffff );
if( get_plus_arg( CHECK, "PEU_DTM_NMBR_CLK_SYMBLS=" ) ){
nmbr_clk_symbls = get_plus_arg( NUM, "PEU_DTM_NMBR_CLK_SYMBLS=" );
printf(" XXXXXXXXXXX PEU_DTM_NMBR_CLK_SYMBLS nmbr_clk_symbls=%0d \n",nmbr_clk_symbls);
}
//Data D21.5=xb5 is alternating 1's & 0's to allow bit lock to happen first
repeat( nmbr_clk_symbls/250 ){
Pod.FNXPCIEEnableTrans.Transmit_symbol_ToLink(250, 9'h0b5);
printf("After calling send D21.5=xb5 clock pattern \n");
repeat( 250 ) @( posedge CLOCK );
printf("After send D21.5=xb5 clock pattern delay\n");
}
Pod.FNXPCIEEnableTrans.Transmit_symbol_ToLink(nmbr_clk_symbls%250, 9'h0b5);
printf("After calling final send D21.5=xb5 clock pattern \n");
repeat( nmbr_clk_symbls%250 ) @( posedge CLOCK );
printf("After final send D21.5=xb5 clock pattern delay\n");
if( get_plus_arg( CHECK, "PEU_DTM_NMBR_FTS_SYMBLS=" ) ){
nmbr_fts_symbls = get_plus_arg( NUM, "PEU_DTM_NMBR_FTS_SYMBLS=" );
printf(" XXXXXXXXXXX PEU_DTM_NMBR_FTS_SYMBLS nmbr_fts_symbls=%0d \n",nmbr_fts_symbls);
}
//Request Denali to send # of FTS-Fast Training Sequences
repeat( nmbr_fts_symbls/50 ){
Pod.FNXPCIEEnableTrans.TransmitFTSToLink( 50 );
printf("After send # of FTS-Fast \n");
repeat( 50 * 4 ) @( posedge CLOCK );
}
Pod.FNXPCIEEnableTrans.TransmitFTSToLink( nmbr_fts_symbls%50 );
Pod.FNXPCIEEnableTrans.TransmitSKPToLink( 1 );
repeat( (nmbr_fts_symbls%50) * 4 ) @( posedge CLOCK );
printf("After final send fts pattern delay\n");
// 10/17/06
//Wait for the force Denali to L0 loop to complete
wait_child();
}