Skip to content

Commit 70c3beb

Browse files
authored
Merge pull request #8953 from gadfort/create_obs
odb: add create_obstruction to mirror create_blockage
2 parents c5048e0 + b489b04 commit 70c3beb

File tree

7 files changed

+226
-3
lines changed

7 files changed

+226
-3
lines changed

src/odb/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,35 @@ create_blockage
429429
| `soft` | (optional): Create a soft blockage only blocked during initial placement. |
430430

431431

432+
### Create Routing Obstruction
433+
434+
This command provides a unified interface for creating routing blockages.
435+
436+
```tcl
437+
create_obstruction
438+
-region {x1 y1 x2 y2}
439+
-layer layer
440+
[-inst instance]
441+
[-slot]
442+
[-fill]
443+
[-except_pg]
444+
[-min_spacing space]
445+
[-effective_width width]
446+
```
447+
448+
#### Options
449+
450+
| Switch Name | Description |
451+
| ----- | ----- |
452+
| `region` | (required) Obstruction coordinates in microns. For example, {0 0 10 10} |
453+
| `layer`| (required) Layer to apply the obstruction on. |
454+
| `inst` | (optional): Associate obstruction with a specific instance. |
455+
| `slot` | (optional): Mark as a slot obstruction.
456+
| `fill` | (optional): Mark as a fill obstruction.
457+
| `min_spacing` | (optional): Add a minimum spacing to the obstruction. |
458+
| `effective_width` | (optional): Add an effective width to the obstruction. |
459+
460+
432461
## Example scripts
433462

434463
After building successfully, run OpenDB Tcl shell using

