diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc index 6070f5ab5..455c60dae 100644 --- a/src/db/db/dbCompoundOperation.cc +++ b/src/db/db/dbCompoundOperation.cc @@ -459,6 +459,24 @@ void CompoundRegionLogicalBoolOperationNode::implement_compute_local (db::Layout // --------------------------------------------------------------------------------------------- +CompoundRegionCountFilterNode::CompoundRegionCountFilterNode (CompoundRegionOperationNode *input, bool invert, size_t min_count, size_t max_count) + : CompoundRegionMultiInputOperationNode (input), m_min_count (min_count), m_max_count (max_count), m_invert (invert) +{ + // .. nothing yet .. +} + +CompoundRegionCountFilterNode::~CompoundRegionCountFilterNode () +{ + // .. nothing yet .. +} + +std::string CompoundRegionCountFilterNode::generated_description () const +{ + return std::string ("count_filter") + CompoundRegionMultiInputOperationNode::generated_description (); +} + +// --------------------------------------------------------------------------------------------- + CompoundRegionGeometricalBoolOperationNode::CompoundRegionGeometricalBoolOperationNode (GeometricalOp op, CompoundRegionOperationNode *a, CompoundRegionOperationNode *b) : CompoundRegionMultiInputOperationNode (a, b), m_op (op) { @@ -675,7 +693,7 @@ run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layo if (op == CompoundRegionGeometricalBoolOperationNode::And) { write_result (layout, res, ea & eb); } else if (op == CompoundRegionGeometricalBoolOperationNode::Or) { - write_result (layout, res, ea + eb); + write_result (layout, res, ea | eb); } else if (op == CompoundRegionGeometricalBoolOperationNode::Xor) { write_result (layout, res, ea ^ eb); } else if (op == CompoundRegionGeometricalBoolOperationNode::Not) { @@ -992,8 +1010,62 @@ void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db:: } -template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; -template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; + +// --------------------------------------------------------------------------------------------- + +CompoundRegionJoinOperationNode::CompoundRegionJoinOperationNode (const std::vector &inputs) + : CompoundRegionMultiInputOperationNode (inputs) +{ + // .. nothing yet .. +} + +std::string CompoundRegionJoinOperationNode::generated_description () const +{ + // TODO: could be nicer ... + std::string r; + r = "if-then"; + return r + CompoundRegionMultiInputOperationNode::generated_description (); +} + +CompoundRegionJoinOperationNode::ResultType +CompoundRegionJoinOperationNode::result_type () const +{ + ResultType result = Region; + for (size_t i = 0; i < children (); ++i) { + if (i == 0) { + result = child (i)->result_type (); + } else { + tl_assert (result == child (i)->result_type ()); + } + } + return result; +} + +template +void CompoundRegionJoinOperationNode::implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + for (unsigned int ci = 0; ci < children (); ++ci) { + + shape_interactions computed; + const shape_interactions &child_interactions = interactions_for_child (interactions, ci, computed); + + child (ci)->compute_local (layout, child_interactions, results, max_vertex_count, area_ratio); + + } +} + +template void CompoundRegionJoinOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionJoinOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionJoinOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionJoinOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionJoinOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; +template void CompoundRegionJoinOperationNode::implement_compute_local (db::Layout *, const shape_interactions &, std::vector > &, size_t, double) const; // --------------------------------------------------------------------------------------------- diff --git a/src/db/db/dbCompoundOperation.h b/src/db/db/dbCompoundOperation.h index 9cc55f968..c725a138f 100644 --- a/src/db/db/dbCompoundOperation.h +++ b/src/db/db/dbCompoundOperation.h @@ -26,12 +26,14 @@ #include "dbCommon.h" #include "dbLocalOperation.h" #include "dbHierProcessor.h" +#include "dbEdgeProcessor.h" #include "dbRegionDelegate.h" #include "dbRegion.h" #include "dbEdges.h" #include "dbEdgePairs.h" #include "dbRegionProcessors.h" #include "dbRegionLocalOperations.h" +#include "dbLocalOperationUtils.h" #include "dbTypes.h" #include "gsiObject.h" @@ -438,6 +440,71 @@ private: }; +class DB_PUBLIC CompoundRegionCountFilterNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionCountFilterNode (CompoundRegionOperationNode *input, bool invert, size_t min_count, size_t max_count); + ~CompoundRegionCountFilterNode (); + + virtual std::string generated_description () const; + + // specifies the result type + virtual ResultType result_type () const + { + return child (0)->result_type (); + } + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + +private: + size_t m_min_count, m_max_count; + bool m_invert; + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + std::vector > one; + one.push_back (std::unordered_set ()); + + child (0)->compute_local (layout, interactions, one, max_vertex_count, area_ratio); + + if ((one.front ().size () >= m_min_count && one.front ().size () < m_max_count) != m_invert) { + results.front ().insert (one.front ().begin (), one.front ().end ()); + } + } +}; + + class DB_PUBLIC CompoundRegionGeometricalBoolOperationNode : public CompoundRegionMultiInputOperationNode { @@ -673,6 +740,59 @@ private: db::pull_with_edge_local_operation m_op; }; +/** + * @brief Implements the joining of results + * + * This operator joins all inputs into a common output. + * The types of the inputs must be the same. + */ + +class DB_PUBLIC CompoundRegionJoinOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionJoinOperationNode (const std::vector &inputs); + + virtual std::string generated_description () const; + + // specifies the result type + virtual ResultType result_type () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + +private: + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; +}; /** * @brief Implements the case selection @@ -915,6 +1035,69 @@ private: CompoundTransformationReducer m_vars; }; +class DB_PUBLIC CompoundRegionMergeOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionMergeOperationNode (bool min_coherence, unsigned int min_wc, CompoundRegionOperationNode *input) + : CompoundRegionMultiInputOperationNode (input), m_min_coherence (min_coherence), m_min_wc (min_wc) + { } + + ~CompoundRegionMergeOperationNode () { } + + virtual ResultType result_type () const { return Region; } + + virtual std::string description () const + { + return std::string ("merged") + CompoundRegionMultiInputOperationNode::generated_description (); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + +private: + bool m_min_coherence; + unsigned int m_min_wc; + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + std::vector > one; + one.push_back (std::unordered_set ()); + + child (0)->compute_local (layout, interactions, one, max_vertex_count, area_ratio); + + db::EdgeProcessor ep; + + // count edges and reserve memory + size_t n = 0; + for (typename std::unordered_set::const_iterator p = one.front ().begin (); p != one.front ().end (); ++p) { + n += p->vertices (); + } + ep.reserve (n); + + // insert the polygons into the processor + n = 0; + for (typename std::unordered_set::const_iterator p = one.front ().begin (); p != one.front ().end (); ++p) { + ep.insert (*p, n); + ++n; + } + + // and run the merge step + db::MergeOp op (m_min_wc); + db::polygon_ref_generator pc (layout, results.front ()); + db::PolygonGenerator pg (pc, false /*don't resolve holes*/, m_min_coherence); + ep.process (pg, op); + } +}; + class DB_PUBLIC CompoundRegionEdgeToPolygonProcessingOperationNode : public CompoundRegionMultiInputOperationNode { diff --git a/src/db/db/dbPolygon.h b/src/db/db/dbPolygon.h index c0ca15f90..6d3c58246 100644 --- a/src/db/db/dbPolygon.h +++ b/src/db/db/dbPolygon.h @@ -3226,6 +3226,22 @@ public: return this->obj ().is_box (); } + /** + * @brief Returns a value indicating whether the polygon is rectilinear + */ + bool is_rectilinear () const + { + return this->obj ().is_rectilinear (); + } + + /** + * @brief Returns the number of vertices + */ + size_t vertices () const + { + return this->obj ().vertices (); + } + /** * @brief Return the transformed object * diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 09ff12df2..6e48a2daf 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -46,26 +46,6 @@ static inline const db::PolygonRef *push_polygon_to_heap (db::Layout *layout, co return &heap.back (); } -struct ResultInserter -{ - typedef db::Polygon value_type; - - ResultInserter (db::Layout *layout, std::unordered_set &result) - : mp_layout (layout), mp_result (&result) - { - // .. nothing yet .. - } - - void insert (const db::Polygon &p) - { - (*mp_result).insert (db::PolygonRef (p, mp_layout->shape_repository ())); - } - -private: - db::Layout *mp_layout; - std::unordered_set *mp_result; -}; - template struct result_counting_inserter { diff --git a/src/db/db/gsiDeclDbCompoundOperation.cc b/src/db/db/gsiDeclDbCompoundOperation.cc index d3d6379c5..4ea70119e 100644 --- a/src/db/db/gsiDeclDbCompoundOperation.cc +++ b/src/db/db/gsiDeclDbCompoundOperation.cc @@ -198,6 +198,11 @@ static db::CompoundRegionOperationNode *new_case (const std::vector decl_CompoundRegionOperationNode ("db", " "rendered if c2 isn't empty etc. If none of the conditions renders a non-empty set and a default result is present, the default will be " "returned. Otherwise, the result is empty." ) + + gsi::constructor ("new_count_filter", &new_count_filter, gsi::arg ("inputs"), gsi::arg ("invert", false), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", std::numeric_limits::max ()), + "@brief Creates a node selecting results but their shape count.\n" + ) + gsi::constructor ("new_corners_as_rectangles", &new_corners_as_rectangles, gsi::arg ("input"), gsi::arg ("angle_start"), gsi::arg ("angle_end"), gsi::arg ("dim"), "@brief Creates a node turning corners into rectangles.\n" ) + @@ -570,6 +584,9 @@ Class decl_CompoundRegionOperationNode ("db", " gsi::constructor ("new_sized", &new_sized, gsi::arg ("input"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"), "@brief Creates a node providing sizing.\n" ) + + gsi::constructor ("new_merged", &new_merged, gsi::arg ("input"), gsi::arg ("min_coherence", false), gsi::arg ("min_wc", 0), + "@brief Creates a node providing merged input polygons.\n" + ) + gsi::constructor ("new_minkowsky_sum", &new_minkowsky_sum_node1, gsi::arg ("input"), gsi::arg ("e"), "@brief Creates a node providing a Minkowsky sum with an edge.\n" ) + diff --git a/src/db/unit_tests/dbCompoundOperationTests.cc b/src/db/unit_tests/dbCompoundOperationTests.cc index 6224bc65d..aea096750 100644 --- a/src/db/unit_tests/dbCompoundOperationTests.cc +++ b/src/db/unit_tests/dbCompoundOperationTests.cc @@ -749,3 +749,114 @@ TEST(13d_EdgeProcessor) run_test13 (_this, true); } +void run_test14 (tl::TestBase *_this, bool deep) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/drc/compound_14.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::RegionCheckOptions check_options; + check_options.metrics = db::Projection; + + db::DeepShapeStore dss; + + db::Region r, r2; + prep_layer (ly, 1, r, dss, deep); + prep_layer (ly, 2, r2, dss, deep); + + db::CompoundRegionOperationPrimaryNode *primary = new db::CompoundRegionOperationPrimaryNode (); + db::CompoundRegionOperationSecondaryNode *secondary = new db::CompoundRegionOperationSecondaryNode (&r2); + + std::vector inputs; + inputs.push_back (primary); + inputs.push_back (secondary); + db::CompoundRegionJoinOperationNode *join = new db::CompoundRegionJoinOperationNode (inputs); + + EXPECT_EQ (join->result_type () == db::CompoundRegionJoinOperationNode::Region, true); + + db::CompoundRegionMergeOperationNode merge1 (false, 0, join); + db::CompoundRegionMergeOperationNode merge2 (false, 1, join); + + db::Region res1 = r.cop_to_region (merge1); + + unsigned int l1000 = ly.get_layer (db::LayerProperties (1000, 0)); + res1.insert_into (&ly, *ly.begin_top_down (), l1000); + + db::Region res2 = r.cop_to_region (merge2); + + unsigned int l1001 = ly.get_layer (db::LayerProperties (1001, 0)); + res2.insert_into (&ly, *ly.begin_top_down (), l1001); + + CHECKPOINT(); + db::compare_layouts (_this, ly, make_au ("14", deep)); +} + +TEST(14_JoinAndMerged) +{ + run_test14 (_this, false); +} + +TEST(14d_JoinAndMerged) +{ + run_test14 (_this, true); +} + +void run_test15 (tl::TestBase *_this, bool deep) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/drc/compound_15.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::RegionCheckOptions check_options; + check_options.metrics = db::Projection; + + db::DeepShapeStore dss; + + db::Region r, r2; + prep_layer (ly, 1, r, dss, deep); + prep_layer (ly, 2, r2, dss, deep); + + db::CompoundRegionOperationPrimaryNode *primary = new db::CompoundRegionOperationPrimaryNode (); + + db::CompoundRegionProcessingOperationNode *corners1 = new db::CompoundRegionProcessingOperationNode (new db::CornersAsRectangles (-180.0, 180.0, 1), primary, true /*processor is owned*/); + db::CompoundRegionCountFilterNode count1 (corners1, false, 5, 10000); + + db::CompoundRegionToEdgeProcessingOperationNode *corners2 = new db::CompoundRegionToEdgeProcessingOperationNode (new db::CornersAsDots (-180.0, 180.0), primary, true /*processor is owned*/); + db::CompoundRegionCountFilterNode count2 (corners2, true, 5, 10000); + + EXPECT_EQ (count1.result_type () == db::CompoundRegionJoinOperationNode::Region, true); + EXPECT_EQ (count2.result_type () == db::CompoundRegionJoinOperationNode::Edges, true); + + db::Region res1 = r.cop_to_region (count1); + + unsigned int l1000 = ly.get_layer (db::LayerProperties (1000, 0)); + res1.insert_into (&ly, *ly.begin_top_down (), l1000); + + db::Edges res2 = r.cop_to_edges (count2); + + unsigned int l1001 = ly.get_layer (db::LayerProperties (1001, 0)); + res2.insert_into (&ly, *ly.begin_top_down (), l1001); + + CHECKPOINT(); + db::compare_layouts (_this, ly, make_au ("15", deep)); +} + +TEST(15_JoinAndMerged) +{ + run_test15 (_this, false); +} + +TEST(15d_JoinAndMerged) +{ + run_test15 (_this, true); +} diff --git a/testdata/drc/compound_14.gds b/testdata/drc/compound_14.gds new file mode 100644 index 000000000..6b2abc7f8 Binary files /dev/null and b/testdata/drc/compound_14.gds differ diff --git a/testdata/drc/compound_15.gds b/testdata/drc/compound_15.gds new file mode 100644 index 000000000..6b2abc7f8 Binary files /dev/null and b/testdata/drc/compound_15.gds differ diff --git a/testdata/drc/compound_au14.gds b/testdata/drc/compound_au14.gds new file mode 100644 index 000000000..3565b5ef4 Binary files /dev/null and b/testdata/drc/compound_au14.gds differ diff --git a/testdata/drc/compound_au14d.gds b/testdata/drc/compound_au14d.gds new file mode 100644 index 000000000..4b7886e44 Binary files /dev/null and b/testdata/drc/compound_au14d.gds differ diff --git a/testdata/drc/compound_au15.gds b/testdata/drc/compound_au15.gds new file mode 100644 index 000000000..fdcdf20fe Binary files /dev/null and b/testdata/drc/compound_au15.gds differ diff --git a/testdata/drc/compound_au15d.gds b/testdata/drc/compound_au15d.gds new file mode 100644 index 000000000..9c02b90d4 Binary files /dev/null and b/testdata/drc/compound_au15d.gds differ