#!/pkg/bin/tclsh
# ---------------------------------------------------------------------
# tm_scan -Scans TM register and memories to look for abnormalities
#
# July 2011, Hai Nguyen
#
# Copyright (c) 2011, 2014 by cisco Systems, Inc.
# All rights reserved.
#--------------------------------------------------------------------

global head_ptr
global MAX_INTF 
global ERROR_ENCOUNTERED

set user_counter_start 8192
set user_counter_count 100
set MAX_INTF 271

set date [exec date]
puts "date=$date\n"

proc print_help { } {
   puts "tm_scan   Scans TM register and memories to look for abnormalities in TM"
   puts "param1    (np_id|all)"
   puts "           np_id      np to scan"
   puts "           all        all NPs will be scanned"
   puts "param2     dmainfo    get dma info"
   puts "           port       get port status "
   puts "           idma       get idma info"
   puts "           ocfdbudget get ocfd budget status"
   puts "           frag       get fragment info (after OQ)"
   puts "           coq        get cell OQ"
   puts "           os         get output stage"
   puts "           frd        get frame descriptor info"
   puts "           cred       get port credit"
   puts "           phymap     get physical map of physical to internal interfaces"
   puts "           intmap     get internal interface map of internal to physical interfaces"
   puts "           occ        TBD"
   puts "           l1sram     get l1 sram status"
   puts "param3     optional goes with counter.  specifies start of usercounters e.g 0x2000, 0x82000"
   puts "           defaults to 0x2000"
   puts "param4     optional goes with counter.  specifies number of entries to scan"
   puts "           defaults to 100"
}

if {$argc == 0} {
    print_help
    return
}

set np_ids [lindex $argv 0]
set param1 $np_ids
set param2 [lindex $argv 1]


if {[regexp "he" $param1]} {
    print_help
    return
}

if {[regexp "all" $param1]} {
   set np_ids [exec show_np -h | grep {\-e} | grep NP]
   set np_ids [lindex $np_ids end]
   set np_ids [string trim $np_ids "\{"]
   set np_ids [string trim $np_ids "\}"]
   regsub -all {\|} $np_ids " " np_ids
   puts "NPs to read are $np_ids"
}

if {[regexp "ignore_bp" $param2]} {
   foreach np_id $np_ids {
      set data [exec show_np -e $np_id -r reg=5517,READ]
      puts "--- BEFORE ---"
      puts $data
      # we just need to zero out the bp_cfg register
      exec show_np -e $np_id -r reg=5517,val=0x0,WR
      set data [exec show_np -e $np_id -r reg=5517,READ]
      puts "--- AFTER ---"
      puts $data
      return
   }
}



#####################################################################
# BEG PROCs
#####################################################################

# 
# Get node_id
#
proc get_node_id { } {
    set node_id 0
    if { ![catch {set out [exec show_platform | grep "My Node id"]} fid ] } {
        # the line card name is in the 4th column
        set node_id [lindex $out end]
        set node_id "0x$node_id"
    } 
    return $node_id
}

# 
# Get port_mapping
#
proc get_port_mapping { array_name np } {
    upvar $array_name port_map 
    set node_id [get_node_id]
    if { ![catch {set out [exec prm_np_show portmap -e $np -s $node_id]} fid ] } {

        set out [split $out "\n"]
        foreach line $out {
            set index [lindex $line 0]
            set map [lindex $line 1]
            if {[regexp \[0-9\] $index] } {
                set port_map($index) $map
            }
        }
    } 
}

proc byte2bits {i} {
   binary scan [binary format I1 $i] B* x
   set x [string range $x 24 31]
   return $x
}



proc int2bits {i} {
   binary scan [binary format I1 $i] B* x
   regsub -all {\d(?=(\d{8})+($))} $x {\0,} x
   return $x
}

proc get_fin_fout { np_id } {

    set TM_OQ_0_FIN 21544
    set TM_OQ_1_FIN 21646

    # get tm0
    if { ![catch {set data [exec show_np -e $np_id -r reg=$TM_OQ_0_FIN,READ,range=2 | grep reg]}] } {
        set data [split $data "\n"]
        set i 0
        foreach counter "TM_OQ_0_FIN_COUNTER TM_OQ_0_FOUT_COUNTER" {
            puts " NP=$np_id $counter [lindex $data $i]"
            incr i
        }
    }
    puts "\n"
    # get tm1
    if { ![catch {set data [exec show_np -e $np_id -r reg=$TM_OQ_1_FIN,READ,range=2 | grep reg]}] } {
        set data [split $data "\n"]
        set i 0
        foreach counter "TM_OQ_1_FIN_COUNTER TM_OQ_1_FOUT_COUNTER" {
            puts " NP=$np_id $counter [lindex $data $i]"
            incr i
        }
    }
    puts "\n"

}

# get mem data
proc get_mem_data { np mem_id length entity}  {
   set data [ exec show_np -e $np -m mem=$mem_id,start=$entity,length=$length | grep x \
       | grep -v start ]
   # puts "reading $np -m mem=$mem_id,start=$start_addr,length=8"
   if {[regexp "fail" $data]} {
	  puts "raw data = $data"
	  puts "failed to read mem_id=$mem_id, length=$length, np=$np, entity=$entity"
	  return "failed"
   }
   set data1 ""
   set data [split $data "\n"]
   foreach line $data {
       regsub -all {0x} $line "" line
#puts "line=$line"
      append data1 [lrange $line 1 end]
      append data1 " "
   }
   return $data1
}



proc get_bit_position { data } {
    set shift_val 1
    set out_list {} 
    for {set i 0} { $i <= 32 } { incr i } {
       if {[expr { $shift_val & $data }] } {
           lappend out_list $i
       }
       set shift_val [expr { $shift_val << 1}]
    }
    return $out_list
}

proc print_data {name i} {
   binary scan [binary format I1 $i] B* x
   regsub -all {\d(?=(\d{8})+($))} $x {\0,} x
   puts "    >>> name = $name, binary bits=$x, hex=$i"
   return $x
}

proc get_reg_value { np reg_id } {

   set data [ exec show_np -e $np -r reg=$reg_id,READ ]
   if {[regexp "incorrect" $data]} {
      puts $data
      puts "failed to read reg_id=$reg_id, np=$np"
      return "failed"
   }
   set data [exec echo $data | grep x]
   # the data is in the last column
   set data [lindex $data end]
   # remove the brackets
   set data [string trim $data "\["]
   set data [string trim $data "\]"]
   # sometimes we get data like this
   #  reg 5671 = [0x  1f] or  reg 5671 = [0x121f]
   # either way, we need to make sure the is an x infront to signify hex
   if {![regexp "x" $data]} {
       set data "0x$data"
   }
   return $data

}

proc byte_swap_16 { data } {
   set byte1 [expr {$data >> 8} ]
   set out [expr {[ expr { [expr {$data << 8 }] & 0xff00}] | $byte1 }]
   return $out
}

proc byte_swap_32 { data } {
   set MSB [ expr {[byte_swap_16 [expr { $data & 0xffff }]] << 16 }]
   set LSB [expr { [expr { $data >> 16 }]  & 0xffff }]
   set LSB [byte_swap_16 $LSB]
   set out [expr {$MSB + $LSB}]
}

###########
# input: list of 4 bytes
# output: reverse the bytes and output in hex format
###########
proc reverse_hex_bytes { data } {
   set out "[lindex $data 3] [lindex $data 2] [lindex $data 1] [lindex $data 0]"
   
   set out 0
   for { set i 0 } { $i < 4 } { incr i } {
       set shift [expr $i * 8]
       set val "0x[lindex $data $i]"
       set val [expr {$val << $shift}]
       set out [expr { $val + $out }] 
   }
   set out "0x[format %x $out]"
   return $out
}


