// ========== Copyright Header Begin ========================================== // // OpenSPARC T2 Processor File: scanUtilsClass.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 #include #include // TAP specific defines #include // jtag interface #include #include #include //extern SystemTap dft; extern "C" task PLI_InitFlopPliWithChaindef_vr(string topMod, integer scanCfg, integer asicGates, integer chainEnable); extern "C" function string PLI_JtagShiftExpData_vr(integer chain, string scanIn); extern "C" function string PLI_JtagShiftExpDataConcat_vr(string scanIn); extern "C" task PLI_JtagCheckExpData_vr(integer chain); #define CLASSNAME scanUtilities #define MFG_SCAN_CFG 0 #define JTAG_SCAN_CHAINSEL_CFG 1 #define JTAG_SCAN_CONCAT_CFG 2 #define TT_SCAN_CFG 3 #define MAX_SCAN_CHAINS 32 #define MAX_SHIFT_COUNT 75000 #define TT_FUNC_CLK_DEFAULT 2 #define TT_MAX_CMP_CLKS 255 #define TT_MAX_IO_CLKS 63 #define MAX_WAIT_BEFORE_SCAN 100 #define MAX_WAIT_BEFORE_TT 100 #define MAX_WAIT_AFTER_TT 100 #define MAX_NUM_OF_SHIFTS 50 #define BITS_IN_SCAN_STRING 32 class CLASSNAME extends SystemTap { local string className = "scanUtilities"; local string topLevel = "tb_top.cpu"; local bit [31:0] chainEn; local integer scanChainConfig; local integer maxShift; local integer asicGatesPresent; local bit [31:0] scanInData; local integer refModelEnabled; task new ( StandardDisplay dbgIn, integer refModEn=0, bit [32:0] scanData=33'h100000000 ); function bit [31:0] getMfgChainEn(); function bit [5:0] getJtagChainEn(); function integer getMaxShiftCount(); function integer checkForAsicGates(); task setupChipForScanDump(); function integer tapJTAGSerscan ( integer shiftCount, bit [5:0] chainSel, integer scanOutChecking ); function integer checkIfAsicCluster( integer chain ); } ///////////////////////////////////////////////////////////////////////////// task CLASSNAME::new(StandardDisplay dbgIn, integer refModEn=0, bit [32:0] scanData=33'h100000000) { //tap_port = tap_bind; //dbg = dbgIn; //tap_state_reg = 4'bx; //tap_port.$test_mode = 1'b0 soft async; // JTAG debug mode unless told to goto manufacturing test //tap_port.$trst_n = 1'bx soft async; //tap_port.$tdi = 1'bx soft async; //tap_port.$tms = 1'b1 soft async; //if (!get_plus_arg(CHECK, "noJtagTapReset")) { //dbg.dispmon(dispmonScope, MON_INFO, "WARNING: systemTapClass.vr : skip calling TapResetType1() to reset TAP"); //// Toggle TRST_L 0 -> 1 //TapResetType1(); //} super.new(dbgIn); chainEn = 31'h00000000; asicGatesPresent = 0; scanChainConfig = JTAG_SCAN_CHAINSEL_CFG; if (scanData[32]==1) { scanInData = urandom(); } else { scanInData = scanData[31:0]; } refModelEnabled = refModEn; } function bit [31:0] CLASSNAME::getMfgChainEn() { if (get_plus_arg(CHECK, "chainsel=")) { chainEn = get_plus_arg(HNUM, "chainsel="); `PR_ALWAYS(className, MON_ALWAYS, psprintf("Chain Enable is: %0h\n", chainEn)); } else { `PR_ALWAYS(className, MON_ALWAYS, psprintf("Chain Enable is: %0h\n", chainEn)); } getMfgChainEn = chainEn; } function bit [5:0] CLASSNAME::getJtagChainEn() { chainEn[5] = 1'b1; if (get_plus_arg(CHECK, "chainsel=")) { chainEn[4:0] = get_plus_arg(NUM, "chainsel="); scanChainConfig = JTAG_SCAN_CHAINSEL_CFG; `PR_ALWAYS(className, MON_ALWAYS, psprintf("Chain Enable is: %d\n", chainEn)); } else { // concat all chains chainEn[5] = 1'b0; scanChainConfig = JTAG_SCAN_CONCAT_CFG; `PR_ALWAYS(className, MON_ALWAYS, psprintf("No chain enable selected; scanning all chains concatonated\n")); } getJtagChainEn = chainEn; } function integer CLASSNAME::getMaxShiftCount() { if (get_plus_arg(CHECK, "maxchain=")) { maxShift = get_plus_arg(NUM, "maxchain="); } else { maxShift = MAX_SHIFT_COUNT; } `PR_ALWAYS(className, MON_ALWAYS ,psprintf("Maximum number of scan shifts is %d\n", maxShift)); getMaxShiftCount = maxShift; } function integer CLASSNAME::checkForAsicGates() { if (get_plus_arg(CHECK, "asicGates")) { asicGatesPresent = 1; `PR_ALWAYS(className, MON_ALWAYS ,psprintf("Asic gates are present in model\n")); } checkForAsicGates = asicGatesPresent; } task CLASSNAME::setupChipForScanDump() { if (asicGatesPresent) { `PR_ALWAYS(className, MON_ALWAYS ,psprintf("Configuring pli to look for flops in the asic clusters")); } else { `PR_ALWAYS(className, MON_ALWAYS ,psprintf("Pli will bypass asic clusters when looking for flops (rtl)")); } PLI_InitFlopPliWithChaindef_vr(topLevel, scanChainConfig, asicGatesPresent, chainEn); } function integer CLASSNAME::tapJTAGSerscan(integer shiftCount, bit [5:0] chainSel, integer scanOutChecking) { integer patBitSel, chainTotal, i; integer sawPattern; string refModTdo; bit [31:0] scanOutDataSeen; bit [0:0] prevTdi; `PR_ALWAYS(className, MON_ALWAYS, psprintf("Chain: %0d, Enabled: %01b \n", chainSel[4:0], chainSel[5])); tapJTAGSerscan = 0; patBitSel = 0; chainTotal = 0; scanOutDataSeen = BITS_IN_SCAN_STRING'b0; `PR_ALWAYS(className, MON_ALWAYS, psprintf("Data pattern shifted in will be %d\n", scanInData)); if (refModelEnabled) `PR_ALWAYS(className, MON_ALWAYS, psprintf("Enabling scan chain reference model\n")); // JTAG instructions to kick-off serscan `PR_ALWAYS(className, MON_ALWAYS, psprintf("TapIRLoad of TAP_SCAN_SERIAL_SEL\n")); void = dft.TapIRLoad(TAP_SCAN_SERIAL_SEL); void = dft.TapDRLoad(dft.cnv2str(chainSel,6)); `PR_ALWAYS(className, MON_ALWAYS, psprintf("TapIRLoad of TAP_SCAN_SERIAL\n")); void = dft.TapIRLoad(TAP_SCAN_SERIAL); dft.TapGoto(TAP_SHIFT_DR); `PR_ALWAYS(className, MON_ALWAYS, psprintf("Begin shifting...\n")); sawPattern=0; repeat(shiftCount) { dft.tap_port.$tdi = scanInData[patBitSel]; @(posedge dft.tap_port.$tck); scanOutDataSeen[30:0] = scanOutDataSeen[31:1]; scanOutDataSeen[31] = dft.tap_port.$tdo; if (refModelEnabled && chainTotal>0) { `PR_ALWAYS(className, MON_ALWAYS, psprintf("Shifting Scan Chain Reference Model\n")); if (chainSel[5]==1'b0) { refModTdo = PLI_JtagShiftExpDataConcat_vr(dft.cnv2str(prevTdi,1)); } else { refModTdo = PLI_JtagShiftExpData_vr(chainSel[4:0], dft.cnv2str(prevTdi,1)); } if (refModTdo != dft.BinToChar(scanOutDataSeen[31])) { `PR_ERROR(className, MON_ERROR, psprintf("ERROR: tdo value from Scan Chain Reference Model did not match actual tdo value")); `PR_ERROR(className, MON_ERROR, psprintf("Expected tdo value=%s, Actual tdo value=%s\n", refModTdo, dft.BinToChar(scanOutDataSeen[31]))); } `PR_ALWAYS(className, MON_ALWAYS, psprintf("Checking Scan Chain Reference Model\n")); if (chainSel[5]==1'b0) { PLI_JtagCheckExpData_vr(31); } else { PLI_JtagCheckExpData_vr(chainSel[4:0]); } } // save for reference model prevTdi = scanInData[patBitSel]; patBitSel = (patBitSel+1) % BITS_IN_SCAN_STRING; chainTotal++; tapJTAGSerscan = chainTotal; if ((chainTotal%500)==0) { `PR_ALWAYS(className, MON_ALWAYS, psprintf("Flops shifted=%d", chainTotal)); } if (scanOutChecking) { if (scanOutDataSeen===scanInData) { sawPattern=1; `PR_ALWAYS(className, MON_ALWAYS, psprintf("TDO saw pattern shifted into TDI (%BITS_IN_SCAN_STRINGb)", scanOutDataSeen)); `PR_ALWAYS(className, MON_ALWAYS, psprintf("Final flop count=%d\n", chainTotal)); break; } } } if (scanOutChecking) { if (!sawPattern) { `PR_ERROR(className, MON_ERR, psprintf("\nDiag Finished with ERRORs\n" "FAILED: NO MATCH AFTER =%d cycles\n\n", chainTotal)); } } `PR_ALWAYS(className, MON_ALWAYS, psprintf("tapJTAGSerscan(): Done shifting\n")); // Cannot count the final word shift tapJTAGSerscan = (tapJTAGSerscan>BITS_IN_SCAN_STRING) ? tapJTAGSerscan-BITS_IN_SCAN_STRING : tapJTAGSerscan; //void = dft.TapIRLoad(TAP_BYPASS_INST); //dft.TapGoto(TAP_IDLE); `PR_ALWAYS(className, MON_ALWAYS, psprintf("Done tapJTAGSerscan\n")); } /* task shiftScanChainModel(bit[5:0] chain_sel) { StandardDisplay dbg; string className = "shiftScanChainModel"; @(probe_if.jtag_instr); while (probe_if.jtag_instr != 8'h80) { // wait until we see the TAP_SERSCAN instruction @(probe_if.jtag_instr); } @(posedge probe_if.shift_dr_state); @(negedge dft.tap_port.$tck); // no shift on first tck while (probe_if.shift_dr_state==1) { @(negedge dft.tap_port.$tck); dbg.dispmon(className, MON_ALWAYS, psprintf("shiftScanChainModel(): Shifting scan chain model\n")); //if (chain_sel[5] == 1'b0) verilog_PLI_jtag_shift_exp_data_concat(dft.tap_port.$tdi); PLI_JtagShiftExpData_vr(chain_sel[4:0], "1"); @(posedge dft.tap_port.$tck); dbg.dispmon(className, MON_ALWAYS, psprintf("shiftScanChainModel(): Checking scan chain model\n")); if (chain_sel[5] == 1'b0) PLI_JtagCheckExpData_vr(31); else PLI_JtagCheckExpData_vr(chain_sel[4:0]); } } */ function integer CLASSNAME::checkIfAsicCluster(integer chain) { if ((chain==19) || (chain==21) || (chain==20) || (chain==28) || (chain==29) || (chain==30)) { checkIfAsicCluster=1; } else { checkIfAsicCluster=0; } }