mirror of https://github.com/KLayout/klayout.git
WIP: implemented AND/NOT in deep region, added tests.
This commit is contained in:
parent
694730746b
commit
cfa0e8431c
|
|
@ -27,6 +27,7 @@
|
||||||
#include "dbRegion.h"
|
#include "dbRegion.h"
|
||||||
#include "dbShapeProcessor.h"
|
#include "dbShapeProcessor.h"
|
||||||
#include "dbFlatRegion.h"
|
#include "dbFlatRegion.h"
|
||||||
|
#include "dbHierProcessor.h"
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
@ -111,6 +112,12 @@ DeepRegion::DeepRegion ()
|
||||||
init ();
|
init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeepRegion::DeepRegion (const DeepLayer &dl)
|
||||||
|
: AsIfFlatRegion (), m_deep_layer (dl)
|
||||||
|
{
|
||||||
|
init ();
|
||||||
|
}
|
||||||
|
|
||||||
DeepRegion::~DeepRegion ()
|
DeepRegion::~DeepRegion ()
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
|
|
@ -285,5 +292,67 @@ DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsi
|
||||||
m_deep_layer.insert_into (layout, into_cell, into_layer);
|
m_deep_layer.insert_into (layout, into_cell, into_layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegionDelegate *
|
||||||
|
DeepRegion::and_with (const Region &other) const
|
||||||
|
{
|
||||||
|
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||||
|
|
||||||
|
if (empty () || other.empty ()) {
|
||||||
|
|
||||||
|
// Nothing to do
|
||||||
|
return new EmptyRegion ();
|
||||||
|
|
||||||
|
} else if (! other_deep) {
|
||||||
|
|
||||||
|
return AsIfFlatRegion::and_with (other);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return new DeepRegion (and_or_not_with (other_deep, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegionDelegate *
|
||||||
|
DeepRegion::not_with (const Region &other) const
|
||||||
|
{
|
||||||
|
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||||
|
|
||||||
|
if (empty ()) {
|
||||||
|
|
||||||
|
// Nothing to do
|
||||||
|
return new EmptyRegion ();
|
||||||
|
|
||||||
|
} else if (other.empty () && ! strict_handling ()) {
|
||||||
|
|
||||||
|
// Nothing to do
|
||||||
|
return clone ();
|
||||||
|
|
||||||
|
} else if (! other_deep) {
|
||||||
|
|
||||||
|
return AsIfFlatRegion::not_with (other);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return new DeepRegion (and_or_not_with (other_deep, false));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeepLayer
|
||||||
|
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
|
||||||
|
{
|
||||||
|
DeepLayer dl_out (m_deep_layer.derived ());
|
||||||
|
|
||||||
|
db::BoolAndOrNotLocalOperation op (and_op);
|
||||||
|
|
||||||
|
db::LocalProcessor proc (const_cast <db::Layout *> (m_deep_layer.layout ()), const_cast <db::Cell *> (m_deep_layer.initial_cell ()), other->deep_layer ().layout (), other->deep_layer ().initial_cell ());
|
||||||
|
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||||
|
|
||||||
|
proc.run (&op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
|
||||||
|
|
||||||
|
return dl_out;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,22 @@ public:
|
||||||
virtual bool equals (const Region &other) const;
|
virtual bool equals (const Region &other) const;
|
||||||
virtual bool less (const Region &other) const;
|
virtual bool less (const Region &other) const;
|
||||||
|
|
||||||
|
virtual RegionDelegate *and_with (const Region &other) const;
|
||||||
|
virtual RegionDelegate *not_with (const Region &other) const;
|
||||||
|
|
||||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||||
|
|
||||||
|
const DeepLayer &deep_layer () const
|
||||||
|
{
|
||||||
|
return m_deep_layer;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void merged_semantics_changed ();
|
virtual void merged_semantics_changed ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeepRegion &operator= (const DeepRegion &other);
|
DeepRegion &operator= (const DeepRegion &other);
|
||||||
|
DeepRegion (const DeepLayer &dl);
|
||||||
|
|
||||||
DeepLayer m_deep_layer;
|
DeepLayer m_deep_layer;
|
||||||
// @@@ have hierarchical merged polygons later
|
// @@@ have hierarchical merged polygons later
|
||||||
|
|
@ -85,6 +94,7 @@ private:
|
||||||
|
|
||||||
void init ();
|
void init ();
|
||||||
void ensure_merged_polygons_valid () const;
|
void ensure_merged_polygons_valid () const;
|
||||||
|
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,12 @@ DeepLayer::~DeepLayer ()
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeepLayer
|
||||||
|
DeepLayer::derived () const
|
||||||
|
{
|
||||||
|
return DeepLayer (const_cast <db::DeepShapeStore *> (mp_store.get ()), m_layout, const_cast <db::Layout *> (layout ())->insert_layer ());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const
|
DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const
|
||||||
{
|
{
|
||||||
|
|
@ -76,6 +82,22 @@ DeepLayer::layout () const
|
||||||
return const_cast<db::DeepShapeStore *> (mp_store.get ())->layout (m_layout);
|
return const_cast<db::DeepShapeStore *> (mp_store.get ())->layout (m_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db::Cell *
|
||||||
|
DeepLayer::initial_cell ()
|
||||||
|
{
|
||||||
|
db::Layout *ly = layout ();
|
||||||
|
tl_assert (ly->begin_top_down () != ly->end_top_down ());
|
||||||
|
return &ly->cell (*ly->begin_top_down ());
|
||||||
|
}
|
||||||
|
|
||||||
|
const db::Cell *
|
||||||
|
DeepLayer::initial_cell () const
|
||||||
|
{
|
||||||
|
const db::Layout *ly = layout ();
|
||||||
|
tl_assert (ly->begin_top_down () != ly->end_top_down ());
|
||||||
|
return &ly->cell (*ly->begin_top_down ());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DeepLayer::check_dss () const
|
DeepLayer::check_dss () const
|
||||||
{
|
{
|
||||||
|
|
@ -89,6 +111,7 @@ DeepLayer::check_dss () const
|
||||||
static size_t s_instance_count = 0;
|
static size_t s_instance_count = 0;
|
||||||
|
|
||||||
DeepShapeStore::DeepShapeStore ()
|
DeepShapeStore::DeepShapeStore ()
|
||||||
|
: m_threads (1)
|
||||||
{
|
{
|
||||||
++s_instance_count;
|
++s_instance_count;
|
||||||
}
|
}
|
||||||
|
|
@ -103,6 +126,11 @@ size_t DeepShapeStore::instance_count ()
|
||||||
return s_instance_count;
|
return s_instance_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeepShapeStore::set_threads (int n)
|
||||||
|
{
|
||||||
|
m_threads = n;
|
||||||
|
}
|
||||||
|
|
||||||
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count)
|
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count)
|
||||||
{
|
{
|
||||||
unsigned int layout_index = 0;
|
unsigned int layout_index = 0;
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,17 @@ public:
|
||||||
*/
|
*/
|
||||||
const db::Layout *layout () const;
|
const db::Layout *layout () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the layout object
|
||||||
|
* The return value is guaranteed to be non-null.
|
||||||
|
*/
|
||||||
|
db::Cell *initial_cell ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the initial cell object (const version)
|
||||||
|
*/
|
||||||
|
const db::Cell *initial_cell () const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the layer
|
* @brief Gets the layer
|
||||||
*/
|
*/
|
||||||
|
|
@ -101,6 +112,24 @@ public:
|
||||||
*/
|
*/
|
||||||
void insert_into (Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
void insert_into (Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a derived new deep layer
|
||||||
|
* Derived layers use the same layout and context, but are initially
|
||||||
|
* empty layers for use as output layers on the same hierarchy.
|
||||||
|
*/
|
||||||
|
DeepLayer derived () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the shape store object
|
||||||
|
* This is a pure const version to prevent manipulation of the store.
|
||||||
|
* This method is intended to fetch configuration options from the store.
|
||||||
|
*/
|
||||||
|
const DeepShapeStore *store () const
|
||||||
|
{
|
||||||
|
check_dss ();
|
||||||
|
return mp_store.get ();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class DeepShapeStore;
|
friend class DeepShapeStore;
|
||||||
|
|
||||||
|
|
@ -172,6 +201,21 @@ public:
|
||||||
*/
|
*/
|
||||||
static size_t instance_count ();
|
static size_t instance_count ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The deep shape store also keeps the number of threads to allocate for the hierarchical processor
|
||||||
|
*
|
||||||
|
* This is a kind of hack, but it's convenient.
|
||||||
|
*/
|
||||||
|
void set_threads (int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the number of threads
|
||||||
|
*/
|
||||||
|
int threads () const
|
||||||
|
{
|
||||||
|
return m_threads;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class DeepLayer;
|
friend class DeepLayer;
|
||||||
|
|
||||||
|
|
@ -189,6 +233,7 @@ private:
|
||||||
tl::stable_vector<db::Layout> m_layouts;
|
tl::stable_vector<db::Layout> m_layouts;
|
||||||
tl::stable_vector<db::HierarchyBuilder> m_builders;
|
tl::stable_vector<db::HierarchyBuilder> m_builders;
|
||||||
layout_map_type m_layout_map;
|
layout_map_type m_layout_map;
|
||||||
|
int m_threads;
|
||||||
|
|
||||||
struct DeliveryMappingCacheKey
|
struct DeliveryMappingCacheKey
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -720,6 +720,12 @@ int td_simple ();
|
||||||
int po_any ();
|
int po_any ();
|
||||||
|
|
||||||
Class<db::DeepShapeStore> decl_DeepShapeStore ("db", "DeepShapeStore",
|
Class<db::DeepShapeStore> decl_DeepShapeStore ("db", "DeepShapeStore",
|
||||||
|
method ("threads=", &db::DeepShapeStore::set_threads, gsi::arg ("threads"),
|
||||||
|
"@brief Sets the number of threads for use for operations acting on this heap\n"
|
||||||
|
) +
|
||||||
|
method ("threads", &db::DeepShapeStore::threads,
|
||||||
|
"@brief Gets the number of threads for use for operations acting on this heap\n"
|
||||||
|
) +
|
||||||
method ("instance_count", db::DeepShapeStore::instance_count, "@hide"),
|
method ("instance_count", db::DeepShapeStore::instance_count, "@hide"),
|
||||||
"@brief An opaque layout heap for the deep region processor\n"
|
"@brief An opaque layout heap for the deep region processor\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -735,6 +741,9 @@ Class<db::DeepShapeStore> decl_DeepShapeStore ("db", "DeepShapeStore",
|
||||||
"region = RBA::Region::new(cell.begin(layer), dss)\n"
|
"region = RBA::Region::new(cell.begin(layer), dss)\n"
|
||||||
"@/code\n"
|
"@/code\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"The DeepShapeStore object also supplies some configuration options "
|
||||||
|
"for the operations acting on the deep regions. See for example \\threads=.\n"
|
||||||
|
"\n"
|
||||||
"This class has been introduced in version 0.26.\n"
|
"This class has been introduced in version 0.26.\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,66 @@ TEST(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECKPOINT();
|
CHECKPOINT();
|
||||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au1.gds");
|
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au2.gds");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(3_BoolAndNot)
|
||||||
|
{
|
||||||
|
db::Layout ly;
|
||||||
|
{
|
||||||
|
std::string fn (tl::testsrc ());
|
||||||
|
fn += "/testdata/algo/deep_region_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 l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||||
|
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||||
|
unsigned int l42 = ly.get_layer (db::LayerProperties (42, 0));
|
||||||
|
|
||||||
|
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
|
||||||
|
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
|
||||||
|
db::Region r42 (db::RecursiveShapeIterator (ly, top_cell, l42), dss);
|
||||||
|
db::Region box (db::Box (2000, -1000, 6000, 4000));
|
||||||
|
|
||||||
|
db::Region r2minus3 = r2 - r3;
|
||||||
|
db::Region r2minusbox = r2 - box;
|
||||||
|
db::Region r2minus42 = r2 - r42;
|
||||||
|
db::Region rboxminus3 = box - r3;
|
||||||
|
db::Region r42minus3 = r42 - r3;
|
||||||
|
db::Region r42minus42 = r42 - r42;
|
||||||
|
|
||||||
|
db::Region r2and3 = r2 & r3;
|
||||||
|
db::Region r2andbox = r2 & box;
|
||||||
|
db::Region r2and42 = r2 & r42;
|
||||||
|
db::Region rboxand3 = box & r3;
|
||||||
|
db::Region r42and3 = r42 & r3;
|
||||||
|
db::Region r42and42 = r42 & r42;
|
||||||
|
|
||||||
|
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)), r2minus3);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2minusbox);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2minus42);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), rboxminus3);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r42minus3);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r42minus42);
|
||||||
|
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2and3);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2andbox);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r2and42);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), rboxand3);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r42and3);
|
||||||
|
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), r42and42);
|
||||||
|
|
||||||
|
CHECKPOINT();
|
||||||
|
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au3.gds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue