File: blifanno.tcl.in

package info (click to toggle)
qflow 1.3.17%2Bdfsg.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 3,852 kB
  • sloc: ansic: 8,342; csh: 3,873; sh: 2,869; makefile: 426; tcl: 6
file content (203 lines) | stat: -rwxr-xr-x 6,931 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#!TCLSH_PATH
#---------------------------------------------------------------------------
# blifanno.tcl ---
#
# Read a BLIF file and a post-placement DEF file.  The placement stage is
# assumed to have rewired buffer trees for optimal placement, making the
# BLIF file netlist invalid.  The contents of the DEF file are used to
# back-annotate the correct buffer tree connections to the BLIF netlist.
# The output is a corrected BLIF netlist.
#
#---------------------------------------------------------------------------
namespace path {::tcl::mathop ::tcl::mathfunc}

if {$argc < 2} {
   puts stdout "Usage:  blifanno.tcl <blif_file> <def_file> \[<blif_out>\]"
   exit 0
}

puts stdout "Running blifanno.tcl"

# NOTE:  There is no scaling.  GrayWolf values are in centimicrons,
# as are DEF values (UNITS DISTANCE MICRONS 100)

set blifinname [lindex $argv 0]
set defname [lindex $argv 1]

set units 100		;# write centimicron units into the DEF file

#-----------------------------------------------------------------
# Open all files for reading and writing
#-----------------------------------------------------------------

if [catch {open $defname r} fdef] {
   puts stderr "Error: can't open file $defname for input"
   return
}

if [catch {open $blifinname r} fnet] {
   puts stderr "Error: can't open file $blifinname for input"
   return
}

if {$argc == 3} {
   set blifoutname [lindex $argv 2]
   if [catch {open $blifoutname w} fout] {
      puts stderr "Error: can't open file $blifoutname for output"
      return
   }
} else {
   set fout stdout
}

#----------------------------------------------------------------
# Read through a LEF file section that we don't care about.
#----------------------------------------------------------------

proc skip_section {leffile sectionname} {
   while {[gets $leffile line] >= 0} {
      if [regexp {[ \t]*END[ \t]+([^ \t]+)[ \t]*$} $line lmatch sectiontest] {
         if {"$sectiontest" != "$sectionname"} {
            puts -nonewline stderr "Unexpected END statement $line "
            puts stderr "while reading section $sectionname"
         }
         break
      }
   }
}

#-----------------------------------------------------------------
# Parse the NETS section of the DEF file
# Assuming this file was generated by place2def, each net
# connection should be on a separate line.
#-----------------------------------------------------------------

proc parse_nets {deffile nets} {
   upvar $nets rdict
   set ignore 0
   while {[gets $deffile line] >= 0} {
      if [regexp {[ \t]*END[ \t]+([^ \t]+)[ \t\n]*$} $line lmatch sectiontest] {
         if {"$sectiontest" == "NETS"} {
	    break
	 } else {
            puts -nonewline stderr "Unexpected END statement $line "
            puts stderr "while reading section NETS"
         }
         break
      } elseif [regexp {[ \t]*-[ \t]+([^ \t]+)} $line lmatch netname] {
	 set ignore 0
      } elseif [regexp {[ \t]*\+[ \t]+([^ \t]+)} $line lmatch option] {
	 set ignore 1
      } elseif {$ignore == 0} {
	 if [regexp {[ \t]*\([ \t]*([^ \t]+)[ \t]+([^ \t]+)[ \t]*\)[ \t\n;]*$} \
		$line lmatch instname pinname] {
	    dict set rdict ${instname}/${pinname} $netname
	 }
      }
   }
}

#-----------------------------------------------------------------
# Read the DEF file once to get the number of rows and the length
# of each row
#-----------------------------------------------------------------

puts stdout "Reading DEF file ${defname}. . ."
flush stdout

while {[gets $fdef line] >= 0} {
   if [regexp {[ \t]*COMPONENTS[ \t]+([^ \t]+)[ \t]*;} $line lmatch number] {
      skip_section $fdef COMPONENTS
   } elseif [regexp {[ \t]*SPECIALNETS[ \t]+([^ \t]+)} $line lmatch netnums] {
      skip_section $fdef SPECIALNETS
   } elseif [regexp {[ \t]*NETS[ \t]+([^ \t]+)} $line lmatch netnums] {
      set nets [dict create]
      # Parse the "NETS" section
      parse_nets $fdef nets
      # puts stdout "Done with NETS section, dict size is [dict size $nets]"
   } elseif [regexp {[ \t]*PINS[ \t]+([^ \t]+)} $line lmatch pinnum] {
      skip_section $fdef PINS
   } elseif [regexp {[ \t]*VIAS[ \t]+(.+)[ \t]*$} $line lmatch number] {
      skip_section $fdef VIAS
   } elseif [regexp {[ \t]*END[ \t]+DESIGN[ \t]*$} $line lmatch] {
      break
   } elseif [regexp {^[ \t]*#} $line lmatch] {
      # Comment line, ignore.
   } elseif ![regexp {^[ \t]*$} $line lmatch] {
      # Other things we don't care about
      set matches 0
      if [regexp {[ \t]*NAMESCASESENSITIVE} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*VERSION} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*BUSBITCHARS} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*DIVIDERCHAR} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*USEMINSPACING} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*CLEARANCEMEASURE} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*MANUFACTURINGGRID} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*UNITS} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*DESIGN} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*DIEAREA} $line lmatch] {
         incr matches
      } elseif [regexp {[ \t]*TRACKS} $line lmatch] {
         incr matches
      } else {
         puts stderr "Unexpected input in DEF file:"
         puts stdout "Line is: $line"
      }
   }
}

close $fdef

#-----------------------------------------------------------------
# Now read the BLIF netlist, and rewrite all net connections from
# the list found in the DEF file
#-----------------------------------------------------------------

set instcount [dict create]

while {[gets $fnet line] >= 0} {
   if [regexp {^[ \t]*\.gate[ \t]+([^ \t]+)[ \t]+(.*)$} \
		$line lmatch macroname rest] {
      if {[dict exists $instcount $macroname]} {
	 set iidx [dict get $instcount $macroname]
	 incr iidx
	 dict set instcount $macroname $iidx
      } else {
	 dict set instcount $macroname 1
	 set iidx 1
      }
      set gateline ".gate $macroname"
      while {[regexp {[ \t]*([^ \t]+)[ \t]*=[ \t]*([^ \t]+)[ \t]*(.*)$} \
		$rest lmatch pinname netname nextconn] > 0} {
	 if {[catch {set newnet [dict get $nets ${macroname}_${iidx}/${pinname}]}]} {
	    # NOTE:  Dangling buffer outputs (for debug) do not show up in
	    # graywolf output.  They cannot be sorted, so just copy them
	    # as they are in the original blif file.
	    set gateline "${gateline} ${pinname}=${netname}"
	 } else {
	    set gateline "${gateline} ${pinname}=${newnet}"
	 }
	 set rest $nextconn
      }
      puts $fout "$gateline"
   } else {
      puts $fout $line
   }
}

#-----------------------------------------------------------------
#-----------------------------------------------------------------

close $fnet
if {$fout != "stdout"} {close $fout}

puts stdout "Done with blifanno.tcl"