From 526f1aeacc6a7006f088f3a2554e9a72079e4b76 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Thu, 11 Aug 2022 01:02:45 +0200
Subject: [PATCH] [Consider merging] provide an option to produce antenna DRC
debug output
---
src/db/db/dbLayoutToNetlist.cc | 106 +++++++++++++++++-
src/db/db/dbLayoutToNetlist.h | 12 +-
src/db/db/gsiDeclDbLayoutToNetlist.cc | 23 ++--
src/drc/drc/built-in-macros/_drc_netter.rb | 40 +++++--
src/drc/drc/built-in-macros/_drc_source.rb | 18 ++-
src/lay/lay/doc/about/drc_ref_layer.xml | 6 +
src/lay/lay/doc/about/drc_ref_netter.xml | 6 +-
src/lay/lay/doc/about/drc_ref_source.xml | 18 ++-
src/lay/lay/doc/images/drc_and1.png | Bin 8547 -> 7844 bytes
src/lay/lay/doc/images/drc_and2.png | Bin 9237 -> 8724 bytes
src/lay/lay/doc/images/drc_and3.png | Bin 9444 -> 8963 bytes
src/lay/lay/doc/images/drc_centers1.png | Bin 7687 -> 6877 bytes
src/lay/lay/doc/images/drc_centers2.png | Bin 7678 -> 6855 bytes
src/lay/lay/doc/images/drc_corners1.png | Bin 8099 -> 7823 bytes
src/lay/lay/doc/images/drc_corners2.png | Bin 7954 -> 7635 bytes
src/lay/lay/doc/images/drc_corners3.png | Bin 8145 -> 7893 bytes
src/lay/lay/doc/images/drc_covering.png | Bin 9823 -> 8869 bytes
src/lay/lay/doc/images/drc_enc1.png | Bin 9244 -> 8707 bytes
src/lay/lay/doc/images/drc_enc1u.png | Bin 9372 -> 8823 bytes
src/lay/lay/doc/images/drc_enc2.png | Bin 9250 -> 8781 bytes
src/lay/lay/doc/images/drc_enc2u.png | Bin 9419 -> 8965 bytes
src/lay/lay/doc/images/drc_encd1.png | Bin 9333 -> 8814 bytes
src/lay/lay/doc/images/drc_encd1u.png | Bin 9446 -> 8933 bytes
src/lay/lay/doc/images/drc_encd2.png | Bin 9332 -> 8859 bytes
src/lay/lay/doc/images/drc_encd2u.png | Bin 9503 -> 9049 bytes
src/lay/lay/doc/images/drc_end_segments1.png | Bin 7694 -> 6900 bytes
src/lay/lay/doc/images/drc_end_segments2.png | Bin 7796 -> 7006 bytes
src/lay/lay/doc/images/drc_extended1.png | Bin 7344 -> 6731 bytes
src/lay/lay/doc/images/drc_extended2.png | Bin 7529 -> 7137 bytes
src/lay/lay/doc/images/drc_extended3.png | Bin 7686 -> 7187 bytes
src/lay/lay/doc/images/drc_extended4.png | Bin 7545 -> 6922 bytes
src/lay/lay/doc/images/drc_extent_refs1.png | Bin 7228 -> 6382 bytes
src/lay/lay/doc/images/drc_extent_refs10.png | Bin 7229 -> 6398 bytes
src/lay/lay/doc/images/drc_extent_refs11.png | Bin 7264 -> 6372 bytes
src/lay/lay/doc/images/drc_extent_refs12.png | Bin 7469 -> 6615 bytes
src/lay/lay/doc/images/drc_extent_refs13.png | Bin 7375 -> 6635 bytes
src/lay/lay/doc/images/drc_extent_refs20.png | Bin 7342 -> 6488 bytes
src/lay/lay/doc/images/drc_extent_refs21.png | Bin 7379 -> 6537 bytes
src/lay/lay/doc/images/drc_extent_refs22.png | Bin 7359 -> 6498 bytes
src/lay/lay/doc/images/drc_extent_refs23.png | Bin 7322 -> 6481 bytes
src/lay/lay/doc/images/drc_extent_refs24.png | Bin 7264 -> 6425 bytes
src/lay/lay/doc/images/drc_extent_refs25.png | Bin 7266 -> 6435 bytes
src/lay/lay/doc/images/drc_extent_refs26.png | Bin 7310 -> 6479 bytes
src/lay/lay/doc/images/drc_extent_refs27.png | Bin 7306 -> 6482 bytes
src/lay/lay/doc/images/drc_extent_refs30.png | Bin 7370 -> 6517 bytes
src/lay/lay/doc/images/drc_extent_refs31.png | Bin 7561 -> 6778 bytes
src/lay/lay/doc/images/drc_extents1.png | Bin 7225 -> 6234 bytes
src/lay/lay/doc/images/drc_extents2.png | Bin 8723 -> 8239 bytes
src/lay/lay/doc/images/drc_holes.png | Bin 7838 -> 7159 bytes
src/lay/lay/doc/images/drc_hulls.png | Bin 7793 -> 6310 bytes
src/lay/lay/doc/images/drc_in.png | Bin 8028 -> 7187 bytes
src/lay/lay/doc/images/drc_inside.png | Bin 8951 -> 8230 bytes
src/lay/lay/doc/images/drc_inside_part.png | Bin 9172 -> 8670 bytes
src/lay/lay/doc/images/drc_interacting.png | Bin 9065 -> 8120 bytes
src/lay/lay/doc/images/drc_interacting2.png | Bin 9393 -> 8492 bytes
src/lay/lay/doc/images/drc_interacting3.png | Bin 9335 -> 8673 bytes
src/lay/lay/doc/images/drc_interacting4.png | Bin 8990 -> 8295 bytes
src/lay/lay/doc/images/drc_interacting5.png | Bin 9565 -> 8807 bytes
src/lay/lay/doc/images/drc_join1.png | Bin 8557 -> 7364 bytes
src/lay/lay/doc/images/drc_join2.png | Bin 10345 -> 9789 bytes
src/lay/lay/doc/images/drc_merged1.png | Bin 8009 -> 6650 bytes
src/lay/lay/doc/images/drc_merged2.png | Bin 8087 -> 6710 bytes
src/lay/lay/doc/images/drc_merged3.png | Bin 8616 -> 7914 bytes
src/lay/lay/doc/images/drc_merged4.png | Bin 8372 -> 7832 bytes
src/lay/lay/doc/images/drc_middle1.png | Bin 7080 -> 6212 bytes
src/lay/lay/doc/images/drc_moved1.png | Bin 8384 -> 7341 bytes
src/lay/lay/doc/images/drc_not1.png | Bin 8667 -> 8016 bytes
src/lay/lay/doc/images/drc_not2.png | Bin 10062 -> 9566 bytes
src/lay/lay/doc/images/drc_not3.png | Bin 9318 -> 8822 bytes
src/lay/lay/doc/images/drc_not_covering.png | Bin 10077 -> 9016 bytes
src/lay/lay/doc/images/drc_not_in.png | Bin 8011 -> 7200 bytes
src/lay/lay/doc/images/drc_not_inside.png | Bin 8708 -> 8057 bytes
.../lay/doc/images/drc_not_interacting.png | Bin 9297 -> 8698 bytes
.../lay/doc/images/drc_not_interacting2.png | Bin 9353 -> 8695 bytes
.../lay/doc/images/drc_not_interacting3.png | Bin 9457 -> 8549 bytes
.../lay/doc/images/drc_not_interacting4.png | Bin 9231 -> 8628 bytes
.../lay/doc/images/drc_not_interacting5.png | Bin 9615 -> 8775 bytes
src/lay/lay/doc/images/drc_not_outside.png | Bin 8760 -> 7984 bytes
.../lay/doc/images/drc_not_overlapping.png | Bin 9213 -> 8587 bytes
src/lay/lay/doc/images/drc_or1.png | Bin 8562 -> 7409 bytes
src/lay/lay/doc/images/drc_or2.png | Bin 10320 -> 9776 bytes
src/lay/lay/doc/images/drc_outside.png | Bin 9093 -> 8488 bytes
src/lay/lay/doc/images/drc_outside_part.png | Bin 9623 -> 9115 bytes
src/lay/lay/doc/images/drc_overlap1.png | Bin 9938 -> 9376 bytes
src/lay/lay/doc/images/drc_overlap1u.png | Bin 10038 -> 9480 bytes
src/lay/lay/doc/images/drc_overlap2.png | Bin 9859 -> 9386 bytes
src/lay/lay/doc/images/drc_overlap2u.png | Bin 10076 -> 9577 bytes
src/lay/lay/doc/images/drc_overlapping.png | Bin 8785 -> 7991 bytes
src/lay/lay/doc/images/drc_raw1.png | Bin 9559 -> 8934 bytes
src/lay/lay/doc/images/drc_raw2.png | Bin 10827 -> 9153 bytes
src/lay/lay/doc/images/drc_raw3.png | Bin 9705 -> 7980 bytes
src/lay/lay/doc/images/drc_rotated1.png | Bin 10230 -> 9245 bytes
.../lay/doc/images/drc_rounded_corners.png | Bin 8888 -> 8171 bytes
src/lay/lay/doc/images/drc_scaled1.png | Bin 8517 -> 7551 bytes
src/lay/lay/doc/images/drc_separation1.png | Bin 8898 -> 8437 bytes
src/lay/lay/doc/images/drc_separation10.png | Bin 7193 -> 6276 bytes
src/lay/lay/doc/images/drc_separation11.png | Bin 7519 -> 6554 bytes
src/lay/lay/doc/images/drc_separation1u.png | Bin 8984 -> 8551 bytes
src/lay/lay/doc/images/drc_separation1un.png | Bin 9768 -> 9378 bytes
src/lay/lay/doc/images/drc_separation2.png | Bin 7401 -> 6971 bytes
src/lay/lay/doc/images/drc_separation3.png | Bin 7610 -> 7154 bytes
src/lay/lay/doc/images/drc_separation4.png | Bin 8098 -> 7589 bytes
src/lay/lay/doc/images/drc_separation5.png | Bin 6923 -> 5998 bytes
src/lay/lay/doc/images/drc_separation6.png | Bin 7172 -> 6218 bytes
src/lay/lay/doc/images/drc_separation7.png | Bin 7018 -> 6082 bytes
src/lay/lay/doc/images/drc_separation8.png | Bin 7326 -> 6400 bytes
src/lay/lay/doc/images/drc_separation9.png | Bin 7120 -> 6188 bytes
src/lay/lay/doc/images/drc_shielded1.png | Bin 8068 -> 7535 bytes
src/lay/lay/doc/images/drc_shielded2.png | Bin 8203 -> 7510 bytes
src/lay/lay/doc/images/drc_shielded3.png | Bin 8664 -> 8034 bytes
src/lay/lay/doc/images/drc_shielded4.png | Bin 8875 -> 8108 bytes
src/lay/lay/doc/images/drc_sized1.png | Bin 6954 -> 5762 bytes
src/lay/lay/doc/images/drc_sized2.png | Bin 7297 -> 5886 bytes
src/lay/lay/doc/images/drc_sized3.png | Bin 7251 -> 6022 bytes
src/lay/lay/doc/images/drc_sized4.png | Bin 7217 -> 5965 bytes
src/lay/lay/doc/images/drc_sized5.png | Bin 7145 -> 5944 bytes
src/lay/lay/doc/images/drc_sized6.png | Bin 7190 -> 6031 bytes
src/lay/lay/doc/images/drc_space1.png | Bin 8077 -> 7285 bytes
src/lay/lay/doc/images/drc_space1u.png | Bin 8161 -> 7395 bytes
src/lay/lay/doc/images/drc_space2.png | Bin 7969 -> 7218 bytes
src/lay/lay/doc/images/drc_space2u.png | Bin 8100 -> 7317 bytes
src/lay/lay/doc/images/drc_space3.png | Bin 7970 -> 7259 bytes
src/lay/lay/doc/images/drc_space3u.png | Bin 8091 -> 7374 bytes
.../lay/doc/images/drc_start_segments1.png | Bin 7718 -> 6960 bytes
.../lay/doc/images/drc_start_segments2.png | Bin 7858 -> 7121 bytes
src/lay/lay/doc/images/drc_textpoly1.png | Bin 6618 -> 5631 bytes
src/lay/lay/doc/images/drc_textpoly2.png | Bin 6586 -> 5600 bytes
src/lay/lay/doc/images/drc_texts1.png | Bin 5104 -> 4128 bytes
src/lay/lay/doc/images/drc_texts2.png | Bin 5187 -> 4161 bytes
src/lay/lay/doc/images/drc_transformed1.png | Bin 8977 -> 8155 bytes
src/lay/lay/doc/images/drc_width1.png | Bin 7841 -> 7081 bytes
src/lay/lay/doc/images/drc_width1u.png | Bin 7936 -> 7113 bytes
src/lay/lay/doc/images/drc_width2.png | Bin 7559 -> 6877 bytes
src/lay/lay/doc/images/drc_width2u.png | Bin 7612 -> 6809 bytes
src/lay/lay/doc/images/drc_width3.png | Bin 7872 -> 7122 bytes
src/lay/lay/doc/images/drc_width3u.png | Bin 7184 -> 6381 bytes
src/lay/lay/doc/images/drc_width4.png | Bin 8406 -> 7692 bytes
src/lay/lay/doc/images/drc_width4u.png | Bin 7472 -> 6683 bytes
src/lay/lay/doc/images/drc_width5u.png | Bin 7602 -> 6869 bytes
src/lay/lay/doc/images/drc_width6u.png | Bin 7767 -> 7031 bytes
src/lay/lay/doc/images/drc_with_angle1.png | Bin 8824 -> 7955 bytes
src/lay/lay/doc/images/drc_with_angle2.png | Bin 9072 -> 8139 bytes
src/lay/lay/doc/images/drc_with_angle3.png | Bin 8327 -> 7449 bytes
src/lay/lay/doc/images/drc_with_angle4.png | Bin 8683 -> 7688 bytes
src/lay/lay/doc/images/drc_xor1.png | Bin 8668 -> 7689 bytes
src/lay/lay/doc/images/drc_xor2.png | Bin 10387 -> 9845 bytes
testdata/drc/drcSimpleTests_5.drc | 6 +
testdata/drc/drcSimpleTests_5i.drc | 6 +
testdata/drc/drcSimpleTests_6.drc | 3 +
testdata/drc/drcSimpleTests_7.drc | 15 +++
testdata/drc/drcSimpleTests_au5.gds | Bin 4588 -> 12592 bytes
testdata/drc/drcSimpleTests_au6.gds | Bin 1626 -> 4484 bytes
testdata/drc/drcSimpleTests_au7.gds | Bin 10074 -> 25856 bytes
153 files changed, 225 insertions(+), 34 deletions(-)
diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc
index 6b9bf63cc..d8c9114d5 100644
--- a/src/db/db/dbLayoutToNetlist.cc
+++ b/src/db/db/dbLayoutToNetlist.cc
@@ -1366,9 +1366,10 @@ compute_area_and_perimeter_of_net_shapes (const db::hier_clusters
perimeter = ap_collector.perimeter ();
}
-static void
+static db::Point
get_merged_shapes_of_net (const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Shapes &shapes)
{
+ db::Point ref;
db::EdgeProcessor ep;
// count vertices and reserve space
@@ -1380,16 +1381,76 @@ get_merged_shapes_of_net (const db::hier_clusters &clusters, db::c
size_t p = 0;
for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
- ep.insert (rci.trans () * rci->polygon_ref (), ++p);
+ if (p == 0) {
+ db::PolygonRef pr = (rci.trans () * rci->polygon_ref ());
+ db::PolygonRef::polygon_edge_iterator e = pr.begin_edge ();
+ if (! e.at_end ()) {
+ // pick one reference point for the label
+ ref = (*e).p1 ();
+ ep.insert (pr, ++p);
+ }
+ } else {
+ ep.insert (rci.trans () * rci->polygon_ref (), ++p);
+ }
}
db::ShapeGenerator sg (shapes);
db::PolygonGenerator pg (sg, false);
db::SimpleMerge op;
ep.process (pg, op);
+
+ return ref;
}
-db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector > &diodes)
+static std::string
+create_antenna_msg (double agate, db::Polygon::area_type agate_int, double gate_area_factor, db::Polygon::perimeter_type pgate_int, double gate_perimeter_factor,
+ double ametal, db::Polygon::area_type ametal_int, double metal_area_factor, db::Polygon::perimeter_type pmetal_int, double metal_perimeter_factor,
+ const std::vector > &diodes,
+ const std::vector &adiodes_int,
+ double r, double ratio, double dbu)
+{
+ std::string msg;
+ msg += tl::sprintf ("agate_eff: %.12g, ", agate);
+ if (fabs (gate_area_factor) > 1e-6) {
+ msg += tl::sprintf ("agate: %.12g, agate_factor: %.12g, ", agate_int * dbu * dbu, gate_area_factor);
+ }
+ if (fabs (gate_perimeter_factor) > 1e-6) {
+ msg += tl::sprintf ("pgate: %.12g, pgate_factor: %.12g, ", pgate_int * dbu * dbu, gate_perimeter_factor);
+ }
+ msg += tl::sprintf ("ametal_eff: %.12g, ", ametal);
+ if (fabs (metal_area_factor) > 1e-6) {
+ msg += tl::sprintf ("ametal: %.12g, ametal_factor: %.12g, ", ametal_int * dbu * dbu, metal_area_factor);
+ }
+ if (fabs (metal_perimeter_factor) > 1e-6) {
+ msg += tl::sprintf ("pmetal: %.12g, pmetal_factor: %.12g, ", pmetal_int * dbu * dbu, metal_perimeter_factor);
+ }
+ if (! adiodes_int.empty ()) {
+ msg += "adiodes: [";
+ for (auto d = adiodes_int.begin (); d != adiodes_int.end (); ++d) {
+ if (d != adiodes_int.begin ()) {
+ msg += ", ";
+ }
+ msg += tl::sprintf ("%.12g", *d * dbu * dbu);
+ }
+ msg += "], ";
+ }
+ if (! diodes.empty ()) {
+ msg += "diode_factors: [";
+ for (auto d = diodes.begin (); d != diodes.end (); ++d) {
+ if (d != diodes.begin ()) {
+ msg += ", ";
+ }
+ msg += tl::sprintf ("%.12g", d->second);
+ }
+ msg += "], ";
+ }
+ msg += tl::sprintf ("ratio: %.12g, ", ametal / agate);
+ msg += tl::sprintf ("max_ratio_eff: %.12g, ", r);
+ msg += tl::sprintf ("max_ratio: %.12g", ratio);
+ return msg;
+}
+
+db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector > &diodes, db::Texts *values)
{
// TODO: that's basically too much .. we only need the clusters
if (! m_netlist_extracted) {
@@ -1401,6 +1462,11 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a
db::DeepLayer dl (&dss (), m_layout_index, ly.insert_layer ());
+ db::DeepLayer dlv;
+ if (values) {
+ dlv = db::DeepLayer (&dss (), m_layout_index, ly.insert_layer ());
+ }
+
for (db::Layout::bottom_up_const_iterator cid = ly.begin_bottom_up (); cid != ly.end_bottom_up (); ++cid) {
const connected_clusters &clusters = m_net_clusters.clusters_per_cell (*cid);
@@ -1408,6 +1474,8 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a
continue;
}
+ std::vector adiodes_int;
+
for (connected_clusters::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) {
if (! clusters.is_root (*c)) {
@@ -1417,13 +1485,18 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a
double r = ratio;
bool skip = false;
- for (std::vector >::const_iterator d = diodes.begin (); d != diodes.end () && ! skip; ++d) {
+ adiodes_int.clear ();
+ adiodes_int.reserve (diodes.size ());
+
+ for (auto d = diodes.begin (); d != diodes.end () && ! skip; ++d) {
db::Polygon::area_type adiode_int = 0;
db::Polygon::perimeter_type pdiode_int = 0;
compute_area_and_perimeter_of_net_shapes (m_net_clusters, *cid, *c, layer_of (*d->first), adiode_int, pdiode_int);
+ adiodes_int.push_back (adiode_int);
+
if (fabs (d->second) < db::epsilon) {
if (adiode_int > 0) {
skip = true;
@@ -1465,12 +1538,29 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a
}
if (tl::verbosity () >= 50) {
- tl::info << "cell [" << ly.cell_name (*cid) << "]: agate=" << tl::to_string (agate) << ", ametal=" << tl::to_string (ametal) << ", r=" << tl::sprintf ("%.12g", r);
+ tl::info << "cell [" << ly.cell_name (*cid) << "]: " <<
+ create_antenna_msg (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
+ ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
+ diodes, adiodes_int, r, ratio, dbu);
}
if (ametal / agate > r + db::epsilon) {
+
db::Shapes &shapes = ly.cell (*cid).shapes (dl.layer ());
- get_merged_shapes_of_net (m_net_clusters, *cid, *c, layer_of (metal), shapes);
+ db::Point ref = get_merged_shapes_of_net (m_net_clusters, *cid, *c, layer_of (metal), shapes);
+
+ if (values) {
+
+ // generate a data string with the details of the antenna computation (intentionally like JSON)
+ std::string msg = create_antenna_msg (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
+ ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
+ diodes, adiodes_int, r, ratio, dbu);
+
+ db::Shapes &shapesv = ly.cell (*cid).shapes (dlv.layer ());
+ shapesv.insert (db::Text (msg, db::Trans (ref - db::Point ())));
+
+ }
+
}
}
@@ -1481,6 +1571,10 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a
}
+ if (values) {
+ *values = db::Texts (new db::DeepTexts (dlv));
+ }
+
return db::Region (new db::DeepRegion (dl));
}
diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h
index 6b04e5cce..f1b099076 100644
--- a/src/db/db/dbLayoutToNetlist.h
+++ b/src/db/db/dbLayoutToNetlist.h
@@ -856,18 +856,18 @@ public:
* regardless of the diode's area.
* In other words: any diode will make the net safe against antenna discharge.
*/
- db::Region antenna_check (const db::Region &gate, double gate_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector > &diodes = std::vector > ())
+ db::Region antenna_check (const db::Region &gate, double gate_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector > &diodes = std::vector > (), db::Texts *values = 0)
{
- return antenna_check (gate, 1.0, gate_perimeter_factor, metal, 1.0, metal_perimeter_factor, ratio, diodes);
+ return antenna_check (gate, 1.0, gate_perimeter_factor, metal, 1.0, metal_perimeter_factor, ratio, diodes, values);
}
/**
* @brief Variant of the antenna check not using the perimeter
* This version uses 0 for the perimeter factor hence not taking into account the perimeter at all.
*/
- db::Region antenna_check (const db::Region &gate, const db::Region &metal, double ratio, const std::vector > &diodes = std::vector > ())
+ db::Region antenna_check (const db::Region &gate, const db::Region &metal, double ratio, const std::vector > &diodes = std::vector > (), db::Texts *values = 0)
{
- return antenna_check (gate, 1.0, 0.0, metal, 1.0, 0.0, ratio, diodes);
+ return antenna_check (gate, 1.0, 0.0, metal, 1.0, 0.0, ratio, diodes, values);
}
/**
@@ -879,8 +879,10 @@ public:
*
* where f is the area scale factor and t the perimeter scale factor. This version allows to ignore the
* area contribution entirely and switch to a perimeter-based antenna check by setting f to zero.
+ *
+ * If values is non-null, texts explaining the violations are placed there.
*/
- db::Region antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector > &diodes = std::vector > ());
+ db::Region antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector > &diodes = std::vector > (), Texts *values = 0);
/**
* @brief Saves the database to the given path
diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc
index 6f8b86c47..4d98e4f17 100644
--- a/src/db/db/gsiDeclDbLayoutToNetlist.cc
+++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc
@@ -98,7 +98,7 @@ static std::vector l2n_layer_names (const db::LayoutToNetlist *l2n)
return ln;
}
-static db::Region antenna_check3 (db::LayoutToNetlist *l2n, const db::Region &poly, double poly_area_factor, double poly_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector &diodes)
+static db::Region antenna_check3 (db::LayoutToNetlist *l2n, const db::Region &poly, double poly_area_factor, double poly_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector &diodes, db::Texts *texts)
{
std::vector > diode_pairs;
@@ -127,17 +127,17 @@ static db::Region antenna_check3 (db::LayoutToNetlist *l2n, const db::Region &po
}
- return l2n->antenna_check (poly, poly_area_factor, poly_perimeter_factor, metal, metal_area_factor, metal_perimeter_factor, ratio, diode_pairs);
+ return l2n->antenna_check (poly, poly_area_factor, poly_perimeter_factor, metal, metal_area_factor, metal_perimeter_factor, ratio, diode_pairs, texts);
}
-static db::Region antenna_check2 (db::LayoutToNetlist *l2n, const db::Region &poly, double poly_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector &diodes)
+static db::Region antenna_check2 (db::LayoutToNetlist *l2n, const db::Region &poly, double poly_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector &diodes, db::Texts *texts)
{
- return antenna_check3 (l2n, poly, 1, poly_perimeter_factor, metal, 1, metal_perimeter_factor, ratio, diodes);
+ return antenna_check3 (l2n, poly, 1, poly_perimeter_factor, metal, 1, metal_perimeter_factor, ratio, diodes, texts);
}
-static db::Region antenna_check (db::LayoutToNetlist *l2n, const db::Region &poly, const db::Region &metal, double ratio, const std::vector &diodes)
+static db::Region antenna_check (db::LayoutToNetlist *l2n, const db::Region &poly, const db::Region &metal, double ratio, const std::vector &diodes, db::Texts *texts)
{
- return antenna_check3 (l2n, poly, 1, 0, metal, 1, 0, ratio, diodes);
+ return antenna_check3 (l2n, poly, 1, 0, metal, 1, 0, ratio, diodes, texts);
}
static void join_net_names (db::LayoutToNetlist *l2n, const std::string &s)
@@ -701,7 +701,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"@brief Reads the extracted netlist from the file.\n"
"This method employs the native format of KLayout.\n"
) +
- gsi::method_ext ("antenna_check", &antenna_check, gsi::arg ("gate"), gsi::arg ("metal"), gsi::arg ("ratio"), gsi::arg ("diodes", std::vector (), "[]"),
+ gsi::method_ext ("antenna_check", &antenna_check, gsi::arg ("gate"), gsi::arg ("metal"), gsi::arg ("ratio"), gsi::arg ("diodes", std::vector (), "[]"), gsi::arg ("texts", (db::Texts *) 0, "nil"),
"@brief Runs an antenna check on the extracted clusters\n"
"\n"
"The antenna check will traverse all clusters and run an antenna check\n"
@@ -741,8 +741,13 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"# diode_layer1 increases the ratio by 50 per square micrometer area:\n"
"errors = l2n.antenna(poly, metal, 10.0 [ [ diode_layer, 50.0 ] ])\n"
"@/code\n"
+ "\n"
+ "If 'texts' is non-nil, this text collection will receive labels explaining the error in "
+ "terms of area values and relevant ratio.\n"
+ "\n"
+ "The 'texts' parameter has been added in version 0.27.11."
) +
- gsi::method_ext ("antenna_check", &antenna_check2, gsi::arg ("gate"), gsi::arg ("gate_perimeter_factor"), gsi::arg ("metal"), gsi::arg ("metal_perimeter_factor"), gsi::arg ("ratio"), gsi::arg ("diodes", std::vector (), "[]"),
+ gsi::method_ext ("antenna_check", &antenna_check2, gsi::arg ("gate"), gsi::arg ("gate_perimeter_factor"), gsi::arg ("metal"), gsi::arg ("metal_perimeter_factor"), gsi::arg ("ratio"), gsi::arg ("diodes", std::vector (), "[]"), gsi::arg ("texts", (db::Texts *) 0, "nil"),
"@brief Runs an antenna check on the extracted clusters taking the perimeter into account\n"
"\n"
"This version of the \\antenna_check method allows taking the perimeter of gate or metal into account. "
@@ -759,7 +764,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"\n"
"This variant has been introduced in version 0.26.6.\n"
) +
- gsi::method_ext ("antenna_check", &antenna_check3, gsi::arg ("gate"), gsi::arg ("gate_area_factor"), gsi::arg ("gate_perimeter_factor"), gsi::arg ("metal"), gsi::arg ("metal_area_factor"), gsi::arg ("metal_perimeter_factor"), gsi::arg ("ratio"), gsi::arg ("diodes", std::vector (), "[]"),
+ gsi::method_ext ("antenna_check", &antenna_check3, gsi::arg ("gate"), gsi::arg ("gate_area_factor"), gsi::arg ("gate_perimeter_factor"), gsi::arg ("metal"), gsi::arg ("metal_area_factor"), gsi::arg ("metal_perimeter_factor"), gsi::arg ("ratio"), gsi::arg ("diodes", std::vector (), "[]"), gsi::arg ("texts", (db::Texts *) 0, "nil"),
"@brief Runs an antenna check on the extracted clusters taking the perimeter into account and providing an area factor\n"
"\n"
"This (most generic) version of the \\antenna_check method allows taking the perimeter of gate or metal into account and also "
diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb
index 7e8de64e0..6b81ceb41 100644
--- a/src/drc/drc/built-in-macros/_drc_netter.rb
+++ b/src/drc/drc/built-in-macros/_drc_netter.rb
@@ -351,7 +351,7 @@ module DRC
# %DRC%
# @brief Performs an antenna check
# @name antenna_check
- # @synopsis antenna_check(gate, metal, ratio, [ diode_specs ... ])
+ # @synopsis antenna_check(gate, metal, ratio, [ diode_specs ... ] [, texts ])
#
# The antenna check is used to avoid plasma induced damage. Physically,
# the damage happes if during the manufacturing of a metal layer with
@@ -486,8 +486,13 @@ module DRC
# The error shapes produced by the antenna check are copies
# of the metal shapes on the metal layers of each network
# violating the antenna rule.
+ #
+ # You can specify a text layer (use "labels" to create one). It will receive
+ # error labels describing the measured values and computation parameters for debugging
+ # the layout. This option has been introduced in version 0.27.11.
+ #
- def antenna_check(agate, ametal, ratio, *diodes)
+ def antenna_check(agate, ametal, ratio, *args)
@engine._context("antenna_check") do
@@ -529,18 +534,31 @@ module DRC
raise("Ratio argument is not a number")
end
- dl = diodes.collect do |d|
- if d.is_a?(Array)
- d.size == 2 || raise("Diode specification pair expects two elements")
- d[0].requires_region
- [ d[0].data, d[1].to_f ]
- else
- d.requires_region
- [ d.data, 0.0 ]
+ dl = []
+ texts = nil
+ n = 3
+ args.each do |a|
+ if a.is_a?(Array)
+ a.size == 2 || raise("Diode specification pair expects two elements for argument #{n + 1}")
+ if ! a[0].is_a?(DRC::DRCLayer)
+ raise("Diode specification pair needs a layer for the first argument of argument #{n + 1}")
+ end
+ a[0].requires_region
+ dl << [ a[0].data, a[1].to_f ]
+ elsif ! a.is_a?(DRC::DRCLayer)
+ raise("Argument #{n + 1} has to be a layer")
+ else
+ a.requires_texts_or_region
+ if a.data.is_a?(RBA::Region)
+ dl << [ a.data, 0.0 ]
+ else
+ texts = a.data
+ end
end
+ n += 1
end
- DRC::DRCLayer::new(@engine, @engine._cmd(l2n_data, :antenna_check, gate.data, gate_area_factor, gate_perimeter_factor, metal.data, metal_area_factor, metal_perimeter_factor, ratio, dl))
+ DRC::DRCLayer::new(@engine, @engine._cmd(l2n_data, :antenna_check, gate.data, gate_area_factor, gate_perimeter_factor, metal.data, metal_area_factor, metal_perimeter_factor, ratio, dl, texts))
end
diff --git a/src/drc/drc/built-in-macros/_drc_source.rb b/src/drc/drc/built-in-macros/_drc_source.rb
index 600630949..0af32c75a 100644
--- a/src/drc/drc/built-in-macros/_drc_source.rb
+++ b/src/drc/drc/built-in-macros/_drc_source.rb
@@ -367,6 +367,7 @@ CODE
# %DRC%
# @name input
# @brief Specifies input from a source
+ # @synopsis source.input
# @synopsis source.input(layer)
# @synopsis source.input(layer, datatype)
# @synopsis source.input(layer_into)
@@ -405,6 +406,8 @@ CODE
# True text layers should be preferred over mixed polygon/text layers if text object processing
# is required.
#
+ # "input" without any arguments will create a new, empty original layer.
+ #
# Use the global version of "input" without a source object to address the default source.
def input(*args)
@@ -417,6 +420,7 @@ CODE
# %DRC%
# @name labels
# @brief Gets the labels (texts) from an input layer
+ # @synopsis source.labels
# @synopsis source.labels(layer)
# @synopsis source.labels(layer, datatype)
# @synopsis source.labels(layer_into)
@@ -429,6 +433,8 @@ CODE
# to provide text support but a layer type which is provided for carrying text objects
# explicitly.
#
+ # "labels" without any arguments will create a new, empty original layer.
+ #
# Use the global version of "labels" without a source object to address the default source.
def labels(*args)
@@ -441,6 +447,7 @@ CODE
# %DRC%
# @name polygons
# @brief Gets the polygon shapes (or shapes that can be converted polygons) from an input layer
+ # @synopsis source.polygons
# @synopsis source.polygons(layer)
# @synopsis source.polygons(layer, datatype)
# @synopsis source.polygons(layer_into)
@@ -452,6 +459,8 @@ CODE
#
# This method is identical to \input with respect to the options supported.
#
+ # "polygons" without any arguments will create a new, empty original layer.
+ #
# Use the global version of "polygons" without a source object to address the default source.
def polygons(*args)
@@ -464,6 +473,7 @@ CODE
# %DRC%
# @name edges
# @brief Gets the edge shapes (or shapes that can be converted edges) from an input layer
+ # @synopsis source.edges
# @synopsis source.edges(layer)
# @synopsis source.edges(layer, datatype)
# @synopsis source.edges(layer_into)
@@ -478,6 +488,8 @@ CODE
#
# Use the global version of "edges" without a source object to address the default source.
#
+ # "edges" without any arguments will create a new, empty original layer.
+ #
# This method has been introduced in version 0.27.
def edges(*args)
@@ -490,6 +502,7 @@ CODE
# %DRC%
# @name edge_pairs
# @brief Gets the edge pairs from an input layer
+ # @synopsis source.edge_pairs
# @synopsis source.edge_pairs(layer)
# @synopsis source.edge_pairs(layer, datatype)
# @synopsis source.edge_pairs(layer_into)
@@ -504,6 +517,8 @@ CODE
#
# Use the global version of "edge_pairs" without a source object to address the default source.
#
+ # "edge_pairs" without any arguments will create a new, empty original layer.
+ #
# This method has been introduced in version 0.27.
def edge_pairs(*args)
@@ -517,7 +532,8 @@ CODE
# @name make_layer
# @brief Creates an empty polygon layer based on the hierarchy of the layout
# @synopsis make_layer
- # This method delivers a new empty original layer.
+ # This method delivers a new empty original layer. It is provided to keep old code working.
+ # Use "input" without arguments instead.
def make_layer
layers = []
diff --git a/src/lay/lay/doc/about/drc_ref_layer.xml b/src/lay/lay/doc/about/drc_ref_layer.xml
index 9c6966097..f475254c3 100644
--- a/src/lay/lay/doc/about/drc_ref_layer.xml
+++ b/src/lay/lay/doc/about/drc_ref_layer.xml
@@ -3037,6 +3037,12 @@ The effect of the operation is shown in these examples:
+"texts?" - Returns true, if the layer is a text collection
+
+Usage:
+
"texts_not" - Selects texts from an original layer not matching a specific selection
Usage:
diff --git a/src/lay/lay/doc/about/drc_ref_netter.xml b/src/lay/lay/doc/about/drc_ref_netter.xml
index 5d9c091da..2b317dcc1 100644
--- a/src/lay/lay/doc/about/drc_ref_netter.xml
+++ b/src/lay/lay/doc/about/drc_ref_netter.xml
@@ -65,7 +65,7 @@ More methods will be added in the future to support network-related features.
Usage:
-- antenna_check(gate, metal, ratio, [ diode_specs ... ])
+- antenna_check(gate, metal, ratio, [ diode_specs ... ] [, texts ])
The antenna check is used to avoid plasma induced damage. Physically,
@@ -201,6 +201,10 @@ errors = antenna_check(perimeter_only(gate, 0.5), ...)
The error shapes produced by the antenna check are copies
of the metal shapes on the metal layers of each network
violating the antenna rule.
+
+You can specify a text layer (use "labels" to create one). It will receive
+error labels describing the measured values and computation parameters for debugging
+the layout. This option has been introduced in version 0.27.11.
"clear_connections" - Clears all connections stored so far
diff --git a/src/lay/lay/doc/about/drc_ref_source.xml b/src/lay/lay/doc/about/drc_ref_source.xml
index 20a46bee9..439157065 100644
--- a/src/lay/lay/doc/about/drc_ref_source.xml
+++ b/src/lay/lay/doc/about/drc_ref_source.xml
@@ -58,6 +58,7 @@ same but without clipping is touching or
Usage: