#!/pkg/bin/tclsh
# ---------------------------------------------------------------------
# tm_scan -Scans TM register and memories to look for abnormalities
#
# July 2011, Hai Nguyen
#
# Copyright (c) 2011 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 "data=$date"

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 "           comp_odma_stat      compare odma_stat0 between 2 NPs"
   puts "param2     queuestat    scan through queue stat counters"
   puts "           get_dma_stat        get odma_stat0 "
   puts "           credit_check        check credits for all levels"
   puts "           ignore_bp  zero out the TM_OQ_CFG_BP_P2"
   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 "comp_dma_stat" $param1]} {
    set param2 [lindex $argv 0]
    set np_ids [lrange $argv 1 end]
}

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
   }
}



# these reg_id and mem_id are hardcoded, verify before using
# registers are in block 33
set TM_REG {{TM_ODMA_STAT_1 5309} {TM_ODMA_STAT_3 5311} {RFD_FC_STS 4934}\
            {TM_OQ_ACNT_GLOB_P2 5545}\
            {TM_OQ_ECNT_GLOB_P2 5546}\
	        {TM_OQ_FRD_TOTAL 5486}\
            {TM_OQ_ECC_DOUBLE_COUNT_ERR 5508} {TM_OQ_SINGLE_ECC 5511}\
            {TM_DMA_ECC_DOUBLE_COUNT_ERR 5339} {TM_DMA_SINGLE_ECC 5342}\
            {TM_OQ_ECC_DOUBLE_ERROR_0_P2 5553} {TM_OQ_ECC_SINGLE_ERROR_0_P2 5553}\
            {VDMA_ALL_RX_CRC_ERR_P2 5380}\
            {VDMA_PP_RX_CRC_ERR_P2  5381}\
            {IF2_IR_ILKN_FC_RED_LATE_CFG_P2  2247}\
	        {ICFD_TOTAL_BUDGET_STATUS 2807}\
	        {OCFD_TOTAL_BUDGET_STATUS  2862}\
            {TM_PTR_Q_ECC_DOUBLE_ERROR_CNT 5445}\
            {TM_PTR_Q_ECC_DR_ERROR_DATA  5446}\
            {TM_PTR_Q_ECC_ADDR_ERROR_SELECT 5447}\
            {TM_PTR_Q_ECC_SINGLE_ERROR_CNT 5448}\
            {TM_PTR_Q_ECC_DOUBLE_ERROR_MASK_0 5449}\
            {TM_PTR_Q_ECC_DOUBLE_ERROR_0 5451}\
            {TM_PTR_Q_ECC_SINGLE_ERROR_0 5452}\
            }

#{IF2_IR_ILKN_0_MAC_CFG_6_P2  2339}\
#{IF2_IR_ILKN_1_MAC_CFG_6_P2  2376}\

set TM_DMA_IND_ADDR 5261
set TM_DMA_IND_CMD  5260
set TM_ODMA_STAT0   5308

# mem block 35
set TM_MEM {{TM_OQ_CHNL_STS_P2 92} {TM_OQ_EA_IF_STS_L0 88} {TM_OQ_EA_P_STS_L1 87} }

# 
# 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 map_intf_to_name { intf_id } {
    set intf_name "intf_id_$intf_id\_unknown"
    if { $intf_id < 10 } {
        set intf_name "XAUI-$intf_id"
    } elseif { $intf_id == 10 } {
        set intf_name "Interlaken-0"
    } elseif { $intf_id == 11 } {
        set intf_name "Interlaken-0"
    } elseif { $intf_id == 12 } {
        set intf_name "Interlaken-2"
    } elseif { $intf_id > 12 && $intf_id < 16 } {
        set intf_name "Reserved"
    } elseif { $intf_id >= 16 && $intf_id <= 39 } {
        set id [expr $intf_id - 16]
        set intf_name "SGMII-$id"
    } elseif { $intf_id >= 40 && $intf_id <= 63 } {
        set id [expr $intf_id - 16]
        set intf_name "QSGMII-$id"
    } elseif { $intf_id == 64 } {
        set intf_name "HostSMGII-0"
    } elseif { $intf_id == 65 } {
        set intf_name "HostSMGII-1"
    } 
    return $intf_name
}