proc get_reg_data { np reg_id name} {
   global head_ptr
   # puts " NP=$np, register_name=$name register_id=$reg_id"
   set data [ exec show_np -e $np -r reg=$reg_id,READ ]
   if {[regexp "incorrect" $data]} {
      puts $data
      puts "failed to read reg_id=$reg_id, np=$np"
      return "failed"
   }
   set data [exec echo $data | grep x]
   # the data is in the last column
   set data [lindex $data end]
   # remove the brackets
   set data [string trim $data "\["]
   set data [string trim $data "\]"]
   # sometimes we get data like this
   #  reg 5671 = [0x  1f] or  reg 5671 = [0x121f]
   # either way, we need to make sure the is an x infront to signify hex
   if {![regexp "x" $data]} {
       set data "0x$data"
   }
   puts " NP=$np, reg=$name\($data)"
   if {[regexp "TM_ODMA_STAT_1" $name]} {
       # decode TM_ODMA_STAT1
       # bits 31->16 and 7->0 must be 0 other wise there is an internal error
       set internal_errors [expr {$data & 0xffff00ff} ]
       set head_ptr [expr {$data & 0x0000ff00} ]
       set head_ptr [expr {$head_ptr >> 8} ]
       if {$internal_errors > 0 } {
           print_data $name $data
           puts "     ---------> Internal errors indicated in $name 0x[format %x $internal_errors]  <---------"
           puts "                bits 31->16 and 7->0 indicates errors, only valid if traffic generator stopped"
# dump the dma stats for all 80 entries


set ERROR_ENCOUNTERED 1

       } else {
           # if no errors, we do not want to print anything
           # puts "     No Internal errors indicated in $name bits 31->16 and 7->0 are 0"
           # puts "     head_ptr=$head_ptr"
       }
   } elseif {[regexp "TM_ODMA_STAT_3" $name]} {
       # decode TM_ODMA_STAT3
           set tail_ptr [expr {$data & 0x000000ff} ]
              #puts "         tail_ptr=$tail_ptr, head_ptr=$head_ptr"
           if { $head_ptr != $tail_ptr } {
              print_data $name $data
              puts "     tail_ptr=$tail_ptr, head_ptr=$head_ptr"
           }
   } elseif {[regexp "RFD_FC_STS" $name]} {
       if {$data > 0 } {
           print_data $name $data
           puts "     --------->  Flow control encountered NP=$np reg=$name flags=$data  <--------"
           set port [expr {$data & 0x3ff}]
           set port [get_bit_position $port]
           if {[llength $port]} {
               puts "                 port $port are in Flow control "
           }
           set port [ expr { $data >> 16} ]
           set port [ expr { $port  & 0x3ff}]
           set port [get_bit_position $port]
           if {[llength $port]} {
               puts "                 auxilary ports $port are in Flow control "
           }
 set ERROR_ENCOUNTERED 1
       }
   } elseif {[regexp "TM_OQ_ECNT_GLOB_P2" $name] || [regexp "TM_OQ_ACNT_GLOB_P2" $name] } {
       # now decode the info
       # bit 0-2 
       #     0 = allow all to schedule
       #     1 = priorities 0..2
       #     2 = priorities 0..1
       #     3 = priorities 0
       #     4 = stop scheduling
       # bit 3-21 current actual counter (byte count)
       set fc_status [expr {$data >> 24 }]
       set fc_status [expr {$fc_status & 7 }]
       if {$fc_status == 0 } {
           # don't display anything for normal case
           # puts "        fc_state = allow all"
       } else {
		   print_data $name $data
           if {$fc_status == 1} {
			   puts "        $name fc_state = allow 0-2 <---- Normal prio traffic blocked"
 set ERROR_ENCOUNTERED 1
		   } elseif {$fc_status == 2} {
			   puts "        $name fc_state = allow 0-1 <---- Prio2 and Normal prio traffic blocked"
 set ERROR_ENCOUNTERED 1
		   } elseif {$fc_status == 3} {
			   puts "        $name fc_state = allow 0 <----  Prio 1, prior2, and Normal prio traffic blocked"
 set ERROR_ENCOUNTERED 1
		   } elseif {$fc_status == 4} {
			   puts "        $name fc_state = stopped <---- All traffic blocked"
 set ERROR_ENCOUNTERED 1
		   }
           # now get the counters and stats
           # for ECNT CNTR = bits 0-18
           # for ACNT CNTR = bits 0-10
           set counter $data

           if { [regexp "TM_OQ_ECNT_GLOB_P2" $name] } {
               set counter [ expr { $counter & 0x7ff } ]
           } else {
               set counter [ expr { $counter & 0x7ffff } ]
           }
           puts "          Counter = $counter"
       }

   } else {
      # dump data if non-zero
      if { $data != 0 } {
          print_data $name $data
      }
   }

   return $data
}

proc get_reg_data_no_print { np reg_id name} {
   # puts " NP=$np, register_name=$name register_id=$reg_id"
   set data [ exec show_np -e $np -r reg=$reg_id,READ ]
   if {[regexp "incorrect" $data]} {
      puts $data
      puts "failed to read reg_id=$reg_id, np=$np"
      return "failed"
   }
   set data [exec echo $data | grep x]
   # the data is in the last column
   set data [lindex $data end]
   # remove the brackets
   set data [string trim $data "\["]
   set data [string trim $data "\]"]
   # sometimes we get data like this
   #  reg 5671 = [0x  1f] or  reg 5671 = [0x121f]
   # either way, we need to make sure the is an x infront to signify hex
   if {![regexp "x" $data]} {
       set data "0x$data"
   }
   return $data
}

proc print_nonzero_framecount { buffer } {
   
   set count 0
   set data [split $buffer "\n"]
   set queue_id 0
   set non_zer0_entry 0
   foreach line $data {
       # if we have a nonzero framecount, dump out the entry
       if {[regexp "Frame:  " $line]} {
           set count [lindex $line 1]
           if {$count != "0x0000000000000000" } {
               set non_zer0_entry 1
           }
           # if we also have hardware counter, we need to display as well.
           if {[llength $line ] > 2 } {
               set count [lindex $line 3]
               if {$count != "0x0000000000000000" } {
                   set non_zer0_entry 1
               }
           }
       }
       if {[regexp {Counter: .*Counter:} $line]} {
           set counter [lindex $line 1]
           if { $counter >= 0x5f0000 } {
               set queue_id [expr {$counter - 0x5f0000}]
               set queue_id [expr {$queue_id / 5}]
           } else {
               set queue_id "unknown fast queue"
           }
       }
   }
   if {$non_zer0_entry > 0 } {
      puts "            ----  Non-zero frame count for queue ($queue_id) -------"
      puts "$buffer"
   }
   #if {$queue_id == 32 || $queue_id == 74 || $queue_id == 135} {
   #   puts "data for $queue_id is count=$count"
   #   puts "$buffer\n\n"
#
#   }
}


proc get_nonzero_framecount { buffer } {
   
   set data [split $buffer "\n"]
   set entry ""
   foreach line $data {
       # look for beginning of next entry
       if {[regexp {Shadow|Hardware} $line]} {
           # check and print non-zero counts
           print_nonzero_framecount $entry
           # start new entry
           set entry "$line\n"
       } else {
           append entry "$line\n"
       }
   }
   print_nonzero_framecount $entry
}

proc get_user_counter { np start_addr count} {
   puts " NP=$np, start=$start_addr, count=$count"

   set data ""
   set start $start_addr
   for { set i 0 } { $i < $count } { incr i } {
       # read 1024 bytes at a time
	   if { ![catch {set data [ exec show_np -e $np -u start=$start,length=1,READ,DB,LOG \
                       ] } fid ] } {
           get_nonzero_framecount $data    
       } else { 
          #puts "no data"
       }
       incr start 1
   }
   return $data
}

proc get_user_queuestat { np start_addr count} {
   puts " NP=$np, start=$start_addr, count=$count"

   puts "Start time [exec date]"
   # read 256 fast queue 
   puts " *******************************************************************" 
   puts " **************  Retrieving fast queue statistics  *****************"
   puts " *******************************************************************" 
   puts " executing::  show_np -e $np -u start=0x600,length=256,READ,DB,LOG\n"
   if { ![catch {set data [ exec show_np -e $np -u start=0x600,length=256,READ,DB,LOG \
                      ] } fid ] } {
       get_nonzero_framecount $data    
   } else { 
       puts " Failed executing::  show_np -e $np -u start=0x600,length=256,READ,DB,LOG"
   }

   set data ""
   set start $start_addr
   puts " *********************************************************************" 
   puts " **************  Retrieving normal queue statistics  *****************"
   puts " *********************************************************************" 
   for { set i 0 } { $i < $count } { incr i 1024 } {
       # read 1024 entries at a time
	   puts " executing::  show_np -e $np -u start=0x[format %x $start],length=1024,READ,DB,LOG"
	   if { ![catch {set data [ exec show_np -e $np -u start=$start,length=1024,READ,DB,LOG \
                       ] } fid ] } {
           get_nonzero_framecount $data    
       } else { 
	       puts " Failed executing::  show_np -e $np -u start=0x[format %x $start],length=1024,READ,DB,LOG"
       }
       incr start 1024
   }
   puts "end time [exec date]"
   return $data
}


proc decode_frd_totals { data } {
    set data [expr {$data & 0xfff}]
    return $data
}

proc get_frd_totals { np } {
   set EZapiRegID_TM_OQ_0_FRD_TOTAL  21529
   set EZapiRegID_TM_OQ_1_FRD_TOTAL  21631

   puts " ##############################################"
   puts " #  Frame descriptor still in OQ"
   puts " ##############################################"
   set data [get_reg_data $np $EZapiRegID_TM_OQ_0_FRD_TOTAL "EZapiRegID_TM_0_FRD_TOTAL"]
   set data [decode_frd_totals $data]
   set data [get_reg_data $np $EZapiRegID_TM_OQ_1_FRD_TOTAL "EZapiRegID_TM_1_FRD_TOTAL"]
   set data [decode_frd_totals $data]
   return $data
}

proc decode_frg_dft { entity data} {

   switch -exact $entity {
        0 {
              # get flush and no recycle counters
              puts "       Flush and no Recycle      = [reverse_hex_bytes [lrange $data 0 3]]"
              puts "       Flush from fetch unit     = [reverse_hex_bytes [lrange $data 4 7]]"
              puts "       Recycle from output stage = [reverse_hex_bytes [lrange $data 8 11]]"
              puts "       RFD fast                  = [reverse_hex_bytes [lrange $data 12 15]]"
              puts "       RFD slow                  = [reverse_hex_bytes [lrange $data 16 19]]"
              puts "       # of FD from OQ           = [reverse_hex_bytes [lrange $data 20 23]]"
              puts "       pkt cell desc. FRG->COQ   = [reverse_hex_bytes [lrange $data 24 27]]"
              puts "       Free LongTerm crdit for OQ= [reverse_hex_bytes [lrange $data 27 31]]"
          }
        1 {
              # get flush and no recycle counters
              puts "       Hi Prio Pkt TM_OQ to FIFO FRG = [reverse_hex_bytes [lrange $data 0 3]]"
              puts "       Lo Prio Pkt TM_OQ to FIFO FRG = [reverse_hex_bytes [lrange $data 4 7]]"
              puts "       Pkts from FRG to COQ          = [reverse_hex_bytes [lrange $data 8 11]]"
              puts "       Flush and no recycle          = [reverse_hex_bytes [lrange $data 12 15]]"
              puts "       Int MemMgmt recyle from EXU   = [reverse_hex_bytes [lrange $data 16 19]]"
              puts "       Int MemMgmt recyle from TMRDMA= [reverse_hex_bytes [lrange $data 20 23]]"
              puts "       Int MemMgmt recyle from OS    = [reverse_hex_bytes [lrange $data 24 27]]"
              puts "       Int MemMgmt recyle to RFD     = [reverse_hex_bytes [lrange $data 28 31]]"
          }
        default {
              puts "       No decode available "
              puts "       [reverse_hex_bytes [lrange $data 0 3]] [reverse_hex_bytes [lrange $data 4 7]] \
                           [reverse_hex_bytes [lrange $data 8 11]] [reverse_hex_bytes [lrange $data 12 15]] \
                           [reverse_hex_bytes [lrange $data 16 19]] [reverse_hex_bytes [lrange $data 20 23]] \
                           [reverse_hex_bytes [lrange $data 24 27]] [reverse_hex_bytes [lrange $data 28 31]]"

             }
   }  

} 

##################################################################**#
# Fragmentator:: There are 10 lines but we only 1st 2 are applicable
##################################################################**#
proc get_frg_dft { np } {
   set EZapiMemId_TMOD_0_FRG_DFT 571
   set EZapiMemId_TMOD_1_FRG_DFT 636
   set length 32
   for {set entity 0} {$entity < 3} { incr entity } {
       set data [get_mem_data $np $EZapiMemId_TMOD_0_FRG_DFT $length $entity]
       puts "   EZapiMemId_TMOD_0_FRG_DFT($entity) = $data"
       decode_frg_dft $entity $data
       set data [get_mem_data $np $EZapiMemId_TMOD_1_FRG_DFT $length $entity]
       puts "   EZapiMemId_TMOD_1_FRG_DFT($entity) = $data"
       decode_frg_dft $entity $data
   }

}

proc decode_coq_dft { entity data} {

   switch -exact $entity {
        0 {
              # get flush and no recycle counters
              puts "       link_element(0-15) pop_cntr (16-31)      = [reverse_hex_bytes [lrange $data 0 3]]"
              puts "       Frames from FRG to COQ                   = [reverse_hex_bytes [lrange $data 4 7]]"
              puts "       Frames from COQ to OS                    = [reverse_hex_bytes [lrange $data 8 11]]"
              puts "       # of cell descriptor from FRG to COQ     = [reverse_hex_bytes [lrange $data 12 15]]"
              puts "       # of cell descriptor from COQ to OS      = [reverse_hex_bytes [lrange $data 16 19]]"
              puts "       Decisions taken by fabric arbiter        = [reverse_hex_bytes [lrange $data 20 23]]"
              puts "       packet cell desc. alloc to COQ from FRG  = [reverse_hex_bytes [lrange $data 24 27]]"
              puts "       # frames from COQ to OS  in process      = [reverse_hex_bytes [lrange $data 28 31]]"
          }
        default {
              puts "       No decode available for line $entity"
              puts "       [reverse_hex_bytes [lrange $data 0 3]] [reverse_hex_bytes [lrange $data 4 7]] \
                           [reverse_hex_bytes [lrange $data 8 11]] [reverse_hex_bytes [lrange $data 12 15]] \
                           [reverse_hex_bytes [lrange $data 16 19]] [reverse_hex_bytes [lrange $data 20 23]] \
                           [reverse_hex_bytes [lrange $data 24 27]] [reverse_hex_bytes [lrange $data 28 31]]"

             }
   }  

} 


proc decode_reo_info { data } {

    set count "0x[format %x [expr {$data & 0x7fffffff}]]"
    set stopped "0x[format %x [ expr {$data >> 31}]]"
    set out "    data=$data, frame count = $count, stopped due to BP = $stopped"
    return $out
}

proc get_coq_dft { np } {
   set EZapiMemId_TMOD_0_COQ_DFT  589
   set EZapiMemId_TMOD_1_COQ_DFT  654
   set EZapiRegId_TMOD_0_OS_REO_CNT0 19731 
   set EZapiRegId_TMOD_0_OS_REO_CNT1 19732 
   set EZapiRegId_TMOD_1_OS_REO_CNT0 19892 
   set EZapiRegId_TMOD_1_OS_REO_CNT1 19893 
   set EZapiRegId_TMOD_0_OS_NETIF_MNG_IMEM_EMEM 19724 
   set EZapiRegId_TMOD_1_OS_NETIF_MNG_IMEM_EMEM 19885 

   set length 32
   for {set entity 0} {$entity < 5} { incr entity } {
       set data [get_mem_data $np $EZapiMemId_TMOD_0_COQ_DFT $length $entity]
       puts "   EZapiMemId_TMOD_0_COQ_DFT($entity) = $data"
       decode_coq_dft $entity $data
       set data [get_mem_data $np $EZapiMemId_TMOD_1_COQ_DFT $length $entity]
       puts "   EZapiMemId_TMOD_1_COQ_DFT($entity) = $data"
       decode_coq_dft $entity $data
   }
   # get the OS to IF 0/2 counts
   puts "   ###########################################################"
   puts "   # TM0 Frames from OS to interface engine 0/2"
   puts "   ###########################################################"
   set data [get_reg_value $np $EZapiRegId_TMOD_0_OS_REO_CNT0]
   set out [decode_reo_info $data]
   puts "$out"
   puts "   ###########################################################"
   puts "   # TM1 Frames from OS to interface engine 0/2"
   puts "   ###########################################################"
   set data [get_reg_value $np $EZapiRegId_TMOD_1_OS_REO_CNT0]
   set out [decode_reo_info $data]
   puts "$out"

   # get the OS to IF 1/3 counts
   puts "\n   ###########################################################"
   puts "   # TM0 Frames from OS to interface engine 1/3"
   puts "   ###########################################################"
   set data [get_reg_value $np $EZapiRegId_TMOD_0_OS_REO_CNT1]
   set out [decode_reo_info $data]
   puts "$out"
   puts "\n   ###########################################################"
   puts "   # TM1 Frames from OS to interface engine 1/3"
   puts "   ###########################################################"
   set data [get_reg_value $np $EZapiRegId_TMOD_1_OS_REO_CNT1]
   set out [decode_reo_info $data]
   puts "$out"

   puts "\n   ###########################################################"
   puts "   # TM0 IMEM/EMEM frame counts from COQ to OS"
   puts "   ###########################################################"
   set data [get_reg_value $np $EZapiRegId_TMOD_0_OS_NETIF_MNG_IMEM_EMEM]
   set imem "0x[format %x [expr {$data & 0xffff}]]"
   set emem "0x[format %x [expr {$data >> 16}]]"
   puts "    (data=$data) TM0 IMEM Frame counts = $imem, EMEM Frame counts = $emem"

   puts "\n   ###########################################################"
   puts "   # TM1 IMEM/EMEM frame counts from COQ to OS"
   puts "   ###########################################################"
   set data [get_reg_value $np $EZapiRegId_TMOD_1_OS_NETIF_MNG_IMEM_EMEM]
   set imem "0x[format %x [expr {$data & 0xffff}]]"
   set emem "0x[format %x [expr {$data >> 16}]]"
   puts "    (data=$data) TM1 IMEM Frame counts = $imem, EMEM Frame counts = $emem"

}

proc decode_os_rl_cntr { data } {
    set data [reverse_hex_bytes [lrange $data 0 3]]
    set data [expr {$data & 0x7fff}]
    set data "0x[format %x $data]"
    return $data
}

proc decode_port_threshold { data } {
    set data [reverse_hex_bytes [lrange $data 0 3]]
    set threshold [expr {$data & 0x3fff}]
    set threshold "0x[format %x $threshold]"
    set ready_to_receive [expr {$data >> 14}]
    set ready_to_receive [expr {$ready_to_receive & 1}]
    return "$data, threshold=$threshold, RDY_TO_RCV=$ready_to_receive"
}
proc get_os_rl_cntr { np } {
   set EZapiMemId_TMOD_0_OS_RL_CNTR   606
   # set EZapiMemId_TMOD_0_OS_NETIF_PORT_THRESHOLD 610
   set EZapiMemId_TMOD_0_OS_NETIF_PORT_THRESHOLD 623
   set EZapiMemId_TMOD_1_OS_RL_CNTR   671
   #set EZapiMemId_TMOD_1_OS_NETIF_PORT_THRESHOLD 675
   set EZapiMemId_TMOD_1_OS_NETIF_PORT_THRESHOLD 688
   set length 4
   puts "    ##############################################"
   puts "    #  Printing non-zero output stage counters"
   puts "    ##############################################"
   for {set entity 0} {$entity < 144} { incr entity } {
       set data [get_mem_data $np $EZapiMemId_TMOD_0_OS_RL_CNTR $length $entity]
       set data [decode_os_rl_cntr $data]
       if {$data > 0} {
           puts "   EZapiMemId_TMOD_0_OS_RL_CNTR($entity) = $data"
           set data [get_mem_data $np $EZapiMemId_TMOD_0_OS_NETIF_PORT_THRESHOLD $length $entity]
           set data [decode_port_threshold $data]
           puts "   EZapiMemId_TMOD_0_OS_NETIF_PORT_THRESHOLD($entity) = $data"
       }

       set data [get_mem_data $np $EZapiMemId_TMOD_1_OS_RL_CNTR $length $entity]
       set data [decode_os_rl_cntr $data]
       if {$data > 0} {
           puts "   EZapiMemId_TMOD_1_OS_RL_CNTR($entity) = $data"
           set data [get_mem_data $np $EZapiMemId_TMOD_1_OS_NETIF_PORT_THRESHOLD $length $entity]
           set data [decode_port_threshold $data]
           puts "   EZapiMemId_TMOD_1_OS_NETIF_PORT_THRESHOLD($entity) = $data"
       }
   }

}

proc get_phy_port_map { np } {
   set EZapiMemId_TMOD_0_OS_PHY_PORT_NETIF_MAP  608
   set EZapiMemId_TMOD_1_OS_PHY_PORT_NETIF_MAP  673
   set length 4

   puts "##############################################"
   puts "#  Printing physical port to physical port mapping"
   puts "##############################################"
   for {set entity 0} {$entity < 256} { incr entity } {
       set data [get_mem_data $np $EZapiMemId_TMOD_0_OS_PHY_PORT_NETIF_MAP $length $entity]
       set data  [reverse_hex_bytes [lrange $data 0 3]]
       set data [ expr {$data & 0xff}]
       puts "    TM_0:: Internal($entity) is mapped to $data"
       set data [get_mem_data $np $EZapiMemId_TMOD_1_OS_PHY_PORT_NETIF_MAP $length $entity]
       set data  [reverse_hex_bytes [lrange $data 0 3]]
       set data  [ expr {$data & 0xff}]
       puts "    TM_1:: Internal($entity) is mapped to $data"
   }
}

proc get_int_port_map { np } {
   set EZapiMemId_TMOD_0_OS_NETIF_PHY_PORT_MAP  609
   set EZapiMemId_TMOD_1_OS_NETIF_PHY_PORT_MAP  674
   set length 4

   puts "##############################################"
   puts "#  Printing Internal port to physical port mapping"
   puts "##############################################"
   for {set entity 0} {$entity < 144} { incr entity } {
       set data [get_mem_data $np $EZapiMemId_TMOD_0_OS_NETIF_PHY_PORT_MAP $length $entity]
       set data  [reverse_hex_bytes [lrange $data 0 3]]
       set data [ expr {$data & 0xff}]
       puts "    TM_0:: Internal($entity) is mapped to $data"
       set data [get_mem_data $np $EZapiMemId_TMOD_1_OS_NETIF_PHY_PORT_MAP $length $entity]
       set data  [reverse_hex_bytes [lrange $data 0 3]]
       set data  [ expr {$data & 0xff}]
       puts "    TM_1:: Internal($entity) is mapped to $data"
   }
}


#####################################################################
#
#####################################################################
proc get_tm_dma_info { np } {
    set   EZapiRegId_TM_DMA_0_TMARB_DFT_ADDR  20741 
    set   EZapiRegId_TM_DMA_0_TMARB_DFT_DATA  20742

    set   EZapiRegId_TM_DMA_1_TMARB_DFT_ADDR  21019
    set   EZapiRegId_TM_DMA_1_TMARB_DFT_DATA  21020


    set description { "EMEM_FD_RD    " "EMEM_FD_WR    " "EMEM_QD_QIN_RD" "EMEM_QD_SCH_RD" "EMEM_QD_QIN_WR"\
               "EMEM_QD_SCH_WR " "IMEM_QD_FD_QIN_RD" "IMEM_FD_QD_SCH_RD" "IMEM_FD_QD_QIN_WR" "IMEM_FD_QD_SCH_WR"} 

    puts "   #########  TM 0 DMA access status ###########"
    foreach item "1 2 3 4 5 6 7 8 9 10" { 
        set out [exec show_np -e $np -r reg=$EZapiRegId_TM_DMA_0_TMARB_DFT_ADDR,val=$item,WR]
        #puts $out
        #puts "exec show_np -e $np -r reg=$EZapiRegId_TM_DMA_0_TMARB_DFT_ADDR,val=$item,WR"
        set out [get_reg_value $np $EZapiRegId_TM_DMA_0_TMARB_DFT_DATA]
        #puts "get_reg_value $np $EZapiRegId_TM_DMA_0_TMARB_DFT_DATA]"
        set desc [lindex $description [expr {$item-1}]]
        puts "   $desc\t --> $out"
    }

    puts "   #########  TM 1 DMA access status ###########"
    foreach item "1 2 3 4 5 6 7 8 9 10" { 
        set out [exec show_np -e $np -r reg=$EZapiRegId_TM_DMA_1_TMARB_DFT_ADDR,val=$item,WR]
        #puts $out
        #puts "exec show_np -e $np -r reg=$EZapiRegId_TM_DMA_0_TMARB_DFT_ADDR,val=$item,WR"
        set out [get_reg_value $np $EZapiRegId_TM_DMA_1_TMARB_DFT_DATA]
        #puts "get_reg_value $np $EZapiRegId_TM_DMA_0_TMARB_DFT_DATA]"
        set desc [lindex $description [expr {$item-1}]]
        puts "   $desc\t --> $out"
    }


}

