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