From 80ad38f81b1740befdf6194d1027e3f7d8a84ec0 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 4 May 2025 14:36:34 +0200 Subject: [PATCH] WIP: debugging, tests. Triangulation should be safer now against linear chains of vertexes. --- src/db/db/dbPLCTriangulation.cc | 22 ++++- src/db/unit_tests/dbPLCTriangulationTests.cc | 22 ++++- src/pex/pex/pexRNetExtractor.cc | 16 +++- src/pex/pex/pexSquareCountingRExtractor.cc | 5 +- src/pex/unit_tests/pexRNetExtractorTests.cc | 81 +++++++++++++++++++ testdata/pex/netex_test1.gds | Bin 0 -> 1066 bytes 6 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 testdata/pex/netex_test1.gds diff --git a/src/db/db/dbPLCTriangulation.cc b/src/db/db/dbPLCTriangulation.cc index f8f4fdcc9..70f784f3a 100644 --- a/src/db/db/dbPLCTriangulation.cc +++ b/src/db/db/dbPLCTriangulation.cc @@ -1471,12 +1471,17 @@ Triangulation::triangulate (const db::Region ®ion, const std::vector > edge_contours; + for (auto p = region.begin_merged (); ! p.at_end (); ++p) { + make_contours (*p, trans, edge_contours); + } + unsigned int id = 0; for (auto v = vertexes.begin (); v != vertexes.end (); ++v) { insert_point (trans * *v)->set_is_precious (true, id++); } - create_constrained_delaunay (region, trans); + constrain (edge_contours); refine (parameters); } @@ -1495,12 +1500,15 @@ Triangulation::triangulate (const db::Polygon &poly, const std::vector > edge_contours; + make_contours (poly, trans, edge_contours); + unsigned int id = 0; for (auto v = vertexes.begin (); v != vertexes.end (); ++v) { insert_point (trans * *v)->set_is_precious (true, id++); } - create_constrained_delaunay (poly, trans); + constrain (edge_contours); refine (parameters); } @@ -1517,12 +1525,15 @@ Triangulation::triangulate (const db::Polygon &poly, const std::vector > edge_contours; + make_contours (poly, trans, edge_contours); + unsigned int id = 0; for (auto v = vertexes.begin (); v != vertexes.end (); ++v) { insert_point (trans * *v)->set_is_precious (true, id++); } - create_constrained_delaunay (poly, trans); + constrain (edge_contours); refine (parameters); } @@ -1539,12 +1550,15 @@ Triangulation::triangulate (const db::DPolygon &poly, const std::vector > edge_contours; + make_contours (poly, trans, edge_contours); + unsigned int id = 0; for (auto v = vertexes.begin (); v != vertexes.end (); ++v) { insert_point (trans * *v)->set_is_precious (true, id++); } - create_constrained_delaunay (poly, trans); + constrain (edge_contours); refine (parameters); } diff --git a/src/db/unit_tests/dbPLCTriangulationTests.cc b/src/db/unit_tests/dbPLCTriangulationTests.cc index f31a049b2..2e3845e54 100644 --- a/src/db/unit_tests/dbPLCTriangulationTests.cc +++ b/src/db/unit_tests/dbPLCTriangulationTests.cc @@ -1118,11 +1118,29 @@ TEST(triangulate_with_vertexes) EXPECT_EQ (vp, 0); } + // normal triangulation vertexes.clear (); vertexes.push_back (db::Point (50, 50)); tri.triangulate (poly, vertexes, param, trans); - EXPECT_EQ (plc.to_string (), "((-0.45, 0), (-0.5, -0.05), (-0.5, 0.05)), ((0.5, 0.05), (-0.45, 0), (-0.5, 0.05)), ((-0.45, 0), (0.5, -0.05), (-0.5, -0.05)), ((-0.45, 0), (0.5, 0.05), (0.5, -0.05))"); + EXPECT_EQ (plc.to_string (), "((-0.5, -0.05), (-0.5, 0.05), (-0.45, 0)), ((-0.5, 0.05), (0.5, 0.05), (-0.45, 0)), ((0.5, -0.05), (-0.45, 0), (0.5, 0.05)), ((0.5, -0.05), (-0.5, -0.05), (-0.45, 0))"); + + for (auto v = vertexes.begin (); v != vertexes.end (); ++v) { + auto *vp = tri.find_vertex_for_point (trans * *v); + if (! vp) { + tl::warn << "Vertex not present in output: " << v->to_string (); + EXPECT_EQ (1, 0); + } + } + + // linear chain of vertexes must not break triangulation + vertexes.clear (); + vertexes.push_back (db::Point (50, 50)); + vertexes.push_back (db::Point (100, 50)); + vertexes.push_back (db::Point (150, 50)); + tri.triangulate (poly, vertexes, param, trans); + + EXPECT_EQ (plc.to_string (), "((-0.5, -0.05), (-0.5, 0.05), (-0.45, 0)), ((-0.4, 0), (-0.45, 0), (-0.5, 0.05)), ((-0.5, -0.05), (-0.45, 0), (-0.4, 0)), ((0.5, -0.05), (-0.35, 0), (0.5, 0.05)), ((-0.5, -0.05), (-0.35, 0), (0.5, -0.05)), ((-0.5, -0.05), (-0.4, 0), (-0.35, 0)), ((-0.35, 0), (-0.5, 0.05), (0.5, 0.05)), ((-0.35, 0), (-0.4, 0), (-0.5, 0.05))"); for (auto v = vertexes.begin (); v != vertexes.end (); ++v) { auto *vp = tri.find_vertex_for_point (trans * *v); @@ -1139,7 +1157,7 @@ TEST(triangulate_with_vertexes) tri.triangulate (poly, vertexes, param, trans); EXPECT_GT (plc.num_polygons (), size_t (380)); - EXPECT_LT (plc.num_polygons (), size_t (400)); + EXPECT_LT (plc.num_polygons (), size_t (420)); for (auto t = plc.begin (); t != plc.end (); ++t) { EXPECT_LE (t->area (), param.max_area); diff --git a/src/pex/pex/pexRNetExtractor.cc b/src/pex/pex/pexRNetExtractor.cc index 592d48859..5894ac356 100644 --- a/src/pex/pex/pexRNetExtractor.cc +++ b/src/pex/pex/pexRNetExtractor.cc @@ -79,7 +79,7 @@ RNetExtractor::extract (const RExtractorTech &tech, vp_offset += p->second.size (); } for (auto p = polygon_ports.begin (); p != polygon_ports.end () && p->first < g->first; ++p) { - vp_offset += p->second.size (); + pp_offset += p->second.size (); } // fetch the port list for vertex ports @@ -377,6 +377,7 @@ private: // for internal nodes always create a node in the target network global = mp_rnetwork->create_node (local->type, ++m_next_internal_port_index); + global->location = local->location; } else if (local->type == RNode::VertexPort) { @@ -409,7 +410,7 @@ private: if (i2n != m_id_to_node.end ()) { global = i2n->second; } else { - global = mp_rnetwork->create_node (RNode::VertexPort, index_from_id (id) + m_polygon_port_index_offset); + global = mp_rnetwork->create_node (RNode::PolygonPort, index_from_id (id) + m_polygon_port_index_offset); global->location = local->location; m_id_to_node.insert (std::make_pair (id, global)); } @@ -422,7 +423,7 @@ private: } // create the R elements in the target network - for (auto e = local_network.begin_elements (); e != local_network.begin_elements (); ++e) { + for (auto e = local_network.begin_elements (); e != local_network.end_elements (); ++e) { const RElement *local = e.operator-> (); @@ -431,7 +432,14 @@ private: tl_assert (ia != n2n.end ()); tl_assert (ia != n2n.end ()); - mp_rnetwork->create_element (local->conductance, ia->second, ib->second); + double c; + if (mp_cond->resistance < 1e-10) { + c = RElement::short_value (); + } else { + c = local->conductance / mp_cond->resistance; + } + + mp_rnetwork->create_element (c, ia->second, ib->second); } } diff --git a/src/pex/pex/pexSquareCountingRExtractor.cc b/src/pex/pex/pexSquareCountingRExtractor.cc index 5c69b1fb3..acf9689d1 100644 --- a/src/pex/pex/pexSquareCountingRExtractor.cc +++ b/src/pex/pex/pexSquareCountingRExtractor.cc @@ -181,7 +181,8 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector { rnetwork.clear (); - db::CplxTrans trans = db::CplxTrans (m_dbu) * db::ICplxTrans (db::Trans (db::Point () - polygon.box ().center ())); + db::CplxTrans to_um (m_dbu); + db::CplxTrans trans = to_um * db::ICplxTrans (db::Trans (db::Point () - polygon.box ().center ())); auto inv_trans = trans.inverted (); db::plc::Graph plc; @@ -285,7 +286,7 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector auto n4p = nodes_for_ports.find (p->first); if (n4p == nodes_for_ports.end ()) { pex::RNode *node = rnetwork.create_node (p->first.type, p->first.port_index); - node->location = trans * p->first.location; + node->location = to_um * p->first.location; n4p = nodes_for_ports.insert (std::make_pair (p->first, node)).first; } p->second = n4p->second; diff --git a/src/pex/unit_tests/pexRNetExtractorTests.cc b/src/pex/unit_tests/pexRNetExtractorTests.cc index 241ded8df..5227a323b 100644 --- a/src/pex/unit_tests/pexRNetExtractorTests.cc +++ b/src/pex/unit_tests/pexRNetExtractorTests.cc @@ -137,3 +137,84 @@ TEST(netex_viagen2) "R $10(0.6,4.9;1.2,5.1) $11(0.6,4.9;1.2,5.1) 25" ); } + +TEST(netex_2layer) +{ + db::Layout ly; + + { + std::string fn = tl::testdata () + "/pex/netex_test1.gds"; + tl::InputStream is (fn); + db::Reader reader (is); + reader.read (ly); + } + + TestableRNetExtractor rex (ly.dbu ()); + + auto tc = ly.cell_by_name ("TOP"); + tl_assert (tc.first); + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l1p = ly.get_layer (db::LayerProperties (1, 1)); + unsigned int l1v = ly.get_layer (db::LayerProperties (1, 2)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + unsigned int l3p = ly.get_layer (db::LayerProperties (3, 1)); + unsigned int l3v = ly.get_layer (db::LayerProperties (3, 2)); + + std::map geo; + geo.insert (std::make_pair (l1, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l1)))); + geo.insert (std::make_pair (l2, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l2)))); + geo.insert (std::make_pair (l3, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l3)))); + + pex::RNetwork network; + + pex::RExtractorTech tech; + + pex::RExtractorTechVia via1; + via1.bottom_conductor = l1; + via1.cut_layer = l2; + via1.top_conductor = l3; + via1.resistance = 2.0; + via1.merge_distance = 0.2; + tech.vias.push_back (via1); + + pex::RExtractorTechConductor cond1; + cond1.layer = l1; + cond1.resistance = 0.5; + tech.conductors.push_back (cond1); + + pex::RExtractorTechConductor cond2; + cond2.layer = l3; + cond2.resistance = 0.25; + tech.conductors.push_back (cond2); + + std::map > vertex_ports; + std::map > polygon_ports; + + db::Region l1p_region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l1p)); + for (auto p = l1p_region.begin_merged (); ! p.at_end (); ++p) { + polygon_ports[l1].push_back (*p); + } + + db::Region l3p_region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l3p)); + for (auto p = l3p_region.begin_merged (); ! p.at_end (); ++p) { + polygon_ports[l3].push_back (*p); + } + + db::Region l1v_region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l1v)); + for (auto p = l1v_region.begin_merged (); ! p.at_end (); ++p) { + vertex_ports[l1].push_back (p->box ().center ()); + } + + db::Region l3v_region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l3v)); + for (auto p = l3v_region.begin_merged (); ! p.at_end (); ++p) { + vertex_ports[l3].push_back (p->box ().center ()); + } + + rex.extract (tech, geo, vertex_ports, polygon_ports, network); + + EXPECT_EQ (network.to_string (true), + "" + ); +} diff --git a/testdata/pex/netex_test1.gds b/testdata/pex/netex_test1.gds new file mode 100644 index 0000000000000000000000000000000000000000..3eef63f00905aea0289f9ba77a3478d07e320a94 GIT binary patch literal 1066 zcmb7@u}i~16vn??l50RK(dr^W0+F_ZAc&$aLW@I-1s#e==l%%}4*mmf-F0wtb?net z{8L)%P>P+;cX>H`SlVjf_$BZ1z3+QR0tq2*5IG_@fDaFO>>#%95eV6+SAk8}KdU?( zU%b7HPS3mh&yTGpB7cES%IkUs@B%>Q1q9@p0I(OjN~tHasM5BVscXVpCw&gfe43Y6 z^xg^(Y_O-?cBtoS z1&-n=O`T}#UE4nyu|65;$=RQ2>M7^yOQBNZrq(Gnxn+MtQzy>V>)f1^=hn0HGW8jM zK0il)zraD8_P?0J25{J;`7@e2(e`J(V0~eij*h;2P0<6k?x!?$qOIriv;4goUUJbVN9W!lC7 literal 0 HcmV?d00001