#####################################################################
#
#####################################################################
proc get_idma_count { np_id } {

    set regs {{EZapiRegId_TM_DMA_0_TM_IDMA_FD_FIFO_STAT_CNTR_0 20683}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_FD_FIFO_STAT_CNTR_1 20684}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_FD_FIFO_STAT_CNTR_2 20685}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_FD_FIFO_STAT_CNTR_3 20686}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_FD_FIFO_STAT_CNTR_0 20961}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_FD_FIFO_STAT_CNTR_1 20962}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_FD_FIFO_STAT_CNTR_2 20963}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_FD_FIFO_STAT_CNTR_3 20964}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_VQM_STAT_CNTR_0 20687}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_VQM_STAT_CNTR_1 20688}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_VQM_STAT_CNTR_2 20689}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_VQM_STAT_CNTR_3 20690}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_VQM_STAT_CNTR_0 20965}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_VQM_STAT_CNTR_1 20966}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_VQM_STAT_CNTR_2 20967}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_VQM_STAT_CNTR_3 20968}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_FD_FIFO_STAT_0 20679}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_FD_FIFO_STAT_1 20680}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_FD_FIFO_STAT_2 20681}\
    {EZapiRegId_TM_DMA_0_TM_IDMA_FD_FIFO_STAT_3 20681}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_FD_FIFO_STAT_0 20957}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_FD_FIFO_STAT_1 20958}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_FD_FIFO_STAT_2 20959}\
    {EZapiRegId_TM_DMA_1_TM_IDMA_FD_FIFO_STAT_3 20960}\
    }

    foreach reg $regs {
        set name [lindex $reg 0]
        set id [lindex $reg 1]
        set data [get_reg_data_no_print $np_id $id $name]
        if { $data != 0 } {
            puts " NP=$np_id, reg=$name\($data)"
        }
    }

}


proc decode_port_sts { data } {
    set out "  "
    if {[expr {$data & 0x10000000}]} {
        set out "CHNL_FC=1 "
    }
    if {[expr {$data & 0x20000000}]} {
        append out "CHNL_FORCE_STOP=1 "
    }
    if {[expr {$data & 0x100000}]} {
        append out "credit priority0 blocked = 1 "
    }
    if {[expr {$data & 0x200000}]} {
        append out "credit priority1 blocked = 1 "
    }
    if {[expr {$data & 0x400000}]} {
        append out "credit priority2 blocked = 1 "
    }
    if {[expr {$data & 0x800000}]} {
        append out "credit priority3 blocked = 1 "
    }
    if {[expr {$data & 0x1000000}]} {
        append out "aggr credit priority0 blocked = 1 "
    }
    if {[expr {$data & 0x2000000}]} {
        append out "aggr credit priority1 blocked = 1 "
    }
    if {[expr {$data & 0x4000000}]} {
        append out "aggr credit priority2 blocked = 1 "
    }
    if {[expr {$data & 0x8000000}]} {
        append out "aggr credit priority3 blocked = 1 "
    }
    set temp [expr {$data & 0xf}]
    if {$temp} {
        append out "Frame In not empty "
    }
    set temp [expr {$data >> 4}]
    set temp [expr {$temp & 0xf}]
    if {$temp} {
        append out "P0 counter = $temp, "
    }
    set temp [expr {$data >> 8}]
    set temp [expr {$temp & 0xf}]
    if {$temp} {
        append out "P1 counter = $temp, "
    }
    set temp [expr {$data >> 12}]
    set temp [expr {$temp & 0xf}]
    if {$temp} {
        append out "P2 counter = $temp, "
    }
    set temp [expr {$data >> 16}]
    set temp [expr {$temp & 0xf}]
    if {$temp} {
        append out "P3 counter = $temp "
    }
    return $out
}

#####################################################################
#
#####################################################################
proc get_port_sts { np_id } {
    puts "\n"
    puts "*****************************************"
    puts "*********  Flow control to TM OQ"
    puts "*  Status: 0-3  0 = empty"
    puts "*  P0/P1/P2/P3 counters: 4-7/8-11/12-15/16-19"
    puts "*  P0/P1/P2/P3 channel credit sign : 20/17/18/19??"
    puts "*  P0/P1/P2/P3 channel aggr sign : 20/21/22/23"
    puts "*  P0/P1/P2/P3 channel aggr sign : 24/25/26/27"
    puts "*  Flow Control  b28"
    puts "*  Channel Force b29 0=not stopped due to forced, 1=stopped due to forced"
    puts "*****************************************"
    set EZapiMemId_TM_OQ_0_PORT_STS 721
    set EZapiMemId_TM_OQ_1_PORT_STS 758
    set length 4
    for {set entity 0} {$entity < 144} { incr entity } {
        set data [get_mem_data $np_id $EZapiMemId_TM_OQ_0_PORT_STS $length $entity]
        set data [reverse_hex_bytes [lrange $data 0 3]]
        set out [decode_port_sts $data]
        # don't print out entries that are not active which has default init value
        if { $data != 0x20000000 && $data != 0x2f000000 } {
            puts "    EZapiMemId_TM_OQ_0_PORT_STS($entity) = $data,$out"
        }
        set data [get_mem_data $np_id $EZapiMemId_TM_OQ_1_PORT_STS $length $entity]
        set data [reverse_hex_bytes [lrange $data 0 3]]
        set out [decode_port_sts $data]
        # don't print out entries that are not active which has default init value
        if { $data != 0x20000000 && $data != 0x2f000000 } {
            puts "    EZapiMemId_TM_OQ_1_PORT_STS($entity) = $data,$out"
        }
    }
}


#####################################################################
#  GET OCFD table
#####################################################################
proc get_ocfdq_status_table { np_id } {
    set  EZapiMemId_CMEM_OCFD_QUEUE_STATUS_TAB  361
    set  entity_max 16
   puts ">>> CMEM_OCFD_QUEUE_STATUS_TAB <<<"
   for { set entity 0 } { $entity < $entity_max } { incr entity } {
       set data [ exec show_np -e $np_id -m mem=$EZapiMemId_CMEM_OCFD_QUEUE_STATUS_TAB,start=$entity,length=8 | grep x ]
       # puts "reading $np -m mem=$mem_id,start=$start_addr,length=8"
       if {[regexp "fail" $data]} {
          puts "raw data = $data"
          puts "failed to read mem_id=$EZapiMemId_CMEM_OCFD_QUEUE_STATUS_TAB, np=$np_id, entity=$entity"
          return "failed"
       }
       # puts "$data"
       # the data is in the last column
       #set data [lrange $data 2 end]

       regsub -all {0x} $data "" data
       set idx [ expr {[llength $data] - 8 } ]
       set data [lrange $data $idx end]
       set _data "0"
       for { set i 0 } { $i < 4} { incr i } {
           set temp_data [lindex $data $i]
           if {![regexp "x" $temp_data]} {
               set temp_data "0x$temp_data"
           }
           set _data [ expr [ expr { $_data << 8 } ] + $temp_data ]
       }
       set high_word $_data

       set _data "0"
       for { set i 4 } { $i < 8} { incr i } {
           set temp_data [lindex $data $i]
           if {![regexp "x" $temp_data]} {
               set temp_data "0x$temp_data"
           }
           set _data [ expr [ expr { $_data << 8 } ] + $temp_data ]
       }
       set low_word $_data
       puts "   Index=$entity :: >>> 0x[format %x $high_word]:[format %x $low_word]"
    }
}

proc decode_port_aggr_credits { data } {
   set temp [reverse_hex_bytes [lrange $data 0 3]]
   set p0_credits [expr {$temp & 0xfff}]
   set p1_credits [expr {$temp >> 12}]
   set p1_credits [expr {$p1_credits & 0xfff}]
   set temp1 [reverse_hex_bytes [lrange $data 4 7]]
   set out "$temp1:$temp\t\t P0=$p0_credits, p1=$p1_credits,"
   set p2_credits [expr {$temp >> 24 }]
   set p2_credits [expr {$temp & 0xff }]
   # for P2, need 4 MSB from temp1 data
   set msb [expr {[expr {$temp1 & 0xf}] << 8}]
   set p2_credits [expr {$p2_credits + $msb}]
   set p3_credits [expr {$temp1 >> 4}]
   set p3_credits [expr {$p3_credits & 0xfff}]
   append out " P2=$p2_credits, p3=$p3_credits"
   return $out
}

