diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3b1fba45..1c0720e77 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,7 +66,7 @@ jobs: mkdir -p $HOST_CCACHE_DIR - name: Build wheels (ARM) if: matrix.os == 'ubuntu-24.04-arm' - uses: pypa/cibuildwheel@v2.23.3 + uses: pypa/cibuildwheel@v3.0.0 env: # override the default CentOS “yum install … ccache” and drop ccache CIBW_BEFORE_ALL_LINUX: | @@ -81,7 +81,7 @@ jobs: - name: Build wheels (all other platforms) if: matrix.os != 'ubuntu-24.04-arm' - uses: pypa/cibuildwheel@v2.23.3 + uses: pypa/cibuildwheel@v3.0.0 env: CIBW_BUILD: ${{ matrix.cibuild }} CIBW_ARCHS_MACOS: ${{ matrix.macos-arch }} diff --git a/ci-scripts/docker/docker_prepare.sh b/ci-scripts/docker/docker_prepare.sh index 4fb6e50c5..141f57f1a 100644 --- a/ci-scripts/docker/docker_prepare.sh +++ b/ci-scripts/docker/docker_prepare.sh @@ -11,16 +11,18 @@ if [[ -f "/etc/centos-release" ]]; then [ $s -eq 0 ] || exit $s if [[ -d "/usr/lib64/ccache" ]]; then - ln -s /usr/bin/ccache /usr/lib64/ccache/c++ - ln -s /usr/bin/ccache /usr/lib64/ccache/cc - ln -s /usr/bin/ccache /usr/lib64/ccache/gcc - ln -s /usr/bin/ccache /usr/lib64/ccache/g++ + for comp in c++ cc gcc g++; do + if ! [ -e /usr/lib64/ccache/$comp ]; then + ln -s /usr/bin/ccache /usr/lib64/ccache/$comp + fi + done export PATH="/usr/lib64/ccache:$PATH" elif [[ -d "/usr/lib/ccache" ]]; then - ln -s /usr/bin/ccache /usr/lib/ccache/c++ - ln -s /usr/bin/ccache /usr/lib/ccache/cc - ln -s /usr/bin/ccache /usr/lib/ccache/gcc - ln -s /usr/bin/ccache /usr/lib/ccache/g++ + for comp in c++ cc gcc g++; do + if ! [ -e /usr/lib/ccache/$comp ]; then + ln -s /usr/bin/ccache /usr/lib/ccache/$comp + fi + done export PATH="/usr/lib/ccache:$PATH" fi diff --git a/src/db/db/dbPLCConvexDecomposition.cc b/src/db/db/dbPLCConvexDecomposition.cc index 426dfa06d..17b664cb5 100644 --- a/src/db/db/dbPLCConvexDecomposition.cc +++ b/src/db/db/dbPLCConvexDecomposition.cc @@ -429,12 +429,6 @@ ConvexDecomposition::decompose (const db::Polygon &poly, const ConvexDecompositi decompose (poly, parameters, db::CplxTrans (dbu)); } -void -ConvexDecomposition::decompose (const db::Polygon &poly, const std::vector &vertexes, const ConvexDecompositionParameters ¶meters, double dbu) -{ - decompose (poly, vertexes, parameters, db::CplxTrans (dbu)); -} - void ConvexDecomposition::decompose (const db::Polygon &poly, const ConvexDecompositionParameters ¶meters, const db::CplxTrans &trans) { @@ -444,15 +438,6 @@ ConvexDecomposition::decompose (const db::Polygon &poly, const ConvexDecompositi hertel_mehlhorn_decomposition (tri, parameters); } -void -ConvexDecomposition::decompose (const db::Polygon &poly, const std::vector &vertexes, const ConvexDecompositionParameters ¶meters, const db::CplxTrans &trans) -{ - Triangulation tri (mp_graph); - tri.triangulate (poly, vertexes, parameters.tri_param, trans); - - hertel_mehlhorn_decomposition (tri, parameters); -} - void ConvexDecomposition::decompose (const db::DPolygon &poly, const ConvexDecompositionParameters ¶meters, const db::DCplxTrans &trans) { @@ -462,15 +447,6 @@ ConvexDecomposition::decompose (const db::DPolygon &poly, const ConvexDecomposit hertel_mehlhorn_decomposition (tri, parameters); } -void -ConvexDecomposition::decompose (const db::DPolygon &poly, const std::vector &vertexes, const ConvexDecompositionParameters ¶meters, const db::DCplxTrans &trans) -{ - Triangulation tri (mp_graph); - tri.triangulate (poly, vertexes, parameters.tri_param, trans); - - hertel_mehlhorn_decomposition (tri, parameters); -} - void ConvexDecomposition::decompose (const db::Region ®ion, const ConvexDecompositionParameters ¶meters, double dbu) { diff --git a/src/db/db/dbPLCConvexDecomposition.h b/src/db/db/dbPLCConvexDecomposition.h index 6b0effc43..d236a29ef 100644 --- a/src/db/db/dbPLCConvexDecomposition.h +++ b/src/db/db/dbPLCConvexDecomposition.h @@ -118,15 +118,12 @@ public: // more versions void decompose (const db::Region ®ion, const ConvexDecompositionParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ()); void decompose (const db::Polygon &poly, const ConvexDecompositionParameters ¶meters, double dbu = 1.0); - void decompose (const db::Polygon &poly, const std::vector &vertexes, const ConvexDecompositionParameters ¶meters, double dbu = 1.0); void decompose (const db::Polygon &poly, const ConvexDecompositionParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ()); - void decompose (const db::Polygon &poly, const std::vector &vertexes, const ConvexDecompositionParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ()); /** * @brief Decomposes a floating-point polygon */ void decompose (const db::DPolygon &poly, const ConvexDecompositionParameters ¶meters, const db::DCplxTrans &trans = db::DCplxTrans ()); - void decompose (const db::DPolygon &poly, const std::vector &vertexes, const ConvexDecompositionParameters ¶meters, const db::DCplxTrans &trans = db::DCplxTrans ()); private: Graph *mp_graph; diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 792d65d15..b258f5aad 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -2269,7 +2269,7 @@ Class decl_dbNetlist ("db", "Netlist", "This method is a convenience method that runs \\make_top_level_pins, \\purge, \\combine_devices and \\purge_nets." ) + gsi::method_ext ("read", &read_netlist, gsi::arg ("file"), gsi::arg ("reader"), - "@brief Writes the netlist to the given file using the given reader object to parse the file\n" + "@brief Reads the netlist from the given file using the given reader object to parse the file\n" "See \\NetlistSpiceReader for an example for a parser. " ) + gsi::method_ext ("write", &write_netlist, gsi::arg ("file"), gsi::arg ("writer"), gsi::arg ("description", std::string ()), diff --git a/src/db/unit_tests/dbPLCConvexDecompositionTests.cc b/src/db/unit_tests/dbPLCConvexDecompositionTests.cc index 007e6d4d6..22b8282b6 100644 --- a/src/db/unit_tests/dbPLCConvexDecompositionTests.cc +++ b/src/db/unit_tests/dbPLCConvexDecompositionTests.cc @@ -110,49 +110,6 @@ TEST(basic) db::compare_layouts (_this, *ly, tl::testdata () + "/algo/hm_decomposition_au4.gds"); } -TEST(internal_vertex) -{ - db::plc::Graph plc; - TestableConvexDecomposition decomp (&plc); - - db::Point contour[] = { - db::Point (0, 0), - db::Point (0, 100), - db::Point (1000, 100), - db::Point (1000, 0) - }; - - std::vector vertexes; - vertexes.push_back (db::Point (0, 50)); // on edge - vertexes.push_back (db::Point (200, 70)); - vertexes.push_back (db::Point (0, 0)); // on vertex - - db::Polygon poly; - poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0])); - - double dbu = 0.001; - - db::plc::ConvexDecompositionParameters param; - decomp.decompose (poly, vertexes, param, dbu); - - EXPECT_EQ (plc.begin () == plc.end (), false); - if (plc.begin () == plc.end ()) { - return; - } - - auto p = plc.begin (); - EXPECT_EQ (p->polygon ().to_string (), "(0,0;0,0.05;0,0.1;1,0.1;1,0)"); - - std::vector ip; - for (size_t i = 0; i < p->internal_vertexes (); ++i) { - ip.push_back (p->internal_vertex (i)->to_string () + "#" + tl::join (p->internal_vertex (i)->ids ().begin (), p->internal_vertex (i)->ids ().end (), ",")); - } - std::sort (ip.begin (), ip.end ()); - EXPECT_EQ (tl::join (ip, "/"), "(0, 0)#2/(0, 0.05)#0/(0.2, 0.07)#1"); - - EXPECT_EQ (++p == plc.end (), true); -} - TEST(problematic_polygon) { db::Point contour[] = { diff --git a/src/pex/pex/pexSquareCountingRExtractor.cc b/src/pex/pex/pexSquareCountingRExtractor.cc index 08b324d13..eb04fb78d 100644 --- a/src/pex/pex/pexSquareCountingRExtractor.cc +++ b/src/pex/pex/pexSquareCountingRExtractor.cc @@ -35,17 +35,9 @@ const double infinite_squares = 1e10; namespace { -class PolygonPortInteractionReceiver - : public db::box_scanner_receiver2 +class PortInteractionReceiverBase { public: - void add (const db::Polygon *obj1, const size_t &index1, const db::Polygon *obj2, const size_t &index2) - { - if (db::interact_pp (*obj1, *obj2)) { - m_interactions[index1].insert (index2); - } - } - const std::set &interactions (size_t index) const { static std::set empty; @@ -57,10 +49,42 @@ public: } } +protected: + void insert (size_t index1, size_t index2) + { + m_interactions[index1].insert (index2); + } + private: std::map > m_interactions; }; +class PolygonPortInteractionReceiver + : public db::box_scanner_receiver2, + public PortInteractionReceiverBase +{ +public: + void add (const db::Polygon *obj1, const size_t &index1, const db::Polygon *obj2, const size_t &index2) + { + if (db::interact_pp (*obj1, *obj2)) { + insert (index1, index2); + } + } +}; + +class VertexPortInteractionReceiver + : public db::box_scanner_receiver2, + public PortInteractionReceiverBase +{ +public: + void add (const db::Polygon *obj1, const size_t &index1, const db::Point *obj2, const size_t &index2) + { + if (obj1->box ().contains (*obj2) && db::inside_poly (obj1->begin_edge (), *obj2) >= 0) { + insert (index1, index2); + } + } +}; + struct JoinEdgeSets { void operator() (std::set &a, const std::set &b) const @@ -188,12 +212,9 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector db::plc::Graph plc; db::plc::ConvexDecomposition decomp (&plc); - decomp.decompose (polygon, vertex_ports, m_decomp_param, trans); + decomp.decompose (polygon, m_decomp_param, trans); - // Set up a scanner to detect interactions between polygon ports - // and decomposed polygons - - db::box_scanner2 scanner; + // create a heap for the scanners std::vector > decomp_polygons; for (auto p = plc.begin (); p != plc.end (); ++p) { @@ -201,17 +222,50 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector decomp_polygons.back ().first = inv_trans * p->polygon (); } - for (auto i = decomp_polygons.begin (); i != decomp_polygons.end (); ++i) { - scanner.insert1 (&i->first, i - decomp_polygons.begin ()); + // Set up a scanner to detect interactions between polygon ports + // and decomposed polygons + + PolygonPortInteractionReceiver interactions_pp; + + if (! decomp_polygons.empty () && ! polygon_ports.empty ()) { + + db::box_scanner2 scanner; + + for (auto i = decomp_polygons.begin (); i != decomp_polygons.end (); ++i) { + scanner.insert1 (&i->first, i - decomp_polygons.begin ()); + } + + for (auto i = polygon_ports.begin (); i != polygon_ports.end (); ++i) { + scanner.insert2 (i.operator-> (), i - polygon_ports.begin ()); + } + + db::box_convert bc; + scanner.process (interactions_pp, 1, bc, bc); + } - for (auto i = polygon_ports.begin (); i != polygon_ports.end (); ++i) { - scanner.insert2 (i.operator-> (), i - polygon_ports.begin ()); - } + // Set up a scanner to detect interactions between vertex ports + // and decomposed polygons - PolygonPortInteractionReceiver interactions; - db::box_convert bc; - scanner.process (interactions, 1, bc, bc); + VertexPortInteractionReceiver interactions_vp; + + if (! decomp_polygons.empty () && ! vertex_ports.empty ()) { + + db::box_scanner2 scanner; + + for (auto i = decomp_polygons.begin (); i != decomp_polygons.end (); ++i) { + scanner.insert1 (&i->first, i - decomp_polygons.begin ()); + } + + for (auto i = vertex_ports.begin (); i != vertex_ports.end (); ++i) { + scanner.insert2 (i.operator-> (), i - vertex_ports.begin ()); + } + + db::box_convert bc1; + db::box_convert bc2; + scanner.process (interactions_vp, 1, bc1, bc2); + + } // Generate the internal ports: those are defined by edges connecting two polygons @@ -253,8 +307,8 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector ports.clear (); const db::Polygon &db_poly = p->first; - const db::plc::Polygon *plc_poly = p->second; - const std::set &pp_indexes = interactions.interactions (p - decomp_polygons.begin ()); + const std::set &pp_indexes = interactions_pp.interactions (p - decomp_polygons.begin ()); + const std::set &vp_indexes = interactions_vp.interactions (p - decomp_polygons.begin ()); const std::vector &ip_indexes = internal_port_indexes [p - decomp_polygons.begin ()]; // set up the ports: @@ -266,16 +320,12 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector } // 2. vertex ports - for (size_t i = 0; i < plc_poly->internal_vertexes (); ++i) { - auto v = plc_poly->internal_vertex (i); - db::Point loc = inv_trans * *v; - for (auto pi = v->ids ().begin (); pi != v->ids ().end (); ++pi) { - ports.push_back (std::make_pair (PortDefinition (pex::RNode::VertexPort, loc, *pi), (pex::RNode *) 0)); - } + for (auto i = vp_indexes.begin (); i != vp_indexes.end (); ++i) { + db::Point loc = vertex_ports [*i]; + ports.push_back (std::make_pair (PortDefinition (pex::RNode::VertexPort, db::Box (loc, loc), (unsigned int) *i), (pex::RNode *) 0)); } // 3. polygon ports - // (NOTE: here we only take the center of the bounding box) for (auto i = pp_indexes.begin (); i != pp_indexes.end (); ++i) { db::Box loc = polygon_ports [*i].box (); ports.push_back (std::make_pair (PortDefinition (pex::RNode::PolygonPort, loc, (unsigned int) *i), (pex::RNode *) 0)); diff --git a/src/pex/pex/pexTriangulationRExtractor.cc b/src/pex/pex/pexTriangulationRExtractor.cc index 500a5c179..be25c043e 100644 --- a/src/pex/pex/pexTriangulationRExtractor.cc +++ b/src/pex/pex/pexTriangulationRExtractor.cc @@ -46,6 +46,8 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< tl::SelfTimer timer (tl::verbosity () >= m_tri_param.base_verbosity + 1, "Extracting resistor network from polygon (TriangulationRExtractor)"); db::CplxTrans trans = db::CplxTrans (m_dbu) * db::ICplxTrans (db::Trans (db::Point () - polygon.box ().center ())); + db::CplxTrans dbu_trans = db::CplxTrans (m_dbu); + db::DCplxTrans v2loc_trans = dbu_trans * trans.inverted (); // vertex to node location db::plc::Graph plc; db::plc::Triangulation tri (&plc); @@ -56,8 +58,6 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< tri.triangulate (polygon, vertex_ports, m_tri_param, trans); - plc.dump ("debug.gds"); - } else { tl::SelfTimer timer_tri (tl::verbosity () >= m_tri_param.base_verbosity + 11, "Triangulation step"); @@ -150,7 +150,7 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< } else { n = rnetwork.create_node (pex::RNode::PolygonPort, (unsigned int) port_index, 0); pport_nodes.insert (std::make_pair (port_index, n)); - n->location = trans * polygon_ports [port_index].box (); + n->location = dbu_trans * polygon_ports [port_index].box (); } } else if (vertex->is_precious ()) { @@ -159,7 +159,7 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< size_t port_index = size_t (*pi); if (port_index < vertex_ports.size ()) { RNode *nn = rnetwork.create_node (pex::RNode::VertexPort, (unsigned int) port_index, 0); - nn->location = db::DBox (*vertex, *vertex); + nn->location = v2loc_trans * db::DBox (*vertex, *vertex); if (n) { // in case of multiple vertexes on the same spot, short them rnetwork.create_element (RElement::short_value (), n, nn); @@ -173,7 +173,7 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< } else { n = rnetwork.create_node (pex::RNode::Internal, (unsigned int) internal_node_id++, 0); - n->location = db::DBox (*vertex, *vertex); + n->location = v2loc_trans * db::DBox (*vertex, *vertex); } @@ -205,7 +205,7 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< // create a new vertex port and short it to the polygon port auto n = rnetwork.create_node (pex::RNode::VertexPort, (unsigned int) iv, 0); - n->location = db::DBox (trans * vp, trans * vp); + n->location = dbu_trans * db::Box (vp, vp); rnetwork.create_element (pex::RElement::short_value (), n, ip->second); } diff --git a/src/pex/unit_tests/pexSquareCountingRExtractorTests.cc b/src/pex/unit_tests/pexSquareCountingRExtractorTests.cc index 5b566152d..0bb1dcb87 100644 --- a/src/pex/unit_tests/pexSquareCountingRExtractorTests.cc +++ b/src/pex/unit_tests/pexSquareCountingRExtractorTests.cc @@ -213,3 +213,35 @@ TEST(extraction_meander) "R V0(0.3,0;0.3,0) V1(4.3,1;4.3,1) 10.0543767445" // that is pretty much the length of the center line / width :) ) } + +TEST(issue_2102) +{ + db::Point contour[] = { + db::Point (-85, -610), + db::Point (-85, 610), + db::Point (85, 610), + db::Point (85, 440), + db::Point (65, 440), + db::Point (65, -610) + }; + + db::Polygon poly; + poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0])); + + double dbu = 0.001; + + pex::RNetwork rn; + pex::SquareCountingRExtractor rex (dbu); + + std::vector vertex_ports; + vertex_ports.push_back (db::Point (0, 525)); + vertex_ports.push_back (db::Point (-85, -610)); + + std::vector polygon_ports; + + rex.extract (poly, vertex_ports, polygon_ports, rn); + + EXPECT_EQ (network2s (rn), + "R V0(0,0.525;0,0.525) V1(-0.085,-0.61;-0.085,-0.61) 7.89600487195" // was crashing before + ) +} diff --git a/src/pex/unit_tests/pexTriangulationRExtractorTests.cc b/src/pex/unit_tests/pexTriangulationRExtractorTests.cc index ab485e7cb..06d0806c1 100644 --- a/src/pex/unit_tests/pexTriangulationRExtractorTests.cc +++ b/src/pex/unit_tests/pexTriangulationRExtractorTests.cc @@ -63,8 +63,8 @@ TEST(extraction) rex.extract (poly, vertex_ports, polygon_ports, rn); - EXPECT_EQ (rn.to_string (), - "R V0 V1 10.0938" + EXPECT_EQ (rn.to_string (true), + "R V0(0,0.05;0,0.05) V1(1,0.05;1,0.05) 10.0938" ) } @@ -93,8 +93,8 @@ TEST(extraction_with_polygon_ports) rex.extract (poly, vertex_ports, polygon_ports, rn); - EXPECT_EQ (rn.to_string (), - "R P0 P1 10" + EXPECT_EQ (rn.to_string (true), + "R P0(-0.1,0;0,0.1) P1(1,0;1.1,0.1) 10" ) }