Hierarchical implementation of self-overlap merge.

This commit is contained in:
Matthias Koefferlein 2019-02-13 22:41:12 +01:00
parent ddcfda8761
commit 78617930dd
6 changed files with 139 additions and 42 deletions

View File

@ -294,16 +294,31 @@ public:
m_ep.set_base_verbosity (vb);
}
db::Shapes &merged (size_t cid, db::cell_index_type ci, bool initial = true)
db::Shapes &merged (size_t cid, db::cell_index_type ci, unsigned int min_wc = 0)
{
return compute_merged (cid, ci, true, min_wc);
}
void erase (size_t cid, db::cell_index_type ci)
{
m_merged_cluster.erase (std::make_pair (cid, ci));
}
private:
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
unsigned int m_layer;
db::Layout *mp_layout;
const db::hier_clusters<db::PolygonRef> *mp_hc;
bool m_min_coherence;
db::EdgeProcessor m_ep;
db::Shapes &compute_merged (size_t cid, db::cell_index_type ci, bool initial, unsigned int min_wc)
{
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes>::iterator s = m_merged_cluster.find (std::make_pair (cid, ci));
// some sanity checks: initial clusters are single-use, are never generated twice and cannot be retrieved again
if (initial) {
tl_assert (s == m_merged_cluster.end ());
m_done.insert (std::make_pair (cid, ci));
} else {
tl_assert (m_done.find (std::make_pair (cid, ci)) == m_done.end ());
}
if (s != m_merged_cluster.end ()) {
@ -315,51 +330,60 @@ public:
const db::connected_clusters<db::PolygonRef> &cc = mp_hc->clusters_per_cell (ci);
const db::local_cluster<db::PolygonRef> &c = cc.cluster_by_id (cid);
std::list<std::pair<const db::Shapes *, db::ICplxTrans> > merged_child_clusters;
if (min_wc > 0) {
const db::connected_clusters<db::PolygonRef>::connections_type &conn = cc.connections_for_cluster (cid);
for (db::connected_clusters<db::PolygonRef>::connections_type::const_iterator i = conn.begin (); i != conn.end (); ++i) {
const db::Shapes &cc_shapes = merged (i->id (), i->inst ().inst_ptr.cell_index (), false);
merged_child_clusters.push_back (std::make_pair (&cc_shapes, i->inst ().complex_trans ()));
}
// We cannot merge bottom-up in min_wc mode, so we just use the recursive cluster iterator
m_ep.clear ();
m_ep.clear ();
size_t pi = 0;
size_t pi = 0;
for (std::list<std::pair<const db::Shapes *, db::ICplxTrans> >::const_iterator i = merged_child_clusters.begin (); i != merged_child_clusters.end (); ++i) {
for (db::Shapes::shape_iterator s = i->first->begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
if (s->is_polygon ()) {
db::Polygon poly;
s->polygon (poly);
m_ep.insert (poly.transformed (i->second), pi++);
for (db::recursive_cluster_shape_iterator<db::PolygonRef> s = db::recursive_cluster_shape_iterator<db::PolygonRef> (*mp_hc, m_layer, ci, cid); !s.at_end (); ++s) {
db::Polygon poly = s->obj ();
poly.transform (s.trans () * db::ICplxTrans (s->trans ()));
m_ep.insert (poly, pi++);
}
} else {
std::list<std::pair<const db::Shapes *, db::ICplxTrans> > merged_child_clusters;
const db::connected_clusters<db::PolygonRef>::connections_type &conn = cc.connections_for_cluster (cid);
for (db::connected_clusters<db::PolygonRef>::connections_type::const_iterator i = conn.begin (); i != conn.end (); ++i) {
const db::Shapes &cc_shapes = compute_merged (i->id (), i->inst ().inst_ptr.cell_index (), false, min_wc);
merged_child_clusters.push_back (std::make_pair (&cc_shapes, i->inst ().complex_trans ()));
}
m_ep.clear ();
size_t pi = 0;
for (std::list<std::pair<const db::Shapes *, db::ICplxTrans> >::const_iterator i = merged_child_clusters.begin (); i != merged_child_clusters.end (); ++i) {
for (db::Shapes::shape_iterator s = i->first->begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
if (s->is_polygon ()) {
db::Polygon poly;
s->polygon (poly);
m_ep.insert (poly.transformed (i->second), pi++);
}
}
}
}
for (db::local_cluster<db::PolygonRef>::shape_iterator s = c.begin (m_layer); !s.at_end (); ++s) {
db::Polygon poly = s->obj ();
poly.transform (s->trans ());
m_ep.insert (poly, pi++);
for (db::local_cluster<db::PolygonRef>::shape_iterator s = c.begin (m_layer); !s.at_end (); ++s) {
db::Polygon poly = s->obj ();
poly.transform (s->trans ());
m_ep.insert (poly, pi++);
}
}
// and run the merge step
db::MergeOp op (0);
db::MergeOp op (min_wc);
db::PolygonRefToShapesGenerator pr (mp_layout, &s->second);
db::PolygonGenerator pg (pr, false /*don't resolve holes*/, m_min_coherence);
m_ep.process (pg, op);
return s->second;
}
private:
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
std::set<std::pair<size_t, db::cell_index_type> > m_done;
unsigned int m_layer;
db::Layout *mp_layout;
const db::hier_clusters<db::PolygonRef> *mp_hc;
bool m_min_coherence;
db::EdgeProcessor m_ep;
};
}
@ -402,7 +426,7 @@ DeepRegion::ensure_merged_polygons_valid () const
if (cc.is_root (*cl)) {
db::Shapes &s = cm.merged (*cl, c->cell_index ());
c->shapes (m_merged_polygons.layer ()).insert (s);
s.clear (); // not needed anymore
cm.erase (*cl, c->cell_index ()); // not needed anymore
}
}
}
@ -873,8 +897,7 @@ DeepRegion::merged_in_place ()
RegionDelegate *
DeepRegion::merged_in_place (bool min_coherence, unsigned int min_wc)
{
// TODO: can probably be optimized
return db::AsIfFlatRegion::merged_in_place (min_coherence, min_wc);
return merged (min_coherence, min_wc);
}
RegionDelegate *
@ -898,8 +921,39 @@ DeepRegion::merged () const
RegionDelegate *
DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
{
// TODO: can probably be optimized
return db::AsIfFlatRegion::merged (min_coherence, min_wc);
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
db::hier_clusters<db::PolygonRef> hc;
db::Connectivity conn;
conn.connect (m_deep_layer);
// TODO: this uses the wrong verbosity inside ...
hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
DeepLayer dl_out (m_deep_layer.derived ());
ClusterMerger cm (m_deep_layer.layer (), layout, hc, min_coherence, report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity ());
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::connected_clusters<db::PolygonRef> &cc = hc.clusters_per_cell (c->cell_index ());
for (db::connected_clusters<db::PolygonRef>::all_iterator cl = cc.begin_all (); ! cl.at_end (); ++cl) {
if (cc.is_root (*cl)) {
db::Shapes &s = cm.merged (*cl, c->cell_index (), min_wc);
c->shapes (dl_out.layer ()).insert (s);
cm.erase (*cl, c->cell_index ()); // not needed anymore
}
}
}
db::DeepRegion *res = new db::DeepRegion (dl_out);
res->set_is_merged (true);
return res;
}
RegionDelegate *

