From 0c5293410076307f99859b9c83296f6f160a47f5 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 26 May 2024 15:17:58 +0200
Subject: [PATCH 01/13] Trying a solution for issue #1719, part 2
The solution is to drop clusters that have no area
and not connections downward. This implies, we cannot
connect from upward to such clusters - i.e. we cannot
force a pin inside a subcircuit with a plain text. We
need some polygon at least. This is not a problem as
texts were not enough so far anyway.
---
src/db/db/dbHierNetworkProcessor.cc | 21 ++++++
src/lvs/unit_tests/lvsSimpleTests.cc | 12 ++++
testdata/lvs/stray_texts.gds | Bin 0 -> 1742 bytes
testdata/lvs/stray_texts1.cir | 12 ++++
testdata/lvs/stray_texts1.l2n | 98 +++++++++++++++++++++++++++
testdata/lvs/stray_texts1.lvs | 28 ++++++++
testdata/lvs/stray_texts2.cir | 12 ++++
testdata/lvs/stray_texts2.l2n | 96 ++++++++++++++++++++++++++
testdata/lvs/stray_texts2.lvs | 25 +++++++
9 files changed, 304 insertions(+)
create mode 100644 testdata/lvs/stray_texts.gds
create mode 100644 testdata/lvs/stray_texts1.cir
create mode 100644 testdata/lvs/stray_texts1.l2n
create mode 100644 testdata/lvs/stray_texts1.lvs
create mode 100644 testdata/lvs/stray_texts2.cir
create mode 100644 testdata/lvs/stray_texts2.l2n
create mode 100644 testdata/lvs/stray_texts2.lvs
diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc
index bd7dbd903..4c868b8fa 100644
--- a/src/db/db/dbHierNetworkProcessor.cc
+++ b/src/db/db/dbHierNetworkProcessor.cc
@@ -2903,11 +2903,32 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c
}
bs2.process (*rec, 1 /*touching*/, local_cluster_box_convert (), cibc);
+
}
// join local clusters which got connected by child clusters
rec->finish_cluster_to_instance_interactions ();
+ {
+ // remove empty or point-like clusters which do not make a downward connection - i.e. from stray texts.
+ // This implies, we cannot connect from upward down to such nets too. In other words: to force a pin,
+ // inside a cell we need more than a text.
+ // (issue #1719, part 2)
+ std::vector::id_type> to_delete;
+ for (typename connected_clusters::const_iterator c = local.begin (); c != local.end (); ++c) {
+ box_type bbox = c->bbox ();
+ if ((bbox.empty () || (bbox.width () == 0 && bbox.height () == 0)) && local.connections_for_cluster (c->id ()).empty ()) {
+ to_delete.push_back (c->id ());
+ }
+ }
+ for (auto i = to_delete.begin (); i != to_delete.end (); ++i) {
+ local.remove_cluster (*i);
+ }
+ if (tl::verbosity () >= m_base_verbosity + 20) {
+ tl::info << "Removed " << to_delete.size () << " clusters because they are point-like or empty and do not have connections downward (stray texts)";
+ }
+ }
+
if (tl::verbosity () >= m_base_verbosity + 20) {
tl::info << "Cluster build cache statistics (instance to shape cache): size=" << rec->cluster_cache_size () << ", hits=" << rec->cluster_cache_hits () << ", misses=" << rec->cluster_cache_misses ();
}
diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc
index 1f06fefcf..050f039eb 100644
--- a/src/lvs/unit_tests/lvsSimpleTests.cc
+++ b/src/lvs/unit_tests/lvsSimpleTests.cc
@@ -338,3 +338,15 @@ TEST(55_SoftConnectionSecondLevel)
{
run_test (_this, "soft_connect6", "soft_connect6.gds", true, false /*no LVS*/);
}
+
+// Issue #1719, part 2
+TEST(60_StrayTextsDoNotMakeNets)
+{
+ run_test (_this, "stray_texts1", "stray_texts.gds", true, false /*no LVS*/);
+}
+
+// Issue #1719, part 2
+TEST(61_StrayTextsDoNotMakeNets)
+{
+ run_test (_this, "stray_texts2", "stray_texts.gds", true, false /*no LVS*/);
+}
diff --git a/testdata/lvs/stray_texts.gds b/testdata/lvs/stray_texts.gds
new file mode 100644
index 0000000000000000000000000000000000000000..d97c2a0da4043fb3b5b83577beed7bfb781acf79
GIT binary patch
literal 1742
zcma)+ze^lZ5XZm!ZtvZCcLs9_5#>q=K_o&NNs54a1`p34g@ss%Sc;?yVqsycbt==O
z2uYX9!aqPHMT(H(2q{wq5wVxM^*j4^yd$~i?ZNUnX6HNeW@hKX!k9Hw15@~mJVsGO
z1a$vLWNf2813b>Aqnx|2>&`D!JL$;}3~(gDv7^}{FD1XD+DWgzv_U=l
zCp64iu6C$)?O*wBeoth6b~xZyQkE&k&l%+ccEnDzl`<>8Z|es$Jk8?E9B;G6Wz6^V
zZA)CX>+PzL-_IXDzy4*vDGqG%
zB;RE+bLmOa8^(0sFgIY_ZO)NhG;8UGCRDr75wx(Kp`Y4aM6*^lg6oj%pYB^z^Op
zeM88Hn`y3;YEPI<^Z)!TY|QzEW7Kg&^UsuOzh7_n`JO9b_o+ML4YQ+EdqQvi?(@rs
tDES?eyjq_}PoGPPFJ#^&D!(b!F7)+J`tJOs|KMkY6Q$ZadTv`7;ue3kFFpVO
literal 0
HcmV?d00001
diff --git a/testdata/lvs/stray_texts1.cir b/testdata/lvs/stray_texts1.cir
new file mode 100644
index 000000000..daf84569f
--- /dev/null
+++ b/testdata/lvs/stray_texts1.cir
@@ -0,0 +1,12 @@
+* Extracted by KLayout
+
+.SUBCKT TOP
+X$1 \$2 \$5 \$4 E \$1 MIDDLE
+.ENDS TOP
+
+.SUBCKT MIDDLE B \$I4 \$I3 \$I2 \$I1
+X$1 \$I1 B \$I3 \$I4 \$I2 F CHILD
+.ENDS MIDDLE
+
+.SUBCKT CHILD A B C D \$8 \$9
+.ENDS CHILD
diff --git a/testdata/lvs/stray_texts1.l2n b/testdata/lvs/stray_texts1.l2n
new file mode 100644
index 000000000..04c1dbed5
--- /dev/null
+++ b/testdata/lvs/stray_texts1.l2n
@@ -0,0 +1,98 @@
+#%l2n-klayout
+W(TOP)
+U(0.001)
+L(l1 '1/0')
+L(l2 '1/0')
+L(l3 '2/0')
+C(l1 l2 l3)
+C(l2 l1 l2 l3)
+C(l3 l1 l2 l3)
+X(CHILD
+ R((-1230 410) (4330 220))
+ N(1 I(A)
+ J(l1 A (-560 550))
+ R(l2 (-80 -80) (170 160))
+ )
+ N(2 I(B)
+ J(l1 B (660 510))
+ J(l1 B (560 10))
+ R(l2 (-650 -90) (160 150))
+ R(l2 (410 -140) (140 160))
+ )
+ N(3 I(C)
+ J(l1 C (-1160 530))
+ R(l2 (-70 -90) (160 170))
+ )
+ N(4 I(D)
+ J(l1 D (1820 510))
+ R(l2 (-70 -90) (160 160))
+ )
+ N(5
+ R(l2 (2370 410) (170 200))
+ )
+ N(6
+ R(l2 (2910 430) (190 200))
+ )
+ P(1 I(A))
+ P(2 I(B))
+ P(3 I(C))
+ P(4 I(D))
+ P(5)
+ P(6)
+)
+X(MIDDLE
+ R((-1230 410) (4330 220))
+ N(1 I(B)
+ J(l1 B (640 520))
+ J(l1 B (550 0))
+ )
+ N(2 I(F)
+ J(l1 F (3000 510))
+ )
+ N(3)
+ N(4)
+ N(5)
+ N(6)
+ P(1 I(B))
+ P(3)
+ P(4)
+ P(5)
+ P(6)
+ X(1 CHILD Y(0 0)
+ P(0 6)
+ P(1 1)
+ P(2 4)
+ P(3 3)
+ P(4 5)
+ P(5 2)
+ )
+)
+X(TOP
+ R((-1280 -190) (4350 840))
+ N(1
+ R(l3 (-680 -160) (170 760))
+ R(l3 (-170 -790) (860 270))
+ R(l3 (-200 -270) (220 780))
+ )
+ N(2
+ R(l3 (530 -180) (220 790))
+ R(l3 (-220 -790) (790 180))
+ R(l3 (-260 -180) (260 810))
+ )
+ N(3 I(E)
+ J(l1 E (2400 460))
+ )
+ N(4
+ R(l3 (-1280 -150) (210 750))
+ )
+ N(5
+ R(l3 (1660 -190) (240 840))
+ )
+ X(1 MIDDLE Y(-30 -40)
+ P(0 2)
+ P(1 5)
+ P(2 4)
+ P(3 3)
+ P(4 1)
+ )
+)
diff --git a/testdata/lvs/stray_texts1.lvs b/testdata/lvs/stray_texts1.lvs
new file mode 100644
index 000000000..8022443d6
--- /dev/null
+++ b/testdata/lvs/stray_texts1.lvs
@@ -0,0 +1,28 @@
+
+$lvs_test_source && source($lvs_test_source)
+
+if $lvs_test_target_l2n
+ report_netlist($lvs_test_target_l2n)
+else
+ report_netlist
+end
+
+writer = write_spice(true, false)
+$lvs_test_target_cir && target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
+
+deep
+
+# separate labels and polygons
+
+l1l = labels(1, 0)
+l1 = polygons(1, 0)
+l2 = input(2, 0)
+
+connect(l1l, l1)
+connect(l1l, l2)
+connect(l1, l2)
+
+connect_implicit("*", "*")
+
+netlist
+
diff --git a/testdata/lvs/stray_texts2.cir b/testdata/lvs/stray_texts2.cir
new file mode 100644
index 000000000..267834fdc
--- /dev/null
+++ b/testdata/lvs/stray_texts2.cir
@@ -0,0 +1,12 @@
+* Extracted by KLayout
+
+.SUBCKT TOP
+X$1 \$2 \$5 \$4 E \$1 MIDDLE
+.ENDS TOP
+
+.SUBCKT MIDDLE B \$I4 \$I3 \$I2 \$I1
+X$1 \$I1 B \$I3 \$I4 \$I2 F CHILD
+.ENDS MIDDLE
+
+.SUBCKT CHILD A B C D \$6 \$7
+.ENDS CHILD
diff --git a/testdata/lvs/stray_texts2.l2n b/testdata/lvs/stray_texts2.l2n
new file mode 100644
index 000000000..a014cac50
--- /dev/null
+++ b/testdata/lvs/stray_texts2.l2n
@@ -0,0 +1,96 @@
+#%l2n-klayout
+W(TOP)
+U(0.001)
+L(l1 '1/0')
+L(l2 '2/0')
+C(l1 l1 l2)
+C(l2 l1 l2)
+X(CHILD
+ R((-1230 410) (4330 220))
+ N(1 I(A)
+ R(l1 (-640 470) (170 160))
+ R(l1 (-90 -80) (0 0))
+ )
+ N(2 I(B)
+ R(l1 (570 430) (160 150))
+ R(l1 (-70 -70) (0 0))
+ R(l1 (480 -70) (140 160))
+ R(l1 (-60 -80) (0 0))
+ )
+ N(3 I(C)
+ R(l1 (-1230 440) (160 170))
+ R(l1 (-90 -80) (0 0))
+ )
+ N(4 I(D)
+ R(l1 (1750 420) (160 160))
+ R(l1 (-90 -70) (0 0))
+ )
+ N(5
+ R(l1 (2370 410) (170 200))
+ )
+ N(6
+ R(l1 (2910 430) (190 200))
+ )
+ P(1 I(A))
+ P(2 I(B))
+ P(3 I(C))
+ P(4 I(D))
+ P(5)
+ P(6)
+)
+X(MIDDLE
+ R((-1230 410) (4330 220))
+ N(1 I(B)
+ R(l1 (640 520) (0 0))
+ R(l1 (550 0) (0 0))
+ )
+ N(2 I(F)
+ R(l1 (3000 510) (0 0))
+ )
+ N(3)
+ N(4)
+ N(5)
+ N(6)
+ P(1 I(B))
+ P(3)
+ P(4)
+ P(5)
+ P(6)
+ X(1 CHILD Y(0 0)
+ P(0 6)
+ P(1 1)
+ P(2 4)
+ P(3 3)
+ P(4 5)
+ P(5 2)
+ )
+)
+X(TOP
+ R((-1280 -190) (4350 840))
+ N(1
+ R(l2 (-680 -160) (170 760))
+ R(l2 (-170 -790) (860 270))
+ R(l2 (-200 -270) (220 780))
+ )
+ N(2
+ R(l2 (530 -180) (220 790))
+ R(l2 (-220 -790) (790 180))
+ R(l2 (-260 -180) (260 810))
+ )
+ N(3 I(E)
+ R(l1 (2400 460) (0 0))
+ )
+ N(4
+ R(l2 (-1280 -150) (210 750))
+ )
+ N(5
+ R(l2 (1660 -190) (240 840))
+ )
+ X(1 MIDDLE Y(-30 -40)
+ P(0 2)
+ P(1 5)
+ P(2 4)
+ P(3 3)
+ P(4 1)
+ )
+)
diff --git a/testdata/lvs/stray_texts2.lvs b/testdata/lvs/stray_texts2.lvs
new file mode 100644
index 000000000..993f44944
--- /dev/null
+++ b/testdata/lvs/stray_texts2.lvs
@@ -0,0 +1,25 @@
+
+$lvs_test_source && source($lvs_test_source)
+
+if $lvs_test_target_l2n
+ report_netlist($lvs_test_target_l2n)
+else
+ report_netlist
+end
+
+writer = write_spice(true, false)
+$lvs_test_target_cir && target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
+
+deep
+
+# polygons and labels on same layer
+
+l1 = input(1, 0)
+l2 = input(2, 0)
+
+connect(l1, l2)
+
+connect_implicit("*", "*")
+
+netlist
+
From 35d9068f725c5c1f8d09d65e26f8ab317c458fcd Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 26 May 2024 17:08:34 +0200
Subject: [PATCH 02/13] Updating unit tests - stray text nets are gone.
---
src/db/db/dbHierNetworkProcessor.cc | 2 +-
testdata/lvs/bbdevices1.cir | 4 ----
testdata/lvs/bbdevices1.lvsdb | 12 ------------
testdata/lvs/bbdevices2.cir | 4 ----
testdata/lvs/bbdevices2.lvsdb | 12 ------------
testdata/lvs/bbdevices3.cir | 4 ----
testdata/lvs/bbdevices3.lvsdb | 12 ------------
testdata/lvs/bbdevices4.cir | 4 ----
testdata/lvs/bbdevices4.lvsdb | 12 ------------
testdata/lvs/bbdevices5.cir | 4 ----
testdata/lvs/bbdevices5.lvsdb | 12 ------------
testdata/lvs/bbdevices6.cir | 4 ----
testdata/lvs/bbdevices6.lvsdb | 12 ------------
13 files changed, 1 insertion(+), 97 deletions(-)
diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc
index 4c868b8fa..4c5c089ea 100644
--- a/src/db/db/dbHierNetworkProcessor.cc
+++ b/src/db/db/dbHierNetworkProcessor.cc
@@ -2917,7 +2917,7 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c
std::vector::id_type> to_delete;
for (typename connected_clusters::const_iterator c = local.begin (); c != local.end (); ++c) {
box_type bbox = c->bbox ();
- if ((bbox.empty () || (bbox.width () == 0 && bbox.height () == 0)) && local.connections_for_cluster (c->id ()).empty ()) {
+ if ((bbox.empty () || (bbox.width () == 0 && bbox.height () == 0)) && c->get_global_nets ().empty () && local.connections_for_cluster (c->id ()).empty ()) {
to_delete.push_back (c->id ());
}
}
diff --git a/testdata/lvs/bbdevices1.cir b/testdata/lvs/bbdevices1.cir
index 80ce62dca..2738f6c53 100644
--- a/testdata/lvs/bbdevices1.cir
+++ b/testdata/lvs/bbdevices1.cir
@@ -47,7 +47,6 @@ X$14 4 BBGATEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
-* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@@ -55,7 +54,6 @@ X$14 4 BBGATEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
-* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@@ -63,7 +61,6 @@ X$14 4 BBGATEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
-* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@@ -71,5 +68,4 @@ X$14 4 BBGATEST
.SUBCKT BWBTEST 2
* net 1 B
* net 2 A
-* net 3 BWBTEST
.ENDS BWBTEST
diff --git a/testdata/lvs/bbdevices1.lvsdb b/testdata/lvs/bbdevices1.lvsdb
index 27cd08e35..482fe39a9 100644
--- a/testdata/lvs/bbdevices1.lvsdb
+++ b/testdata/lvs/bbdevices1.lvsdb
@@ -60,9 +60,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
- net(3 name(BWBTEST)
- rect(l15 (754500 -114000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -82,9 +79,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
- net(3 name(FWBTEST)
- rect(l3 (798000 565500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -104,9 +98,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
- net(3 name(FBGATEST)
- rect(l3 (-417000 610500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -126,9 +117,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
- net(3 name(BBGATEST)
- rect(l15 (-422000 -313000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
diff --git a/testdata/lvs/bbdevices2.cir b/testdata/lvs/bbdevices2.cir
index bac395789..cad12158b 100644
--- a/testdata/lvs/bbdevices2.cir
+++ b/testdata/lvs/bbdevices2.cir
@@ -48,7 +48,6 @@ X$14 7 6 BBGATEST
.SUBCKT BBGATEST 1 2
* net 1 B
* net 2 A
-* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@@ -57,7 +56,6 @@ X$14 7 6 BBGATEST
.SUBCKT FBGATEST 1 2
* net 1 B
* net 2 A
-* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@@ -66,7 +64,6 @@ X$14 7 6 BBGATEST
.SUBCKT FWBTEST 1 2
* net 1 B
* net 2 A
-* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@@ -75,5 +72,4 @@ X$14 7 6 BBGATEST
.SUBCKT BWBTEST 1 2
* net 1 B
* net 2 A
-* net 3 BWBTEST
.ENDS BWBTEST
diff --git a/testdata/lvs/bbdevices2.lvsdb b/testdata/lvs/bbdevices2.lvsdb
index c9372a16f..49b82b677 100644
--- a/testdata/lvs/bbdevices2.lvsdb
+++ b/testdata/lvs/bbdevices2.lvsdb
@@ -60,9 +60,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
- net(3 name(BWBTEST)
- rect(l15 (754500 -114000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -83,9 +80,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
- net(3 name(FWBTEST)
- rect(l3 (798000 565500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -106,9 +100,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
- net(3 name(FBGATEST)
- rect(l3 (-417000 610500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -129,9 +120,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
- net(3 name(BBGATEST)
- rect(l15 (-422000 -313000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
diff --git a/testdata/lvs/bbdevices3.cir b/testdata/lvs/bbdevices3.cir
index 82abe4cee..675240f7b 100644
--- a/testdata/lvs/bbdevices3.cir
+++ b/testdata/lvs/bbdevices3.cir
@@ -47,7 +47,6 @@ X$14 4 BBGATEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
-* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@@ -55,7 +54,6 @@ X$14 4 BBGATEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
-* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@@ -63,7 +61,6 @@ X$14 4 BBGATEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
-* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@@ -71,5 +68,4 @@ X$14 4 BBGATEST
.SUBCKT BWBTEST 1
* net 1 B
* net 2 A
-* net 3 BWBTEST
.ENDS BWBTEST
diff --git a/testdata/lvs/bbdevices3.lvsdb b/testdata/lvs/bbdevices3.lvsdb
index 819e2dbe9..1f7335c95 100644
--- a/testdata/lvs/bbdevices3.lvsdb
+++ b/testdata/lvs/bbdevices3.lvsdb
@@ -60,9 +60,6 @@ layout(
rect(l15 (830000 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
- net(3 name(BWBTEST)
- rect(l15 (757500 -114000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -82,9 +79,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
- net(3 name(FWBTEST)
- rect(l3 (798000 565500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -104,9 +98,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
- net(3 name(FBGATEST)
- rect(l3 (-417000 610500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -126,9 +117,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
- net(3 name(BBGATEST)
- rect(l15 (-422000 -313000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
diff --git a/testdata/lvs/bbdevices4.cir b/testdata/lvs/bbdevices4.cir
index 61fcf18da..4a99dee30 100644
--- a/testdata/lvs/bbdevices4.cir
+++ b/testdata/lvs/bbdevices4.cir
@@ -20,7 +20,6 @@ X$13 4 BBGATEST
.SUBCKT BWBTEST
* net 1 B
* net 2 A
-* net 3 BWBTEST
.ENDS BWBTEST
* cell FDPTEST
@@ -52,7 +51,6 @@ X$13 4 BBGATEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
-* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@@ -60,7 +58,6 @@ X$13 4 BBGATEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
-* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@@ -68,5 +65,4 @@ X$13 4 BBGATEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
-* net 3 FWBTEST
.ENDS FWBTEST
diff --git a/testdata/lvs/bbdevices4.lvsdb b/testdata/lvs/bbdevices4.lvsdb
index 5a9aa2c04..fe5d26b4a 100644
--- a/testdata/lvs/bbdevices4.lvsdb
+++ b/testdata/lvs/bbdevices4.lvsdb
@@ -60,9 +60,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
- net(3 name(FWBTEST)
- rect(l3 (798000 565500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -82,9 +79,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
- net(3 name(FBGATEST)
- rect(l3 (-417000 610500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -104,9 +98,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
- net(3 name(BBGATEST)
- rect(l15 (-422000 -313000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -186,9 +177,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
- net(3 name(BWBTEST)
- rect(l15 (754500 -114000) (0 0))
- )
)
circuit(testall
diff --git a/testdata/lvs/bbdevices5.cir b/testdata/lvs/bbdevices5.cir
index de64bad72..5b4ecfb20 100644
--- a/testdata/lvs/bbdevices5.cir
+++ b/testdata/lvs/bbdevices5.cir
@@ -47,7 +47,6 @@ X$14 5 BWBTEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
-* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@@ -55,7 +54,6 @@ X$14 5 BWBTEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
-* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@@ -63,7 +61,6 @@ X$14 5 BWBTEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
-* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@@ -71,5 +68,4 @@ X$14 5 BWBTEST
.SUBCKT BWBTEST 2
* net 1 B
* net 2 A
-* net 3 BWBTEST
.ENDS BWBTEST
diff --git a/testdata/lvs/bbdevices5.lvsdb b/testdata/lvs/bbdevices5.lvsdb
index 56183ddcd..42cef8ab3 100644
--- a/testdata/lvs/bbdevices5.lvsdb
+++ b/testdata/lvs/bbdevices5.lvsdb
@@ -60,9 +60,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
- net(3 name(BWBTEST)
- rect(l15 (754500 -114000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -82,9 +79,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
- net(3 name(FWBTEST)
- rect(l3 (798000 565500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -104,9 +98,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
- net(3 name(FBGATEST)
- rect(l3 (-417000 610500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -126,9 +117,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
- net(3 name(BBGATEST)
- rect(l15 (-422000 -313000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
diff --git a/testdata/lvs/bbdevices6.cir b/testdata/lvs/bbdevices6.cir
index 39fba7dc1..22cc76a10 100644
--- a/testdata/lvs/bbdevices6.cir
+++ b/testdata/lvs/bbdevices6.cir
@@ -47,7 +47,6 @@ X$14 3 FBGATEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
-* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@@ -55,7 +54,6 @@ X$14 3 FBGATEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
-* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@@ -63,7 +61,6 @@ X$14 3 FBGATEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
-* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@@ -71,5 +68,4 @@ X$14 3 FBGATEST
.SUBCKT BWBTEST 2
* net 1 B
* net 2 A
-* net 3 BWBTEST
.ENDS BWBTEST
diff --git a/testdata/lvs/bbdevices6.lvsdb b/testdata/lvs/bbdevices6.lvsdb
index d15a89969..b0264ad49 100644
--- a/testdata/lvs/bbdevices6.lvsdb
+++ b/testdata/lvs/bbdevices6.lvsdb
@@ -60,9 +60,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
- net(3 name(BWBTEST)
- rect(l15 (754500 -114000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -82,9 +79,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
- net(3 name(FWBTEST)
- rect(l3 (798000 565500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
@@ -104,9 +98,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
- net(3 name(FBGATEST)
- rect(l3 (-417000 610500) (0 0))
- )
# Outgoing pins and their connections to nets
pin(1 name(B))
@@ -126,9 +117,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
- net(3 name(BBGATEST)
- rect(l15 (-422000 -313000) (0 0))
- )
# Outgoing pins and their connections to nets
pin(2 name(A))
From 994b23abf6fed97e7a23833d97ebf4e3a02b4be4 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 26 May 2024 17:23:50 +0200
Subject: [PATCH 03/13] Refining solution of issue #1719, part 2
---
src/db/db/dbHierNetworkProcessor.cc | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc
index 4c5c089ea..7f2acce95 100644
--- a/src/db/db/dbHierNetworkProcessor.cc
+++ b/src/db/db/dbHierNetworkProcessor.cc
@@ -2817,6 +2817,18 @@ private:
std::map m_global_net_to_entries;
};
+template
+struct is_for_nets
+{
+ static bool value () { return false; }
+};
+
+template <>
+struct is_for_nets
+{
+ static bool value () { return true; }
+};
+
}
template
@@ -2909,7 +2921,8 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c
// join local clusters which got connected by child clusters
rec->finish_cluster_to_instance_interactions ();
- {
+ if (is_for_nets::value ()) {
+
// remove empty or point-like clusters which do not make a downward connection - i.e. from stray texts.
// This implies, we cannot connect from upward down to such nets too. In other words: to force a pin,
// inside a cell we need more than a text.
@@ -2927,6 +2940,7 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c
if (tl::verbosity () >= m_base_verbosity + 20) {
tl::info << "Removed " << to_delete.size () << " clusters because they are point-like or empty and do not have connections downward (stray texts)";
}
+
}
if (tl::verbosity () >= m_base_verbosity + 20) {
From 14b1fddcc54ea9ae9dcc5ea4767a4dca0f70c728 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 26 May 2024 19:32:15 +0200
Subject: [PATCH 04/13] Trying to improve must-connect error messages
* Avoid repetitions
* Include geometry for nets if possible
* Better wording
* All joined nets tested together - leaner code
---
src/db/db/dbLayoutToNetlist.cc | 194 ++++++++++++++----
src/db/db/dbLayoutToNetlist.h | 4 +-
src/lvs/unit_tests/lvsTests.cc | 2 +-
testdata/lvs/double_height2.lvsdb | 6 +-
testdata/lvs/double_height2_texts.lvsdb | 6 +-
testdata/lvs/must_connect1.lvsdb | 2 +-
testdata/lvs/must_connect1_tl.lvsdb | 2 +-
testdata/lvs/must_connect2.lvsdb | 6 +-
.../ringo_simple_implicit_connections.lvsdb.1 | 2 +-
.../ringo_simple_implicit_connections.lvsdb.2 | 2 +-
testdata/lvs/test_22a.lvsdb.1 | 2 +-
testdata/lvs/test_22a.lvsdb.2 | 2 +-
testdata/lvs/test_22b.lvsdb.1 | 2 +-
testdata/lvs/test_22b.lvsdb.2 | 2 +-
testdata/lvs/test_22c.lvsdb.1 | 2 +-
testdata/lvs/test_22c.lvsdb.2 | 2 +-
testdata/lvs/test_22d.lvsdb.1 | 2 +-
testdata/lvs/test_22d.lvsdb.2 | 2 +-
testdata/lvs/test_22d.lvsdb.3 | 2 +-
19 files changed, 176 insertions(+), 68 deletions(-)
diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc
index bc865bdc5..9275b442f 100644
--- a/src/db/db/dbLayoutToNetlist.cc
+++ b/src/db/db/dbLayoutToNetlist.cc
@@ -508,12 +508,37 @@ void LayoutToNetlist::do_join_nets (db::Circuit &c, const std::vector
return;
}
+ check_must_connect (c, nets);
+
for (auto n = nets.begin () + 1; n != nets.end (); ++n) {
- check_must_connect (c, *nets [0], **n);
c.join_nets (nets [0], *n);
}
}
+void LayoutToNetlist::check_must_connect (const db::Circuit &c, const std::vector &nets)
+{
+ std::vector unique_nets;
+ unique_nets.reserve (nets.size ());
+ std::set seen;
+ for (auto n = nets.begin (); n != nets.end (); ++n) {
+ if (seen.find (*n) == seen.end ()) {
+ seen.insert (*n);
+ unique_nets.push_back (*n);
+ }
+ }
+ if (unique_nets.size () < size_t (2)) {
+ return;
+ }
+
+ bool same_names = true;
+ for (auto n = unique_nets.begin () + 1; n != unique_nets.end () && same_names; ++n) {
+ same_names = (unique_nets.front ()->expanded_name () == (*n)->expanded_name ());
+ }
+
+ std::vector path;
+ check_must_connect_impl (c, unique_nets, c, unique_nets, path, same_names);
+}
+
static std::string subcircuit_to_string (const db::SubCircuit &sc)
{
if (! sc.name ().empty ()) {
@@ -533,14 +558,31 @@ static db::DPolygon subcircuit_geometry (const db::SubCircuit &sc, const db::Lay
return db::DPolygon (sc.trans () * dbox);
}
-void LayoutToNetlist::check_must_connect (const db::Circuit &c, const db::Net &a, const db::Net &b)
+static db::DBox net_geometry_box (const db::Circuit &c, const db::Net *net, const db::Layout *layout, const db::hier_clusters &net_clusters)
{
- if (&a == &b) {
- return;
+ if (! layout || ! net) {
+ return db::DBox ();
}
- std::vector path;
- check_must_connect_impl (c, a, b, c, a, b, path);
+ auto nc = net_clusters.clusters_per_cell (c.cell_index ());
+ auto lc = nc.cluster_by_id (net->cluster_id ());
+
+ return db::CplxTrans (layout->dbu ()) * lc.bbox ();
+}
+
+static db::DPolygon net_geometry (const db::Circuit &c, const db::Net *net, const db::Layout *layout, const db::hier_clusters &net_clusters)
+{
+ auto box = net_geometry_box (c, net, layout, net_clusters);
+ return box.empty () ? db::DPolygon () : db::DPolygon (box);
+}
+
+static db::DPolygon net_geometry (const db::Circuit &c, const std::vector &nets, const db::Layout *layout, const db::hier_clusters &net_clusters)
+{
+ db::DBox box;
+ for (auto n = nets.begin (); n != nets.end (); ++n) {
+ box += net_geometry_box (c, *n, layout, net_clusters);
+ }
+ return box.empty () ? db::DPolygon () : db::DPolygon (box);
}
static std::string path_msg (const std::vector &path)
@@ -562,46 +604,98 @@ static std::string path_msg (const std::vector &path)
return msg;
}
-void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::Net &a, const db::Net &b, const db::Circuit &c_org, const db::Net &a_org, const db::Net &b_org, std::vector &path)
+static bool all_nets_are_same (const std::vector &nets)
+{
+ for (auto n = nets.begin () + 1; n != nets.end (); ++n) {
+ if (*n != nets.front ()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool no_pins_on_any_net (const std::vector &nets)
+{
+ for (auto n = nets.begin (); n != nets.end (); ++n) {
+ if ((*n)->begin_pins () == (*n)->end_pins ()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static std::string net_names_msg (const std::vector &nets)
+{
+ std::set names;
+ for (auto n = nets.begin (); n != nets.end (); ++n) {
+ names.insert ((*n)->expanded_name ());
+ }
+
+ std::string msg;
+ size_t num = names.size ();
+ size_t i = 0;
+ for (auto n = names.begin (); n != names.end (); ++n, ++i) {
+ if (i > 0) {
+ if (i + 1 < num) {
+ msg += ", ";
+ } else {
+ msg += tl::to_string (tr (" and "));
+ }
+ }
+ msg += *n;
+ }
+
+ return msg;
+}
+
+void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const std::vector &nets, const db::Circuit &c_org, const std::vector &nets_org, std::vector &path, bool same_names)
{
if (c.begin_refs () != c.end_refs () && path.empty ()) {
- if (a.begin_pins () == a.end_pins ()) {
- db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected to outside")), a_org.expanded_name ()));
- error.set_cell_name (c.name ());
- error.set_category_name ("must-connect");
- log_entry (error);
- }
- if (b.begin_pins () == b.end_pins ()) {
- db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected to outside")), a_org.expanded_name ()));
- error.set_cell_name (c.name ());
- error.set_category_name ("must-connect");
- log_entry (error);
+ for (auto n = nets.begin (); n != nets.end (); ++n) {
+
+ if ((*n)->begin_pins () == (*n)->end_pins ()) {
+ std::string msg;
+ if (same_names) {
+ msg = tl::sprintf (tl::to_string (tr ("Must-connect subnet of %s does not have any pin at all")), (*n)->expanded_name ());
+ } else {
+ msg = tl::sprintf (tl::to_string (tr ("Must-connect net %s does not have any pin at all")), (*n)->expanded_name ());
+ }
+ db::LogEntryData error (db::Error, msg);
+ error.set_cell_name (c.name ());
+ error.set_geometry (net_geometry (c, *n, internal_layout (), net_clusters ()));
+ error.set_category_name ("must-connect");
+ log_entry (error);
+ }
+
}
- } else if (c.begin_refs () == c.end_refs () || a.begin_pins () == a.end_pins () || b.begin_pins () == b.end_pins ()) {
+ } else if (c.begin_refs () == c.end_refs () || no_pins_on_any_net (nets)) {
- if (a_org.expanded_name () == b_org.expanded_name ()) {
+ if (same_names) {
if (path.empty ()) {
- db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name ()) + path_msg (path));
+ db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect subnets of %s must be connected further up in the hierarchy - this is an error at chip top level")), nets_org.front ()->expanded_name ()) + path_msg (path));
warn.set_cell_name (c.name ());
+ warn.set_geometry (net_geometry (c, nets, internal_layout (), net_clusters ()));
warn.set_category_name ("must-connect");
log_entry (warn);
} else {
- db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), c_org.name ()) + path_msg (path));
+ db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect subnets of %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), nets_org.front ()->expanded_name (), c_org.name ()) + path_msg (path));
warn.set_cell_name (c.name ());
warn.set_geometry (subcircuit_geometry (*path.back (), internal_layout ()));
warn.set_category_name ("must-connect");
log_entry (warn);
}
} else {
+ std::string net_names = net_names_msg (nets_org);
if (path.empty ()) {
- db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), b_org.expanded_name ()) + path_msg (path));
+ db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s must be connected further up in the hierarchy - this is an error at chip top level")), net_names) + path_msg (path));
warn.set_cell_name (c.name ());
+ warn.set_geometry (net_geometry (c, nets, internal_layout (), net_clusters ()));
warn.set_category_name ("must-connect");
log_entry (warn);
} else {
- db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), b_org.expanded_name (), c_org.name ()) + path_msg (path));
+ db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), net_names, c_org.name ()) + path_msg (path));
warn.set_cell_name (c.name ());
warn.set_geometry (subcircuit_geometry (*path.back (), internal_layout ()));
warn.set_category_name ("must-connect");
@@ -611,35 +705,49 @@ void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::N
}
- if (a.begin_pins () != a.end_pins () && b.begin_pins () != b.end_pins ()) {
+ if (! no_pins_on_any_net (nets)) {
for (auto ref = c.begin_refs (); ref != c.end_refs (); ++ref) {
const db::SubCircuit &sc = *ref;
// TODO: consider the case of multiple pins on a net (rare)
- const db::Net *net_a = sc.net_for_pin (a.begin_pins ()->pin_id ());
- const db::Net *net_b = sc.net_for_pin (b.begin_pins ()->pin_id ());
+ std::vector new_nets;
+ new_nets.reserve (nets.size ());
+
+ bool failed = false;
+ std::set seen;
+ size_t i = 0;
+ for (auto n = nets.begin (); n != nets.end (); ++n, ++i) {
+
+ if (seen.find (*n) != seen.end ()) {
+ continue;
+ }
+ seen.insert (*n);
+
+ const db::Net *new_net = sc.net_for_pin ((*n)->begin_pins ()->pin_id ());
+ new_nets.push_back (new_net);
+
+ if (new_net == 0) {
+ failed = true;
+ std::string msg;
+ if (same_names) {
+ msg = tl::sprintf (tl::to_string (tr ("Must-connect subnet of %s of circuit %s has no outside connection at all%s")), nets_org[i]->expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path);
+ } else {
+ msg = tl::sprintf (tl::to_string (tr ("Must-connect net %s of circuit %s has no outside connection at all%s")), nets_org[i]->expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path);
+ }
+ db::LogEntryData error (db::Error, msg);
+ error.set_cell_name (sc.circuit ()->name ());
+ error.set_geometry (subcircuit_geometry (sc, internal_layout ()));
+ error.set_category_name ("must-connect");
+ log_entry (error);
+ }
- if (net_a == 0) {
- db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s of circuit %s is not connected at all%s")), a_org.expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path));
- error.set_cell_name (sc.circuit ()->name ());
- error.set_geometry (subcircuit_geometry (sc, internal_layout ()));
- error.set_category_name ("must-connect");
- log_entry (error);
}
- if (net_b == 0) {
- db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s of circuit %s is not connected at all%s")), b_org.expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path));
- error.set_cell_name (sc.circuit ()->name ());
- error.set_geometry (subcircuit_geometry (sc, internal_layout ()));
- error.set_category_name ("must-connect");
- log_entry (error);
- }
-
- if (net_a && net_b && net_a != net_b) {
+ if (! failed && ! all_nets_are_same (new_nets)) {
path.push_back (&sc);
- check_must_connect_impl (*sc.circuit (), *net_a, *net_b, c_org, a_org, b_org, path);
+ check_must_connect_impl (*sc.circuit (), new_nets, c_org, nets_org, path, same_names);
path.pop_back ();
}
diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h
index 812ee5d7b..e8c78d217 100644
--- a/src/db/db/dbLayoutToNetlist.h
+++ b/src/db/db/dbLayoutToNetlist.h
@@ -1109,8 +1109,8 @@ private:
void do_soft_connections ();
void join_nets_from_pattern (db::Circuit &c, const tl::GlobPattern &p);
void join_nets_from_pattern (db::Circuit &c, const std::set &p);
- void check_must_connect (const db::Circuit &c, const db::Net &a, const db::Net &b);
- void check_must_connect_impl (const db::Circuit &c, const db::Net &a, const db::Net &b, const db::Circuit &c_org, const db::Net &a_org, const db::Net &b_org, std::vector &path);
+ void check_must_connect (const db::Circuit &c, const std::vector &nets);
+ void check_must_connect_impl (const db::Circuit &c, const std::vector &nets, const db::Circuit &c_org, const std::vector &nets_org, std::vector &path, bool same_names);
// for debugging and testing
void place_soft_connection_diodes ();
diff --git a/src/lvs/unit_tests/lvsTests.cc b/src/lvs/unit_tests/lvsTests.cc
index a21008c38..001df63da 100644
--- a/src/lvs/unit_tests/lvsTests.cc
+++ b/src/lvs/unit_tests/lvsTests.cc
@@ -171,7 +171,7 @@ TEST(20_private)
TEST(21_private)
{
- run_test (_this, "test_21.lylvs", "test_21.cir.gz", "test_21.gds.gz", true, "test_21_4.lvsdb");
+ run_test (_this, "test_21.lylvs", "test_21.cir.gz", "test_21.gds.gz", true, "test_21_5.lvsdb");
}
// issue #1021
diff --git a/testdata/lvs/double_height2.lvsdb b/testdata/lvs/double_height2.lvsdb
index 3c2330e64..ff5e4200a 100644
--- a/testdata/lvs/double_height2.lvsdb
+++ b/testdata/lvs/double_height2.lvsdb
@@ -27,9 +27,9 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
- H(W B('Must-connect nets GND must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect'))
- H(W B('Must-connect nets R must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect'))
- H(W B('Must-connect nets R of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$1') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
+ H(W B('Must-connect subnets of GND must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect') Q('(0.27,0.8;0.27,8.4;0.32,8.4;0.32,0.8)'))
+ H(W B('Must-connect subnets of R must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect') Q('(1.48,2.37;1.48,7.46;2.61,7.46;2.61,2.37)'))
+ H(W B('Must-connect subnets of R of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$1') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS
diff --git a/testdata/lvs/double_height2_texts.lvsdb b/testdata/lvs/double_height2_texts.lvsdb
index 6dc2a6872..c5b5b94bf 100644
--- a/testdata/lvs/double_height2_texts.lvsdb
+++ b/testdata/lvs/double_height2_texts.lvsdb
@@ -27,9 +27,9 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
- H(W B('Must-connect nets GND must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect'))
- H(W B('Must-connect nets R must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect'))
- H(W B('Must-connect nets R of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$1') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
+ H(W B('Must-connect subnets of GND must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect') Q('(0.27,0.8;0.27,8.4;0.32,8.4;0.32,0.8)'))
+ H(W B('Must-connect subnets of R must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect') Q('(1.48,2.37;1.48,7.46;2.61,7.46;2.61,2.37)'))
+ H(W B('Must-connect subnets of R of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$1') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS
diff --git a/testdata/lvs/must_connect1.lvsdb b/testdata/lvs/must_connect1.lvsdb
index 6d86052d3..1d91c7e7e 100644
--- a/testdata/lvs/must_connect1.lvsdb
+++ b/testdata/lvs/must_connect1.lvsdb
@@ -27,7 +27,7 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
- H(W B('Must-connect nets VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect'))
+ H(W B('Must-connect subnets of VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect') Q('(3.61,0.7;3.61,8.89;11.365,8.89;11.365,0.7)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS
diff --git a/testdata/lvs/must_connect1_tl.lvsdb b/testdata/lvs/must_connect1_tl.lvsdb
index 0bd8468c4..fa05c7401 100644
--- a/testdata/lvs/must_connect1_tl.lvsdb
+++ b/testdata/lvs/must_connect1_tl.lvsdb
@@ -27,7 +27,7 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
- H(E B('Must-connect nets VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect'))
+ H(E B('Must-connect subnets of VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect') Q('(3.61,0.7;3.61,8.89;11.365,8.89;11.365,0.7)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS
diff --git a/testdata/lvs/must_connect2.lvsdb b/testdata/lvs/must_connect2.lvsdb
index 8a9daf6e2..9357d2c35 100644
--- a/testdata/lvs/must_connect2.lvsdb
+++ b/testdata/lvs/must_connect2.lvsdb
@@ -27,9 +27,9 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
- H(W B('Must-connect nets VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect'))
- H(W B('Must-connect nets VDD must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect'))
- H(W B('Must-connect nets VSS of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$2') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
+ H(W B('Must-connect subnets of VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect') Q('(3.61,0.7;3.61,8.89;11.365,8.89;11.365,0.7)'))
+ H(W B('Must-connect subnets of VDD must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect') Q('(2.595,4.725;2.595,4.805;11.865,4.805;11.865,4.725)'))
+ H(W B('Must-connect subnets of VSS of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$2') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS
diff --git a/testdata/lvs/ringo_simple_implicit_connections.lvsdb.1 b/testdata/lvs/ringo_simple_implicit_connections.lvsdb.1
index 576801b98..90d11e8b4 100644
--- a/testdata/lvs/ringo_simple_implicit_connections.lvsdb.1
+++ b/testdata/lvs/ringo_simple_implicit_connections.lvsdb.1
@@ -39,7 +39,7 @@ layout(
global(l10 SUBSTRATE)
# Log entries
- message(warning description('Must-connect nets VDD must be connected further up in the hierarchy - this is an error at chip top level') cell(RINGO) cat('must-connect'))
+ message(warning description('Must-connect subnets of VDD must be connected further up in the hierarchy - this is an error at chip top level') cell(RINGO) cat('must-connect') polygon('(2.95,7.25;2.95,7.4;25.1,7.4;25.1,7.25)'))
# Device class section
class(PMOS MOS4)
diff --git a/testdata/lvs/ringo_simple_implicit_connections.lvsdb.2 b/testdata/lvs/ringo_simple_implicit_connections.lvsdb.2
index 86c5148b8..145f3cd6a 100644
--- a/testdata/lvs/ringo_simple_implicit_connections.lvsdb.2
+++ b/testdata/lvs/ringo_simple_implicit_connections.lvsdb.2
@@ -39,7 +39,7 @@ layout(
global(l10 SUBSTRATE)
# Log entries
- message(warning description('Must-connect nets VDD must be connected further up in the hierarchy - this is an error at chip top level') cell(RINGO) cat('must-connect'))
+ message(warning description('Must-connect subnets of VDD must be connected further up in the hierarchy - this is an error at chip top level') cell(RINGO) cat('must-connect') polygon('(2.95,7.25;2.95,7.4;25.1,7.4;25.1,7.25)'))
# Device class section
class(PMOS MOS4)
diff --git a/testdata/lvs/test_22a.lvsdb.1 b/testdata/lvs/test_22a.lvsdb.1
index ed14452f3..3b1267688 100644
--- a/testdata/lvs/test_22a.lvsdb.1
+++ b/testdata/lvs/test_22a.lvsdb.1
@@ -71,7 +71,7 @@ layout(
global(l6 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.385,-0.305;-0.385,5.855;9.105,5.855;9.105,-0.305)'))
# Device class section
class(active_res RES)
diff --git a/testdata/lvs/test_22a.lvsdb.2 b/testdata/lvs/test_22a.lvsdb.2
index 653bea80f..bd5c980af 100644
--- a/testdata/lvs/test_22a.lvsdb.2
+++ b/testdata/lvs/test_22a.lvsdb.2
@@ -71,7 +71,7 @@ layout(
global(l6 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.385,-0.305;-0.385,5.855;9.105,5.855;9.105,-0.305)'))
# Device class section
class(active_res RES)
diff --git a/testdata/lvs/test_22b.lvsdb.1 b/testdata/lvs/test_22b.lvsdb.1
index 37f240e44..bac531746 100644
--- a/testdata/lvs/test_22b.lvsdb.1
+++ b/testdata/lvs/test_22b.lvsdb.1
@@ -71,7 +71,7 @@ layout(
global(l6 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.385,-0.305;-0.385,5.855;9.105,5.855;9.105,-0.305)'))
# Device class section
class(active_res RES)
diff --git a/testdata/lvs/test_22b.lvsdb.2 b/testdata/lvs/test_22b.lvsdb.2
index 806634244..cac410e2b 100644
--- a/testdata/lvs/test_22b.lvsdb.2
+++ b/testdata/lvs/test_22b.lvsdb.2
@@ -71,7 +71,7 @@ layout(
global(l6 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.385,-0.305;-0.385,5.855;9.105,5.855;9.105,-0.305)'))
# Device class section
class(active_res RES)
diff --git a/testdata/lvs/test_22c.lvsdb.1 b/testdata/lvs/test_22c.lvsdb.1
index f61eaa9e9..029afa97f 100644
--- a/testdata/lvs/test_22c.lvsdb.1
+++ b/testdata/lvs/test_22c.lvsdb.1
@@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)
diff --git a/testdata/lvs/test_22c.lvsdb.2 b/testdata/lvs/test_22c.lvsdb.2
index c85f87ba1..7a023acbf 100644
--- a/testdata/lvs/test_22c.lvsdb.2
+++ b/testdata/lvs/test_22c.lvsdb.2
@@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)
diff --git a/testdata/lvs/test_22d.lvsdb.1 b/testdata/lvs/test_22d.lvsdb.1
index 45e3e88fc..bb827e1c7 100644
--- a/testdata/lvs/test_22d.lvsdb.1
+++ b/testdata/lvs/test_22d.lvsdb.1
@@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)
diff --git a/testdata/lvs/test_22d.lvsdb.2 b/testdata/lvs/test_22d.lvsdb.2
index 22c7b9fa6..7b32708a2 100644
--- a/testdata/lvs/test_22d.lvsdb.2
+++ b/testdata/lvs/test_22d.lvsdb.2
@@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)
diff --git a/testdata/lvs/test_22d.lvsdb.3 b/testdata/lvs/test_22d.lvsdb.3
index 5c772a9c5..d1f5b2a20 100644
--- a/testdata/lvs/test_22d.lvsdb.3
+++ b/testdata/lvs/test_22d.lvsdb.3
@@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)
From 3edb193562df21e4e3e32c0aea3149e88e84f517 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 26 May 2024 22:55:37 +0200
Subject: [PATCH 05/13] A proposal for fixing issue #1719, part 1
---
src/db/db/dbNetlistCompare.cc | 61 ++++++++++++++++++----
src/db/db/dbNetlistCompare.h | 1 +
src/db/db/gsiDeclDbNetlist.cc | 4 +-
src/lvs/lvs/built-in-macros/_lvs_netter.rb | 31 ++++++++++-
4 files changed, 83 insertions(+), 14 deletions(-)
diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc
index 6040ba4a8..038fb9e7c 100644
--- a/src/db/db/dbNetlistCompare.cc
+++ b/src/db/db/dbNetlistCompare.cc
@@ -86,14 +86,17 @@ NetlistComparer::exclude_resistors (double threshold)
void
NetlistComparer::same_nets (const db::Net *na, const db::Net *nb, bool must_match)
{
- tl_assert (na && na);
- m_same_nets [std::make_pair (na->circuit (), nb->circuit ())].push_back (std::make_pair (std::make_pair (na, nb), must_match));
+ if (na || nb) {
+ m_same_nets [std::make_pair (na->circuit (), nb->circuit ())].push_back (std::make_pair (std::make_pair (na, nb), must_match));
+ }
}
void
NetlistComparer::same_nets (const db::Circuit *ca, const db::Circuit *cb, const db::Net *na, const db::Net *nb, bool must_match)
{
- m_same_nets [std::make_pair (ca, cb)].push_back (std::make_pair (std::make_pair (na, nb), must_match));
+ if (na || nb) {
+ m_same_nets [std::make_pair (ca, cb)].push_back (std::make_pair (std::make_pair (na, nb), must_match));
+ }
}
void
@@ -207,6 +210,49 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
return res;
}
+/**
+ * @brief Returns a consolidated list of identical nets for a circuit pair (aka "same_nets")
+ *
+ * The list is reduced by duplicates of the first net such, that the
+ * last "same_nets" entry wins.
+ *
+ * The return value is a list of net pairs and a flag indicating "must_match" mode.
+ * The second net can be null if "must_match" is true, indicating that no schematic
+ * net with the same name was found - hence a mismatch exists.
+ */
+std::vector, bool> >
+NetlistComparer::get_net_identity (const db::Circuit *ca, const db::Circuit *cb) const
+{
+ std::vector, bool> > net_identity;
+
+ std::map, std::vector, bool> > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb));
+ if (sn != m_same_nets.end ()) {
+
+ const std::vector, bool> > &ni = sn->second;
+
+ // take last definition for a given first net
+ net_identity.reserve (ni.size ());
+ std::set seen;
+ for (auto i = ni.end (); i != ni.begin (); ) {
+ --i;
+ const Net *main_net = i->first.first ? i->first.first : i->first.second;
+ const Net *other_net = i->first.first ? i->first.second : i->first.first;
+ if (seen.find (main_net) == seen.end () && (! other_net || seen.find (other_net) == seen.end ())) {
+ net_identity.push_back (*i);
+ seen.insert (main_net);
+ if (other_net) {
+ seen.insert (other_net);
+ }
+ }
+ }
+
+ std::reverse (net_identity.begin (), net_identity.end ());
+
+ }
+
+ return net_identity;
+}
+
bool
NetlistComparer::compare_impl (const db::Netlist *a, const db::Netlist *b) const
{
@@ -344,13 +390,6 @@ NetlistComparer::compare_impl (const db::Netlist *a, const db::Netlist *b) const
tl_assert (i->second.second.size () == size_t (1));
const db::Circuit *cb = i->second.second.front ();
- std::vector, bool> > empty;
- const std::vector, bool> > *net_identity = ∅
- std::map, std::vector, bool> > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb));
- if (sn != m_same_nets.end ()) {
- net_identity = &sn->second;
- }
-
if (all_subcircuits_verified (ca, verified_circuits_a) && all_subcircuits_verified (cb, verified_circuits_b)) {
if (db::NetlistCompareGlobalOptions::options ()->debug_netcompare) {
@@ -362,7 +401,7 @@ NetlistComparer::compare_impl (const db::Netlist *a, const db::Netlist *b) const
}
bool pin_mismatch = false;
- bool g = compare_circuits (ca, cb, device_categorizer, circuit_categorizer, circuit_pin_mapper, *net_identity, pin_mismatch, c12_pin_mapping, c22_pin_mapping);
+ bool g = compare_circuits (ca, cb, device_categorizer, circuit_categorizer, circuit_pin_mapper, get_net_identity (ca, cb), pin_mismatch, c12_pin_mapping, c22_pin_mapping);
if (! g) {
good = false;
}
diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h
index 0dff2e059..18ff5288d 100644
--- a/src/db/db/dbNetlistCompare.h
+++ b/src/db/db/dbNetlistCompare.h
@@ -387,6 +387,7 @@ protected:
void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, db::DeviceEquivalenceTracker &device_eq, bool &good) const;
void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinCategorizer &circuit_pin_mapper, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, db::SubCircuitEquivalenceTracker &subcircuit_eq, bool &good) const;
bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const;
+ std::vector, bool> > get_net_identity (const db::Circuit *ca, const db::Circuit *cb) const;
mutable NetlistCompareLogger *mp_logger;
bool m_with_log;
diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc
index a1163ae29..f84294c9f 100644
--- a/src/db/db/gsiDeclDbNetlist.cc
+++ b/src/db/db/gsiDeclDbNetlist.cc
@@ -1451,7 +1451,7 @@ nets_by_name_const (const db::Circuit *circuit, const std::string &name_pattern)
}
for (db::Circuit::const_net_iterator n = circuit->begin_nets (); n != circuit->end_nets (); ++n) {
const db::Net *net = n.operator-> ();
- if (glob.match (net->name ())) {
+ if (!net->name ().empty () && glob.match (net->name ())) {
res.push_back (net);
}
}
@@ -1480,7 +1480,7 @@ nets_by_name_const_from_netlist (const db::Netlist *netlist, const std::string &
for (auto n = c->begin_nets (); n != c->end_nets (); ++n) {
const db::Net *net = n.operator-> ();
// NOTE: we only pick root nets (pin_count == 0 or in top cell)
- if ((is_top || net->pin_count () == 0) && glob.match (net->name ())) {
+ if ((is_top || net->pin_count () == 0) && !net->name ().empty () && glob.match (net->name ())) {
res.push_back (net);
}
}
diff --git a/src/lvs/lvs/built-in-macros/_lvs_netter.rb b/src/lvs/lvs/built-in-macros/_lvs_netter.rb
index 9eb5b5541..4b3a44f7c 100644
--- a/src/lvs/lvs/built-in-macros/_lvs_netter.rb
+++ b/src/lvs/lvs/built-in-macros/_lvs_netter.rb
@@ -552,6 +552,9 @@ CODE
# same_nets("INV*", "A*")
# @/code
#
+ # A plain "*" for the net pattern forces all (named) nets to be equivalent between layout and schematic.
+ # Unnamed nets from the extracted netlist are not considered - i.e. nets without a label.
+ #
# After using this function, the compare algorithm will consider these nets equivalent.
# Use this method to provide hints for the comparer in cases which are difficult to
# resolve otherwise.
@@ -560,6 +563,16 @@ CODE
# Names are case sensitive for layout-derived netlists and case-insensitive for SPICE schematic netlists.
#
# Use this method andwhere in the script before the \compare call.
+ #
+ # Multiple calls of "same_nets" can be used. The calls are effective in the order
+ # the are given. For example, the following sequence specifies equivalence of all
+ # equally named nets, with the exception of "A" and "B" which are equivalent to each other
+ # inside cell "ND2", despite their different name:
+ #
+ # @code
+ # same_nets("*", "*")
+ # same_nets("ND2", "A", "B")
+ # @/code
def same_nets(*args)
_same_nets_impl(false, *args)
@@ -573,6 +586,22 @@ CODE
# @synopsis same_nets!(circuit_a, net_a, circuit_b, net_b)
# This method is equivalent to \same_nets, but requires identity of the given nets.
# If the specified nets do not match, an error is reported.
+ #
+ # For example, this global specification requires all named nets from the
+ # layout to have an equivalent net in the schematic and those nets need to be
+ # identical for all circuits:
+ #
+ # @code
+ # same_nets!("*", "*")
+ # @/code
+ #
+ # The following specification requires "A" and "B" to be identical in
+ # circuit "ND2". It is not an error if either "A" does not exist in the
+ # layout or "B" does not exist in the schematic:
+ #
+ # @code
+ # same_nets!("ND2", "A", "B")
+ # @/code
def same_nets!(*args)
_same_nets_impl(true, *args)
@@ -655,7 +684,7 @@ CODE
nets = []
n2n.keys.sort.each do |n|
- if force || (n2n[n][0] && n2n[n][1])
+ if n2n[n][0] && (force || n2n[n][1])
nets << n2n[n]
end
end
From f01d8d46b586359f7bb01144fb68f094cda331a3 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Mon, 27 May 2024 00:43:36 +0200
Subject: [PATCH 06/13] Improving reports for errors in 'same_nets' cases
---
src/db/db/dbNetlistCompare.cc | 24 ++++++++++++++++++++----
src/db/db/dbNetlistCompareUtils.cc | 2 +-
src/db/db/dbNetlistCompareUtils.h | 1 +
testdata/lvs/blackbox3.lvsdb | 7 ++++---
testdata/lvs/blackbox4.lvsdb | 5 ++---
testdata/lvs/blackbox5.lvsdb | 8 ++------
6 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc
index 038fb9e7c..6d0e3128c 100644
--- a/src/db/db/dbNetlistCompare.cc
+++ b/src/db/db/dbNetlistCompare.cc
@@ -938,8 +938,16 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
if (mp_logger) {
if (p->second && ! exact_match) {
if (m_with_log) {
- mp_logger->log_entry (db::Error,
- tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
+ if (! p->first.first) {
+ mp_logger->log_entry (db::Error,
+ tl::sprintf (tl::to_string (tr ("Right-side net %s is paired explicitly with a left-side one, but no net is present there")), expanded_name (p->first.second)));
+ } else if (! p->first.second) {
+ mp_logger->log_entry (db::Error,
+ tl::sprintf (tl::to_string (tr ("Left-side net %s is paired explicitly with a right-side one, but no net is present there")), expanded_name (p->first.first)));
+ } else {
+ mp_logger->log_entry (db::Error,
+ tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
+ }
}
mp_logger->net_mismatch (p->first.first, p->first.second);
} else {
@@ -950,7 +958,11 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
} else if (p->second && g1.has_node_index_for_net (p->first.first)) {
if (mp_logger) {
- mp_logger->net_mismatch (p->first.first, 0);
+ mp_logger->net_mismatch (p->first.first, p->first.second);
+ if (m_with_log && p->first.second) {
+ mp_logger->log_entry (db::Error,
+ tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
+ }
}
size_t ni1 = g1.node_index_for_net (p->first.first);
@@ -959,7 +971,11 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
} else if (p->second && g2.has_node_index_for_net (p->first.second)) {
if (mp_logger) {
- mp_logger->net_mismatch (0, p->first.second);
+ mp_logger->net_mismatch (p->first.first, p->first.second);
+ if (m_with_log && p->first.first) {
+ mp_logger->log_entry (db::Error,
+ tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
+ }
}
size_t ni2 = g2.node_index_for_net (p->first.second);
diff --git a/src/db/db/dbNetlistCompareUtils.cc b/src/db/db/dbNetlistCompareUtils.cc
index 97951ca25..0e7be811a 100644
--- a/src/db/db/dbNetlistCompareUtils.cc
+++ b/src/db/db/dbNetlistCompareUtils.cc
@@ -73,7 +73,7 @@ nl_compare_debug_indent (size_t depth)
const std::string var_sep = tl::to_string (tr (" vs. "));
-static std::string
+std::string
expanded_name (const db::Net *a)
{
if (a == 0) {
diff --git a/src/db/db/dbNetlistCompareUtils.h b/src/db/db/dbNetlistCompareUtils.h
index 55614577a..f84c30ab0 100644
--- a/src/db/db/dbNetlistCompareUtils.h
+++ b/src/db/db/dbNetlistCompareUtils.h
@@ -83,6 +83,7 @@ const size_t unknown_id = std::numeric_limits::max () - 1;
// Some utilities
std::string nl_compare_debug_indent (size_t depth);
+std::string expanded_name (const db::Net *a);
std::string nets2string (const db::Net *a, const db::Net *b);
std::string nets2string (const std::pair &np);
diff --git a/testdata/lvs/blackbox3.lvsdb b/testdata/lvs/blackbox3.lvsdb
index f95a64186..0ea7fb1e5 100644
--- a/testdata/lvs/blackbox3.lvsdb
+++ b/testdata/lvs/blackbox3.lvsdb
@@ -185,10 +185,9 @@ xref(
)
circuit(TOP TOP nomatch
log(
- entry(error description('Nets $1 vs. (not connected) are paired explicitly, but are not identical topologically'))
+ entry(error description('Nets 7 are paired explicitly, but are not identical topologically'))
)
xref(
- net(() 7 mismatch)
net(1 () mismatch)
net(5 1 match)
net(4 2 match)
@@ -196,8 +195,10 @@ xref(
net(3 4 match)
net(7 5 match)
net(8 6 match)
+ net(9 7 mismatch)
net(6 8 match)
- circuit(1 1 mismatch)
+ circuit(() 1 mismatch)
+ circuit(1 () mismatch)
)
)
)
diff --git a/testdata/lvs/blackbox4.lvsdb b/testdata/lvs/blackbox4.lvsdb
index a54819f42..5e782006a 100644
--- a/testdata/lvs/blackbox4.lvsdb
+++ b/testdata/lvs/blackbox4.lvsdb
@@ -181,9 +181,8 @@ xref(
)
circuit(TOP TOP nomatch
log(
- entry(error description('Nets (not connected) vs. 5 are paired explicitly, but are not identical topologically'))
- entry(error description('Nets 5,7 vs. (not connected) are paired explicitly, but are not identical topologically'))
- entry(error description('Nets (not connected) vs. 7 are paired explicitly, but are not identical topologically'))
+ entry(error description('Left-side net 5,7 is paired explicitly with a right-side one, but no net is present there'))
+ entry(error description('Net 5,7 is not matching any net from reference netlist'))
)
xref(
net(() 5 mismatch)
diff --git a/testdata/lvs/blackbox5.lvsdb b/testdata/lvs/blackbox5.lvsdb
index 391475a66..6d8f88e0a 100644
--- a/testdata/lvs/blackbox5.lvsdb
+++ b/testdata/lvs/blackbox5.lvsdb
@@ -184,15 +184,11 @@ xref(
)
circuit(TOP TOP nomatch
log(
- entry(error description('Nets $1 vs. (not connected) are paired explicitly, but are not identical topologically'))
- entry(error description('Nets (not connected) vs. 5 are paired explicitly, but are not identical topologically'))
- entry(error description('Nets 5,7 vs. (not connected) are paired explicitly, but are not identical topologically'))
- entry(error description('Nets (not connected) vs. 7 are paired explicitly, but are not identical topologically'))
+ entry(error description('Left-side net 5,7 is paired explicitly with a right-side one, but no net is present there'))
)
xref(
net(() 5 mismatch)
- net(() 7 mismatch)
- net(1 () mismatch)
+ net(1 7 match)
net(5 1 match)
net(4 2 match)
net(2 3 match)
From 45e77ce40ca2fcfb4e32425c87426ce2c5b0cbd1 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Mon, 27 May 2024 19:02:38 +0200
Subject: [PATCH 07/13] Fixed a typo
---
src/db/db/dbLayoutToNetlist.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc
index 9275b442f..86b7d50ab 100644
--- a/src/db/db/dbLayoutToNetlist.cc
+++ b/src/db/db/dbLayoutToNetlist.cc
@@ -1018,7 +1018,7 @@ void LayoutToNetlist::register_layer (const ShapeCollection &collection, const s
throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n_in);
}
- // Caution: this make create names which clash with future explicit names. Hopefully, the generated names are unique enough.
+ // Caution: this may create names which clash with future explicit names. Hopefully, the generated names are unique enough.
std::string n = n_in.empty () ? make_new_name () : n_in;
db::DeepLayer dl;
From dc526132c0be6149b6a252942003368c70ad7120 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Mon, 27 May 2024 19:02:53 +0200
Subject: [PATCH 08/13] Part 3 of issue #1719
New LVS/DRC functions: "name" and "name_prefix"
to control what layer names are used. "name" needs
to be used explicitly and before a layer is used
(and gets auto-assigned a name).
---
src/drc/drc/built-in-macros/_drc_engine.rb | 14 ++++
src/drc/drc/built-in-macros/_drc_netter.rb | 91 +++++++++++++++++++---
2 files changed, 94 insertions(+), 11 deletions(-)
diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb
index 14a384a1a..765fc4215 100644
--- a/src/drc/drc/built-in-macros/_drc_engine.rb
+++ b/src/drc/drc/built-in-macros/_drc_engine.rb
@@ -2394,6 +2394,18 @@ CODE
# @synopsis extract_devices(extractor_class, name, layer_hash)
# See \Netter#extract_devices for a description of that function.
+ # %DRC%
+ # @name name
+ # @brief Assigns a name to a layer for reference in the LVS database
+ # @synopsis name(layer, name)
+ # See \Netter#name for a description of that function.
+
+ # %DRC%
+ # @name name_prefix
+ # @brief Specifies the layer name prefix for auto-generated layer names
+ # @synopsis name_prefix(prefix)
+ # See \Netter#name_prefix for a description of that function.
+
# %DRC%
# @name netlist
# @brief Obtains the extracted netlist from the default \Netter
@@ -2408,6 +2420,8 @@ CODE
connect_global
soft_connect
soft_connect_global
+ name_prefix
+ name
connect_implicit
connect_explicit
device_scaling
diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb
index 627dd85a9..4a3b023f9 100644
--- a/src/drc/drc/built-in-macros/_drc_netter.rb
+++ b/src/drc/drc/built-in-macros/_drc_netter.rb
@@ -68,6 +68,7 @@ module DRC
@post_extract_config = []
@l2n = nil
@lnum = 0
+ @name_prefix = "l"
@device_scaling = 1.0
@ignore_extraction_errors = false
@top_level = false
@@ -106,8 +107,8 @@ module DRC
a.requires_texts_or_region
b.requires_texts_or_region
- register_layer(a.data)
- register_layer(b.data)
+ _register_layer(a.data, "connect")
+ _register_layer(b.data, "connect")
a.data.is_a?(RBA::Region) && @l2n.connect(a.data)
b.data.is_a?(RBA::Region) && @l2n.connect(b.data)
@l2n.connect(a.data, b.data)
@@ -150,8 +151,8 @@ module DRC
a.requires_texts_or_region
b.requires_texts_or_region
- register_layer(a.data)
- register_layer(b.data)
+ _register_layer(a.data, "soft_connect")
+ _register_layer(b.data, "soft_connect")
# soft connections imply hard intra-layer connections
a.data.is_a?(RBA::Region) && @l2n.connect(a.data)
b.data.is_a?(RBA::Region) && @l2n.connect(b.data)
@@ -177,7 +178,7 @@ module DRC
l.is_a?(DRC::DRCLayer) || raise("Layer argument must be a layer")
l.requires_texts_or_region
- register_layer(l.data)
+ _register_layer(l.data, "connect_global")
l.data.is_a?(RBA::Region) && @l2n.connect(l.data)
@l2n.connect_global(l.data, name)
@@ -204,7 +205,7 @@ module DRC
l.is_a?(DRC::DRCLayer) || raise("Layer argument must be a layer")
l.requires_texts_or_region
- register_layer(l.data)
+ _register_layer(l.data, "soft_connect_global")
l.data.is_a?(RBA::Region) && @l2n.connect(l.data)
@l2n.soft_connect_global(l.data, name)
@@ -282,7 +283,7 @@ module DRC
layer_selection.keys.sort.each do |n|
l = layer_selection[n]
l.requires_texts_or_region
- register_layer(l.data)
+ _register_layer(l.data, "extract_devices")
ls[n.to_s] = l.data
end
@@ -294,6 +295,70 @@ module DRC
end
+ # %DRC%
+ # @name name
+ # @brief Assigns a name to a layer
+ # @synopsis name(layer, name)
+ # Layer names are listed in the LayoutToNetlist (L2N) or LVS database. They
+ # are used to identify the layers, the net or device terminal geometries are
+ # on. It is usual to have computed layers, so it is necessary to indicate the
+ # purpose of the layer for later reuse of the geometries.
+ #
+ # It is a good practice to assign names to computed and original layers,
+ # for example:
+ #
+ # @code
+ # poly = input(...)
+ # poly_resistor = input(...)
+ #
+ # poly_wiring = poly - poly_resistor
+ # name(poly_wiring, "poly_wiring")
+ # @/code
+ #
+ # Names must be assigned before the layers are used for the first time
+ # in \connect, \soft_connect, \connect_global, \soft_connect_global and
+ # extract_devices statements.
+ #
+ # If layers are not named, they will be given a name made from the
+ # \name_prefix and an incremental number when the layer is used for the
+ # first time.
+ #
+ # \name can only be used once on a layer and the layer names must be
+ # unique (not taken by another layer).
+
+ # %DRC%
+ # @name name_prefix
+ # @brief Specifies the name prefix for auto-generated layer names
+ # @synopsis name_prefix(prefix)
+ # See \\name for details. The default prefix is "l".
+
+ def name(l, name)
+
+ @engine._context("name") do
+
+ l.is_a?(DRC::DRCLayer) || raise("First argument must be a layer")
+ (name.is_a?(String) && name != "") || raise("Second argument must be a non-empty string")
+
+ id = l.data.data_id
+
+ if @layers && @layers[id]
+ # already registered
+ if @layers[id][1] != name
+ raise("Layer already registered with name #{@layers[id][1]} in context: #{@layers[id][2]}")
+ end
+ return
+ end
+
+ self._register_layer(l.data, "name", name)
+
+ end
+
+ end
+
+ def name_prefix(prefix)
+ @name_prefix = prefix.to_s
+ end
+
# %DRC%
# @name device_scaling
# @brief Specifies a dimension scale factor for the geometrical device properties
@@ -792,7 +857,7 @@ module DRC
end
- def register_layer(data)
+ def _register_layer(data, context, name = nil)
id = data.data_id
ensure_data
@@ -802,11 +867,15 @@ module DRC
return
end
- @layers[id] = data
- @lnum += 1
+ if !name
+ @lnum += 1
+ name = @name_prefix + @lnum.to_s
+ end
+
+ @layers[id] = [ data, name, context ]
# every layer gets registered and intra-layer connections are made
- @l2n.register(data, "l" + @lnum.to_s)
+ @l2n.register(data, name)
end
From 2360eb41fdcd0459120e7b682408fc2fd8a6b933 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Mon, 27 May 2024 19:04:06 +0200
Subject: [PATCH 09/13] Generated documentation
---
src/doc/doc/about/drc_ref_global.xml | 18 ++++++++++++
src/doc/doc/about/drc_ref_netter.xml | 43 ++++++++++++++++++++++++++++
src/doc/doc/about/lvs_ref_netter.xml | 29 +++++++++++++++++++
3 files changed, 90 insertions(+)
diff --git a/src/doc/doc/about/drc_ref_global.xml b/src/doc/doc/about/drc_ref_global.xml
index 45b725686..7fe05da4a 100644
--- a/src/doc/doc/about/drc_ref_global.xml
+++ b/src/doc/doc/about/drc_ref_global.xml
@@ -1175,6 +1175,24 @@ four-terminal MOS transistor.
See DeviceExtractorMOS4Transistor for more details
about this extractor (non-strict mode applies for 'mos4').
+"name" - Assigns a name to a layer for reference in the LVS database
+
+Usage:
+
+
+See Netter#name for a description of that function.
+
+"name_prefix" - Specifies the layer name prefix for auto-generated layer names
+
+Usage:
+
+
+See Netter#name_prefix for a description of that function.
+
"netlist" - Obtains the extracted netlist from the default Netter
diff --git a/src/doc/doc/about/drc_ref_netter.xml b/src/doc/doc/about/drc_ref_netter.xml
index bd82b4fbd..4ffc860eb 100644
--- a/src/doc/doc/about/drc_ref_netter.xml
+++ b/src/doc/doc/about/drc_ref_netter.xml
@@ -422,6 +422,49 @@ but no error is raised.
The LayoutToNetlist object provides access to the internal details of
the netter object.
+"name" - Assigns a name to a layer
+
+Usage:
+
+
+Layer names are listed in the LayoutToNetlist (L2N) or LVS database. They
+are used to identify the layers, the net or device terminal geometries are
+on. It is usual to have computed layers, so it is necessary to indicate the
+purpose of the layer for later reuse of the geometries.
+
+It is a good practice to assign names to computed and original layers,
+for example:
+
+
+poly = input(...)
+poly_resistor = input(...)
+
+poly_wiring = poly - poly_resistor
+name(poly_wiring, "poly_wiring")
+
+
+Names must be assigned before the layers are used for the first time
+in connect , soft_connect , connect_global , soft_connect_global and
+extract_devices statements.
+
+If layers are not named, they will be given a name made from the
+name_prefix and an incremental number when the layer is used for the
+first time.
+
+name can only be used once on a layer and the layer names must be
+unique (not taken by another layer).
+
+"name_prefix" - Specifies the name prefix for auto-generated layer names
+
+Usage:
+
+
+See for details. The default prefix is "l".
+
"netlist" - Gets the extracted netlist or triggers extraction if not done yet
Usage:
diff --git a/src/doc/doc/about/lvs_ref_netter.xml b/src/doc/doc/about/lvs_ref_netter.xml
index 9feef786f..c983b88f0 100644
--- a/src/doc/doc/about/lvs_ref_netter.xml
+++ b/src/doc/doc/about/lvs_ref_netter.xml
@@ -396,6 +396,9 @@ the schematic netlist for all circuits starting with "INV":
same_nets("INV*", "A*")
+A plain "*" for the net pattern forces all (named) nets to be equivalent between layout and schematic.
+Unnamed nets from the extracted netlist are not considered - i.e. nets without a label.
+
After using this function, the compare algorithm will consider these nets equivalent.
Use this method to provide hints for the comparer in cases which are difficult to
resolve otherwise.
@@ -404,6 +407,16 @@ circuit_a and net_a are for the layout netlist, circuit_b and net_b for the sche
Names are case sensitive for layout-derived netlists and case-insensitive for SPICE schematic netlists.
Use this method andwhere in the script before the compare call.
+
+Multiple calls of "same_nets" can be used. The calls are effective in the order
+the are given. For example, the following sequence specifies equivalence of all
+equally named nets, with the exception of "A" and "B" which are equivalent to each other
+inside cell "ND2", despite their different name:
+
+
+same_nets("*", "*")
+same_nets("ND2", "A", "B")
+
"same_nets!" - Establishes an equivalence between the nets with matching requirement
@@ -416,6 +429,22 @@ Use this method andwhere in the script before the compare
This method is equivalent to same_nets , but requires identity of the given nets.
If the specified nets do not match, an error is reported.
+
+For example, this global specification requires all named nets from the
+layout to have an equivalent net in the schematic and those nets need to be
+identical for all circuits:
+
+
+same_nets!("*", "*")
+
+
+The following specification requires "A" and "B" to be identical in
+circuit "ND2". It is not an error if either "A" does not exist in the
+layout or "B" does not exist in the schematic:
+
+
+same_nets!("ND2", "A", "B")
+
"schematic" - Gets, sets or reads the reference netlist
From f1d3597b2e22cb2db24e585dbd38acefb171324e Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Mon, 27 May 2024 19:06:56 +0200
Subject: [PATCH 10/13] Small doc update
---
src/doc/doc/about/drc_ref_netter.xml | 2 +-
src/drc/drc/built-in-macros/_drc_netter.rb | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/doc/doc/about/drc_ref_netter.xml b/src/doc/doc/about/drc_ref_netter.xml
index 4ffc860eb..e299ae380 100644
--- a/src/doc/doc/about/drc_ref_netter.xml
+++ b/src/doc/doc/about/drc_ref_netter.xml
@@ -447,7 +447,7 @@ name(poly_wiring, "poly_wiring")
Names must be assigned before the layers are used for the first time
in connect , soft_connect , connect_global , soft_connect_global and
-extract_devices statements.
+extract_devices statements.
If layers are not named, they will be given a name made from the
name_prefix and an incremental number when the layer is used for the
diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb
index 4a3b023f9..2e5be7906 100644
--- a/src/drc/drc/built-in-macros/_drc_netter.rb
+++ b/src/drc/drc/built-in-macros/_drc_netter.rb
@@ -317,7 +317,7 @@ module DRC
#
# Names must be assigned before the layers are used for the first time
# in \connect, \soft_connect, \connect_global, \soft_connect_global and
- # extract_devices statements.
+ # \extract_devices statements.
#
# If layers are not named, they will be given a name made from the
# \name_prefix and an incremental number when the layer is used for the
From 496818f0a83d569cd28a5d83580317d4c06a3911 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Tue, 28 May 2024 23:21:58 +0200
Subject: [PATCH 11/13] Added testdata for #1719, part 3
---
src/lvs/unit_tests/lvsSimpleTests.cc | 11 +-
testdata/lvs/layer_names.cir | 50 +++
testdata/lvs/layer_names.gds | Bin 0 -> 5258 bytes
testdata/lvs/layer_names.lvs | 105 +++++++
testdata/lvs/layer_names.lvsdb | 434 +++++++++++++++++++++++++++
5 files changed, 598 insertions(+), 2 deletions(-)
create mode 100644 testdata/lvs/layer_names.cir
create mode 100644 testdata/lvs/layer_names.gds
create mode 100644 testdata/lvs/layer_names.lvs
create mode 100644 testdata/lvs/layer_names.lvsdb
diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc
index 050f039eb..6ed065c3d 100644
--- a/src/lvs/unit_tests/lvsSimpleTests.cc
+++ b/src/lvs/unit_tests/lvsSimpleTests.cc
@@ -339,14 +339,21 @@ TEST(55_SoftConnectionSecondLevel)
run_test (_this, "soft_connect6", "soft_connect6.gds", true, false /*no LVS*/);
}
-// Issue #1719, part 2
+// Issue #1719, part 2 (ignore stray texts)
TEST(60_StrayTextsDoNotMakeNets)
{
run_test (_this, "stray_texts1", "stray_texts.gds", true, false /*no LVS*/);
}
-// Issue #1719, part 2
+// Issue #1719, part 2 (ignore stray texts)
TEST(61_StrayTextsDoNotMakeNets)
{
run_test (_this, "stray_texts2", "stray_texts.gds", true, false /*no LVS*/);
}
+
+// Issue #1719, part 3 (layer naming)
+TEST(62_LayerNames)
+{
+ run_test (_this, "layer_names", "layer_names.gds", false, true, "TOP");
+}
+
diff --git a/testdata/lvs/layer_names.cir b/testdata/lvs/layer_names.cir
new file mode 100644
index 000000000..9acc99ffe
--- /dev/null
+++ b/testdata/lvs/layer_names.cir
@@ -0,0 +1,50 @@
+* Extracted by KLayout
+
+* cell TOP
+* pin A
+* pin C
+* pin SUBSTRATE
+.SUBCKT TOP 2 3 4
+* net 2 A
+* net 3 C
+* net 4 SUBSTRATE
+* cell instance $1 r0 *1 0,0
+X$1 2 3 1 6 4 DINV
+* cell instance $2 r0 *1 3.6,0
+X$2 5 6 1 4 INVX1
+.ENDS TOP
+
+* cell DINV
+* pin A<1>
+* pin A<2>
+* pin B<2>
+* pin VDD
+* pin VSS
+.SUBCKT DINV 1 2 3 5 6
+* net 1 A<1>
+* net 2 A<2>
+* net 3 B<2>
+* net 4 B<1>
+* net 5 VDD
+* net 6 VSS
+* cell instance $1 r0 *1 0,0
+X$1 4 5 1 6 INVX1
+* cell instance $2 r0 *1 1.8,0
+X$2 3 5 2 6 INVX1
+.ENDS DINV
+
+* cell INVX1
+* pin OUT
+* pin VDD
+* pin IN
+* pin VSS
+.SUBCKT INVX1 1 2 3 4
+* net 1 OUT
+* net 2 VDD
+* net 3 IN
+* net 4 VSS
+* device instance $1 r0 *1 0.85,5.8 PMOS
+M$1 1 3 2 2 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
+* device instance $2 r0 *1 0.85,2.135 NMOS
+M$2 1 3 4 4 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
+.ENDS INVX1
diff --git a/testdata/lvs/layer_names.gds b/testdata/lvs/layer_names.gds
new file mode 100644
index 0000000000000000000000000000000000000000..3329c14d1b9eb2f7b126d6fda2935ac9377839f0
GIT binary patch
literal 5258
zcmcJT&1+m$7{=eZcjjg?ndY-3CYks}DMf;kRuG|-BnB~FCH8v)XrY
zk)4e7h%fg43EFoBzOTeZcCw%!F6jH{|B&?>sm;qIx5uHu6jKwdr@ymK2oR?J?TyO-+(?a`V{-WQ_#PP
zzTZGiFntdGAI&K{SgEI$h1$5t4wmZE$AWLr`Tjj8_2GM^p8aG!_CJMQl)c!0tLO1!
zZhusP?heN9O;L8z_rG_hZ6nhzppoNi5>Z8&mi=lj(>&q9WuRjeX?doeOdqdl_`8dd
z4w>5c!e^=|dok0Bde%{)ju|S-UesG@rZ#@_nJS`XJ#qa1QIGlT?n!7K*~E-+Sv5eW
zGsBco$}my(Vx}GUPv0!@D&f2AU=)8*e?L}A{TpOA;%J}`Tq&aLV5xuhk@ZOG*l$tx
zqTW*Lj(=e_!Hl-B(mV^_od4b{ZGCfZe+iAW%vzH=3)|x<=4jun-SKhwuVMdpUu%o-
z`bPXUtl93@slpf(*I@FC*$7%7C%?rQ{*+U8(8Vz9&gJeJ${tBDcFi&Lu=b9fW>5Jv
z-!mJ+b^-RGLVQl8I8Wwl?9i*gK737`@hY$n)%0gx1v*vO5eq9ixo$R(*&-KkZZRW7
z*}+OZXPbJgm1ytwSwK6!$NDHEL!GmpJhyrNi%GD9u|7IGyly_!TR`8b7i9-yeRNAg
z9=vb%z-ykf=g{7!nJ7D0sh@_1?aUy%s261iOZD|VTs+~|5j%3Dg}+7F&z0-xmwHF&
z=%0E=*(>z)%Q#8KP5+|oRq<2DI7!A$y(oLH__M#fe&{2w7i9-a$B%Kd9!VYJ7G}k5~Jrp8lz$|1M>((7O}uwm%Wl*ZqkgCczGt#!vlxsMiU4QFbua
zN4I>p{c$gJ57!R&K~Z+FQa=~;3qdc+4wmX`SIwsW#`uA=*D!w9bIJ~u>bX~BU!u<-
z^^Iq9$_|$5>6h`6EsO&Fi?V~2ditfF@lr3!4wmY9BbAU|twCuBA?0zWfYq=hGrVq^~
zZg@J~D`ukX6NO)HHk#|<;Rj^@8PB;z%-{jCCs1~s`Jw;E^t`{boz^|C7i9;LuySw{Jh_&;4W7QUi@N)eUC57>i%a4E
zQ2NQQ;g{U~*6Gg=pdY!V{9L^_h(6En)q(oY@$2~2*AB?}4&|eP>s`_pA(%n;|!_b3GH(7} ex
+end
+ok || raise("nwell layer is already named - this is an error")
+
+# Bulk layer for terminal provisioning
+
+bulk = polygon_layer
+
+# Computed layers
+
+active_in_nwell = active & nwell
+pactive = active_in_nwell & pplus
+pgate = pactive & poly
+psd = pactive - pgate
+ntie = active_in_nwell & nplus
+
+active_outside_nwell = active - nwell
+nactive = active_outside_nwell & nplus
+ngate = nactive & poly
+nsd = nactive - ngate
+ptie = active_outside_nwell & pplus
+
+# Layer names for all other layers
+
+%w(bulk pactive pgate psd ntie nactive ngate nsd poly contact metal1 via1 metal2).each do |v|
+ name(eval(v), v)
+end
+
+# Device extraction
+
+# PMOS transistor device extraction
+extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell,
+ "tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell })
+
+# NMOS transistor device extraction
+extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk,
+ "tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk })
+
+# Define connectivity for netlist extraction
+
+# Inter-layer
+connect(psd, contact)
+connect(nsd, contact)
+connect(poly, contact)
+connect(ntie, contact)
+connect(nwell, ntie)
+connect(ptie, contact)
+connect(contact, metal1)
+connect(metal1, via1)
+connect(via1, metal2)
+
+# Global
+connect_global(bulk, "SUBSTRATE")
+connect_global(ptie, "SUBSTRATE")
+
+ok = true
+begin
+ name(ptie, "ptie")
+ ok = false
+rescue => ex
+end
+ok || raise("ptie layer already used - this is an error")
+
+# Compare section
+
+netlist.simplify
+align
+
+consider_net_names(false)
+
+compare
+
diff --git a/testdata/lvs/layer_names.lvsdb b/testdata/lvs/layer_names.lvsdb
new file mode 100644
index 000000000..1a9df5bf6
--- /dev/null
+++ b/testdata/lvs/layer_names.lvsdb
@@ -0,0 +1,434 @@
+#%lvsdb-klayout
+
+# Layout
+layout(
+ top(TOP)
+ unit(0.001)
+
+ # Layer section
+ # This section lists the mask layers (drawing or derived) and their connections.
+
+ # Mask layers
+ layer(nwell '1/0')
+ layer(poly '5/0')
+ layer(contact '8/0')
+ layer(metal1 '9/0')
+ layer(via1)
+ layer(metal2)
+ layer(bulk)
+ layer(psd)
+ layer(ntie)
+ layer(nsd)
+ layer(l1)
+
+ # Mask layer connectivity
+ connect(nwell nwell ntie)
+ connect(poly poly contact)
+ connect(contact poly contact metal1 psd ntie nsd l1)
+ connect(metal1 contact metal1 via1)
+ connect(via1 metal1 via1 metal2)
+ connect(metal2 via1 metal2)
+ connect(bulk bulk)
+ connect(psd contact psd)
+ connect(ntie nwell contact ntie)
+ connect(nsd contact nsd)
+ connect(l1 contact l1)
+
+ # Global nets and connectivity
+ global(bulk SUBSTRATE)
+ global(l1 SUBSTRATE)
+
+ # Device class section
+ class(PMOS MOS4)
+ class(NMOS MOS4)
+
+ # Device abstracts section
+ # Device abstracts list the pin shapes of the devices.
+ device(D$PMOS PMOS
+ terminal(S
+ rect(psd (-550 -750) (425 1500))
+ )
+ terminal(G
+ rect(poly (-125 -750) (250 1500))
+ )
+ terminal(D
+ rect(psd (125 -750) (425 1500))
+ )
+ terminal(B
+ rect(nwell (-125 -750) (250 1500))
+ )
+ )
+ device(D$NMOS NMOS
+ terminal(S
+ rect(nsd (-550 -475) (425 950))
+ )
+ terminal(G
+ rect(poly (-125 -475) (250 950))
+ )
+ terminal(D
+ rect(nsd (125 -475) (425 950))
+ )
+ terminal(B
+ rect(bulk (-125 -475) (250 950))
+ )
+ )
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(INVX1
+
+ # Circuit boundary
+ rect((-100 400) (2000 7600))
+
+ # Nets with their geometries
+ net(1 name(OUT)
+ rect(contact (1110 5160) (180 180))
+ rect(contact (-180 920) (180 180))
+ rect(contact (-180 -730) (180 180))
+ rect(contact (-180 -4120) (180 180))
+ rect(contact (-180 370) (180 180))
+ rect(metal1 (-240 -790) (300 4790))
+ rect(metal1 (-150 -2500) (0 0))
+ rect(psd (-225 1050) (425 1500))
+ rect(nsd (-425 -4890) (425 950))
+ )
+ net(2 name(VDD)
+ rect(nwell (-100 4500) (2000 3500))
+ rect(contact (-1090 -890) (180 180))
+ rect(contact (-580 -1030) (180 180))
+ rect(contact (-180 -730) (180 180))
+ rect(contact (-180 -730) (180 180))
+ rect(metal1 (-590 1460) (1800 800))
+ rect(metal1 (-1050 -550) (300 300))
+ rect(metal1 (-700 -850) (300 300))
+ rect(metal1 (300 500) (0 0))
+ rect(metal1 (-600 -2200) (300 1400))
+ rect(psd (-350 -1450) (425 1500))
+ rect(ntie (-75 450) (500 500))
+ )
+ net(3 name(IN)
+ rect(poly (725 2860) (250 1940))
+ rect(poly (-525 -1850) (300 300))
+ rect(poly (-25 -1840) (250 1450))
+ rect(poly (-250 1940) (250 2000))
+ rect(poly (-250 -2000) (250 2000))
+ rect(contact (-465 -3790) (180 180))
+ rect(metal1 (-90 -90) (0 0))
+ rect(metal1 (-150 -150) (300 300))
+ )
+ net(4 name(VSS)
+ rect(contact (810 710) (180 180))
+ rect(contact (-580 880) (180 180))
+ rect(contact (-180 370) (180 180))
+ rect(metal1 (-590 -2100) (1800 800))
+ rect(metal1 (-1050 -550) (300 300))
+ rect(metal1 (-100 -150) (0 0))
+ rect(metal1 (-600 400) (300 1360))
+ rect(nsd (-350 -900) (425 950))
+ rect(l1 (-75 -2010) (500 400))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(OUT))
+ pin(2 name(VDD))
+ pin(3 name(IN))
+ pin(4 name(VSS))
+
+ # Devices and their connections
+ device(1 D$PMOS
+ location(850 5800)
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0.6375)
+ param(AD 0.6375)
+ param(PS 3.85)
+ param(PD 3.85)
+ terminal(S 2)
+ terminal(G 3)
+ terminal(D 1)
+ terminal(B 2)
+ )
+ device(2 D$NMOS
+ location(850 2135)
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0.40375)
+ param(AD 0.40375)
+ param(PS 2.75)
+ param(PD 2.75)
+ terminal(S 4)
+ terminal(G 3)
+ terminal(D 1)
+ terminal(B 4)
+ )
+
+ )
+ circuit(DINV
+
+ # Circuit boundary
+ rect((-100 400) (3800 7600))
+
+ # Nets with their geometries
+ net(1 name('A<1>')
+ rect(metal1 (600 3100) (0 0))
+ )
+ net(2 name('A<2>')
+ rect(metal1 (2400 3100) (0 0))
+ )
+ net(3 name('B<2>')
+ rect(metal1 (3000 4000) (0 0))
+ )
+ net(4 name('B<1>')
+ rect(metal1 (1200 4000) (0 0))
+ )
+ net(5 name(VDD)
+ rect(metal1 (1800 7200) (0 0))
+ )
+ net(6 name(VSS)
+ rect(metal1 (1800 800) (0 0))
+ )
+
+ # Outgoing pins and their connections to nets
+ pin(1 name('A<1>'))
+ pin(2 name('A<2>'))
+ pin(3 name('B<2>'))
+ pin(5 name(VDD))
+ pin(6 name(VSS))
+
+ # Subcircuits and their connections
+ circuit(1 INVX1 location(0 0)
+ pin(0 4)
+ pin(1 5)
+ pin(2 1)
+ pin(3 6)
+ )
+ circuit(2 INVX1 location(1800 0)
+ pin(0 3)
+ pin(1 5)
+ pin(2 2)
+ pin(3 6)
+ )
+
+ )
+ circuit(TOP
+
+ # Circuit boundary
+ rect((-100 400) (5600 7600))
+
+ # Nets with their geometries
+ net(1
+ rect(metal1 (3100 2950) (950 300))
+ )
+ net(2 name(A)
+ rect(metal1 (600 3100) (0 0))
+ )
+ net(3 name(C)
+ rect(metal1 (2400 3100) (0 0))
+ )
+ net(4 name(SUBSTRATE))
+ net(5)
+ net(6)
+
+ # Outgoing pins and their connections to nets
+ pin(2 name(A))
+ pin(3 name(C))
+ pin(4 name(SUBSTRATE))
+
+ # Subcircuits and their connections
+ circuit(1 DINV location(0 0)
+ pin(0 2)
+ pin(1 3)
+ pin(2 1)
+ pin(3 6)
+ pin(4 4)
+ )
+ circuit(2 INVX1 location(3600 0)
+ pin(0 5)
+ pin(1 6)
+ pin(2 1)
+ pin(3 4)
+ )
+
+ )
+)
+
+# Reference netlist
+reference(
+
+ # Device class section
+ class(NMOS MOS4)
+ class(PMOS MOS4)
+
+ # Circuit section
+ # Circuits are the hierarchical building blocks of the netlist.
+ circuit(INVX1
+
+ # Nets
+ net(1 name(A))
+ net(2 name(Z))
+ net(3 name(VSS))
+ net(4 name(VDD))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(A))
+ pin(2 name(Z))
+ pin(4 name(VDD))
+ pin(3 name(VSS))
+
+ # Devices and their connections
+ device(1 NMOS
+ name('0')
+ param(L 0.25)
+ param(W 0.95)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 3)
+ terminal(G 1)
+ terminal(D 2)
+ terminal(B 3)
+ )
+ device(2 PMOS
+ name('1')
+ param(L 0.25)
+ param(W 1.5)
+ param(AS 0)
+ param(AD 0)
+ param(PS 0)
+ param(PD 0)
+ terminal(S 4)
+ terminal(G 1)
+ terminal(D 2)
+ terminal(B 4)
+ )
+
+ )
+ circuit(DINV
+
+ # Nets
+ net(1 name('A<1>'))
+ net(2 name('A<2>'))
+ net(3 name('B<1>'))
+ net(4 name('B<2>'))
+ net(5 name(VDD))
+ net(6 name(VSS))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name('A<1>'))
+ pin(2 name('A<2>'))
+ pin(3 name('B<1>'))
+ pin(4 name('B<2>'))
+ pin(5 name(VDD))
+ pin(6 name(VSS))
+
+ # Subcircuits and their connections
+ circuit(1 INVX1 name(A)
+ pin(0 1)
+ pin(1 3)
+ pin(2 5)
+ pin(3 6)
+ )
+ circuit(2 INVX1 name(B)
+ pin(0 2)
+ pin(1 4)
+ pin(2 5)
+ pin(3 6)
+ )
+
+ )
+ circuit(TOP
+
+ # Nets
+ net(1 name(A))
+ net(2 name(C))
+ net(3 name(D))
+ net(4 name(B))
+ net(5 name(E))
+ net(6 name(VDD))
+ net(7 name(VSS))
+
+ # Outgoing pins and their connections to nets
+ pin(1 name(A))
+ pin(2 name(C))
+ pin(3 name(D))
+ pin(6 name(VDD))
+ pin(7 name(VSS))
+
+ # Subcircuits and their connections
+ circuit(1 DINV name('0')
+ pin(0 1)
+ pin(1 2)
+ pin(2 4)
+ pin(3 5)
+ pin(4 6)
+ pin(5 7)
+ )
+ circuit(2 INVX1 name('1')
+ pin(0 5)
+ pin(1 3)
+ pin(2 6)
+ pin(3 7)
+ )
+
+ )
+)
+
+# Cross reference
+xref(
+ circuit(DINV DINV match
+ log(
+ entry(warning description('Matching nets B<1> from an ambiguous group of nets'))
+ entry(warning description('Matching nets B<2> from an ambiguous group of nets'))
+ entry(info description('Matching nets A<1> following an ambiguous match'))
+ entry(info description('Matching nets A<2> following an ambiguous match'))
+ )
+ xref(
+ net(1 1 match)
+ net(2 2 match)
+ net(4 3 warning)
+ net(3 4 warning)
+ net(5 5 match)
+ net(6 6 match)
+ pin(() 2 match)
+ pin(0 0 match)
+ pin(1 1 match)
+ pin(2 3 match)
+ pin(3 4 match)
+ pin(4 5 match)
+ circuit(1 1 match)
+ circuit(2 2 match)
+ )
+ )
+ circuit(INVX1 INVX1 match
+ xref(
+ net(3 1 match)
+ net(1 2 match)
+ net(2 4 match)
+ net(4 3 match)
+ pin(2 0 match)
+ pin(0 1 match)
+ pin(1 2 match)
+ pin(3 3 match)
+ device(2 1 match)
+ device(1 2 match)
+ )
+ )
+ circuit(TOP TOP match
+ xref(
+ net(5 3 match)
+ net(1 5 match)
+ net(6 6 match)
+ net(2 1 match)
+ net(3 2 match)
+ net(4 7 match)
+ pin(() 2 match)
+ pin(() 3 match)
+ pin(0 0 match)
+ pin(1 1 match)
+ pin(2 4 match)
+ circuit(1 1 match)
+ circuit(2 2 match)
+ )
+ )
+)
From da9dc8929c5ba30a261fa37e209a60c61b616c65 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Fri, 31 May 2024 16:03:48 +0200
Subject: [PATCH 12/13] Updating one golden test data file
---
testdata/lvs/test_22c.lvsdb.3 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testdata/lvs/test_22c.lvsdb.3 b/testdata/lvs/test_22c.lvsdb.3
index 2fbe22102..3f52d22f2 100644
--- a/testdata/lvs/test_22c.lvsdb.3
+++ b/testdata/lvs/test_22c.lvsdb.3
@@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
- message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
+ message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)
From 56035abd9ff7fe1d6ae00c1c14b61817ee68e533 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Fri, 31 May 2024 16:29:54 +0200
Subject: [PATCH 13/13] Adjusting DRC/LVS code for Ruby 2.0.0 (protected vs.
private methods)
---
src/drc/drc/built-in-macros/_drc_netter.rb | 62 +++++++++++-----------
1 file changed, 32 insertions(+), 30 deletions(-)
diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb
index 2e5be7906..3e12ac838 100644
--- a/src/drc/drc/built-in-macros/_drc_netter.rb
+++ b/src/drc/drc/built-in-macros/_drc_netter.rb
@@ -826,36 +826,7 @@ module DRC
@l2n.make_soft_connection_diodes = f
end
- private
-
- def cleanup
- @l2n && @l2n.is_extracted? && clear_connections
- end
-
- def ensure_data
- if !@l2n
- @layers = {}
- _make_data
- @l2n.device_scaling = @device_scaling
- @l2n.top_level_mode = @top_level
- end
- end
-
- def _make_data
-
- if @engine._dss
- @engine._dss.is_singular? || raise("The DRC script features more than one or no layout source - network extraction cannot be performed in such configurations")
- @l2n = RBA::LayoutToNetlist::new(@engine._dss)
- else
- layout = @engine.source.layout
- cell_name = @engine.source.cell_name
- @l2n = RBA::LayoutToNetlist::new(cell_name, layout.dbu)
- end
-
- @l2n.name = "DRC"
- @l2n.generator = @engine._generator
-
- end
+ protected
def _register_layer(data, context, name = nil)
@@ -879,6 +850,37 @@ module DRC
end
+ def _make_data
+
+ if @engine._dss
+ @engine._dss.is_singular? || raise("The DRC script features more than one or no layout source - network extraction cannot be performed in such configurations")
+ @l2n = RBA::LayoutToNetlist::new(@engine._dss)
+ else
+ layout = @engine.source.layout
+ cell_name = @engine.source.cell_name
+ @l2n = RBA::LayoutToNetlist::new(cell_name, layout.dbu)
+ end
+
+ @l2n.name = "DRC"
+ @l2n.generator = @engine._generator
+
+ end
+
+ private
+
+ def cleanup
+ @l2n && @l2n.is_extracted? && clear_connections
+ end
+
+ def ensure_data
+ if !@l2n
+ @layers = {}
+ _make_data
+ @l2n.device_scaling = @device_scaling
+ @l2n.top_level_mode = @top_level
+ end
+ end
+
end
end