proc check_tm_dma_stat0_change { np_id } {
    global TM_DMA_IND_ADDR
    global TM_DMA_IND_CMD
    global TM_ODMA_STAT0

    set out ""
    if { ![catch {set out [exec show_prm_server_ltrace -N | grep "ODMA_STAT0 $np_id"]} fid ] } {
        # puts $out
    } else {
        puts "Initial value for odma_stat0 is not available to compare"
        return
    }

    set out [split $out "\n"]
    foreach entry $out {
        if { [regexp "ODMA_STAT0" $entry] } {
            # if we have an entry, store the info
            set index [lindex $entry end-1]
            set value [lindex $entry end]
            # store the index and value in associative array
            set initial_data($index) $value
        }
    }

    if {![array exist initial_data]} {
        puts "Initial value for odma_stat0 is not available to compare"
        return
    }

    # go through and compare all the odma_stat0 entries
    for {set i 0 } { $i < 80 } { incr i } { 
        exec show_np -e $np_id -r reg=$TM_DMA_IND_ADDR,val=$i,WR
        exec show_np -e $np_id -r reg=$TM_DMA_IND_CMD,val=0x10,WR
        set data [get_reg_value $np_id $TM_ODMA_STAT0]
        set current_value [ expr { $data & 0x3ff } ]
        if {[info exists initial_data($i)] } {
            set initial_value [ expr {$initial_data($i) & 0x3ff}]
        }  else {
            set initial_data($i) NOT_AVAIL
            set initial_value $initial_data($i)
        }     
        # compare against initial value
        if {$current_value != $initial_value} {
            puts "TM_ODMA_STAT0($i) initial=$initial_data($i), modified=$data"
        }
    }
}


proc compare_tm_dma_stat { np_id1 np_id2 } {
  #EZapiRegId_TM_DMA_IND_CMD,                                        /*  5260 */
  #EZapiRegId_TM_DMA_IND_ADDR,                                       /*  5261 */
  #TM_ODMA_STAT0   5308

    for {set i 0 } { $i < 80 } { incr i } { 
      exec show_np -e $np_id1 -r reg=5261,val=$i,WR
      exec show_np -e $np_id1 -r reg=5260,val=0x10,WR
      set data1 [get_reg_value $np_id1 5308]

      exec show_np -e $np_id2 -r reg=5261,val=$i,WR
      exec show_np -e $np_id2 -r reg=5260,val=0x10,WR
      set data2 [get_reg_value $np_id2 5308]
      set data1 [ expr { $data1 & 0x3ff } ]
      set data2 [ expr { $data2 & 0x3ff } ]

      if {$data1 != $data2} {
          puts "$i: TM_DMA_STAT0 NP=$np_id1 $data1, NP=$np_id2 $data2"
      }
    }
}

proc get_tm_dma_stat { np_id1 } {
  #EZapiRegId_TM_DMA_IND_CMD,                                        /*  5260 */
  #EZapiRegId_TM_DMA_IND_ADDR,                                       /*  5261 */
  #TM_ODMA_STAT0   5308
    set TM_DMA_TM_IDMA_FD_FIFO_STAT_CNTR 5272
    set TM_DMA_TM_IDMA_FD_FIFO_STAT_P2 5349
    set TM_DMA_TM_IDMA_VQM_STAT_CNTR 5273

    set data1 [get_reg_value $np_id1 $TM_DMA_TM_IDMA_FD_FIFO_STAT_CNTR]
    puts "TM_DMA_TM_IDMA_FD_FIFO_STAT_CNTR (packet sent to TM) $data1\n"
    set data1 [get_reg_value $np_id1 $TM_DMA_TM_IDMA_FD_FIFO_STAT_P2]
    puts "TM_DMA_TM_IDMA_FD_FIFO_STAT_P2 $data1\n"
    set data1 [get_reg_value $np_id1 $TM_DMA_TM_IDMA_VQM_STAT_CNTR]
    puts "TM_DMA_TM_IDMA_VQM_STAT_CNTR (packet sent to video) $data1\n"

    # get the packet sent to TM
    for {set i 0 } { $i < 80 } { incr i } { 
      exec show_np -e $np_id1 -r reg=5261,val=$i,WR
      exec show_np -e $np_id1 -r reg=5260,val=0x10,WR
      set data1 [get_reg_value $np_id1 5308]

      puts "$i: TM_DMA_STAT0 NP=$np_id1 $data1"
    }
}


