Skip to content

Commit c067f25

Browse files
authored
Merge pull request #9745 from The-OpenROAD-Project-staging/missing_para_dbmodnet
Missing para dbmodnet
2 parents 4cd5cd5 + bc23866 commit c067f25

9 files changed

Lines changed: 246 additions & 7 deletions

src/dbSta/include/db_sta/dbNetwork.hh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,10 @@ class dbNetwork : public ConcreteNetwork
367367

368368
// Return the highest net above the given net.
369369
// - If the net is a flat net, return it.
370-
// - If the net is a hier net, return the modnet in the highest hierarchy.
370+
// - If the net is a hier net (dbModNet), return the associated flat dbNet.
371+
// This ensures parasitic externality checks in ensureParasiticNode work
372+
// correctly: net_ is always a flat net, so the comparison net != net_
373+
// must also operate on flat nets.
371374
Net* highestNetAbove(Net* net) const override;
372375

373376
////////////////////////////////////////////////////////////////

src/dbSta/src/dbNetwork.cc

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,9 +2018,18 @@ void dbNetwork::visitConnectedPins(const Net* net,
20182018
}
20192019
}
20202020

2021+
// Caution:
2022+
//- Network::highestConnectedNet(Net *net) retrieves the highest hierarchical
2023+
// net connected to the given net.
2024+
// - But `dbNetwork::highestConnectedNet(Net* net)` retrieves the corresponding
2025+
// flat net for the given net.
2026+
// - It behaves differently to cope with the issue 9724.
2027+
// - This redefinition may cause another issue later when
2028+
// `Network::highestConnectedNet(Net *net)` is used elsewhere.
20212029
const Net* dbNetwork::highestConnectedNet(Net* net) const
20222030
{
2023-
return net;
2031+
const Net* flat = findFlatNet(net);
2032+
return flat ? flat : net;
20242033
}
20252034

20262035
////////////////////////////////////////////////////////////////
@@ -5218,11 +5227,15 @@ Net* dbNetwork::highestNetAbove(Net* net) const
52185227
}
52195228

52205229
if (modnet) {
5230+
// Return the flat net associated with this mod net.
5231+
// Parasitic externality checks in
5232+
// ConcreteParasiticNetwork::ensureParasiticNode compare against net_ which
5233+
// is always a flat net (set via makeParasiticNetwork). Returning the
5234+
// highest mod net causes all pin nodes on hierarchically-connected nets to
5235+
// compare unequal to net_ and be incorrectly marked as external, making
5236+
// node_count_ = 0 and crashing PRIMA in measureThresholds.
52215237
if (dbNet* related_dbnet = modnet->findRelatedNet()) {
5222-
if (odb::dbModNet* highest_modnet
5223-
= related_dbnet->findModNetInHighestHier()) {
5224-
return dbToSta(highest_modnet); // Found the highest modnet
5225-
}
5238+
return dbToSta(related_dbnet);
52265239
}
52275240
}
52285241

