More compound DRC operations (join, merge, count filter)

This commit is contained in:
Matthias Koefferlein 2021-01-04 21:34:12 +01:00
parent ee082f65a0
commit 6dd190e3af
12 changed files with 402 additions and 23 deletions

View File

@ -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::Polygon> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::Polygon> > &, size_t, double) const;
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::PolygonRef> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::PolygonRef> > &, size_t, double) const;
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::Polygon, db::Polygon> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::Polygon> > &, size_t, double) const;
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::PolygonRef, db::PolygonRef> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::PolygonRef> > &, size_t, double) const;
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::Polygon, db::Edge> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::Edge> > &, size_t, double) const;
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::PolygonRef, db::Edge> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::Edge> > &, size_t, double) const;
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::Polygon, db::EdgePair> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::PolygonRef, db::EdgePair> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
// ---------------------------------------------------------------------------------------------
CompoundRegionJoinOperationNode::CompoundRegionJoinOperationNode (const std::vector<CompoundRegionOperationNode *> &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 <class T, class TR>
void CompoundRegionJoinOperationNode::implement_compute_local (db::Layout *layout, const shape_interactions<T, T> &interactions, std::vector<std::unordered_set<TR> > &results, size_t max_vertex_count, double area_ratio) const
{
for (unsigned int ci = 0; ci < children (); ++ci) {
shape_interactions<T, T> computed;
const shape_interactions<T, T> &child_interactions = interactions_for_child<T, T> (interactions, ci, computed);
child (ci)->compute_local (layout, child_interactions, results, max_vertex_count, area_ratio);
}
}
template void CompoundRegionJoinOperationNode::implement_compute_local<db::Polygon, db::Polygon> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::Polygon> > &, size_t, double) const;
template void CompoundRegionJoinOperationNode::implement_compute_local<db::PolygonRef, db::PolygonRef> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::PolygonRef> > &, size_t, double) const;
template void CompoundRegionJoinOperationNode::implement_compute_local<db::Polygon, db::Edge> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::Edge> > &, size_t, double) const;
template void CompoundRegionJoinOperationNode::implement_compute_local<db::PolygonRef, db::Edge> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::Edge> > &, size_t, double) const;
template void CompoundRegionJoinOperationNode::implement_compute_local<db::Polygon, db::EdgePair> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
template void CompoundRegionJoinOperationNode::implement_compute_local<db::PolygonRef, db::EdgePair> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
// ---------------------------------------------------------------------------------------------

View File

@ -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<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &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<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &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<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Edge> > &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<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &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<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::EdgePair> > &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<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::EdgePair> > &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 <class T, class TR>
void implement_compute_local (db::Layout *layout, const shape_interactions<T, T> &interactions, std::vector<std::unordered_set<TR> > &results, size_t max_vertex_count, double area_ratio) const
{
std::vector<std::unordered_set<TR> > one;
one.push_back (std::unordered_set<TR> ());
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<db::Polygon, db::Edge, db::Edge> 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<CompoundRegionOperationNode *> &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<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &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<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &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<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &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<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Edge> > &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<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::EdgePair> > &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<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t max_vertex_count, double area_ratio) const
{
implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio);
}
private:
template <class T, class TR>
void implement_compute_local (db::Layout *layout, const shape_interactions<T, T> &interactions, std::vector<std::unordered_set<TR> > &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<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &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<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &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 <class T>
void implement_compute_local (db::Layout *layout, const shape_interactions<T, T> &interactions, std::vector<std::unordered_set<T> > &results, size_t max_vertex_count, double area_ratio) const
{
std::vector<std::unordered_set<T> > one;
one.push_back (std::unordered_set<T> ());
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<T>::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<T>::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<T> 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
{

View File

@ -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
*

View File

@ -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<db::PolygonRef> &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<db::PolygonRef> *mp_result;
};
template <class TR>
struct result_counting_inserter
{

View File

@ -198,6 +198,11 @@ static db::CompoundRegionOperationNode *new_case (const std::vector<db::Compound
return new db::CompoundRegionLogicalCaseSelectOperationNode (inputs);
}
static db::CompoundRegionOperationNode *new_count_filter (db::CompoundRegionOperationNode *input, bool invert, size_t min_count, size_t max_count)
{
return new db::CompoundRegionCountFilterNode (input, invert, min_count, max_count);
}
static db::CompoundRegionOperationNode *new_corners_as_rectangles (db::CompoundRegionOperationNode *input, double angle_start, double angle_end, db::Coord dim = 1)
{
check_non_null (input, "input");
@ -261,6 +266,12 @@ static db::CompoundRegionOperationNode *new_sized (db::CompoundRegionOperationNo
return new db::CompoundRegionProcessingOperationNode (new db::PolygonSizer (dx, dy, mode), input, true /*processor is owned*/);
}
static db::CompoundRegionOperationNode *new_merged (db::CompoundRegionOperationNode *input, bool min_coherence, unsigned int min_wc)
{
check_non_null (input, "input");
return new db::CompoundRegionMergeOperationNode (min_coherence, min_wc, input);
}
static db::CompoundRegionOperationNode *new_minkowsky_sum_node1 (db::CompoundRegionOperationNode *input, const db::Edge &e)
{
check_non_null (input, "input");
@ -542,6 +553,9 @@ Class<db::CompoundRegionOperationNode> 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<size_t>::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<db::CompoundRegionOperationNode> 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"
) +

View File

@ -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<db::CompoundRegionOperationNode *> 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);
}

BIN
testdata/drc/compound_14.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/compound_15.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/compound_au14.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/compound_au14d.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/compound_au15.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/compound_au15d.gds vendored Normal file

Binary file not shown.