// ========== 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
// ========== Copyright Header End ============================================
#include <vera_defines.vrh>
#include <std_display_class.vrh>
#include <systemTapDefines.vri>
#include <systemTap.if.vri>
#include <systemTapClass.vrh>
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 JTAG_SCAN_CHAINSEL_CFG 1
#define JTAG_SCAN_CONCAT_CFG 2
#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 asicGatesPresent;
local bit [31:0] scanInData;
local integer refModelEnabled;
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 (
function integer checkIfAsicCluster(
/////////////////////////////////////////////////////////////////////////////
task CLASSNAME::new(StandardDisplay dbgIn, integer refModEn=0, bit [32:0] scanData=33'h100000000) {
//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
scanChainConfig = JTAG_SCAN_CHAINSEL_CFG;
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));
`PR_ALWAYS(className, MON_ALWAYS, psprintf("Chain Enable is: %0h\n", chainEn));
function bit [5:0] CLASSNAME::getJtagChainEn() {
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));
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=");
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")) {
`PR_ALWAYS(className, MON_ALWAYS ,psprintf("Asic gates are present in model\n"));
checkForAsicGates = asicGatesPresent;
task CLASSNAME::setupChipForScanDump() {
`PR_ALWAYS(className, MON_ALWAYS ,psprintf("Configuring pli to look for flops in the asic clusters"));
`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;
bit [31:0] scanOutDataSeen;
`PR_ALWAYS(className, MON_ALWAYS, psprintf("Chain: %0d, Enabled: %01b \n", chainSel[4:0], chainSel[5]));
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"));
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"));
refModTdo = PLI_JtagShiftExpDataConcat_vr(dft.cnv2str(prevTdi,1));
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"));
PLI_JtagCheckExpData_vr(31);
PLI_JtagCheckExpData_vr(chainSel[4:0]);
// save for reference model
prevTdi = scanInData[patBitSel];
patBitSel = (patBitSel+1) % BITS_IN_SCAN_STRING;
tapJTAGSerscan = chainTotal;
`PR_ALWAYS(className, MON_ALWAYS, psprintf("Flops shifted=%d", chainTotal));
if (scanOutDataSeen===scanInData)
`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));
`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);
`PR_ALWAYS(className, MON_ALWAYS, psprintf("Done tapJTAGSerscan\n"));
task shiftScanChainModel(bit[5:0] chain_sel)
string className = "shiftScanChainModel";
while (probe_if.jtag_instr != 8'h80)
// wait until we see the TAP_SERSCAN instruction
@(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) {