// ========== 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 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= 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 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 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<> 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(); }