Skip to content

Commit 9afa534

Browse files
openroad: post-route antenna fixing
1 parent 51fcb97 commit 9afa534

File tree

2 files changed

+158
-1
lines changed

2 files changed

+158
-1
lines changed

openroad/scripts/chip.tcl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ source scripts/init_tech.tcl
2525

2626
set log_id 0
2727

28+
# Set number of threads for multithreaded operations
29+
set_thread_count 8
2830

2931
###############################################################################
3032
# Initialization #
@@ -296,12 +298,14 @@ detailed_route -output_drc ${report_dir}/${log_id_str}_${proj_name}_route_drc.rp
296298
-clean_patches \
297299
-verbose 1
298300

301+
# Post-route antenna fixing
302+
source scripts/post_route_antenna_fix.tcl
303+
299304
utl::report "Saving detailed route"
300305
save_checkpoint ${log_id_str}_${proj_name}.drt
301306
report_metrics "${log_id_str}_${proj_name}.drt"
302307
report_image "${log_id_str}_${proj_name}.drt" true false false true
303308

304-
305309
###############################################################################
306310
# FINISHING #
307311
###############################################################################
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Copyright 2025 ETH Zurich and University of Bologna.
2+
# Solderpad Hardware License, Version 0.51, see LICENSE for details.
3+
# SPDX-License-Identifier: SHL-0.51
4+
5+
# Authors:
6+
# - Tobias Senti <tsenti@ethz.ch>
7+
8+
## Post-Route Antenna Fix Script
9+
# This script checks for antenna violations after detailed routing
10+
# and attempts to fix them by adding antenna diodes to the affected pins.
11+
# Runs up to $max_iterations or until no violations are found anymore.
12+
13+
# Maximum number of iterations until giving up
14+
set max_iterations 3
15+
16+
# Counter for unique diode names
17+
if {![info exists ::antennacounter]} {
18+
set ::antennacounter 0
19+
}
20+
21+
set early_exit 0
22+
for {set iteration 1} {$iteration <= $max_iterations} {incr iteration} {
23+
puts "\n\n=== Antenna Fix Iteration $iteration ==="
24+
set report_file_name "post_route_antenna_$iteration.rpt"
25+
26+
puts "Check for antenna violations"
27+
check_antennas -report_file $report_dir/$report_file_name
28+
29+
puts "Parsing antenna report"
30+
31+
# Read in report
32+
set fp [open $report_dir/$report_file_name]
33+
set lines [split [read $fp] "\n"]
34+
close $fp
35+
36+
# Parse report
37+
set net_name ""
38+
set pin_name ""
39+
set has_violation 0
40+
set pin_with_violations {}
41+
foreach line $lines {
42+
# Trim and split line
43+
set line [string trim $line]
44+
set split_parts [split $line]
45+
set parts {}
46+
foreach part $split_parts {
47+
if { $part ne "" } {
48+
lappend parts $part
49+
}
50+
}
51+
52+
# Check if it is a net or pin
53+
set first_word [lindex $parts 0]
54+
if { $first_word eq "Net:" } {
55+
set net_name [lindex $parts 1]
56+
puts "Processing net: $net_name"
57+
}
58+
if { $first_word eq "Pin:" } {
59+
set pin_name [lindex $parts 1]
60+
set has_violation 0
61+
puts " Pin: $pin_name"
62+
}
63+
64+
# Prevent multiple additions of the same pin
65+
if { $has_violation eq 0 } {
66+
# Check if it is a violation line
67+
set last_word [lindex $parts end]
68+
if { $last_word eq "(VIOLATED)" } {
69+
lappend pin_with_violations $pin_name
70+
set has_violation 1
71+
puts " Adding pin $pin_name to violation list"
72+
}
73+
}
74+
}
75+
76+
puts "\n\n"
77+
78+
# If no violations, exit loop
79+
if { [llength $pin_with_violations] eq 0 } {
80+
puts "No antenna violations detected, exiting."
81+
set early_exit 1
82+
break
83+
}
84+
85+
# Add one antenna diode per pin with violation
86+
puts "Add antenna diodes"
87+
set block [ord::get_db_block]
88+
set ant_master [odb::dbDatabase_findMaster [ord::get_db] "sg13g2_antennanp"]
89+
set violation_nets {}
90+
foreach pin $pin_with_violations {
91+
puts "Pin with antenna violation: $pin"
92+
set parts [split $pin "/"]
93+
set pin_name [lindex $parts end]
94+
set cell_name [join [lrange $parts 0 end-1] "/"]
95+
96+
# Get instance
97+
set inst [odb::dbBlock_findInst $block $cell_name]
98+
puts [odb::dbInst_getName $inst]
99+
100+
# Get iterm (db representation of pin)
101+
set iterm [odb::dbInst_findITerm $inst $pin_name]
102+
103+
# Get net connected to iterm
104+
set net [odb::dbITerm_getNet $iterm]
105+
set net_name [odb::dbNet_getName $net]
106+
# remove backslashes from net name
107+
set net_name [string map {"\\" ""} $net_name]
108+
lappend violation_nets $net_name
109+
110+
# Remove routing of the net if it has any
111+
set wire [odb::dbNet_getWire $net]
112+
if { $wire ne "NULL"} {
113+
odb::dbWire_destroy $wire
114+
}
115+
116+
# Create antenna diode instance
117+
set ant_name "post_route_ant_diode_[incr ::antennacounter]"
118+
set inst [odb::dbInst_create $block $ant_master $ant_name]
119+
120+
# Connect antenna diode to the net
121+
set inst_iterm [odb::dbInst_findITerm $inst "A"]
122+
odb::dbITerm_connect $inst_iterm $net
123+
124+
# Place antenna diode near the pin (gate to protect)
125+
set xy [odb::dbITerm_getAvgXY $iterm]
126+
puts "Placing antenna diode at $xy"
127+
odb::dbInst_setLocation $inst [lindex $xy 1] [lindex $xy 2]
128+
odb::dbInst_setPlacementStatus $inst "PLACED"
129+
}
130+
131+
# Refine placement of diodes
132+
puts "Detailed placement"
133+
detailed_placement
134+
135+
# Ensure diodes are connected to power
136+
puts "Connect power"
137+
global_connect
138+
139+
# Reroute affected nets
140+
puts "Detailed route"
141+
detailed_route -output_drc ${report_dir}/${log_id_str}_${proj_name}_post_route_antenna_fix_drc.rpt \
142+
-droute_end_iter 30 \
143+
-drc_report_iter_step 5 \
144+
-save_guide_updates \
145+
-clean_patches \
146+
-verbose 1
147+
}
148+
149+
# Final antenna check if we have not exited early i.e. fixed all violations
150+
if {$early_exit eq 0} {
151+
puts "Final antenna check"
152+
check_antennas -report_file $report_dir/$report_file_name
153+
}

0 commit comments

Comments
 (0)