Skip to content

Commit 9e8f835

Browse files
authored
Merge pull request #10289 from The-OpenROAD-Project-staging/debug_write_verilog_bug
avoid duplicate ports/signals in hier verilogs
2 parents a04ba3c + 590817a commit 9e8f835

8 files changed

Lines changed: 91 additions & 20 deletions

File tree

src/dbSta/include/db_sta/dbNetwork.hh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,12 @@ class dbNetwork : public ConcreteNetwork
479479
static constexpr unsigned DBIDTAG_WIDTH = 0x4;
480480

481481
private:
482+
// Strip the parent-instance prefix from a hierarchical name, treating
483+
// backslash-escaped slashes (\/) as literal name characters rather than
484+
// hierarchy separators. Used to recover an in-module name from a
485+
// path-qualified one stored in ODB.
486+
static std::string stripParentPrefix(const std::string& name);
487+
482488
std::set<const Cell*> hier_modules_;
483489
std::set<const Port*> concrete_ports_;
484490
std::unique_ptr<dbEditHierarchy> hierarchy_editor_;

src/dbSta/src/dbNetwork.cc

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,21 @@ ObjectId dbNetwork::id(const Instance* instance) const
786786
return staToDb(instance)->getId();
787787
}
788788

789+
std::string dbNetwork::stripParentPrefix(const std::string& name)
790+
{
791+
size_t pos = name.length();
792+
while ((pos = name.rfind('/', pos)) != std::string::npos) {
793+
if (pos > 0 && name[pos - 1] == '\\') {
794+
// Escaped slash inside a Verilog escaped identifier; not a
795+
// hierarchy separator. Keep searching to the left.
796+
pos--;
797+
} else {
798+
return name.substr(pos + 1);
799+
}
800+
}
801+
return name;
802+
}
803+
789804
std::string dbNetwork::name(const Port* port) const
790805
{
791806
if (isConcretePort(port)) {
@@ -808,10 +823,7 @@ std::string dbNetwork::name(const Port* port) const
808823
}
809824

810825
if (hasHierarchy()) {
811-
size_t last_idx = name.find_last_of('/');
812-
if (last_idx != std::string::npos) {
813-
name = name.substr(last_idx + 1);
814-
}
826+
name = stripParentPrefix(name);
815827
}
816828
return name;
817829
}
@@ -855,21 +867,7 @@ std::string dbNetwork::name(const Instance* instance) const
855867
}
856868

857869
if (hasHierarchy()) {
858-
size_t last_idx = std::string::npos;
859-
size_t pos = name.length();
860-
while ((pos = name.rfind('/', pos)) != std::string::npos) {
861-
if (pos > 0 && name[pos - 1] == '\\') {
862-
// This is an escaped slash, so we should ignore it and continue
863-
// searching.
864-
pos--;
865-
} else {
866-
last_idx = pos;
867-
break;
868-
}
869-
}
870-
if (last_idx != std::string::npos) {
871-
name = name.substr(last_idx + 1);
872-
}
870+
name = stripParentPrefix(name);
873871
}
874872
return name;
875873
}

src/dbSta/test/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ ALL_TESTS = [
2323
"get_ports1_hier",
2424
"hier2",
2525
"hier3",
26+
"hier_escape_port",
2627
"hierclock",
2728
"hierwrite",
2829
"hier_deep",

src/dbSta/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ or_integration_tests(
1313
get_ports1_hier
1414
hier2
1515
hier3
16+
hier_escape_port
1617
hierclock
1718
hierwrite
1819
hier_deep

src/dbSta/test/hier_escape_port.ok

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[INFO ODB-0227] LEF file: Nangate45/Nangate45.lef, created 22 layers, 27 vias, 135 library cells
2+
[WARNING ORD-0011] Hierarchical flow (-hier) is currently in development and may cause multiple issues. Do not use in production environments.
3+
module top (clk);
4+
input clk;
5+
6+
wire net_c;
7+
wire net_b;
8+
9+
child h1 (.clk(clk),
10+
.\pathA/midB/leaf (net_b),
11+
.\pathA/midC/leaf (net_c));
12+
endmodule
13+
module child (clk,
14+
\pathA/midB/leaf ,
15+
\pathA/midC/leaf );
16+
input clk;
17+
output \pathA/midB/leaf ;
18+
output \pathA/midC/leaf ;
19+
20+
21+
DFF_X1 ff_b (.CK(clk),
22+
.Q(\pathA/midB/leaf ));
23+
DFF_X1 ff_c (.CK(clk),
24+
.Q(\pathA/midC/leaf ));
25+
endmodule
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Two output ports in a child module whose Verilog escaped-identifier
2+
# names differ only in a middle path segment must round-trip through
3+
# write_verilog as two distinct ports, not collapse to a duplicate.
4+
source "helpers.tcl"
5+
read_lef Nangate45/Nangate45.lef
6+
read_liberty Nangate45/Nangate45_typ.lib
7+
read_verilog hier_escape_port.v
8+
link_design -hier top
9+
10+
set verilog_file [make_result_file hier_escape_port.v]
11+
write_verilog $verilog_file
12+
report_file $verilog_file

src/dbSta/test/hier_escape_port.v

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Regression test for dbNetwork::name(Port*) escaped-identifier handling.
2+
//
3+
// `child` has two output ports whose Verilog escaped-identifier names
4+
// (`\pathA/midB/leaf ` and `\pathA/midC/leaf `) differ only in a middle
5+
// segment. Every `/` is a literal name character of the escaped
6+
// identifier (LRM 5.6.1) and is stored as `\/` in ODB.
7+
//
8+
// Before the fix, dbNetwork::name(Port*) stripped at the last `/` without
9+
// honoring the preceding `\`, collapsing both names to `leaf` and
10+
// producing a malformed child module with two identically-named output
11+
// ports on write_verilog round-trip.
12+
13+
module top (clk);
14+
input clk;
15+
wire net_b;
16+
wire net_c;
17+
child h1 (.clk(clk),
18+
.\pathA/midB/leaf (net_b),
19+
.\pathA/midC/leaf (net_c));
20+
endmodule
21+
22+
module child (clk, \pathA/midB/leaf , \pathA/midC/leaf );
23+
input clk;
24+
output \pathA/midB/leaf ;
25+
output \pathA/midC/leaf ;
26+
DFF_X1 ff_b (.CK(clk), .Q(\pathA/midB/leaf ));
27+
DFF_X1 ff_c (.CK(clk), .Q(\pathA/midC/leaf ));
28+
endmodule

src/dbSta/test/hier_weird_port.ok

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ modinst 'u_sub' master 'sub':
2222
head modbterm: 'path\/with\/slash'
2323
--- pin-direction on u_sub ---
2424
u_sub/out dir=output
25-
u_sub/slash dir=input
25+
u_sub/path/with/slash dir=input

0 commit comments

Comments
 (0)