1#!/bin/tcsh -f 2#---------------------------------------------------------- 3# Static timing analysis script using OpenTimer 4#---------------------------------------------------------- 5# Tim Edwards, 10/02/18, for Open Circuit Design 6#---------------------------------------------------------- 7 8# Split out options from the main arguments 9set argline=(`getopt "ad" $argv[1-]`) 10 11set options=`echo "$argline" | awk 'BEGIN {FS = "-- "} END {print $1}'` 12set cmdargs=`echo "$argline" | awk 'BEGIN {FS = "-- "} END {print $2}'` 13set argc=`echo $cmdargs | wc -w` 14 15if ($argc == 2) then 16 set argv1=`echo $cmdargs | cut -d' ' -f1` 17 set argv2=`echo $cmdargs | cut -d' ' -f2` 18else 19 echo "Usage: opentimer.sh [options] <project_path> <source_name>" 20 echo " where" 21 echo " <project_path> is the name of the project directory containing" 22 echo " a file called qflow_vars.sh." 23 echo " <source_name> is the root name of the verilog file" 24 echo " [options] are:" 25 echo " -d use delay file to back-annotate wire delays" 26 echo " -a append to log file (do not overwrite)" 27 exit 1 28endif 29 30set dodelays=0 31set append=0 32 33foreach option (${argline}) 34 switch (${option}) 35 case -d: 36 set dodelays=1 37 breaksw 38 case -a: 39 set append=1 40 breaksw 41 case --: 42 break 43 endsw 44end 45 46set projectpath=$argv1 47set sourcename=$argv2 48set rootname=${sourcename:h} 49 50# This script is called with the first argument <project_path>, which should 51# have file "qflow_vars.sh". Get all of our standard variable definitions 52# from the qflow_vars.sh file. 53 54if (! -f ${projectpath}/qflow_vars.sh ) then 55 echo "Error: Cannot find file qflow_vars.sh in path ${projectpath}" 56 exit 1 57endif 58 59source ${projectpath}/qflow_vars.sh 60source ${techdir}/${techname}.sh 61cd ${projectpath} 62if (-f project_vars.sh) then 63 source project_vars.sh 64endif 65 66if (! ${?opentimer_options} ) then 67 set opentimer_options = "" 68endif 69 70if (!($?logdir)) then 71 set logdir=${projectpath}/log 72endif 73mkdir -p ${logdir} 74if ($dodelays == 1) then 75 set lastlog=${logdir}/route.log 76 set synthlog=${logdir}/post_sta.log 77else 78 set lastlog=${logdir}/place.log 79 set synthlog=${logdir}/sta.log 80 rm -f ${logdir}/route.log >& /dev/null 81endif 82rm -f ${logdir}/post_sta.log >& /dev/null 83rm -f ${logdir}/migrate.log >& /dev/null 84rm -f ${logdir}/drc.log >& /dev/null 85rm -f ${logdir}/lvs.log >& /dev/null 86rm -f ${logdir}/gdsii.log >& /dev/null 87set date=`date` 88 89if ( $append == 0 ) then 90 rm -f ${synthlog} >& /dev/null 91 touch ${synthlog} 92 echo "Qflow static timing analysis logfile created on $date" > ${synthlog} 93else 94 touch ${synthlog} 95 echo "\nQflow static timing analysis logfile appended on $date" >> ${synthlog} 96endif 97 98# Check if last line of log file says "error condition" 99set errcond = `tail -1 ${lastlog} | grep "error condition" | wc -l` 100if ( ${errcond} == 1 ) then 101 echo "Synthesis flow stopped on error condition. Static timing analysis" 102 echo "will not proceed until error condition is cleared." 103 exit 1 104endif 105 106# Prepend techdir to libertyfile unless libertyfile begins with "/" 107# Use "libertymax" and "libertymin" for maximum and minimum timing, 108# respectively, unless they don't exist, in which case use "libertyfile" 109# for both. 110 111set abspath=`echo ${libertyfile} | cut -c1` 112if ( "${abspath}" == "/" ) then 113 set libertypath=${libertyfile} 114 if ( ${?libertymax} ) then 115 set libertymaxpath=${libertymax} 116 else 117 set libertymaxpath=${libertyfile} 118 endif 119 if ( ${?libertymin} ) then 120 set libertyminpath=${libertymin} 121 else 122 set libertyminpath=${libertyfile} 123 endif 124else 125 set libertypath=${techdir}/${libertyfile} 126 if ( ${?libertymax} ) then 127 set libertymaxpath=${techdir}/${libertymax} 128 else 129 set libertymaxpath=${techdir}/${libertyfile} 130 endif 131 if ( ${?libertymin} ) then 132 set libertyminpath=${techdir}/${libertymin} 133 else 134 set libertyminpath=${techdir}/${libertyfile} 135 endif 136endif 137 138# Add hard macros 139 140set hardmacrolibs = "" 141if ( ${?hard_macros} ) then 142 foreach macro_path ( $hard_macros ) 143 foreach file ( `ls ${sourcedir}/${macro_path}` ) 144 if ( ${file:e} == "lib" ) then 145 set hardmacrolibs="${hardmacrolibs} ${sourcedir}/${macro_path}/${file}" 146 endif 147 break 148 end 149 end 150endif 151 152#---------------------------------------------------------- 153# Done with initialization 154#---------------------------------------------------------- 155 156# Check if last line of log file says "error condition" 157set errcond = `tail -1 ${lastlog} | grep "error condition" | wc -l` 158if ( ${errcond} == 1 ) then 159 echo "Synthesis flow stopped on error condition. Timing analysis will not" 160 echo "proceed until error condition is cleared." 161 exit 1 162endif 163 164cd ${layoutdir} 165 166#------------------------------------------------------------------ 167# Generate the static timing analysis results 168#------------------------------------------------------------------ 169 170if ($dodelays == 1) then 171 # Check if a .rc file exists. This file is produced by qrouter 172 # and contains delay information in nested RC pairs 173 if ( -f ${rootname}.rc ) then 174 175 # Run rc2dly 176 echo "Converting qrouter output to vesta delay format" |& tee -a ${synthlog} 177 echo "Running rc2dly -r ${rootname}.rc -l ${libertypath} -V ${synthdir}/${rootname}.rtl.v" \ 178 |& tee -a ${synthlog} 179 echo "-d ${rootname}.dly" |& tee -a ${synthlog} 180 ${bindir}/rc2dly -r ${rootname}.rc -l ${libertypath} \ 181 -V ${synthdir}/${rootname}.rtl.v \ 182 -d ${synthdir}/${rootname}.dly 183 184 # Run rc2dly again to get SPEF format file 185 echo "Converting qrouter output to SPEF delay format" |& tee -a ${synthlog} 186 echo "Running rc2dly -D : -r ${rootname}.rc -l ${libertypath} -V ${synthdir}/${rootname}.rtl.v" \ 187 |& tee -a ${synthlog} 188 echo "-d ${rootname}.spef" |& tee -a ${synthlog} 189 ${bindir}/rc2dly -D : -r ${rootname}.rc -l ${libertypath} \ 190 -V ${synthdir}/${rootname}.rtl.v \ 191 -d ${synthdir}/${rootname}.spef 192 193 # Translate <, >, and $ in file to _ to match the verilog. 194 if ( -f ${synthdir}/${rootname}.spef ) then 195 cat ${synthdir}/${rootname}.spef | sed \ 196 -e 's/\$/_/g' -e 's/</_/g' -e 's/>/_/g' \ 197 -e '/^\*[0-9]/s/\./_/g' \ 198 > ${synthdir}/${rootname}.spefx 199 mv ${synthdir}/${rootname}.spefx ${synthdir}/${rootname}.spef 200 endif 201 202 cd ${synthdir} 203 204 # Spot check for output file 205 if ( ! -f ${rootname}.spef || \ 206 ( -M ${rootname}.spef < -M ${layoutdir}/${rootname}.rc )) then 207 echo "rc2dly failure: No file ${rootname}.spef created." \ 208 |& tee -a ${synthlog} 209 echo "Premature exit." |& tee -a ${synthlog} 210 echo "Synthesis flow stopped due to error condition." >> ${synthlog} 211 exit 1 212 endif 213 214 else 215 echo "Error: No file ${rootname}.rc, cannot back-annotate delays!" \ 216 |& tee -a ${synthlog} 217 echo "Premature exit." |& tee -a ${synthlog} 218 echo "Synthesis flow stopped due to error condition." >> ${synthlog} 219 exit 1 220 endif 221endif 222 223cd ${synthdir} 224 225# Create a shell SDC file if one doesn't exist 226# (This remains to be done and will probably need to be done by a script) 227 228if ( -f ${rootname}.sdc ) then 229else 230 echo "Creating example SDC file for timing" |& tee -a ${synthlog} 231 cat > ${rootname}.sdc << EOF 232create_clock -name clock -period 4000 -waveform {0 2000} [get_ports clock] 233EOF 234endif 235 236# Create the input script for OpenTimer 237 238echo "Creating OpenTimer input file ${rootname}.conf" |& tee -a ${synthlog} 239cat > ${rootname}.conf << EOF 240read_celllib -min ${libertyminpath} 241read_celllib -max ${libertymaxpath} 242EOF 243 244foreach libpath ( $hardmacrolibs ) 245 cat >> ${rootname}.conf << EOF 246read_celllib ${libpath} 247EOF 248end 249 250cat >> ${rootname}.conf << EOF 251read_verilog ${rootname}.rtlbb.v 252EOF 253 254if ( $dodelays == 1 ) then 255 cat >> ${rootname}.conf << EOF 256read_spef ${rootname}.spef 257EOF 258endif 259 260cat >> ${rootname}.conf << EOF 261read_sdc ${rootname}.sdc 262report_timing 263report_path -num_paths 10000 264report_wns 265EOF 266 267echo "" 268if ($dodelays == 1) then 269 echo "Running OpenTimer static timing analysis with back-annotated extracted wire delays" \ 270 |& tee -a ${synthlog} 271else 272 echo "Running OpenTimer static timing analysis" |& tee -a ${synthlog} 273endif 274echo "ot-shell ${opentimer_options} -i ${rootname}.conf" |& tee -a ${synthlog} 275echo "" 276${bindir}/ot-shell ${opentimer_options} -i ${rootname}.conf |& tee -a ${synthlog} 277echo "" 278 279#------------------------------------------------------------ 280# Done! 281#------------------------------------------------------------ 282