src/dbSta/test/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ ALL_TESTS = [
2727
"hierclock",
2828
"hierwrite",
2929
"hier_deep",
30+
"hier_highest_connected_net",
3031
"hier_weird_port",
3132
"levelize_drvr_vertices1",
3233
"make_port",

src/dbSta/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ or_integration_tests(
1717
hierclock
1818
hierwrite
1919
hier_deep
20+
hier_highest_connected_net
2021
hier_weird_port
2122
levelize_drvr_vertices1
2223
make_port

src/dbSta/test/cpp/TestDbSta.cc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,26 @@ TEST_F(TestDbSta, TestHierarchyConnectivity)
8282
ASSERT_NE(modnet_out2, nullptr);
8383
Net* sta_modnet_out2 = db_network_->dbToSta(modnet_out2);
8484
ASSERT_NE(sta_modnet_out2, nullptr);
85+
// highestNetAbove on a mod net now returns the associated flat dbNet, not the
86+
// highest mod net, so that parasitic externality checks work correctly.
8587
Net* sta_highest_modnet_out
8688
= db_network_->highestNetAbove(sta_modnet_mod_out);
87-
ASSERT_EQ(sta_highest_modnet_out, sta_modnet_out2);
89+
ASSERT_EQ(sta_highest_modnet_out, sta_dbnet_out2);
90+
91+
// Regression for PR #3194: dbNetwork::highestConnectedNet on a hier
92+
// dbModNet must return the associated flat dbNet, not the modnet wrapper
93+
// itself. Parasitics::findParasiticNet uses this as the lookup key into
94+
// the parasitic network map. SPEF is a flat format so parasitics are
95+
// keyed by flat dbNet; returning the modnet wrapper caused a cache miss
96+
// and silently degraded delay calculation to LumpedCap.
97+
const Net* sta_highest_connected_modnet
98+
= db_network_->highestConnectedNet(sta_modnet_mod_out);
99+
ASSERT_EQ(sta_highest_connected_modnet, sta_dbnet_out2);
100+
101+
// Flat dbNet input: highestConnectedNet is idempotent.
102+
const Net* sta_highest_connected_flat
103+
= db_network_->highestConnectedNet(sta_dbnet_out2);
104+
ASSERT_EQ(sta_highest_connected_flat, sta_dbnet_out2);
88105

89106
// Check get_ports -of_object Net*
90107
NetTermIterator* term_iter = db_network_->termIterator(sta_dbnet_out2);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
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+
Found 3 unannotated drivers.
4+
ff_out/QN
5+
ff_top/QN
6+
sub_inst/ff_sub/QN
7+
Found 0 partially unannotated drivers.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
*SPEF "IEEE 1481-1998"
2+
*DESIGN "top"
3+
*DATE "now"
4+
*VENDOR "n/a"
5+
*PROGRAM "n/a"
6+
*VERSION "1.0"
7+
*DESIGN_FLOW ""
8+
*DIVIDER /
9+
*DELIMITER :
10+
*BUS_DELIMITER [ ]
11+
*T_UNIT 1 NS
12+
*C_UNIT 1 PF
13+
*R_UNIT 1 OHM
14+
*L_UNIT 1 HENRY
15+
16+
*D_NET clk 0.001
17+
*CONN
18+
*P clk I
19+
*I ck_buf:A I
20+
*CAP
21+
1 clk 0.0005
22+
2 ck_buf:A 0.0005
23+
*RES
24+
1 clk ck_buf:A 0.1
25+
*END
26+
27+
*D_NET clk_int 0.002
28+
*CONN
29+
*I ck_buf:Z O
30+
*I ff_top:CK I
31+
*I ff_out:CK I
32+
*I sub_inst/ff_sub:CK I
33+
*CAP
34+
1 ck_buf:Z 0.0005
35+
2 ff_top:CK 0.0005
36+
3 ff_out:CK 0.0005
37+
4 sub_inst/ff_sub:CK 0.0005
38+
*RES
39+
1 ck_buf:Z ff_top:CK 0.1
40+
2 ck_buf:Z ff_out:CK 0.1
41+
3 ck_buf:Z sub_inst/ff_sub:CK 0.1
42+
*END
43+
44+
*D_NET in 0.001
45+
*CONN
46+
*P in I
47+
*I ff_top:D I
48+
*CAP
49+
1 in 0.0005
50+
2 ff_top:D 0.0005
51+
*RES
52+
1 in ff_top:D 0.1
53+
*END
54+
55+
*D_NET out 0.001
56+
*CONN
57+
*I ff_out:Q O
58+
*P out O
59+
*CAP
60+
1 ff_out:Q 0.0005
61+
2 out 0.0005
62+
*RES
63+
1 ff_out:Q out 0.1
64+
*END
65+
66+
*D_NET midnet 0.001
67+
*CONN
68+
*I ff_top:Q O
69+
*I sub_inst/ff_sub:D I
70+
*CAP
71+
1 ff_top:Q 0.0005
72+
2 sub_inst/ff_sub:D 0.0005
73+
*RES
74+
1 ff_top:Q sub_inst/ff_sub:D 0.1
75+
*END
76+
77+
*D_NET intermediate 0.001
78+
*CONN
79+
*I sub_inst/buf_sub:Z O
80+
*I ff_out:D I
81+
*CAP
82+
1 sub_inst/buf_sub:Z 0.0005
83+
2 ff_out:D 0.0005
84+
*RES
85+
1 sub_inst/buf_sub:Z ff_out:D 0.1
86+
*END
87+
88+
*D_NET sub_inst/q_int 0.001
89+
*CONN
90+
*I sub_inst/ff_sub:Q O
91+
*I sub_inst/buf_sub:A I
92+
*CAP
93+
1 sub_inst/ff_sub:Q 0.0005
94+
2 sub_inst/buf_sub:A 0.0005
95+
*RES
96+
1 sub_inst/ff_sub:Q sub_inst/buf_sub:A 0.1
97+
*END
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Regression for PR #3194: dbNetwork::highestConnectedNet on a hier
2+
# dbModNet must resolve to the associated flat dbNet so that
3+
# Parasitics::findParasiticNet hits the parasitic_network_map_ entry
4+
# inserted under the flat dbNet key.
5+
#
6+
# Why this test uses read_spef rather than estimate_parasitics:
7+
# estimate_parasitics keys parasitic_network_map_ via findParasiticNet
8+
# for BOTH insert and lookup, so the bug is self-consistent and
9+
# invisible (insert key == lookup key, both buggy or both fixed).
10+
# SPEF read keys insertion by flat dbNet (parser -> findNet -> flat
11+
# at top scope) while lookup still uses findParasiticNet ->
12+
# dbNetwork::highestConnectedNet. Pre-fix override echoed the modnet
13+
# wrapper -> modnet key != flat key -> cache miss -> driver
14+
# classified unannotated. Fix returns the related flat dbNet -> hit.
15+
#
16+
# Design (hier_highest_connected_net.v): 2-level hier with reg-to-reg
17+
# data path crossing sub_inst. Top clk is buffered by ck_buf so the
18+
# clock-tree driver iterated is a leaf iterm, not the top BTerm; this
19+
# avoids the top-port bypass branch in Parasitics::findParasiticNet
20+
# (which returns network_->net(term) directly with no
21+
# highestConnectedNet call and is independent of PR #3194) that would
22+
# otherwise leave clk unannotated on the fixed binary too.
23+
#
24+
# Hier-crossing nets (carry both flat dbNet + dbModNet on their leaf
25+
# iterms after link_design -hier):
26+
# clk_int : ck_buf/Z -> ff_top/CK, ff_out/CK, sub_inst/ff_sub/CK
27+
# midnet : ff_top/Q -> sub_inst/ff_sub/D
28+
# intermediate : sub_inst/buf_sub/Z -> ff_out/D
29+
#
30+
# Expected outputs:
31+
#
32+
# Fixed binary:
33+
# Found 3 unannotated drivers.
34+
# ff_out/QN
35+
# ff_top/QN
36+
# sub_inst/ff_sub/QN
37+
# Found 0 partially unannotated drivers.
38+
#
39+
# Bug binary:
40+
# Found 6 unannotated drivers.
41+
# ck_buf/Z
42+
# ff_out/QN
43+
# ff_top/Q
44+
# ff_top/QN
45+
# sub_inst/buf_sub/Z
46+
# sub_inst/ff_sub/QN
47+
# Found 0 partially unannotated drivers.
48+
#
49+
# The 3 baseline entries (ff_top/QN, ff_out/QN, sub_inst/ff_sub/QN)
50+
# are dangling DFF QN outputs -- no loads, no wire, no parasitic
51+
# possible. The 3 bug-extras (ck_buf/Z, ff_top/Q, sub_inst/buf_sub/Z)
52+
# are the modnet-wrapped drivers on the hier-crossing nets above:
53+
# findParasiticNet returns their dbModNet wrapper, SPEF-inserted
54+
# entries are keyed by flat dbNet -> map miss on bug binary, hit on
55+
# fixed binary.
56+
source "helpers.tcl"
57+
read_liberty Nangate45/Nangate45_typ.lib
58+
read_lef Nangate45/Nangate45.lef
59+
read_verilog hier_highest_connected_net.v
60+
link_design top -hier
61+
62+
create_clock -name clk -period 5 [get_ports clk]
63+
set_input_delay -clock clk 0 [get_ports in]
64+
set_output_delay -clock clk 0 [get_ports out]
65+
66+
read_spef hier_highest_connected_net.spef
67+
68+
report_parasitic_annotation -report_unannotated
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// 2-level hier reg-to-reg design. midnet/intermediate span sub_inst
2+
// boundary so leaf iterms on those nets get both flat dbNet and
3+
// dbModNet wrappers after link_design -hier. Clock buffer ck_buf
4+
// isolates the top clk BTerm so driver iteration doesn't hit the
5+
// top-BTerm bypass branch in Parasitics::findParasiticNet (which is
6+
// independent of PR #3194 and would otherwise leave clk unannotated).
7+
8+
module sub (din, sub_clk, dout);
9+
input din;
10+
input sub_clk;
11+
output dout;
12+
13+
wire q_int;
14+
15+
DFF_X1 ff_sub (.D(din), .CK(sub_clk), .Q(q_int));
16+
BUF_X1 buf_sub (.A(q_int), .Z(dout));
17+
endmodule
18+
19+
module top (in, clk, out);
20+
input in;
21+
input clk;
22+
output out;
23+
24+
wire clk_int;
25+
wire midnet;
26+
wire intermediate;
27+
28+
BUF_X1 ck_buf (.A(clk), .Z(clk_int));
29+
DFF_X1 ff_top (.D(in), .CK(clk_int), .Q(midnet));
30+
sub sub_inst (.din(midnet), .sub_clk(clk_int), .dout(intermediate));
31+
DFF_X1 ff_out (.D(intermediate), .CK(clk_int), .Q(out));
32+
endmodule

0 commit comments

Comments
 (0)