proc get_fin_fout { np_id } {

    set TM_OQ_FIN 5501

    if { ![catch {set data [exec show_np -e $np_id -r reg=$TM_OQ_FIN,READ,range=2 | grep reg]}] } {
        set data [split $data "\n"]
        set i 0
        foreach counter "TM_OQ_FIN__COUNTER TM_OQ_FOUT_COUNTER" {
            puts " NP=$np_id $counter [lindex $data $i]"
            incr i
        }
    }
}

proc get_tm_info { np_id } {

	set regs {{PRS_ALL_TOTAL_IN_FRAMES  3705}\
	   {PRS_ALL_TOTAL_OUT_FRAMES  3706}\
	   {RSV_ALL_TOTAL_IN_FRAMES  4035}\
	   {RSV_ALL_TOTAL_OUT_FRAMES 4036}\
	   {MDF_ALL_TOTAL_IN_FRAMES  4322}\
	   {MDF_ALL_TOTAL_OUT_FRAMES 4323}\
	   {ICFD_TOTAL_BUDGET_STATUS 2807}\
	   {OCFD_TOTAL_BUDGET_STATUS  2862}\
	   {IDMA_NUM_OF_BUFF 2639}\
       {IDMA_STS_ERR_CNT_BIT0_P2 2755}\
       {IDMA_STS_ERR_CNT_BIT1_P2 2756}\
       {IDMA_STS_ERR_CNT_P2 2757}\
       {NET_IF2_OOB_STS 348}\
       {ECPU_IC_INT_VEC_STS_2 7523}\
       {ODMA_STS_TMID_P2 2776}\
	}

# 0 - 9
    for {set i 0 } { $i < 10 } { incr i } { 
      exec show_np -e $np_id -r reg=4932,val=$i,WR
      set data [exec show_np -e $np_id -r reg=4933,READ]
      puts "$i: RFD_CNTR_DATA $data\n"
    }

# 0x100 - 0x109
    for {set i 256 } { $i < 266 } { incr i } { 
      exec show_np -e $np_id -r reg=4932,val=$i,WR
      set data [exec show_np -e $np_id -r reg=4933,READ]
      puts "$i: RFD_CNTR_DATA $data\n"
    }

# 0x1c0 - 0x1c3
    for {set i 448 } { $i < 452 } { incr i } { 
      exec show_np -e $np_id -r reg=4932,val=$i,WR
      set data [exec show_np -e $np_id -r reg=4933,READ]
      puts "$i: RFD_CNTR_DATA $data\n"
    }

# 0x1c5
    for {set i 453 } { $i < 454 } { incr i } { 
      exec show_np -e $np_id -r reg=4932,val=$i,WR
      set data [exec show_np -e $np_id -r reg=4933,READ]
      puts "$i: RFD_CNTR_DATA $data\n"
    }

    foreach tm_reg $regs {
      set data [exec show_np -e $np_id -r reg=[lindex $tm_reg 1],READ]
      puts "[lindex $tm_reg 0] $data\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 ]
   # 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"
   }
   # the data is in the last column
   set data [lrange $data 2 end]
   regsub -all {0x} $data "" data
   return $data
}



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}]
}

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_oq_mem_data { np mem_id name} {
   global MAX_INTF
   puts " NP=$np, memory_name=$name memory_id=$mem_id"

   # 
   # get port mapping so we can check to see if we have packets in an undefined interface
   #
   get_port_mapping port_map $np

   set data ""
   for { set interface_number 0 } { $interface_number < $MAX_INTF } { incr interface_number } {


       if {[info exists port_map($interface_number)] } {
           set port_map_entry $port_map($interface_number)
       } else {
           set port_map_entry "- UNDEFINED"
       }

       #set start_addr [ expr { $interface_number * 4 } ]
	   set data [ exec show_np -e $np -m mem=$mem_id,start=$interface_number,length=4 | grep x ]
       #puts "reading $np -m mem=$mem_id,start=$start_addr,length=4"
       #puts "raw data=$data"
	   if {[regexp "fail" $data]} {
		  puts "raw data = $data"
		  puts "failed to read mem_id=$mem_id, np=$np, interface_number=$interface_number"
		  return "failed"
	   }
	   # the data is in the last column
	   set temp [lindex $data end-3]
	   lappend temp [lindex $data end-2]
	   lappend temp [lindex $data end-1]
	   lappend temp [lindex $data end]
       set data $temp
	   regsub -all {0x} $data "" data
	   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 data [byte_swap_32 $_data]
       set intf_name [map_intf_to_name $interface_number]

#puts "ifid=$interface_number data=$data"
	   # print_data $intf_name\-ifid_$interface_number $data

       # now decode the info
       # bit 4-6 = queue counter for priority 0 traffic
       # bit 8-10 = queue counter for priority 1 traffic
       # bit 12-14 = queue counter for priority 2 traffic
       # bit 16-18 = queue counter for priority 2 traffic
       # bits 20-23 
       #if { $data > 0 } {
	   #    print_data $intf_name\-ifid_$interface_number 0x[format %x $data]
       #}
       set queue_counter [expr { [expr {$data >> 4 }] & 7}]
       if {$queue_counter > 0} {
           print_data $intf_name\-ifid_$interface_number 0x[format %x $data]
           puts "        queue_counter for priority 0 = $queue_counter, port_map=$port_map_entry"
       }
       set queue_counter [expr { [expr {$data >> 8 }] & 7}]
       if {$queue_counter > 0} {
           print_data $intf_name\-ifid_$interface_number 0x[format %x $data]
           puts "        queue_counter for priority 1 = $queue_counter, port_map=$port_map_entry"
       }
       set queue_counter [expr { [expr {$data >> 12 }] & 7}]
       if {$queue_counter > 0} {
           print_data $intf_name\-ifid_$interface_number 0x[format %x $data]
           puts "        queue_counter for priority 2 = $queue_counter, port_map=$port_map_entry"
       }
       set queue_counter [expr { [expr {$data >> 16 }] & 7}]
       if {$queue_counter > 0} {
           print_data $intf_name\-ifid_$interface_number 0x[format %x $data]
           puts "        queue_counter for priority 3 = $queue_counter, port_map=$port_map_entry"
       }
       set queue_counter [expr { [expr {$data >> 20 }] & 1 }]
 # comment out for now, causing too much output
       if {$queue_counter > 0} {
           print_data $intf_name\-ifid_$interface_number 0x[format %x $data]
           puts "        Port FC = $queue_counter, port_map=$port_map_entry"
       }
#
# test code
#
#      puts "        bits 20-23 = $queue_counter, port_map=$port_map_entry"
#     

   }
   return $data
}

