// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: sys_reset.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 "ucb___packet.vrh"
#include "rst_defines.vri"
// #include "ccu_top.vri" // @@UPDATE@@ This file should be split and included as reg_top.vri
#include "sys_registers.vrh"
#include "ucb_monitor.vrh"
SystemRegs resetSource; // Physical RST register
SystemRegs resetGenerate; // Physical RST register
SystemRegs resetStatus; // Physical RST register
SystemRegs resetSubsystem; // Physical RST register
SystemRegs resetLocktime; // Physical RST register
SystemRegs resetNiutime; // Physical RST register
SystemRegs resetCcutime; // Physical RST register
SystemRegs resetProptime; // Physical RST register
SystemRegs resetFee; // Physical RST register
integer rst_attribs[RST_LOCK_ATTRIB_COUNT+1][RST_LOCK_ATTRIB_FIELD_COUNT+1] = RST_LOCK;
integer resetSeqTimeout; // timeout of reset seq not progressing (in sysclk cycs)
bit [63:0] temp_reg_val_holder;
rand integer pwron_assrt_time; // Number of cycles to assign the PWRON_RST pin
pwron_assrt_time in { 1 : 30 };
task new(StandardDisplay dbgIn, SystemTap dftIn) {
if (get_plus_arg(CHECK, "rst_resetSeqTimeout="))
resetSeqTimeout = get_plus_arg(NUM, "rst_resetSeqTimeout=");
resetSeqTimeout = TEST_RST_SEQUENCE_TIME;
dbg.dispmon(dispmonScope, MON_INFO, "$Id: sys_reset.vr,v 1.6 2007/07/28 20:36:17 drp Exp $");
resetGenerate = new(dbg,dft,"RST_ASI_RESET_GEN_REG"
, RST_ASI_RESET_GEN_REG, RST_ASI_RESET_GEN_DEF, RST_ASI_RESET_GEN_MASK, creg_bind_rgen);
resetStatus = new(dbg,dft,"RST_ASI_RESET_STAT_REG"
, RST_ASI_RESET_STAT_REG, RST_ASI_RESET_STAT_DEF, RST_ASI_RESET_STAT_MASK, creg_bind_rstat);
resetSource = new(dbg,dft,"RST_ASI_RESET_SOURCE_REG"
, RST_ASI_RESET_SOURCE_REG, RST_ASI_RESET_SOURCE_DEF, RST_ASI_RESET_SOURCE_MASK, creg_bind_rsrc);
resetSubsystem = new(dbg,dft,"RST_ASI_RESET_SSYS_REG"
, RST_ASI_RESET_SSYS_REG, RST_ASI_RESET_SSYS_DEF, RST_ASI_RESET_SSYS_MASK, creg_bind_rssys);
resetLocktime = new(dbg,dft,"RST_ASI_LOCK_TIME_REG"
, RST_ASI_LOCK_TIME_REG, RST_ASI_LOCK_TIME_DEF, RST_ASI_LOCK_TIME_MASK, creg_bind_locktime);
resetNiutime = new(dbg,dft,"RST_ASI_NIU_TIME_REG"
, RST_ASI_NIU_TIME_REG, RST_ASI_NIU_TIME_DEF, RST_ASI_NIU_TIME_MASK, creg_bind_niutime);
resetCcutime = new(dbg,dft,"RST_ASI_CCU_TIME_REG"
, RST_ASI_CCU_TIME_REG, RST_ASI_CCU_TIME_DEF, RST_ASI_CCU_TIME_MASK, creg_bind_ccutime);
resetProptime = new(dbg,dft,"RST_ASI_PROP_TIME_REG"
, RST_ASI_PROP_TIME_REG, RST_ASI_PROP_TIME_DEF, RST_ASI_PROP_TIME_MASK, creg_bind_proptime);
resetFee = new(dbg,dft,"RST_ASI_RESET_FEE_REG"
, RST_ASI_RESET_FEE_REG, RST_ASI_RESET_FEE_DEF, RST_ASI_RESET_FEE_MASK, creg_bind_rfee);
ucb_port = rst_ucb_mon_bind;
if (get_plus_arg(CHECK, "rst_noUcbMon"))
dbg.dispmon(dispmonScope, MON_ALWAYS, "warning: UCB monitor is disable");
ucb_monitor = new("rst_ucb_mon", dbg, ucb_port, 4, 8'h89 , 1); // Instantiate and start the monitor
// dft.stop_port.$rst_tcu_flush_req = 1'b0; // @@UPDATE@@ remove when flush connect to RST
// FC regression failing for PEU because vera driving these inputs to RST
#ifndef FC_BENCH // could not drive package pins becoz vera drives it
rst_port.$l2t0_rst_fatal_error = 1'b0 async ;
rst_port.$l2t1_rst_fatal_error = 1'b0 async ;
rst_port.$l2t2_rst_fatal_error = 1'b0 async ;
rst_port.$l2t3_rst_fatal_error = 1'b0 async ;
rst_port.$l2t4_rst_fatal_error = 1'b0 async ;
rst_port.$l2t5_rst_fatal_error = 1'b0 async ;
rst_port.$l2t6_rst_fatal_error = 1'b0 async ;
rst_port.$l2t7_rst_fatal_error = 1'b0 async ;
rst_port.$ncu_rst_fatal_error = 1'b0 async ;
// sc_port.$por_ = 1'b0 soft async ; // asked for assert from time 0
sc_port.$por_ = 1'bx soft async ;
sc_port.$pb_xir_ = 1'bx soft async ;
sc_port.$pb_rst_ = 1'bx soft async ;
//// Start another process, count the reference clocks
// @@UPDATE@@ This might change -csr
if (sc_port.$por_in_ == 1'b0) {
//------------------ Knobs will be initialized in :/verif/diag files ---------------------
integer pllreset_cyc_cnt; // number of sys clks that PWRON_RST_L is asserted
integer pllreset_min_cycs = 0; // minimum time required to reset pll
dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("PWRON_RST_L assert time is %d pll_sys_clkp cycles", pwron_assrt_time));
repeat (10) @(negedge sc_port.$clk);
sc_port.$por_ = 1'b0; // PRM 1.2 section 13.9.1 step 1
dft.TapDrive_trst_n(1'b0); // PRM 1.2 section 13.9.1 step 1
pllreset_cyc_cnt = get_cycle(sc_port.$clk);
dft.TapDrive_tms(1'b1); // PRM 1.2 section 13.9.1 step 4
sc_port.$pb_xir_ = 1'b1; // Define the XIR & PB now since it matters
repeat (5) @(negedge sc_port.$clk);
dft.TapDrive_trst_n(1'b1); // PRM 1.2 section 13.9.1 step 5
repeat (5) dft.toggleDutTck(); // PRM 1.2 section 13.9.1 step 6
if (get_plus_arg(CHECK, "pllreset_time=")) {
pllreset_min_cycs = get_plus_arg(NUM, "pllreset_time=");
pllreset_cyc_cnt = get_cycle(sc_port.$clk) - pllreset_cyc_cnt;
pllreset_cyc_cnt = pllreset_min_cycs - pllreset_cyc_cnt;
if (pllreset_cyc_cnt > 0)
repeat (pllreset_cyc_cnt) @(posedge sc_port.$clk); // wait to meet min cycs
repeat (pwron_assrt_time) @(negedge sc_port.$clk);
// async_delay = urandom_range(7499, 0);
// dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("PWRON_RST_L deasert asyncdelay is %d ps", async_delay));
sc_port.$por_ = 1'b1 ; // Service processor deasserts
task runRstSequenceJtpor() {
dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("PWRON_RST_L assert time is %d pll_sys_clkp cycles", pwron_assrt_time));
repeat (5) @(posedge sc_port.$clk);
sc_port.$pb_rst_ = 1'b0; // PRM 1.2 section 13.9.1 step 1
dft.TapDrive_trst_n(1'b0); // According to PRM 11.9.1 09/21/2004
dft.TapDrive_tms(1'b1); // PRM 1.2 section 13.9.1 step 4
sc_port.$pb_xir_ = 1'b1; // Define the XIR & PB now since it matters
repeat (5) @(posedge sc_port.$clk);
dft.TapDrive_trst_n(1'b1); // PRM 1.2 section 13.9.1 step 5
repeat (5) dft.toggleDutTck(); // PRM 1.2 section 13.9.1 step 6
repeat (1) @(posedge sc_port.$clk);
//repeat (pwron_assrt_time) @(posedge sc_port.$clk);
sc_port.$por_ = 1'b1; // Service processor deasserts
// repeat (2) @(posedge sc_port.$clk);
//------------------ Update Reset Registers Expected Value ---------------------
task expectedResetUpdate(integer reset_type) {
// Update the Shadow Status registers (RST spec v.0.92)
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_POR_S] = resetStatus.asiVeraValue[RST_ASI_RESET_STAT_POR];
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_WMR_S] = resetStatus.asiVeraValue[RST_ASI_RESET_STAT_WMR];
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_FREQ_S] = resetStatus.asiVeraValue[RST_ASI_RESET_STAT_FREQ];
RST_ASI_RESET_STAT_POR: {
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_POR] = 1'b1;
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_WMR] = 1'b0;
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_FREQ] = 1'b0;
RST_ASI_RESET_STAT_WMR: {
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_POR] = 1'b0;
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_WMR] = 1'b1;
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_FREQ] = 1'b0;
RST_ASI_RESET_STAT_FREQ: {
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_POR] = 1'b0;
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_WMR] = 1'b1;
resetStatus.asiVeraValue[RST_ASI_RESET_STAT_FREQ] = 1'b1;
default: dbg.dispmon(dispmonScope, MON_ERR, psprintf("Unrecognized reset type (%s) for RESET_STAT_REG", reset_type));
//------------------ Update Reset Registers Expected Value ---------------------
task check_resetStatReg(string bitfield) {
expectedResetUpdate(RST_ASI_RESET_STAT_WMR);
else if(bitfield == "POR"){
expectedResetUpdate(RST_ASI_RESET_STAT_POR);
else if (bitfield == "FREQ"){
expectedResetUpdate(RST_ASI_RESET_STAT_FREQ);
dbg.dispmon(dispmonScope, MON_ERR, psprintf("ERROR: Wrong argument to task check_resetStatReg - %s ", bitfield));
resetStatus.printCurrentRegister(); //Fetch asiCurrentValue
resetStatus.printCheckRegister(resetStatus.asiVeraValue , resetStatus.asiCurrentValue);
}// End of check_resetStatReg
// Task to cause a simple POR reset with PWRON_RST_L pin. 02/20/05
// Task to cause a WMR reset with PB_RST_L pin. 03/01/05
// Initiate warm reset through PB_RST_L pin
dbg.dispmon(dispmonScope, MON_ALWAYS, "Assert PB_RST_L pin");
repeat (5) @(posedge sc_port.$clk);
repeat (urandom_range(20, 2)) @(posedge sc_port.$clk);
delay(urandom_range(7499, 0));
sc_port.$pb_rst_ = 1'b1 async;
repeat (20) @(posedge sc_port.$clk);
// Task to cause a WMR reset with L2t_error signal pins. 03/01/05
task gen_fatal_error(string error_type) {
reg [63:0] fee_reg_data = 64'd0;
if (error_type == "L2T_ERR"){
dbg.dispmon(dispmonScope, MON_ALWAYS, "Generate L2t fatal error");
fee_reg_data[8] = random();
fee_reg_data[9] = random();
fee_reg_data[10] = random();
fee_reg_data[11] = random();
fee_reg_data[12] = random();
fee_reg_data[13] = random();
fee_reg_data[14] = random();
fee_reg_data[15] = random();
if (fee_reg_data == 64'd0){
resetFee.ucbWrite(fee_reg_data);
void = resetFee.ucbRead();
repeat (5) @(posedge rst_port.$clk_iol2clk);
rst_port.$l2t0_rst_fatal_error = fee_reg_data[8] async ;
rst_port.$l2t1_rst_fatal_error = fee_reg_data[9] async ;
rst_port.$l2t2_rst_fatal_error = fee_reg_data[10] async ;
rst_port.$l2t3_rst_fatal_error = fee_reg_data[11] async ;
rst_port.$l2t4_rst_fatal_error = fee_reg_data[12] async ;
rst_port.$l2t5_rst_fatal_error = fee_reg_data[13] async ;
rst_port.$l2t6_rst_fatal_error = fee_reg_data[14] async ;
rst_port.$l2t7_rst_fatal_error = fee_reg_data[15] async ;
repeat (1) @(posedge rst_port.$clk_iol2clk);
rst_port.$l2t0_rst_fatal_error = 1'b0 async ;
rst_port.$l2t1_rst_fatal_error = 1'b0 async ;
rst_port.$l2t2_rst_fatal_error = 1'b0 async ;
rst_port.$l2t3_rst_fatal_error = 1'b0 async ;
rst_port.$l2t4_rst_fatal_error = 1'b0 async ;
rst_port.$l2t5_rst_fatal_error = 1'b0 async ;
rst_port.$l2t6_rst_fatal_error = 1'b0 async ;
rst_port.$l2t7_rst_fatal_error = 1'b0 async ;
else if(error_type == "NCU_ERR") {
dbg.dispmon(dispmonScope, MON_ALWAYS, "Generate NCU fatal error");
repeat (5) @(posedge rst_port.$clk_iol2clk);
rst_port.$ncu_rst_fatal_error = 1'b1 async;
repeat (1) @(posedge rst_port.$clk_iol2clk);
rst_port.$ncu_rst_fatal_error = 1'b0 async;
dbg.dispmon(dispmonScope, MON_ERR, "ERROR: Did not specify the type of fatal error to generate");
// For L2 error check weather FEE register is reset to all zeros
fee_reg_data = resetFee.ucbRead() & resetFee.asiWriteableMask;
if (fee_reg_data != 64'd0)
dbg.dispmon(dispmonScope, MON_ERR, "ERROR: RESET_FEE register is not reset after warm reset");
dbg.dispmon(dispmonScope, MON_ERR, psprintf("FEE REG is': 0x%64h", fee_reg_data));
// Task to cause XIR reset through the BUTTON_XIR_L pin
dbg.dispmon(dispmonScope, MON_ALWAYS, "Assert XIR reset");
repeat (urandom_range(20, 2)) @(posedge sc_port.$clk);
delay(urandom_range(7499, 0));
sc_port.$pb_xir_ = 1'b1 async;
repeat (20) @(posedge sc_port.$clk);
// Task for software generated resets, excercice RESET_GEN register and SSYS reg
task software_gen_reset(string rst_type)
bit reset_timeout; //To have smart timeout than default timeout- 03/03/05
dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("%s S/W Reset gen", rst_type));
if (rst_type == "WMR_GEN"){
resetGenerate.printCurrentRegister();
resetGenerate.ucbWrite(64'd1);
if (rst_type == "XIR_GEN"){
resetGenerate.printCurrentRegister();
resetGenerate.ucbWrite(64'd2 );
if (rst_type == "DBR_GEN"){
resetGenerate.printCurrentRegister();
resetGenerate.ucbWrite(64'd8 );
if (rst_type == "SSYS_DMU_PEU"){
resetSubsystem.printCurrentRegister();
resetSubsystem.ucbWrite(64'd2 );
if (rst_type == "SSYS_NIU"){
resetSubsystem.printCurrentRegister();
resetSubsystem.ucbWrite(64'd1 );
dbg.dispmon(dispmonScope, MON_ERR, psprintf("Unrecognized s/w reset to generate for %s in RESET_GEN_REG", rst_type));
if((rst_type == "WMR_GEN") || (rst_type == "DBR_GEN") ){
if(rst_type == "XIR_GEN"){
@(posedge rst_port.$ncu_rst_xir_done async);
else if(rst_type == "SSYS_DMU_PEU"){
@(negedge rst_port.$rst_dmu_peu_wmr_ );
repeat (50) @(posedge sc_port.$clk async);
else if(rst_type == "SSYS_NIU"){
@(negedge rst_port.$rst_niu_wmr_ );
repeat (50) @(posedge sc_port.$clk async);
repeat (resetSeqTimeout) @(posedge sc_port.$clk);
dbg.dispmon(dispmonScope, MON_ERR, psprintf("ERROR: TIMEOUT for %s reset, failed to generate reset ", rst_type));
repeat (50) @(posedge sc_port.$clk);
} // End of software_gen_reset
// This task tests that source register is correctly updated and also clears the field in order to simulate the s/w behaviour
task check_resetSourceReg(string bitfield) {
reg [63:0] expectedVal = 64'd0;
resetSource.printCurrentRegister(); // Update the currentValue variable in the class
if( bitfield == "WMR_GEN")
else if( bitfield == "XIR_GEN")
else if( bitfield == "DBR_GEN")
else if( bitfield == "PWRON_RST")
else if( bitfield == "PB_RST")
else if( bitfield == "PB_XIR")
else if( bitfield == "NCU_FATAL")
else if( bitfield == "L2T_FATAL"){
temp_reg_val_holder = resetSource.asiCurrentValue & 64'h000000000000ff00;
if((resetSource.asiCurrentValue & 64'h000000000000ff00) > 64'd0){
dbg.dispmon(dispmonScope, MON_INFO, psprintf(" Source register is correctly updated for field %s", bitfield));
resetSource.ucbWrite(resetSource.asiWriteableMask);
dbg.dispmon(dispmonScope, MON_ERR, psprintf("ERROR: Source register not set for bit %s ", bitfield));
dbg.dispmon(dispmonScope, MON_ERR, psprintf("ERROR: Wrong argument to task check_resetSourceReg - %s ", bitfield));
expectedVal[bitPosition] = 1'b1;
// if(resetSource.asiCurrentValue[bitPosition] == 1'b1)
if((resetSource.asiWriteableMask & resetSource.asiCurrentValue) == expectedVal)
dbg.dispmon(dispmonScope, MON_INFO, psprintf(" Source register is correctly updated for field %s", bitfield));
dbg.dispmon(dispmonScope, MON_ERR, psprintf("ERROR: Source register NOT correctly updated for reset %s", bitfield));
resetSource.ucbWrite(resetSource.asiWriteableMask);
void = resetSource.ucbRead(); // Dumy read to ensure write completed
} // End of checkSourceReg
task wait_unpark_thread(){
dbg.dispmon(dispmonScope, MON_ALWAYS, "Waiting for unpark_thread ");
@(posedge rst_port.$rst_ncu_unpark_thread);
dbg.dispmon(dispmonScope, MON_ALWAYS, "unpark_thread asserted");
dbg.dispmon(dispmonScope, MON_ALWAYS, "Complete 1000 cycle wait");
repeat (resetSeqTimeout) @(posedge sc_port.$clk);
dbg.dispmon(dispmonScope, MON_ERR, "ERROR: TIMEOUT for task wait_unpark_thread ");
}//End of wait_unpark_thread
dbg.dispmon(dispmonScope, MON_ALWAYS, "Waiting for por2 ");
@(posedge rst_port.$rst_tcu_flush_init_req);
dbg.dispmon(dispmonScope, MON_ALWAYS, "por2");
dbg.dispmon(dispmonScope, MON_ALWAYS, "Complete 1000 cycle wait");
repeat (resetSeqTimeout) @(posedge sc_port.$clk);
dbg.dispmon(dispmonScope, MON_ERR, "ERROR: TIMEOUT for task wait_unpark_thread ");
@(posedge rst_port.$ncu_rst_xir_done);
repeat (resetSeqTimeout) @(posedge sc_port.$clk);
dbg.dispmon(dispmonScope, MON_ERR, "ERROR: TIMEOUT for task wait_xir_reset ");