#####################################################################
#  GET PORT CREDITS
#####################################################################
proc get_port_credits { np_id } {
    puts "*****************************************"
    puts "************  OQ port credits ***********"
    puts "* Each unit is 1Kbytes  "
    puts "* P0 = bits 0-11"
    puts "* P1 = bits 12-23"
    puts "* P0 = bits 23-35"
    puts "* P0 = bits 36-47"
    puts "*****************************************"
    set EZapiMemId_TM_OQ_0_PORT_CREDITS 727
    set EZapiMemId_TM_OQ_1_PORT_CREDITS 764
    set length 8
    for {set entity 0} {$entity < 144} { incr entity } {
        set data [get_mem_data  $np_id $EZapiMemId_TM_OQ_0_PORT_CREDITS $length $entity]
        set data [decode_port_aggr_credits $data]
        # don't print entries that are not active which has the init values below
        if { [regexp "0x80:0x8008008" $data] == 0} {
            puts "    EZapiMemId_TM_0_PORT_CREDITS($entity) = $data"
        }
        set data [get_mem_data $np_id $EZapiMemId_TM_OQ_1_PORT_CREDITS $length $entity]
        set data [decode_port_aggr_credits $data]
        # don't print entries that are not active which has the init values below
        if { [regexp "0x80:0x8008008" $data] == 0} {
            puts "    EZapiMemId_TM_1_PORT_CREDITS($entity) = $data"
        }
    }
    puts "\n"
    puts "*****************************************"
    puts "*********  AGGREGATED CREDITS:***********"
    puts "*********  34 lines of AGGR credit*******"
    puts "* P0 = bits 0-11"
    puts "* P1 = bits 12-23"
    puts "* P2 = bits 23-35"
    puts "* P3 = bits 36-47"
    puts "*****************************************"
    set EZapiMemId_TM_OQ_0_AGGR_CREDITS 717
    set EZapiMemId_TM_OQ_1_AGGR_CREDITS 754
    set length 8
    for {set entity 0} {$entity < 34} { incr entity } {
        set data [get_mem_data $np_id $EZapiMemId_TM_OQ_0_AGGR_CREDITS $length $entity]
        set data [decode_port_aggr_credits $data]
        # don't print entries that are not active which has the init values below
        if { [regexp "0x7ff7:0xff7ff7ff" $data] == 0} {
            puts "    EZapiMemId_TM_OQ_0_AGGR_CREDITS($entity) = $data"
        }
        set data [get_mem_data $np_id $EZapiMemId_TM_OQ_1_AGGR_CREDITS $length $entity]
        set data [decode_port_aggr_credits $data]
        # don't print entries that are not active which has the init values below
        if { [regexp "0x7ff7:0xff7ff7ff" $data] == 0} {
            puts "    EZapiMemId_TM_OQ_1_AGGR_CREDITS($entity) = $data"
        }
    }
}

#####################################################################
#  GET OCFD BUDGET STATUS
#####################################################################
proc get_ocfd_budget_status { np_id } {
    set EZapiRegId_CMEM_OCFD_TOTAL_BUDGET_STATUS  11034 
    puts "\n*****************************************"
    puts "*  OCFD Total budget status frame count  "
    puts "*  0-11  = number of descriptors in OCFDQ"
    puts "*  16-24 = current buffers used by OCFDQ (1buffer = upto 16 descriptors)"
    puts "*  28    = buffers used by OCFDQ reached limit"
    puts "*****************************************"
    set data [get_reg_data $np_id $EZapiRegId_CMEM_OCFD_TOTAL_BUDGET_STATUS\
             "EZapiRegId_CMEM_OCFD_TOTAL_BUDGET_STATUS"]
}

#####################################################################
#  GET OCFD TABLE STATUS
#####################################################################
proc check_ocfd_queue_status_table { np_id } {
   set EZapiRegId_CMEM_CMEM_CMD     10934 
   set EZapiRegId_CMEM_CMEM_ADDR    10935 
   set EZapiRegId_CMEM_CMEM_DATA_1  10927 
   set EZapiRegId_CMEM_CMEM_DATA_2  10928 


    # go through and read all 32 entries
    for {set i 0 } { $i < 32 } { incr i } { 
        exec show_np -e $np_id -r reg=$EZapiRegId_CMEM_CMEM_ADDR,val=$i,WR
        exec show_np -e $np_id -r reg=$EZapiRegId_CMEM_CMEM_CMD,val=0xb7,WR
        set data1 [get_reg_value $np_id $EZapiRegId_CMEM_CMEM_DATA_1]
        set data2 [get_reg_value $np_id $EZapiRegId_CMEM_CMEM_DATA_2]
        if { $data1 > 0 } {
            # bits definination
            # bit 40-32 = number of buffers occupied
            # bit 59-48 = number of frame descriptors 
            # data1 has bits 64-32
            puts "OCFD index $i == $data1  $data2 "
            puts "     buffer occupied = [expr {$data1 & 0x1ff}] "
            set data1 [expr { $data1 >> 16 }]
            puts "     frame descriptors in queue = [expr {$data1 & 0xfff}] \n"
        }
    }
}


