// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: ilupeuMalCplPEUStr.vr
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
#define _INFO_MSG_MAL_CPL(msg) printf( "MalCpl (cyc %0d) %s\n", get_cycle(), msg )
class MalCplPEUStr extends PEUStrBase
local bit f_typeSpecified; // Was a bad-boy type supplied?
local bit [1:0] f_fmt; // The bad format
local bit [4:0] f_type; // The bad type
local bit f_lenSpecified; // Was a TLP length supplied?
local integer f_len; // A requested TLP length
local integer f_cross4K; // By what amount do we cross 4K
local integer f_adjustLen; // The delta to the true length
local integer f_errQueue; // A mailbox for bad pkt headers
local bit f_tdSpecified; // Was the TD supplied?
local bit f_tdFieldValue; // The TD value
local integer f_solicitedCpl;
task new( PEUTestEnv a_env )
function bit SetType( bit [1:0] a_fmt, bit [4:0] a_type )
2'b00 : isInvalid = !( PEC_PCI__TYPE_VALID_00 & ( 1 << a_type ) );
2'b01 : isInvalid = !( PEC_PCI__TYPE_VALID_01 & ( 1 << a_type ) );
2'b10 : isInvalid = !( PEC_PCI__TYPE_VALID_10 & ( 1 << a_type ) );
2'b11 : isInvalid = !( PEC_PCI__TYPE_VALID_11 & ( 1 << a_type ) );
task SetLength( integer a_length )
task AdjustLen( integer a_lengthDelta )
f_adjustLen = a_lengthDelta;
task Cross4K( integer a_dwCount )
task SetErrQueue( integer a_queue )
task SetTD( bit a_TDValue )
f_tdFieldValue = a_TDValue;
task SetSolicited( integer a_solicited )
f_solicitedCpl = a_solicited;
bit [ PEC_PCI__HDR ] reqHdr; // The request TLP's header
bit [ PEC_PCI__HDR ] cplHdr; // The completion TLP's header
bit [ PEC_PCI__HDR ] badCplHdr; // The corrupted completion TLP's header
bit [ 7:0 ] reqTag; // The tag for the TLP
integer pyld; // Reusable pyld variable
// Get in line for a PIO tag
f_env.allocRdTag( reqTag );
// Only PIO reads need completions
f_env.genEgressRdReq( reqTag, reqHdr, pyld, f_len, f_type );
f_env.genEgressRdReq( reqTag, reqHdr, pyld, *, f_type );
f_env.genEgressRdReq( reqTag, reqHdr, pyld, f_len, * );
f_env.genEgressRdReq( reqTag, reqHdr, pyld );
// make sure RequesterID is 0, since RSB
// will check that the completion has this
reqHdr[ PEC_PCI__REQ_ID ] = 16'h0;
// adjust the Fmt field, since it
// might not be what we want
reqHdr[ PEC_PCI__FMT_4DW ] = f_fmt[ 0 ];
if ( reqHdr[ PEC_PCI__FMT_4DW ] === 1'b1 ){
reqHdr[ PEC_PCI__ADDR ] = {urandom(),urandom()};
}else{ //Make sure addr[1:0] = 0
// create completion based on PIO req
f_env.genIngressCpl( reqHdr, cplHdr, pyld );
// corrupt the ingress completion
badCplHdr[ PEC_PCI__TD ] = f_tdFieldValue;
// Force the digest if we've got a
// cpl without data and a negative
if ( f_adjustLen < 0 && !badCplHdr[PEC_PCI__FMT_DATA] )
badCplHdr[PEC_PCI__TD] = 1;
// Check if cpl is supposed to be expected
// drive the ILU with the request
_INFO_MSG_MAL_CPL( psprintf("Sending PIO request (tag=%h)",reqTag) );
f_env.driveILU( reqHdr, 0, 0 );
// expect the request out the TLU
f_env.expectPCIE( reqHdr, 0 );
// drive the TLU with the bad cpl
f_env.drivePCIE( badCplHdr, pyld, f_adjustLen, *, *, f_abortErrTlp );
_INFO_MSG_MAL_CPL( psprintf("Sending malformed completion (tag=%h)",reqTag) );
f_env.waitIngressLatency( badCplHdr, (f_adjustLen>0) ? f_adjustLen : 0 );
mailbox_put( f_errQueue, e_ERR_ue_mfp );
mailbox_put( f_errQueue, (f_adjustLen<0) ? 128'bx : cplHdr );
f_env.drivePCIE( cplHdr, pyld );
f_env.expectILU( cplHdr, pyld );
f_env.freePioTag( reqTag );
else { /* unsolicited cpl */
f_env.drivePCIE( badCplHdr, pyld, f_adjustLen, *, *, f_abortErrTlp );
_INFO_MSG_MAL_CPL( psprintf("Sending malformed completion (tag=%h)",reqTag) );
f_env.waitIngressLatency( badCplHdr, (f_adjustLen>0) ? f_adjustLen : 0 );
mailbox_put( f_errQueue, e_ERR_ue_mfp );
mailbox_put( f_errQueue, (f_adjustLen<0) ? 128'bx : cplHdr );