proc get_if1_status_counters { np_id } {
   set NET_IF1_STATUS_SEL_P2  315
   set NET_IF1_STATUS_RX_DATA_0_P2 316
   set NET_IF1_STATUS_TX_DATA_0_P2 317
   set NET_IF1_STATUS_TX_DATA_1_P2 318
   set NET_IF1_STATUS_PIPE_0_P2  319
   set NET_IF1_STATUS_PIPE_1_P2  320


   set COUNT 64
   for { set i 0 } { $i < $COUNT } { incr i } {
	  set out [exec show_np -e $np_id -r reg=$NET_IF1_STATUS_SEL_P2,val=$i,WR]
      # now read the values
      set out [get_reg_value $np_id $NET_IF1_STATUS_RX_DATA_0_P2]
      if { $out > 0 } {
          set count [ expr { $out & 0xffff } ] 
          set overflow_error [ expr { $out >> 16 } ] 
          set overflow_error [ expr { $overflow_error & 0xff } ] 
          set overflow_discard [ expr { $out >> 24 } ] 
          puts " Rx FIFO (index=$i, data=$out)  RX = $count, overflow error = $overflow_error, \
                 overflow_discard = $overflow_discard"
      }
      set out [get_reg_value $np_id $NET_IF1_STATUS_TX_DATA_0_P2]
      if { $out > 0 } {
          set count [ expr { $out & 0xffff } ] 
          set frame_count [ expr { $out >> 16 } ] 
          puts " Tx FIFO (index=$i, data=$out)  TX = $count, Frame counter = $frame_count"
      }
      set out [get_reg_value $np_id $NET_IF1_STATUS_TX_DATA_1_P2]
      if { $out > 0 } {
          set count [ expr { $out & 0xff } ] 
          puts " Rate Limit FIFO (index=$i, data=$out)  rate-limit = $count"
      }
   }

   set out [get_reg_value $np_id $NET_IF1_STATUS_PIPE_0_P2]
   puts "NET_IF1_STATUS_PIPE_0_P2 = $out"
   set out [get_reg_value $np_id $NET_IF1_STATUS_PIPE_1_P2]
   puts "NET_IF1_STATUS_PIPE_0_P2=$out"
}

