forked from ICBench/OpenSTA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
NetworkEdit.tcl
247 lines (225 loc) · 6.3 KB
/
NetworkEdit.tcl
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# OpenSTA, Static Timing Analyzer
# Copyright (c) 2022, Parallax Software, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# Network editing commands.
namespace eval sta {
proc connect_pin { net pin } {
set insts_port [parse_connect_pin $pin]
if { $insts_port == 0 } {
return 0
}
set net [get_net_warn "net" $net]
if { $net == "NULL" } {
return 0
}
lassign $insts_port inst port
connect_pin_cmd $inst $port $net
return 1
}
proc parse_connect_pin { arg } {
set path_regexp [path_regexp]
set insts_port {}
if { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Pin" } {
set pin $arg
set inst [$pin instance]
set port [$pin port]
} elseif { $object_type == "Port" } {
# Explicit port arg - convert to pin.
set pin [find_pin [get_name $arg]]
set inst [$pin instance]
set port [$pin port]
} else {
sta_error 586 "unsupported object type $object_type."
}
} else {
if {[regexp $path_regexp $arg ignore path_name port_name]} {
set inst [find_instance $path_name]
if { $inst == "NULL" } {
return 0
}
} else {
set inst [top_instance]
set port_name $arg
}
set cell [$inst cell]
set port [$cell find_port $port_name]
if { $port == "NULL" } {
return 0
}
set pin [$inst find_pin $port_name]
}
# Make sure the pin is not currently connected to a net.
if { $pin != "NULL" \
&& ![$pin is_hierarchical] \
&& [$pin net] != "NULL" } {
return 0
}
return [list $inst $port]
}
proc connect_pins { net pins } {
sta_warn 372 "connect_pins is deprecated. Use connect_pin."
# Visit the pins to make sure command will succeed.
set insts_ports [parse_connect_pins $pins]
if { $insts_ports == 0 } {
return 0
}
set net [get_net_warn "net" $net]
if { $net == "NULL" } {
return 0
}
foreach {inst port} $insts_ports {
connect_pin_cmd $inst $port $net
}
return 1
}
proc parse_connect_pins { arg } {
set path_regexp [path_regexp]
set inst_ports {}
# Copy backslashes that will be removed by foreach.
set arg [string map {\\ \\\\} $arg]
foreach obj $arg {
set inst_port [parse_connect_pin $obj]
if { $inst_port == 0 } {
return 0
}
set inst_ports [concat $inst_ports $inst_port]
}
return $inst_ports
}
################################################################
proc delete_instance { instance } {
if { [is_object $instance] } {
set object_type [object_type $instance]
if { $object_type == "Instance" } {
set inst $instance
} else {
sta_error 587 "unsupported object type $object_type."
}
} else {
set inst [find_instance $instance]
}
if { $inst != "NULL" } {
delete_instance_cmd $inst
}
}
################################################################
proc delete_net { net } {
if { [is_object $net] } {
set object_type [object_type $net]
if { $object_type != "Net" } {
sta_error 588 "unsupported object type $object_type."
}
} else {
set net [find_net $net]
}
if { $net != "NULL" } {
delete_net_cmd $net
}
}
################################################################
proc disconnect_pin { net pin } {
set net [get_net_warn "net" $net]
if { $net == "NULL" } {
return 0
}
if { $pin == "-all" } {
set iter [$net connected_pin_iterator]
while {[$iter has_next]} {
set pin [$iter next]
disconnect_pin_cmd $pin
}
$iter finish
return 1
} else {
set pin1 [get_port_pin_warn "pin" $pin]
if { $pin1 == "NULL" } {
return 0
} else {
disconnect_pin_cmd $pin1
return 1
}
}
}
proc disconnect_pins { net pins } {
sta_warn 603 "disconnect_pins is deprecated. Use disconnect_pin."
foreach pin $pins {
disconnect_pin $net $pins
}
}
################################################################
proc make_instance { inst_path lib_cell } {
set lib_cell [get_lib_cell_warn "lib_cell" $lib_cell]
if { $lib_cell != "NULL" } {
set path_regexp [path_regexp]
if {[regexp $path_regexp $inst_path ignore path_name inst_name]} {
set parent [find_instance $path_name]
if { $parent == "NULL" } {
# Parent instance not found. This could be a typo, but since
# SDC does not escape hierarchy dividers it can also be
# an escaped name.
set inst_name $inst_path
set parent [top_instance]
}
} else {
set inst_name $inst_path
set parent [top_instance]
}
return [make_instance_cmd $inst_name $lib_cell $parent]
} else {
return 0
}
}
################################################################
proc make_net { net_path } {
# Copy backslashes that will be removed by foreach.
set net_path [string map {\\ \\\\} $net_path]
set path_regexp [path_regexp]
if {[regexp $path_regexp $net_path ignore path_name net_name]} {
set parent [find_instance $path_name]
if { $parent == "NULL" } {
return 0
}
} else {
set parent [top_instance]
set net_name $net_path
}
return [make_net_cmd $net_name $parent]
}
################################################################
proc replace_cell { instance lib_cell } {
set cell [get_lib_cell_warn "lib_cell" $lib_cell]
if { $cell != "NULL" } {
set inst [get_instance_error "instance" $instance]
set inst_cell [$inst liberty_cell]
if { $inst_cell == "NULL" \
|| ![equiv_cell_ports $inst_cell $cell] } {
return 0
}
replace_cell_cmd $inst $cell
return 1
} else {
return 0
}
}
proc path_regexp {} {
global hierarchy_separator
set id_regexp "\[^${hierarchy_separator}\]+"
set prefix_regexp "${id_regexp}(?:${hierarchy_separator}${id_regexp})*"
return "^(${prefix_regexp})${hierarchy_separator}(${id_regexp})$"
}
# sta namespace end.
}