This repository has been archived by the owner on Aug 3, 2023. It is now read-only.
forked from efabless/OpenLane
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmagic.tcl
executable file
·354 lines (318 loc) · 11.4 KB
/
magic.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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# Copyright 2020-2021 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
proc run_magic {args} {
if { $::env(RUN_MAGIC) } {
TIMER::timer_start
increment_index
puts_info "Running Magic to generate various views..."
# |----------------------------------------------------|
# |---------------- 6. TAPE-OUT ---------------------|
# |----------------------------------------------------|
puts_info "Streaming out GDS II..."
set ::env(CURRENT_STAGE) finishing
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)"
# the following MAGTYPE better be mag for clean GDS generation
# use load -dereference to ignore it later if needed
set ::env(MAGTYPE) mag
# Generate GDS and MAG views
set ::env(MAGIC_GDS) $::env(finishing_results)/$::env(DESIGN_NAME).magic.gds
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/mag_gds.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/gdsii.log]
if { $::env(PRIMARY_SIGNOFF_TOOL) == "magic" } {
set ::env(CURRENT_GDS) $::env(finishing_results)/$::env(DESIGN_NAME).gds
file copy -force $::env(MAGIC_GDS) $::env(CURRENT_GDS)
}
file copy -force $::env(MAGIC_MAGICRC) $::env(finishing_results)/.magicrc
# Take a PNG screenshot
scrot_klayout -log $::env(cts_logs)/screenshot.log
if { ($::env(MAGIC_GENERATE_LEF) && $::env(MAGIC_GENERATE_MAGLEF)) || $::env(MAGIC_INCLUDE_GDS_POINTERS) } {
puts_info "Generating MAGLEF views..."
# Generate mag file that includes GDS pointers
set ::env(MAGTYPE) mag
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/gds_pointers.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/gds_ptrs.log]
# Only keep the properties section in the file
try_catch sed -i -n "/^<< properties >>/,/^<< end >>/p" $::env(finishing_tmpfiles)/gds_ptrs.mag
}
# If desired, copy GDS_* properties into the mag/ view
if { $::env(MAGIC_INCLUDE_GDS_POINTERS) } {
copy_gds_properties $::env(finishing_tmpfiles)/gds_ptrs.mag $::env(finishing_results)/$::env(DESIGN_NAME).mag
}
if { $::env(MAGIC_GENERATE_LEF) } {
# Generate LEF view
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/lef.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/lef.log]
if { $::env(MAGIC_GENERATE_MAGLEF) } {
# Generate MAGLEF view
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/maglef.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/maglef.log]
# By default, copy the GDS properties into the maglef/ view
copy_gds_properties $::env(finishing_tmpfiles)/gds_ptrs.mag $::env(finishing_results)/$::env(DESIGN_NAME).lef.mag
}
}
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "gdsii - magic"
}
}
proc run_magic_drc {args} {
if { $::env(RUN_MAGIC_DRC) } {
increment_index
TIMER::timer_start
puts_info "Running Magic DRC..."
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)"
set ::env(drc_prefix) $::env(finishing_reports)/drc
# Has to be maglef for DRC Checking
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/drc.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/drc.log]
puts_info "Converting Magic DRC Violations to Magic Readable Format..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tcl.py \
-i $::env(drc_prefix).rpt \
-o $::env(drc_prefix).tcl
puts_info "Converting Magic DRC Violations to Klayout XML Database..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tr_drc.py \
-i $::env(drc_prefix).rpt \
-o $::env(drc_prefix).tr
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/tr_drc_to_klayout_drc.py \
-i $::env(drc_prefix).tr \
-o $::env(drc_prefix).klayout.xml \
--design-name $::env(DESIGN_NAME)
if { $::env(MAGIC_CONVERT_DRC_TO_RDB) == 1 } {
puts_info "Converting DRC Violations to RDB Format..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_rdb.py \
--magic_drc_in $::env(drc_prefix).rpt \
--rdb_out $::env(drc_prefix).rdb
puts_info "Converted DRC Violations to RDB Format"
}
file copy -force $::env(MAGIC_MAGICRC) $::env(finishing_results)/.magicrc
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "drc - magic"
quit_on_magic_drc -log $::env(drc_prefix).tr
}
}
proc run_magic_spice_export {args} {
TIMER::timer_start
increment_index
if { [info exist ::env(MAGIC_EXT_USE_GDS)] && $::env(MAGIC_EXT_USE_GDS) } {
set extract_type "gds.spice"
puts_info "Running Magic Spice Export from GDS..."
# GDS extracted file design.gds.spice, log file magic_gds.spice.log
} else {
set extract_type "spice"
puts_info "Running Magic Spice Export from LEF..."
# LEF extracted file design.spice (copied to design.lef.spice), log file magic_spice.log
}
set ::env(magic_extract_prefix) [index_file $::env(finishing_logs)/ext2]
set ::env(EXT_NETLIST) $::env(finishing_results)/$::env(DESIGN_NAME).$extract_type
set magic_export $::env(finishing_tmpfiles)/$extract_type.tcl
set commands \
"
if { \[info exist ::env(MAGIC_EXT_USE_GDS)\] && \$::env(MAGIC_EXT_USE_GDS) } {
gds read \$::env(CURRENT_GDS)
} else {
lef read $::env(TECH_LEF)
if { \[info exist ::env(EXTRA_LEFS)\] } {
set lefs_in \$::env(EXTRA_LEFS)
foreach lef_file \$lefs_in {
lef read \$lef_file
}
}
def read $::env(CURRENT_DEF)
}
load $::env(DESIGN_NAME) -dereference
cd $::env(finishing_results)/
extract do local
extract no capacitance
extract no coupling
extract no resistance
extract no adjust
if { ! $::env(LVS_CONNECT_BY_LABEL) } {
extract unique
}
# extract warn all
extract
ext2spice lvs
ext2spice -o $::env(EXT_NETLIST) $::env(DESIGN_NAME).ext
feedback save $::env(magic_extract_prefix)$extract_type.feedback.txt
# exec cp $::env(DESIGN_NAME).spice $::env(finishing_results)/$::env(DESIGN_NAME).spice
"
set magic_export_file [open $magic_export w]
puts $magic_export_file $commands
close $magic_export_file
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
# the following MAGTYPE has to be maglef for the purpose of LVS
# otherwise underlying device circuits would be considered
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$magic_export \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$extract_type.log]
if { $extract_type == "spice" } {
file copy -force $::env(finishing_results)/$::env(DESIGN_NAME).spice $::env(finishing_results)/$::env(DESIGN_NAME).lef.spice
}
file rename -force {*}[glob $::env(finishing_results)/*.ext] $::env(finishing_tmpfiles)
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "$extract_type extraction - magic"
quit_on_illegal_overlaps -log [index_file $::env(finishing_logs)/ext2$extract_type.feedback.txt]
}
proc export_magic_view {args} {
TIMER::timer_start
set options {
{-def required}
{-output required}
}
set flags {}
parse_key_args "export_magic_views" args arg_values $options flags_map $flags
set script_dir $::env(finishing_tmpfiles)/magic_mag_save.tcl
set commands \
"
lef read $::env(TECH_LEF)
if { \[info exist ::env(EXTRA_LEFS)\] } {
set lefs_in \$::env(EXTRA_LEFS)
foreach lef_file \$lefs_in {
lef read \$lef_file
}
}
def read $arg_values(-def)
save $arg_values(-output)
puts \"\[INFO\]: Done exporting $arg_values(-output)\"
"
set stream [open $script_dir w]
puts $stream $commands
close $stream
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$script_dir \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/save_mag.log]
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "mag export - magic"
}
proc run_magic_antenna_check {args} {
increment_index
TIMER::timer_start
puts_info "Running Magic Antenna Checks..."
set feedback_file [index_file $::env(finishing_logs)/ext2spice.antenna.feedback.txt]
set magic_export $::env(finishing_tmpfiles)/magic_antenna.tcl
set commands \
"
lef read \$::env(TECH_LEF)
if { \[info exist ::env(EXTRA_LEFS)\] } {
set lefs_in \$::env(EXTRA_LEFS)
foreach lef_file \$lefs_in {
lef read \$lef_file
}
}
def read \$::env(CURRENT_DEF)
load \$::env(DESIGN_NAME) -dereference
cd \$::env(finishing_tmpfiles)
select top cell
# for now, do extraction anyway; can be optimized by reading the maglef ext
# but getting many warnings
if { ! \[file exists \$::env(DESIGN_NAME).ext\] } {
extract do local
extract no capacitance
extract no coupling
extract no resistance
extract no adjust
if { ! $::env(LVS_CONNECT_BY_LABEL) } {
extract unique
}
# extract warn all
extract
feedback save $feedback_file
}
antennacheck debug
antennacheck
"
set magic_export_file [open $magic_export w]
puts $magic_export_file $commands
close $magic_export_file
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
# the following MAGTYPE has to be mag; antennacheck needs to know
# about the underlying devices, layers, etc.
set ::env(MAGTYPE) mag
set antenna_log [index_file $::env(finishing_logs)/antenna.log]
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$magic_export \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) $antenna_log
# process the log
try_catch awk "/Cell:/ {print \$2}" $antenna_log > $antenna_log
set ::env(ANTENNA_CHECKER_LOG) $antenna_log
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "antenna check - magic"
}
proc copy_gds_properties {from to} {
# copy GDS properties from $from to $to
set gds_properties [list]
set fp [open $from r]
set mag_lines [split [read $fp] "\n"]
foreach line $mag_lines {
if { [string first "string GDS_" $line] != -1 } {
lappend gds_properties $line
}
}
close $fp
set fp [open $to r]
set mag_lines [split [read $fp] "\n"]
set new_mag_lines [list]
foreach line $mag_lines {
if { [string first "<< end >>" $line] != -1 } {
lappend new_mag_lines [join $gds_properties "\n"]
}
lappend new_mag_lines $line
}
close $fp
set fp [open $to w]
puts $fp [join $new_mag_lines "\n"]
close $fp
}
package provide openlane 0.9