proc get_oq_ea_mem_data { np mem_id name} {

   puts " NP=$np, memory_name=$name memory_id=$mem_id"

   set entity_max 32
   if {[regexp "TM_OQ_EA_P_STS" $name]} {
      set entity_max 256
   }

   set data ""
   for { set entity 0 } { $entity < $entity_max } { incr entity } {
       #set start_addr [ expr { $entity * 8 } ]
	   set data [ exec show_np -e $np -m mem=$mem_id,start=$entity,length=8 | grep 0x | grep -v start]
       #puts "reading $np -m mem=$mem_id,start=$entity,length=8"
	   if {[regexp "fail" $data]} {
		  puts "raw data = $data"
		  puts "failed to read mem_id=$mem_id, np=$np, entity=$entity"
		  return "failed"
	   }
	   # the data is in the last column
	   set data [lrange $data 2 end]

	   regsub -all {0x} $data "" data
	   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 data [byte_swap_32 $_data]
	   # print_data $name $data

#puts "data($entity) = $data"

       # 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 schedule_status [expr { $data & 0x7 }]
       if {$data != 0 } {
	       print_data $name 0x[format %x $data]
		   if {$schedule_status == 0} {
			   puts "        $name (entity=$entity) fc_state = allow all"
		   } elseif {$schedule_status == 1} {
			   puts "        $name (entity=$entity) fc_state = allow 0-2"
 set ERROR_ENCOUNTERED 1
		   } elseif {$schedule_status == 2} {
			   puts "        $name (entity=$entity) fc_state = allow 0-1"
 set ERROR_ENCOUNTERED 1
		   } elseif {$schedule_status == 3} {
			   puts "        $name (entity=$entity) fc_state = allow 0"
 set ERROR_ENCOUNTERED 1
		   } elseif {$schedule_status == 4} {
			   puts "        $name (entity=$entity) fc_state = stopped"
 set ERROR_ENCOUNTERED 1
		   }
		   set queue_counter [expr { [expr { $data >> 3 }] & 0x3ffff}]
		   if {$queue_counter > 0 } {
			  puts "        $name (entity=$entity) current actual counter=$queue_counter"
		   }
       } 
   }
}

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 stop_tm { np_id } {
   # 1. block new incoming QIN requests (halt incoming and scheduling requests)
   #    
  set TM_QC_QC_CONF2_P2 5592
  set TM_QC_QC_CONF     5572
  set TM_SC_L01_IF_FSM  5952
  set TM_SC_L01_PORT_FSM  5977
  set TM_OQ_SM_CFG      5476

  set TM_SC_L234_0_CLASS_FSM 6125
  set TM_SC_L234_1_CLASS_FSM 6360
  set TM_SC_L234_2_CLASS_FSM 6595
  set TM_SC_L234_3_CLASS_FSM 6830
  set TM_SC_L234_0_SUB_FSM   6171
  set TM_SC_L234_1_SUB_FSM   6406
  set TM_SC_L234_2_SUB_FSM   6641
  set TM_SC_L234_3_SUB_FSM   6876
  set TM_SC_L234_0_FLOW_FSM  6223
  set TM_SC_L234_1_FLOW_FSM  6458
  set TM_SC_L234_2_FLOW_FSM  6693
  set TM_SC_L234_3_FLOW_FSM  6928

  # set QC_CONF2 
  set data [get_reg_data $np_id $TM_QC_QC_CONF2_P2 TM_QC_QC_CONF2_P2]
  set data [expr {$data | 96} ]
  exec show_np -e $np_id -r reg=$TM_QC_QC_CONF2_P2,val=$data,WR
  set data [get_reg_data $np_id $TM_QC_QC_CONF2_P2 TM_QC_QC_CONF2_P2 ]

  # set QC_CONF 
  set data [get_reg_data $np_id $TM_QC_QC_CONF TM_QC_QC_CONF]
  set data [expr {$data & 0xfffffff0} ]
  exec show_np -e $np_id -r reg=$TM_QC_QC_CONF,val=$data,WR
  set data [get_reg_data $np_id $TM_QC_QC_CONF TM_QC_QC_CONF ]

  # set TM_SC_L01_IF_FSM
  set data [get_reg_data $np_id $TM_SC_L01_IF_FSM TM_SC_L01_IF_FSM]
  set data [expr {$data & 0xfffffff0} ]
  exec show_np -e $np_id -r reg=$TM_SC_L01_IF_FSM,val=$data,WR
  set data [get_reg_data $np_id $TM_SC_L01_IF_FSM TM_SC_L01_IF_FSM ]

  # set TM_SC_L01_PORT_FSM 
  set data [get_reg_data $np_id $TM_SC_L01_PORT_FSM TM_SC_L01_PORT_FSM]
  set data [expr {$data & 0xfffffff0} ]
  exec show_np -e $np_id -r reg=$TM_SC_L01_PORT_FSM,val=$data,WR
  set data [get_reg_data $np_id $TM_SC_L01_PORT_FSM TM_SC_L01_PORT_FSM ]

  # set TM_OQ_SM_CFG
  set data [get_reg_data $np_id $TM_OQ_SM_CFG TM_OQ_SM_CFG]
  exec show_np -e $np_id -r reg=$TM_OQ_SM_CFG,val=0,WR
  set data [get_reg_data $np_id $TM_OQ_SM_CFG TM_OQ_SM_CFG ]

  # read sub,class FSM 

  set FSMs {6125 6360 6595 6830 6171 6406 6641 6876}
  puts "--- Setting Class and Sub FSM ---"
  foreach FSM $FSMs {
      puts "   --- REG_ID = $FSM ---"
      set data [get_reg_data  $np_id $FSM FSM_CLASS_SUB]
      set data [expr {$data & 0xffffffe0} ]
      exec show_np -e $np_id -r reg=$FSM,val=$data,WR
      set data [get_reg_data $np_id $FSM FSM_CLASS_SUB ]
  }

  set FSMs {6223 6458 6693 6928}
  puts "--- Setting Flow FSM ---"
  foreach FSM $FSMs {
      puts "   --- REG_ID = $FSM ---"
      set data [get_reg_data $np_id $FSM FSM_FLOW]
      set data [expr {$data & 0xfffffff0} ]
      exec show_np -e $np_id -r reg=$FSM,val=$data,WR
      set data [get_reg_data $np_id $FSM FSM_FLOW ]
  }

  return
}