src/odb/src/swig/tcl/odb.tcl

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -865,9 +865,9 @@ proc exclude_io_pin_region { args } {
865865

866866
# Define command arguments for create_blockage (region in microns, density 0-100)
867867
sta::define_cmd_args "create_blockage" { \
868-
[-region {x1 y1 x2 y2}]\
869-
[-inst instance]\
870-
[-max_density density]\
868+
-region {x1 y1 x2 y2} \
869+
[-inst instance] \
870+
[-max_density density] \
871871
[-soft]}
872872

873873
# Placement blockages with various options
@@ -966,6 +966,93 @@ proc create_blockage { args } {
966966
return $blockage
967967
}
968968

969+
# Define command arguments for create_obstruction
970+
sta::define_cmd_args "create_obstruction" { \
971+
-region {x1 y1 x2 y2} \
972+
-layer layer \
973+
[-inst instance] \
974+
[-slot] [-fill] [-except_pg] \
975+
[-min_spacing space] \
976+
[-effective_width width]}
977+
978+
# Placement blockages with various options
979+
proc create_obstruction { args } {
980+
sta::parse_key_args "create_obstruction" args \
981+
keys {-region -layer -inst -min_spacing -effective_width} \
982+
flags {-slot -fill -except_pg}
983+
984+
# Check that no extra arguments remain
985+
sta::check_argc_eq0 "create_obstruction" $args
986+
987+
if { ![info exists keys(-layer)] } {
988+
utl::error ODB 1017 "-layer is required"
989+
}
990+
set layer [[ord::get_db_tech] findLayer $keys(-layer)]
991+
if { $layer == "NULL" } {
992+
utl::error ODB 1018 "Unable to find $keys(-layer)"
993+
}
994+
995+
# Check if coordinates are valid
996+
if { ![info exists keys(-region)] || [llength $keys(-region)] != 4 } {
997+
utl::error ODB 1019 "Invalid coordinates. -region must be a list of 4 values {x1 y1 x2 y2}"
998+
}
999+
1000+
set region $keys(-region)
1001+
set x1 [ord::microns_to_dbu [lindex $region 0]]
1002+
set y1 [ord::microns_to_dbu [lindex $region 1]]
1003+
set x2 [ord::microns_to_dbu [lindex $region 2]]
1004+
set y2 [ord::microns_to_dbu [lindex $region 3]]
1005+
1006+
# Validate coordinate ordering
1007+
if { $x1 >= $x2 || $y1 >= $y2 } {
1008+
utl::error ODB 1020 "Invalid coordinates: \
1009+
x1 ([ord::dbu_to_microns $x1]) must be < x2 ([ord::dbu_to_microns $x2]) and \
1010+
y1 ([ord::dbu_to_microns $y1]) must be < y2 ([ord::dbu_to_microns $y2])"
1011+
}
1012+
1013+
# Get database objects
1014+
set block [ord::get_db_block]
1015+
1016+
# Extract optional arguments
1017+
set inst_obj "NULL"
1018+
if { [info exists keys(-inst)] } {
1019+
set inst_name $keys(-inst)
1020+
set inst_obj [$block findInst $inst_name]
1021+
if { $inst_obj == "NULL" } {
1022+
utl::error ODB 1021 "Instance '$inst_name' not found in design"
1023+
}
1024+
}
1025+
1026+
# Create the obstruction
1027+
set obstruction [odb::dbObstruction_create $block $layer $x1 $y1 $x2 $y2 $inst_obj]
1028+
1029+
if { $obstruction == "NULL" } {
1030+
utl::error ODB 1022 "Failed to create obstruction"
1031+
}
1032+
1033+
if { [info exists flags(-slot)] } {
1034+
$obstruction setSlotObstruction
1035+
}
1036+
1037+
if { [info exists flags(-fill)] } {
1038+
$obstruction setFillObstruction
1039+
}
1040+
1041+
if { [info exists flags(-except_pg)] } {
1042+
$obstruction setExceptPGNetsObstruction
1043+
}
1044+
1045+
if { [info exists keys(-min_spacing)] } {
1046+
$obstruction setMinSpacing [ord::microns_to_dbu $keys(-min_spacing)]
1047+
}
1048+
1049+
if { [info exists keys(-effective_width)] } {
1050+
$obstruction setEffectiveWidth [ord::microns_to_dbu $keys(-effective_width)]
1051+
}
1052+
1053+
return $obstruction
1054+
}
1055+
9691056
sta::define_cmd_args "clear_io_pin_constraints" {}
9701057

9711058
proc clear_io_pin_constraints { args } {

src/odb/test/BUILD

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ COMPULSORY_TESTS = [
147147
"bterm_hier_create",
148148
"check_routing_tracks",
149149
"create_blockage",
150+
"create_obstruction",
150151
"create_sboxes",
151152
"def_dup_net",
152153
"def_parser",
@@ -351,6 +352,9 @@ filegroup(
351352
"all_pins_placed2": [
352353
"design_is_routed1.def",
353354
],
355+
"create_obstruction": [
356+
"create_blockage.def",
357+
],
354358
"dump_netlists": [
355359
"dump_netlists_cdl.ok",
356360
],

src/odb/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ or_integration_tests(
77
bterm_hier_create
88
check_routing_tracks
99
create_blockage
10+
create_obstruction
1011
create_sboxes
1112
def_dup_net
1213
def_parser
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
VERSION 5.8 ;
2+
DIVIDERCHAR "/" ;
3+
BUSBITCHARS "[]" ;
4+
DESIGN test ;
5+
UNITS DISTANCE MICRONS 1000 ;
6+
DIEAREA ( 0 0 ) ( 100000 100000 ) ;
7+
ROW ROW_0 unithd 5060 5440 N DO 195 BY 1 STEP 460 0 ;
8+
ROW ROW_1 unithd 5060 8160 FS DO 195 BY 1 STEP 460 0 ;
9+
ROW ROW_2 unithd 5060 10880 N DO 195 BY 1 STEP 460 0 ;
10+
ROW ROW_3 unithd 5060 13600 FS DO 195 BY 1 STEP 460 0 ;
11+
ROW ROW_4 unithd 5060 16320 N DO 195 BY 1 STEP 460 0 ;
12+
ROW ROW_5 unithd 5060 19040 FS DO 195 BY 1 STEP 460 0 ;
13+
ROW ROW_6 unithd 5060 21760 N DO 195 BY 1 STEP 460 0 ;
14+
ROW ROW_7 unithd 5060 24480 FS DO 195 BY 1 STEP 460 0 ;
15+
ROW ROW_8 unithd 5060 27200 N DO 195 BY 1 STEP 460 0 ;
16+
ROW ROW_9 unithd 5060 29920 FS DO 195 BY 1 STEP 460 0 ;
17+
ROW ROW_10 unithd 5060 32640 N DO 195 BY 1 STEP 460 0 ;
18+
ROW ROW_11 unithd 5060 35360 FS DO 195 BY 1 STEP 460 0 ;
19+
ROW ROW_12 unithd 5060 38080 N DO 195 BY 1 STEP 460 0 ;
20+
ROW ROW_13 unithd 5060 40800 FS DO 195 BY 1 STEP 460 0 ;
21+
ROW ROW_14 unithd 5060 43520 N DO 195 BY 1 STEP 460 0 ;
22+
ROW ROW_15 unithd 5060 46240 FS DO 195 BY 1 STEP 460 0 ;
23+
ROW ROW_16 unithd 5060 48960 N DO 195 BY 1 STEP 460 0 ;
24+
ROW ROW_17 unithd 5060 51680 FS DO 195 BY 1 STEP 460 0 ;
25+
ROW ROW_18 unithd 5060 54400 N DO 195 BY 1 STEP 460 0 ;
26+
ROW ROW_19 unithd 5060 57120 FS DO 195 BY 1 STEP 460 0 ;
27+
ROW ROW_20 unithd 5060 59840 N DO 195 BY 1 STEP 460 0 ;
28+
ROW ROW_21 unithd 5060 62560 FS DO 195 BY 1 STEP 460 0 ;
29+
ROW ROW_22 unithd 5060 65280 N DO 195 BY 1 STEP 460 0 ;
30+
ROW ROW_23 unithd 5060 68000 FS DO 195 BY 1 STEP 460 0 ;
31+
ROW ROW_24 unithd 5060 70720 N DO 195 BY 1 STEP 460 0 ;
32+
ROW ROW_25 unithd 5060 73440 FS DO 195 BY 1 STEP 460 0 ;
33+
ROW ROW_26 unithd 5060 76160 N DO 195 BY 1 STEP 460 0 ;
34+
ROW ROW_27 unithd 5060 78880 FS DO 195 BY 1 STEP 460 0 ;
35+
ROW ROW_28 unithd 5060 81600 N DO 195 BY 1 STEP 460 0 ;
36+
ROW ROW_29 unithd 5060 84320 FS DO 195 BY 1 STEP 460 0 ;
37+
ROW ROW_30 unithd 5060 87040 N DO 195 BY 1 STEP 460 0 ;
38+
ROW ROW_31 unithd 5060 89760 FS DO 195 BY 1 STEP 460 0 ;
39+
COMPONENTS 1 ;
40+
- _INST_ sky130_fd_sc_hd__a2111o_1 + PLACED ( 30000 40000 ) FS ;
41+
END COMPONENTS
42+
BLOCKAGES 4 ;
43+
- LAYER met1 RECT ( 10000 10000 ) ( 20000 20000 ) ;
44+
- LAYER met1 + SLOTS + FILLS RECT ( 10000 10000 ) ( 20000 20000 ) ;
45+
- LAYER met1 + DESIGNRULEWIDTH 500 RECT ( 10000 10000 ) ( 20000 20000 ) ;
46+
- LAYER met1 + COMPONENT _INST_ RECT ( 70000 70000 ) ( 80000 80000 ) ;
47+
END BLOCKAGES
48+
NETS 0 ;
49+
END NETS
50+
END DESIGN

src/odb/test/create_obstruction.ok

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[INFO ODB-0227] LEF file: sky130hd/sky130hd.tlef, created 13 layers, 25 vias
2+
[INFO ODB-0227] LEF file: sky130hd/sky130hd_std_cell.lef, created 437 library cells
3+
[INFO ODB-0128] Design: test
4+
[INFO ODB-0131] Created 1 components and 8 component-terminals.
5+
[ERROR ODB-1017] -layer is required
6+
ODB-1017
7+
[ERROR ODB-1018] Unable to find Metal1
8+
ODB-1018
9+
No differences found.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
source "helpers.tcl"
2+
3+
# Test create_obstruction function
4+
# This test creates various types of obstructions and verifies their properties
5+
6+
# Open database, load lef and design
7+
set db [ord::get_db]
8+
read_lef "sky130hd/sky130hd.tlef"
9+
read_lef "sky130hd/sky130hd_std_cell.lef"
10+
read_def "create_blockage.def"
11+
set chip [$db getChip]
12+
set block [$chip getBlock]
13+
14+
catch { create_obstruction -region {10 10 20 20} } err
15+
puts $err
16+
17+
catch { create_obstruction -layer Metal1 -region {10 10 20 20} } err
18+
puts $err
19+
20+
set b1 [create_obstruction -layer met1 -region {10 10 20 20}]
21+
check "obstruction count" {llength [$block getObstructions]} 1
22+
23+
set b2 [create_obstruction -layer met1 -region {10 10 20 20} -slot -fill -except_pg]
24+
check "obstruction count" {llength [$block getObstructions]} 2
25+
check "obstruction is fill" {$b2 isFillObstruction} 1
26+
check "obstruction is slot" {$b2 isSlotObstruction} 1
27+
check "obstruction is except_pg" {$b2 isExceptPGNetsObstruction} 1
28+
29+
set b3 [create_obstruction -layer met1 -region {10 10 20 20} -min_spacing 1.5 -effective_width 0.5]
30+
check "obstruction count" {llength [$block getObstructions]} 3
31+
check "obstruction is eff width" {$b3 hasEffectiveWidth} 1
32+
check "obstruction is spacing" {$b3 hasMinSpacing} 1
33+
check "obstruction eff width" {$b3 getEffectiveWidth} 500
34+
check "obstruction spacing" {$b3 getMinSpacing} 1500
35+
36+
set b4 [create_obstruction -layer met1 -region {70 70 80 80} -inst "_INST_"]
37+
check "obstruction has instance" {[$b4 getInstance] getName} _INST_
38+
check "obstruction count" {llength [$block getObstructions]} 4
39+
40+
# DEF test
41+
set def_file [make_result_file create_obstruction.def]
42+
write_def $def_file
43+
diff_files create_obstruction.defok $def_file

0 commit comments

Comments
 (0)