proc get_tm_monitor_info { np_id } {

    set EZapiRegId_TM_QC_0_MONITOR4 21858 
    set EZapiRegId_TM_QC_1_MONITOR4 22094 

    set EZapiRegId_TM_QC_0_MONITOR5 21859 
    set EZapiRegId_TM_QC_1_MONITOR5 22095 
 
    set EZapiRegId_TM_QC_0_MONITOR6 21860 
    set EZapiRegId_TM_QC_1_MONITOR6 22096 

    set EZapiRegId_TM_QC_0_MONITOR12 21874
    set EZapiRegId_TM_QC_1_MONITOR12 22110 
 
    set EZapiRegId_TM_QC_0_MONITOR 21854 
    set EZapiRegId_TM_QC_1_MONITOR 22090 

    set EZapiRegId_TM_QC_0_MONITOR1 21855 
    set EZapiRegId_TM_QC_1_MONITOR1 22091 

    set EZapiRegId_TM_QC_0_MONITOR2 21856 
    set EZapiRegId_TM_QC_1_MONITOR2 22092 

    set EZapiRegId_TM_QC_0_MONITOR3 21857 
    set EZapiRegId_TM_QC_1_MONITOR3 22093 

    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR3]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR3]
    puts "    MONITOR3"
    puts "       TM0=$data, TM1=$data1"

    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR4]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR4]
    puts "\n    QIN events received from IDMA, each event = 256B "
    puts "       TM0=$data, TM1=$data1"
    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR5]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR5]
    puts "\n    Schedule events received from scheduler"
    puts "       TM0=$data, TM1=$data1"
    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR6]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR6]
    puts "\n    Byte Count Reply sent from QC to scheduler"
    puts "       TM0=$data, TM1=$data1"
    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR12]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR12]
    puts "\n    QIN Drop Request (TOP requests TM drop)"
    puts "       TM0=$data, TM1=$data1"

    # Mock liveness, rq_drop, fifo_fullness, no_map/always_drop
    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR]

    set data_list "$data $data1"
    for {set i 0} { $i < 2 } { incr i } {
        set data [lindex $data_list $i]
        set mock_liveness [expr { $data & 0x3ff } ]
        set qin_fifo_fullness [expr {[expr { $data >> 10 }] & 0x3f}]
        set sched_fifo_fullness [expr {[expr { $data >> 16 }] & 0x1f}]
        set no_map_alwaysdrop [expr {$data >> 26 }]
        puts "\n    TM$i data=$data, MOCK_LIVENESS=$mock_liveness, QIN_FIFO_FULLNESS=$qin_fifo_fullness"
        puts "         SCHED_FIFO_FULLNESS=$sched_fifo_fullness, NOMAP_ALWAYS_DROP=$no_map_alwaysdrop"
    }

    # mis counters indicating performance degradation
    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR1]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR1]

    set data_list "$data $data1"
    for {set i 0} { $i < 2 } { incr i } {
        set data [lindex $data_list $i]
        set qin_fifo_fullness [expr { $data & 0x1ff } ]
        set miss_event_fifo_fullness [expr {[expr { $data >> 9 }] & 0x1ff}]
        set hit_fifo_fullness [expr {[expr { $data >> 18 }] & 0x3f}]
        set wait_fifo_fullness [expr {$data >> 24 }]
        puts "\n    TM$i data=$data, QIN_FIFO_FULLNESS=$qin_fifo_fullness, MISS_EVENT_FULLNESS=$miss_event_fifo_fullness"
        puts "         HIT_FIFO_FULLNESS=$hit_fifo_fullness, WAIT_FIFO_FULLNESS=$wait_fifo_fullness"
    }

    # mis counters indicating performance degradation
    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR2]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR2]

    set data_list "$data $data1"
    for {set i 0} { $i < 2 } { incr i } {
        set data [lindex $data_list $i]
        set brn_qin_fifo_fullness [expr { $data & 0x1f } ]
        set brn_cache_fifo_fullness [expr {[expr { $data >> 5 }] & 0x1f}]
        set brn_ref_l_fifo_fullness [expr {[expr { $data >> 10 }] & 0x1f}]
        set brn_ref_h_fifo_fullness [expr {[expr { $data >> 15 }] & 0x1f}]
        set disp_concat_fifo_fullness [expr {[expr { $data >> 20 }] & 0x7f}]
        set sch_link_fifo_fullness [expr {$data >> 27 }]
        puts "\n    TM$i data=$data, BRN_QIN_FIFO_FULLNESS=$brn_qin_fifo_fullness, BRN_CCH_QIN_FULLNESS=$brn_cache_fifo_fullness"
        puts "         BRN_REF_L_FIFO_FULLNESS=$brn_ref_l_fifo_fullness, BRN_REF_L_FIFO_FULLNESS=$brn_ref_h_fifo_fullness"
        puts "         DISP_CONCAT_FIFO_FULLNESS=$disp_concat_fifo_fullness, SCH_LINK_FIFO_FULLNESS=$sch_link_fifo_fullness"
    }
    # mis counters and status bits
    set data [get_reg_value $np_id $EZapiRegId_TM_QC_0_MONITOR3]
    set data1 [get_reg_value $np_id $EZapiRegId_TM_QC_1_MONITOR3]

    set data_list "$data $data1"
    for {set i 0} { $i < 2 } { incr i } {
        set data [lindex $data_list $i]
        set stall_from_tm_mem_intf_to_qc_read [expr { $data & 0x1 } ]
        set pipe_from_TMMI [expr {[expr { $data >> 1 }] & 0x1}]
        set qc_read_fd_stall [expr {[expr { $data >> 2 }] & 0x1}]
        set flmi_write_not_ready [expr {[expr { $data >> 3 }] & 0x1}]
        set dispatch_to_wred_fifo_full [expr {[expr { $data >> 4 }] & 0x1}]
        set dispatch_to_sch_bcr_fifo_full [expr {[expr { $data >> 5 }] & 0x1}]
        set dispatch_enqueue_dequeue_fifo_full [expr {[expr { $data >> 6 }] & 0x1}]
        set dispatch_oq_frame_read_fifo_full [expr {[expr { $data >> 7 }] & 0x1}]
        set dispatch_dma_recycle_fifo_full [expr {[expr { $data >> 8 }] & 0x1}]
        set dispatch_ptr_queue_recycle_fifo_full [expr {[expr { $data >> 9 }] & 0x1}]
        set dispatch_ptr_queue_new_pointer_fifo_empty [expr {[expr { $data >> 10 }] & 0x1}]
        set dram_rd_wr_latency [expr {[expr { $data >> 11 }] & 0x1}]
        set dram_rd_latency_or_sch_oq_full [expr {[expr { $data >> 12 }] & 0x1}]
        set tm_stat_fifo_full [expr {[expr { $data >> 13 }] & 0x1}]
        set cache_low_bank_fullness [expr {[expr { $data >> 14 }] & 0x1ff}]
        set cache_high_bank_fullness [expr {$data >> 23 }]
        puts "\n    TM$i data=$data, STALL_FROM_MEM_INTF_TO_QC_READ=$stall_from_tm_mem_intf_to_qc_read,\
                       PIPE_FROM_TMMI=$pipe_from_TMMI"
        puts "         QC_READ_FD_STALL=$qc_read_fd_stall, FLMI_WRITE_NOT_READY=$flmi_write_not_ready"
        puts "         DISPATCH_TO_WRED_FIFO_FULL=$dispatch_to_wred_fifo_full, DISPATCH_TO_SCH_BCR_FIFO_FULL=$dispatch_to_sch_bcr_fifo_full"
        puts "         DISPATCH_EN_DE_QUEUE_FIFO_FULL=$dispatch_enqueue_dequeue_fifo_full, DISPATCH_OQ_FRAME_RD_FIFO_FULL=$dispatch_oq_frame_read_fifo_full"
        puts "         DISPATCH_DMA_RECYCLE_FIFO_FULL=$dispatch_dma_recycle_fifo_full, DISPATCH_PTR_QUEUE_RECYCLE_FIFO_FULL=$dispatch_ptr_queue_recycle_fifo_full"
        puts "         DISPATCH_PTR_QUEUE_NEW_PTR_FIFO_EMPTY=$dispatch_ptr_queue_new_pointer_fifo_empty, DRAM_RD_WR_LATENCY=$dram_rd_wr_latency"
        puts "         DRAM_RD_LATENCY_OR_SCH_OQ_FULL=$dram_rd_latency_or_sch_oq_full, TM_STAT_FIFO_FULL=$tm_stat_fifo_full"
        puts "         CACHE_LOW_BANK_FULLNESS=$cache_low_bank_fullness, CACHE_HI_BANK_FULLNESS=$cache_high_bank_fullness"
    }


}


#####################################################################
#  GET TM OCC data
#####################################################################
proc get_tm_ptr_q_occ_info { np_id } {
   set EZapiRegId_TM_PTR_Q_OCC_DFT_ADDR 21267 
   set EZapiRegId_TM_PTR_Q_OCC_DFT_DATA 21268 
  
   puts "   #################  TM_PTR_Q_OCC_DFT_DATA  #######"
   for {set i 0} { $i < 15 } { incr i } {
        set out [exec show_np -e $np_id -r reg=$EZapiRegId_TM_PTR_Q_OCC_DFT_ADDR,val=$i,WR]
        set data [get_reg_value $np_id $EZapiRegId_TM_PTR_Q_OCC_DFT_DATA]
        puts "   EZapiRegId_TM_PTR_Q_OCC_DFT_DATA(entity=$i) = $data" 
   }
}

#####################################################################
#  GET TM L01 port sram status
#####################################################################
proc get_tm_l01_port_sram_status { np_id } {

   set EZapiMemId_TM_SC_L01_0_PORT_SSTAT_P2  1008   
   set EZapiMemId_TM_SC_L01_1_PORT_SSTAT_P2  1048

   set length 4
   puts "######################################################################"
   puts "#   Ports sram status for L1s"
   puts "######################################################################"
   for {set i 0 } { $i < 512 } { incr i } {
        set data [get_mem_data $np_id $EZapiMemId_TM_SC_L01_0_PORT_SSTAT_P2 $length $i]
        set data [reverse_hex_bytes [lrange $data 0 3]]
        puts "    EZapiMemId_TM_SC_L01_0_PORT_SSTAT_P2($i) = $data"
        set data [get_mem_data $np_id $EZapiMemId_TM_SC_L01_1_PORT_SSTAT_P2 $length $i]
        set data [reverse_hex_bytes [lrange $data 0 3]]
        puts "    EZapiMemId_TM_SC_L01_1_PORT_SSTAT_P2($i) = $data\n"
   }

}

#####################################################################
#  GET TM L01 port sram status
#####################################################################
proc get_tm_l01_port_sram_status_p1 { np_id } {

   set EZapiMemId_TM_SC_L01_0_PORT_SSTAT  987
   set EZapiMemId_TM_SC_L01_1_PORT_SSTAT  1027

   set length 4
   puts "######################################################################"
   puts "#   Ports sram status for L1s"
   puts "######################################################################"
   for {set i 0 } { $i < 512 } { incr i } {
        set data [get_mem_data $np_id $EZapiMemId_TM_SC_L01_0_PORT_SSTAT $length $i]
        set data [reverse_hex_bytes [lrange $data 0 3]]
        puts "    EZapiMemId_TM_SC_L01_0_PORT_SSTAT($i) = $data"
        set data [get_mem_data $np_id $EZapiMemId_TM_SC_L01_1_PORT_SSTAT $length $i]
        set data [reverse_hex_bytes [lrange $data 0 3]]
        puts "    EZapiMemId_TM_SC_L01_1_PORT_SSTAT($i) = $data\n"
   }

}

#####################################################################
#  GET TM L01 port sram status
#####################################################################
proc get_odma_sts_info { np_id } {

   set EZapiRegId_DMA_0_ODMA_STS_SEL  10559 
   set EZapiRegId_DMA_0_ODMA_STS_DATA 10560 

   set EZapiRegId_DMA_1_ODMA_STS_SEL  10790 
   set EZapiRegId_DMA_1_ODMA_STS_DATA 10791

   for {set i 0 } { $i < 10 } { incr i } {
        set out [exec show_np -e $np_id -r reg=$EZapiRegId_DMA_0_ODMA_STS_SEL,val=$i,WR]
        set data [get_reg_value $np_id $EZapiRegId_DMA_0_ODMA_STS_DATA]
        puts "   EZapiRegId_DMA_0_ODMA_STS_DATA(entity=$i) = $data" 
   }

   for {set i 0 } { $i < 10 } { incr i } {
        set out [exec show_np -e $np_id -r reg=$EZapiRegId_DMA_1_ODMA_STS_SEL,val=$i,WR]
        set data [get_reg_value $np_id $EZapiRegId_DMA_1_ODMA_STS_DATA]
        puts "   EZapiRegId_DMA_1_ODMA_STS_DATA(entity=$i) = $data" 
   }

    set EZapiMemId_CMEM_FD_MEM  358   
    puts "######################################################################"
    puts "#   FD MEM SRAM"
    puts "######################################################################"
    for {set i 0 } { $i < 129 } { incr i } {
        set data [get_mem_data $np_id $EZapiMemId_CMEM_FD_MEM 28 $i]
        puts "  Line $i = $data" 
    }
}