if {[regexp "stop_tm" $param2]} {
   foreach np_id $np_ids {
      stop_tm $np_id
   }
   return
}

set ERROR_ENCOUNTERED 0

if {[regexp "poll_tm_mi" $param2]} {
    set TM_MI_TM_MI_ADDR 7046
    set TM_MI_TMMI_STAT_CNTS2_P2 7170
    set TM_MI_TMMI_STAT_CNTS8_P2 7175

    foreach np_id $np_ids {
		for {set i 0 } { $i < 4 } { incr i } { 
		  exec show_np -e $np_id -r reg=$TM_MI_TM_MI_ADDR,val=$i,WR
		  set data [exec show_np -e $np_id -r reg=$TM_MI_TMMI_STAT_CNTS2_P2,READ]
		  puts "$i: TM_MI_TMMI_STAT_CNTS2_P2 $data\n"
		  set data [exec show_np -e $np_id -r reg=$TM_MI_TMMI_STAT_CNTS8_P2,READ]
		  puts "$i: TM_MI_TMMI_STAT_CNTS8_P2 $data\n"
		}
    }
    return
}


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
}


# compare dma_stats between 2 NPs
if {[regexp "comp_dma_stat" $param2]} {
   compare_tm_dma_stat [lindex $np_ids 0] [lindex $np_ids 1]
   return 
}

# get dma_stats 
if {[regexp "get_dma_stat" $param2]} {
   foreach np_id $np_ids {
      get_tm_dma_stat $np_id
      get_tm_info $np_id
   }
   return 
}

