( ESNUG 210 Item 3 ) ---------------------------------------------- [2/24/95]

From: sgolson@trilobyte.com (Steve Golson)
Subject: Synopsys Design Compiler Watchlog Utility

Hi John,

Here is a favorite utility of mine.  It monitors the log file being generated
by any process and annotates it with the elapsed CPU time.  For Synopsys runs
it generates a CPU timestamped output like:

         Beginning Resource Allocation  (constraint driven)
         -----------------------------
         Allocating blocks in 'r1'
  25:03	 Allocating blocks in 'fifo'
	
         Beginning Mapping Optimizations  (Medium effort)
         -------------------------------
  26:02	 Structuring 'fifo'
  32:33	 Mapping 'fifo'

In this example you can see that "Structuring 'fifo'" took (32:33 - 26:02)
6:31 CPU minutes.  (It's great for long compiles; you can see what soaks up
all the time!)

Start watchlog after you start your dc_shell run, and pass it the name
of your logfile and the PID:

	csh> dc_shell -f myscript.ss >& myscript.log &
	[1] 1234
	csh> watchlog myscript.log 1235 >& myscript.watchlog &

Note that the PID returned by csh when you start up dc_shell is the PID of
dc_shell (makes sense!) but the process that we want to watch is
dc_shell_exec, which is typically the next PID in sequence.  Your OS may vary.
(To be sure you could invoke dc_shell_exec directly.)

Watchlog builds a sed script; after the monitored process exits it runs "sed"
on the log file and spits the resulting watchlog file to stdout.

Comments, bug reports, etc. are much appreciated.

  - Steve Golson
    Trilobyte Systems


#! /bin/sh
#
# watchlog 1.5  -- annotates a logfile w/cpu time of the process creating it
#
# Usage: watchlog logfile pid [hostname] [sleep_time]
#   where
#     pid = id of the process to monitor
#     logfile = the logfile being created by the process
#     hostname = host running the process to monitor (optional)
#     sleep_time = seconds to sleep between timestamps (defaults to 60)
#
# watchlog monitors the logfile length and the elapsed cpu time of the
# process.  It generates a sed script that is used to create the annotated
# log after the monitored process exits.

myname="`basename $0`"

# get args
if [ $# -lt 2 ]
then
	echo "Usage: $myname logfile pid [hostname] [sleep_time]" 1>&2
	exit 1
fi
logfile=$1
pid=$2
if [ $# -ge 3 -a "$3" ]
then
	hostname=$3
fi
if [ $# -ge 4 ]
then
	# sleep_time must be a positive integer
	expr "$4" : '[0-9]*[0-9]$' > /dev/null || {
		echo "$myname: bad sleep_time value: $4" 1>&2
		exit 1
		}
fi

# time in seconds between ps runs, defaults to 60
sleep_time=${4-60}

# file where the sed commands go
sed_script="${myname}.$$.sed"

# the ps command, using rsh if hostname exists
ps="${hostname+rsh -n} ${hostname-} /usr/bin/ps $pid"

# make a tab character to use with sed
tab=`echo 't' | tr 't' '\011'`

# make sure we can read logfile
test -r $logfile || {
	echo "$myname: cannot read $logfile" 1>&2
	exit 1
	}

# make sure ps works
$ps > /dev/null &&
ps_info=`$ps | egrep -v "PID"` &&
test "$ps_info" || {
	echo "$myname: $ps failed" 1>&2
	exit 1
	}

# initialize the sed script
echo "# sed script for: $myname $@" > $sed_script &&
echo "# created on `date`" >> $sed_script || {
	echo "$myname: cannot write to $sed_script" 1>&2
	exit 1
	}

### done with initialization
# prepend a tab to every line of logfile
echo "s/^/${tab}/" >> $sed_script || {
	echo "$myname: cannot write to $sed_script" 1>&2
	exit 1
	}

# setup prev_line_num for first time through the while loop
wc_result=`wc -l $logfile`
prev_line_num=`expr "$wc_result" : ' *\([0-9]*\)'`

while
	# while the process still exists
	ps_info=`$ps | egrep -v "PID"`
	test "$ps_info"
do
	# get the number of lines in logfile
	wc_result=`wc -l $logfile`
	line_num=`expr "$wc_result" : ' *\([0-9]*\)'`

	# get the cpu time used by the process so far
	time=`expr "$ps_info" : '.*[^0-9]\([0-9]*:[0-9][0-9]\).*'`

	# format it nicely to fit in 8 spaces "1234:56 "
	time=`expr "    ${time}" : \
		'.*\([ 0-9][ 0-9][ 0-9][ 0-9]:[0-9][0-9]\)'`

	# if logfile has grown
	if expr "$line_num" != "$prev_line_num" > /dev/null
	then
		# mark previous line with current time
		echo "${prev_line_num}s/^/${time}/" >> $sed_script || {
			echo "$myname: cannot write to $sed_script" 1>&2
			exit 1
			}
		# time has been used
		time=""
	fi

	prev_line_num=$line_num

	sleep $sleep_time
done

# process has finished

# if time hasn't been used then put it on the last line found
if [ "$time" ]
then
	echo "${line_num}s/^/${time}/" >> $sed_script || {
		echo "$myname: cannot write to $sed_script" 1>&2
		exit 1
		}
fi

# run sed to make annotated logfile
# unfortunately sed has a bogus 200 command limit, so...

# split up sed_script
split -190 $sed_script ${sed_script}.

# build up a pipe of multiple sed commands
notfirst=""
for file in `/bin/ls ${sed_script}.??`
do
	if [ "$notfirst" ]
	then
		# add to the pipe
		command="$command | sed -f $file"
	else
		# first sed in the pipe, so add logfile
		command="sed -f $file $logfile"
		notfirst="true"
	fi
done

# execute the pipe
eval $command

# cleanup
/bin/rm -f $sed_script ${sed_script}.??

exit 0



 Sign up for the DeepChip newsletter.
Email
 Read what EDA tool users really think.


Feedback About Wiretaps ESNUGs SIGN UP! Downloads Trip Reports Advertise

"Relax. This is a discussion. Anything said here is just one engineer's opinion. Email in your dissenting letter and it'll be published, too."
This Web Site Is Modified Every 2-3 Days
Copyright 1991-2024 John Cooley.  All Rights Reserved.
| Contact John Cooley | Webmaster | Legal | Feedback Form |

   !!!     "It's not a BUG,
  /o o\  /  it's a FEATURE!"
 (  >  )
  \ - / 
  _] [_     (jcooley 1991)