View File

@ -60,7 +60,7 @@ Region::~Region ()
Region &Region::operator= (const Region &other)
{
if (this != &other) {
set_delegate (other.mp_delegate->clone ());
set_delegate (other.mp_delegate->clone (), false);
}
return *this;
}
@ -94,9 +94,13 @@ Region::iter () const
}
void
Region::set_delegate (RegionDelegate *delegate)
Region::set_delegate (RegionDelegate *delegate, bool keep_attributes)
{
if (delegate != mp_delegate) {
if (keep_attributes && delegate && mp_delegate) {
// copy the basic attributes like #threads etc.
delegate->RegionDelegate::operator= (*mp_delegate);
}
delete mp_delegate;
mp_delegate = delegate;
}
@ -159,7 +163,6 @@ Region::flat_region ()
if (! region) {
region = new FlatRegion ();
if (mp_delegate) {
region->RegionDelegate::operator= (*mp_delegate);
region->insert_seq (begin ());
}
if (mp_delegate) {

View File

@ -1786,7 +1786,7 @@ private:
RegionDelegate *mp_delegate;
void set_delegate (RegionDelegate *delegate);
void set_delegate (RegionDelegate *delegate, bool keep_attributes = true);
FlatRegion *flat_region ();
};

View File

@ -868,6 +868,46 @@ TEST(15_Filtered)
}
}
TEST(16_MergeWithMinWC)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_area_peri_l1.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r1_merged_wc0 = r1.merged (true, 0);
db::Region r1_merged_wc1 = r1.merged (true, 1);
db::Region r1_merged_wc2 = r1.merged (true, 2);
EXPECT_EQ (r1_merged_wc0.is_merged (), true);
EXPECT_EQ (r1_merged_wc1.is_merged (), true);
EXPECT_EQ (r1_merged_wc2.is_merged (), true);
{
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1_merged_wc0);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r1_merged_wc1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r1_merged_wc2);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au16.gds");
}
}
TEST(100_Integration)
{
db::Layout ly;

BIN
testdata/algo/deep_region_au16.gds vendored Normal file

Binary file not shown.

Binary file not shown.