# get credits
if {[regexp "credit" $param2]} {
   set TM_SC_L01_IF_CREDITS    173
   set TM_SC_L01_PORT_CREDITS  181
   set TM_SC_L234_0_CLASS_WFQ  224
   set TM_SC_L234_1_CLASS_WFQ  300
   set TM_SC_L234_2_CLASS_WFQ  376
   set TM_SC_L234_3_CLASS_WFQ  452
   foreach np_id $np_ids {
      # get interface credits for l0
      # there are 32 interfaces
      puts "   ------ INTERFACE L0 CREDITS -------"
      puts "b87-80 = wfq credits 3, b79-72 = wfq credits 2, b71-64 = wfq credits 1"
      puts "b63-56 = wfq credits 0, b55-28 = PIR credits, b27-0 = CIR credits"
      for {set i 0} { $i < 32} { incr i }  {
         set data [get_mem_data $np_id $TM_SC_L01_IF_CREDITS 12 $i]
         set bits ""
         foreach byte $data {
            append bits "[byte2bits 0x$byte] "
         }
         set data [string trimleft $data]
         puts "entity=$i, $data: $bits"
      }
      
   }
   # get port credits for l1
   # there are 32 interfaces
   foreach np_id $np_ids {
      # get interface credits for l0
      # there are 32 interfaces
      puts "   ------ PORT L1 CREDITS -------"
      puts "b87-80 = wfq credits 3, b79-72 = wfq credits 2, b71-64 = wfq credits 1"
      puts "b63-56 = wfq credits 0, b55-28 = PIR credits, b27-0 = CIR credits"
      for {set i 0} { $i < 256} { incr i }  {
         set data [get_mem_data $np_id $TM_SC_L01_PORT_CREDITS 12 $i]
         set bits ""
         foreach byte $data {
            append bits "[byte2bits 0x$byte] "
         }
         set data [string trimleft $data]
         puts "entity=$i, $data: $bits"
      }
      
   }
   # get class wfq credits for l3
   # there are 2048 per chunk
   foreach np_id $np_ids {
      puts "\n   ------ CLASS WFQ CREDITS -------"

      puts "   CREDITS_0_0     b7:0    8/10/16 bits per counter, 16/8 counters = 128 bits"
      puts "   CREDITS_0_1     b15:8           0x0     All"
      puts "   CREDITS_0_2     b23:16          0x0     All"
      puts "   CREDITS_0_3     b31:24          0x0     All"
      puts "   CREDITS_1_0     b39:32          0x0     All"
      puts "   CREDITS_1_1     b47:40          0x0     All"
      puts "   CREDITS_1_2     b55:48          0x0     All"
      puts "   CREDITS_1_3     b63:56          0x0     All"
      puts "   CREDITS_2_0     b71:64          0x0     All"
      puts "   CREDITS_2_1     b79:72          0x0     All"
      puts "   CREDITS_2_2     b87:80          0x0     All"
      puts "   CREDITS_2_3     b95:88          0x0     All"
      puts "   CREDITS_3_0     b103:96         0x0     All"
      puts "   CREDITS_3_1     b111:104                0x0     All"
      puts "   CREDITS_3_2     b119:112                0x0     All"
      puts "   CREDITS_3_3     b127:120                0x0     All"
      puts "   FSIGN_E0_P0     b128    entity 0 in the nibble(out of four) and the initialized fsign bit to priority 0"
      puts "   (and so on...)  0x0     All"
      puts "   FSIGN_E0_P1     b129            0x0     All"
      puts "   FSIGN_E0_P2     b130            0x0     All"
      puts "   FSIGN_E0_P3     b131            0x0     All"
      puts "   FSIGN_E1_P0     b132            0x0     All"
      puts "   FSIGN_E1_P1     b133            0x0     All"
      puts "   FSIGN_E1_P2     b134            0x0     All"
      puts "   FSIGN_E1_P3     b135            0x0     All"
      puts "   FSIGN_E2_P0     b136            0x0     All"
      puts "   FSIGN_E2_P1     b137            0x0     All"
      puts "   FSIGN_E2_P2     b138            0x0     All"
      puts "   FSIGN_E2_P3     b139            0x0     All"
      puts "   FSIGN_E3_P0     b140            0x0     All"
      puts "   FSIGN_E3_P1     b141            0x0     All"
      puts "   FSIGN_E3_P2     b142            0x0     All"
      puts "   FSIGN_E3_P3     b143            0x0     All\n"



      for {set i 0} { $i < 2048} { incr i }  {
         set data [get_mem_data $np_id $TM_SC_L234_0_CLASS_WFQ 20 $i]
         #set bits ""
         #foreach byte $data {
         #   append bits "[byte2bits 0x$byte] "
         #}
         set data [string trimleft $data]
         puts "entity=$i (chunk0), $data"
         set data [get_mem_data $np_id $TM_SC_L234_1_CLASS_WFQ 20 $i]
         set data [string trimleft $data]
         puts "entity=$i (chunk1), $data"
         set data [get_mem_data $np_id $TM_SC_L234_2_CLASS_WFQ 20 $i]
         set data [string trimleft $data]
         puts "entity=$i (chunk2), $data"
         set data [get_mem_data $np_id $TM_SC_L234_3_CLASS_WFQ 20 $i]
         set data [string trimleft $data]
         puts "entity=$i (chunk3) $data\n"

      }
      
   }


   return 
}


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

