1#!/usr/local/bin/tclsh8.6 2#--------------------------------------------------------------------------- 3# annotate.tcl --- 4# 5# Read a file "antenna.out" produced by qrouter, and use this to 6# back-annotate the <project>.v verilog structural netlist for input 7# to static timing analysis. 8# 9# The "antenna.out" file contains connections made by the router to 10# antenna anchoring cells. It is solely a product of the routing and 11# should not permanently affect any netlist that becomes input to any 12# stage prior to routing (e.g., the .blif or .cel files used for 13# placement). 14# 15# The output is written to the filename specified. Input and output 16# files are opened at the same time, so do not specify the same file to 17# be overwritten. 18# 19# 5/18/2018: A file "fillcells.txt" containing all the fill cells added 20# to the design may be appended to the "antenna.out" file. Add these to 21# the netlist as well. However, antenna entries in "antenna.out" also 22# appear in "fillcells.txt", so ignore redundant entries. 23#--------------------------------------------------------------------------- 24 25namespace path {::tcl::mathop ::tcl::mathfunc} 26 27if {$argc != 3 && $argc != 4} { 28 puts stdout "Usage: annotate.tcl <antenna_file> <verilog_file> <verilog_out> [<pwrgnd_file>]" 29 exit 0 30} 31 32puts stdout "Running annotate.tcl" 33 34set antennaname [lindex $argv 0] 35set vlogname [lindex $argv 1] 36set vlogoutname [lindex $argv 2] 37 38# If an additional file name is given, it should point to the file 39# that sets vddnet and gndnet in the design (picked up from the LEF 40# files, so no need to re-parse them. 41 42if {$argc == 4} { 43 set pwrgndfile [lindex $argv 3] 44 45 if [catch {open $pwrgndfile r} fpwr] { 46 puts stderr "Can't open file $pwrgndfile for input, assuming standard names." 47 set vddnet false 48 set gndnet false 49 } else { 50 51 # Read file and evaluate the same way the other shell script files are 52 # in other of the qflow Tcl scripts (e.g., ypostproc.tcl). 53 54 while {[gets $fpwr line] >= 0} { 55 set tcmd [string map {= \ } $line] 56 eval $tcmd 57 } 58 close $fpwr 59 } 60} else { 61 set vddnet false 62 set gndnet false 63} 64 65set debug false 66 67#----------------------------------------------------------------- 68# Open antenna file for reading 69#----------------------------------------------------------------- 70 71if [catch {open $antennaname r} fant] { 72 puts stderr "Error: can't open file $antennaname for input" 73 exit 1 74} 75 76#----------------------------------------------------------------- 77# Read the antenna update file. 78#----------------------------------------------------------------- 79 80set added 0 81set changelist [dict create] 82set instlist [dict create] 83 84# NOTE: Lines in section "Unfixed antenna errors" are not nets to be 85# annotated, but a list of nets that are creating DRC antenna errors. 86# These nets are ignored. 87 88set in_unfix false 89while {[gets $fant line] >= 0} { 90 if {$in_unfix == false} { 91 if [regexp {[ \t]*Net=([^ \t]+)[ \t]+Instance=([^ \t]+)[ \t]+Cell=([^ \t]+)[ \t]+Pin=([^ \t]+)} $line lmatch netname instname cellname pinname] { 92 # Keep instances seen in a dictionary and ignore redundant entries 93 if [catch {dict get $instlist $instname}] { 94 incr added 95 dict set changelist $instname [list $netname $cellname $pinname] 96 dict set instlist $instname true 97 } 98 } 99 } 100 if [regexp {[ \t]*Unfixed antenna errors:} $line lmatch] { 101 set in_unfix true 102 } elseif [regexp {[ \t]*# Fill cell instances} $line lmatch] { 103 set in_unfix false 104 } 105} 106if {$added == 0} { 107 puts stdout "No nets needed annotating." 108 exit 0 109} 110 111close $fant ;# Done with antenna input file 112 113#----------------------------------------------------------------- 114# Open verilog files for reading and writing 115#----------------------------------------------------------------- 116 117if [catch {open $vlogname r} fvlog] { 118 puts stderr "Error: can't open file $vlogname for input" 119 exit 1 120} 121 122if [catch {open $vlogoutname w} fvout] { 123 puts stderr "Error: can't open file $vlogoutname for output" 124 exit 1 125} 126 127while {[gets $fvlog line] >= 0} { 128 if [regexp {[ \t]*endmodule} $line lmatch] { 129 # Insert the list here 130 dict for {instname netchange} $changelist { 131 set netname [lindex $netchange 0] 132 set cellname [lindex $netchange 1] 133 set pinname [lindex $netchange 2] 134 if {${pinname} != "-" && ${pinname} != ""} { 135 puts $fvout "${cellname} ${instname} ( .${pinname}(${netname}) );" 136 } else { 137 puts $fvout "${cellname} ${instname} ( );" 138 } 139 } 140 } 141 puts $fvout $line 142} 143 144close $fvlog 145close $fvout 146 147puts stdout "Done with annotate.tcl" 148exit 0 149