#####################################################################
#  GET TM L01 port sram status
#####################################################################
proc get_imem_cache_cnt { np_id } {

   set EZapiRegId_RFD_CACHE_CNTR_SEL  11304 
   set EZapiRegId_RFD_CACHE_CNTR_DATA 11305 

   for {set i 0 } { $i < 48 } { incr i } {
        set out [exec show_np -e $np_id -r reg=$EZapiRegId_RFD_CACHE_CNTR_SEL,val=$i,WR]
        set data [get_reg_value $np_id $EZapiRegId_RFD_CACHE_CNTR_DATA]
        puts "   Port IMEM cache counter(entity=$i) = $data\n" 
   }
   # now get the group global cache counter
   for {set i 0x180 } { $i < 0x188 } { incr i } {
        set out [exec show_np -e $np_id -r reg=$EZapiRegId_RFD_CACHE_CNTR_SEL,val=$i,WR]
        set data [get_reg_value $np_id $EZapiRegId_RFD_CACHE_CNTR_DATA]
        puts "   Group IMEM cache counter(entity=$i) = $data\n" 
   }

   # now get the global cache counter
   set out [exec show_np -e $np_id -r reg=$EZapiRegId_RFD_CACHE_CNTR_SEL,val=0x200,WR]
   set data [get_reg_value $np_id $EZapiRegId_RFD_CACHE_CNTR_DATA]
   puts "   Global IMEM cache counter(entity=$i) = $data" 
}

#####################################################################
# END PROCs
#####################################################################


set ERROR_ENCOUNTERED 0

if {[regexp "count" $param2]} {
    foreach np_id $np_ids {
		puts "Looking for non-zero counters on NP, this could take a while"
		if { $argc > 2 } {
			set user_counter_start [lindex $argv 2]
			if { $argc > 3 } {
				set user_counter_count [lindex $argv 3]
			}
			get_user_counter $np_id $user_counter_start $user_counter_count
		} else {
			# now read the usercounters and only display non-zeros values
			get_user_counter $np_id 0x5f0000 532480
			# read wred count
			# get_user_counter $np_id 532480 1048576
            # puts "Completed [exec date]"
		}
    }
    return
}

if {[regexp "queuestat" $param2]} {
    foreach np_id $np_ids {
		puts "Looking for non-zero counters on NP, this could take a while"
		if { $argc > 2 } {
			set user_counter_start [lindex $argv 2]
			if { $argc > 3 } {
				set user_counter_count [lindex $argv 3]
			}
			get_user_queuestat $np_id $user_counter_start $user_counter_count
		} else {
			# now read the usercounters and only display non-zeros values
			get_user_queuestat $np_id 0x5f0000 262144
			# read wred count
			# get_user_counter $np_id 532480 1048576
            # puts "Completed [exec date]"
		}
    }
    return
}


##############################################################
# Get IMEM cache counters
##############################################################
if {[regexp "imemcache" $param2]} {
   get_imem_cache_cnt $np_ids
   return
}

##############################################################
# Get TM DMA data to show activity in IMEM or EMEM
##############################################################
if {[regexp "dmainfo" $param2]} {
   get_tm_dma_info $np_ids
   return
}

##############################################################
# Get TM port STS
##############################################################
if {[regexp "port" $param2]} {
   get_port_sts $np_ids
   return
}

##############################################################
# Get TM DMA data to show activity in IMEM or EMEM
##############################################################
if {[regexp "idma" $param2]} {
   get_idma_count $np_ids
   return
}

##############################################################
# Get OCFD table status
##############################################################
if {[regexp "ocfdtable" $param2]} {
   get_ocfdq_status_table $np_ids
   return
}

##############################################################
# Get OCFD table status
##############################################################
if {[regexp "ocfdt" $param2]} {
   check_ocfd_queue_status_table $np_ids
   return
}

##############################################################
# Get OCFD budget status
##############################################################
if {[regexp "ocfdb" $param2]} {
   get_ocfd_budget_status $np_ids
   return
}

##############################################################
# Get fragmenter  status
##############################################################
if {[regexp "frag" $param2]} {
   get_frg_dft $np_ids
   return
}

##############################################################
# Get cell oq status
##############################################################
if {[regexp "coq" $param2]} {
   get_coq_dft $np_ids
   return
}

##############################################################
# Get output stage status
##############################################################
if {[regexp "os" $param2]} {
   get_os_rl_cntr $np_ids
   return
}

##############################################################
# Get frd total
##############################################################
if {[regexp "frd" $param2]} {
   get_frd_totals $np_ids
   return
}

##############################################################
# Get port credits
##############################################################
if {[regexp "cred" $param2]} {
   get_port_credits $np_ids
   return
}

##############################################################
# Get port map
##############################################################
if {[regexp "phymap" $param2]} {
   get_phy_port_map $np_ids
   return
}

##############################################################
# Get port map
##############################################################
if {[regexp "intmap" $param2]} {
   get_int_port_map $np_ids
   return
}

##############################################################
# Get tm monitor info
##############################################################
if {[regexp "monitor" $param2]} {
   get_tm_monitor_info $np_ids
   return
}

##############################################################
# Get tm ptr q qcc data
##############################################################
if {[regexp "occ" $param2]} {
   get_tm_ptr_q_occ_info $np_ids
   return
}


##############################################################
# Get tm port sram status
##############################################################
if {[regexp "l1sramp1" $param2]} {
   get_tm_l01_port_sram_status_p1 $np_ids
   return
}

##############################################################
# Get tm port sram status
##############################################################
if {[regexp "l1sram" $param2]} {
   get_tm_l01_port_sram_status $np_ids
   return
}

##############################################################
# Get odma sts info
##############################################################
if {[regexp "odma" $param2]} {
   get_odma_sts_info $np_ids
   return
}

##############################################################
# 
##############################################################
if {[regexp "detail" $param2]} {
   set ERROR_ENCOUNTERED 1
}

#
#  MAIN
#

# 
# get global queue stats
#
set node_id [get_node_id]
puts "########  GLOBAL TM stats counters  ######" 
set out [exec  prm_np_show TM counters -s $node_id]
puts "$out\n"

foreach np_id $np_ids {

    #
    # get the FIN/FOUT counters for both TMs
    #
    get_fin_fout $np_id

    #
    # Get the RFD totals this should be FOUT-FIN
    # upto 4k of FRD
    #
    get_frd_totals $np_id

    #
    # get port credit.  Each credit is 1Kbyte units
    #                   144 lines in total
    #
    #                   p0 = bits 0-11
    #                   p1 = bits 12-23
    #                   p2 = bits 24-35
    #                   p3 = bits 36-47
    #
    #
    #
    get_port_credits $np_id

    ##############################################################################
    #  Get all OQ port STS
    ##############################################################################
    get_port_sts $np_id

    puts "\n"
    puts " *****************************************"
    puts " *********  TM_IDMA frame count          "
    puts " *****************************************"
    get_idma_count $np_id


    ##############################################################################
    #  Get all OCFD INFO 
    ##############################################################################
    get_ocfd_budget_status $np_id
    check_ocfd_queue_status_table $np_id

    puts "\n"
    puts " *****************************************"
    puts " *********  FRG_DFT              *********"
    puts " *****************************************"
    get_frg_dft $np_id

    puts "\n"
    puts " *****************************************"
    puts " *********  COQ_DFT              *********"
    puts " *****************************************"
    get_coq_dft $np_id
    
    puts "\n"
    puts " *****************************************"
    puts " *********  OSREL_CNTR           *********"
    puts " *****************************************"
    get_os_rl_cntr $np_id

    puts "\n"
    puts " *****************************************"
    puts " *********  TM MONITOR INFO      *********"
    puts " *****************************************"
    get_tm_monitor_info $np_id

    puts "\n"
    puts " *****************************************"
    puts " *********  TM DMA INFO          *********"
    puts " *****************************************"
    get_tm_dma_info $np_id


    ##########################################
    # Get OCC info
    ##########################################
    get_tm_ptr_q_occ_info $np_ids
}

set date [exec date]