#
#  MAIN
#

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

foreach np_id $np_ids {
    #get_rfd_counter $np_id 

    #
    # get the FIN/FOUT counters
    #
    get_fin_fout $np_id

	# read content of registers
	foreach tm_reg $TM_REG {
		get_reg_data $np_id [lindex $tm_reg 1] [lindex $tm_reg 0]
	}
	foreach tm_mem $TM_MEM {

       if {[regexp "TM_OQ_CHNL_STS_P2" $tm_mem]} {
		  get_oq_mem_data $np_id [lindex $tm_mem 1] [lindex $tm_mem 0]
       } else {
		  get_oq_ea_mem_data $np_id [lindex $tm_mem 1] [lindex $tm_mem 0]
       }
	}
    check_tm_dma_stat0_change $np_id
    #
    # read the if1 rx/tx stats
    #
    get_if1_status_counters $np_id
    #
    # check for any OOB from logfile
    #
    if { ![catch {set out [exec show_local_log| grep "prm_oob_status_check_action"]} fid ] } {
        puts $out
    } else {
        puts "No OOB logs were observed"
    }

}


# 
# If detected error, we dump more detailed info
#

foreach np_id $np_ids {
	if { $ERROR_ENCOUNTERED == 1 } {
 		get_tm_dma_stat $np_id
 		get_tm_info $np_id

		set TM_MI_TM_MI_ADDR 7046
		set TM_MI_TMMI_STAT_CNTS2_P2 7170
		set TM_MI_TMMI_STAT_CNTS8_P2 7175

	puts "  >>>TM_MI_TM_STAT<<<"
		foreach np_id $np_ids {
			for {set i 0 } { $i < 4 } { incr i } { 
			  exec show_np -e $np_id -r reg=$TM_MI_TM_MI_ADDR,val=$i,WR
			  set data [exec show_np -e $np_id -r reg=$TM_MI_TMMI_STAT_CNTS2_P2,READ]
			  puts "$i: TM_MI_TMMI_STAT_CNTS2_P2 $data\n"
			  set data [exec show_np -e $np_id -r reg=$TM_MI_TMMI_STAT_CNTS8_P2,READ]
			  puts "$i: TM_MI_TMMI_STAT_CNTS8_P2 $data\n"
			}
		}
		set ODMA_STS_SEL_P2 2774
		set ODMA_STS_DATA_P2 2775
		set dataw [exec show_np -e $np_id -r reg=$ODMA_STS_SEL_P2,val=30,WR]
		set data [exec show_np -e $np_id -r reg=$ODMA_STS_DATA_P2,READ]
		puts "  >>> ODMA_STS_DATA_P2 = $dataw\n $data "

	   set NET_IF1_STATUS_SEL_P2 315 
	   set NET_IF1_STATUS_TX_DATA_0_P2 317 
	   set NET_IF1_STATUS_TX_DATA_1_P2 318 
		set dataw [exec show_np -e $np_id -r reg=$NET_IF1_STATUS_SEL_P2,val=4,WR]
		set data [exec show_np -e $np_id -r reg=$NET_IF1_STATUS_TX_DATA_0_P2,READ]
		puts "  >>> ILKN0 TX FIFO INFO <<<"
		puts "  >>> NET_IF1_STATUS_TX_DATA_0_P2 = $dataw\n $data "
		set data [exec show_np -e $np_id -r reg=$NET_IF1_STATUS_TX_DATA_1_P2,READ]
		puts "  >>> NET_IF1_STATUS_TX_DATA_1_P2 = $data \n"


	# get OCFD_QUEUE_STATUS_TABLE

	   set CMEM_OCFD_QUEUE_STATUS_TAB 8
       set entity_max 32

       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=$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=$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 "    >>> 0x[format %x $high_word]:[format %x $low_word]"
		}


	}
}

set date [exec date]


