Initial implementation of complex regions for RecursiveShapeIterator.

This commit is contained in:
Matthias Koefferlein 2017-02-13 00:01:21 +01:00
parent 99edf66fec
commit f71fe1ff05
2 changed files with 484 additions and 30 deletions

View File

@ -20,8 +20,9 @@
*/
#include "dbRecursiveShapeIterator.h"
#include "dbRegion.h"
#include "dbEdgeProcessor.h"
#include "tlProgress.h"
namespace db
@ -73,6 +74,32 @@ RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const
init ();
}
RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const region_type &region, bool overlapping)
{
m_layer = 0;
m_has_layers = false;
m_region = region.bbox ();
mp_layout = 0;
mp_shapes = &shapes;
mp_top_cell = 0;
m_overlapping = overlapping;
init ();
init_complex_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const box_type &region, const region_type &excl_region, bool overlapping)
{
m_layer = 0;
m_has_layers = false;
m_region = region;
mp_layout = 0;
mp_shapes = &shapes;
mp_top_cell = 0;
m_overlapping = overlapping;
init ();
init_complex_region (region, excl_region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type &region, bool overlapping)
: m_box_convert (layout, layer)
{
@ -86,6 +113,34 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
init ();
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type &region, bool overlapping)
: m_box_convert (layout, layer)
{
m_layer = layer;
m_has_layers = false;
m_region = region.bbox ();
mp_layout = &layout;
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
init ();
init_complex_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type &region, const region_type &excl_region, bool overlapping)
: m_box_convert (layout, layer)
{
m_layer = layer;
m_has_layers = false;
m_region = region;
mp_layout = &layout;
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
init ();
init_complex_region (region, excl_region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer)
: m_box_convert (layout, layer)
{
@ -113,6 +168,36 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
init ();
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type &region, bool overlapping)
: m_box_convert (layout)
{
m_layer = 0;
m_layers = layers;
m_has_layers = true;
m_region = region.bbox ();
mp_layout = &layout;
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
init ();
init_complex_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type &region, const region_type &excl_region, bool overlapping)
: m_box_convert (layout)
{
m_layer = 0;
m_layers = layers;
m_has_layers = true;
m_region = region;
mp_layout = &layout;
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
init ();
init_complex_region (region, excl_region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers)
: m_box_convert (layout)
{
@ -141,6 +226,36 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
init ();
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type &region, bool overlapping)
: m_box_convert (layout)
{
m_layer = 0;
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
m_has_layers = true;
m_region = region.bbox ();
mp_layout = &layout;
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
init ();
init_complex_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type &region, const region_type &excl_region, bool overlapping)
: m_box_convert (layout)
{
m_layer = 0;
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
m_has_layers = true;
m_region = region;
mp_layout = &layout;
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
init ();
init_complex_region (region, excl_region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers)
: m_box_convert (layout)
{
@ -164,6 +279,72 @@ RecursiveShapeIterator::init ()
m_shape_flags = shape_iterator::All;
mp_shape_prop_sel = 0;
m_shape_inv_prop_sel = false;
m_inst_quad_id = 0;
m_shape_quad_id = 0;
}
namespace {
struct BoxTreePusher
: public db::SimplePolygonSink
{
BoxTreePusher (RecursiveShapeIterator::box_tree_type *bt)
: mp_bt (bt)
{
// .. nothing yet ..
}
void put (const db::SimplePolygon &sp)
{
mp_bt->insert (sp.box ());
}
private:
RecursiveShapeIterator::box_tree_type *mp_bt;
};
}
void
RecursiveShapeIterator::init_complex_region (const RecursiveShapeIterator::box_type &box, const RecursiveShapeIterator::region_type &excl_region)
{
// Use a boolean NOT and the trapezoid generator to produce a decomposition that goes into the complex region
db::EdgeProcessor ep;
ep.insert (db::Polygon (box), 0);
size_t n = 1;
for (region_type::const_iterator p = excl_region.begin (); !p.at_end (); ++p) {
ep.insert (*p, n);
n += 2;
}
BoxTreePusher btp (&m_complex_region);
db::TrapezoidGenerator tg (btp);
db::BooleanOp op (BooleanOp::ANotB);
ep.process (tg, op);
m_complex_region.sort (db::box_convert <db::Box> ());
}
void
RecursiveShapeIterator::init_complex_region (const RecursiveShapeIterator::region_type &region)
{
// Use a merge and the trapezoid generator to produce a decomposition that goes into the complex region
db::EdgeProcessor ep;
size_t n = 0;
for (region_type::const_iterator p = region.begin (); !p.at_end (); ++p, ++n) {
ep.insert (*p, n);
}
BoxTreePusher btp (&m_complex_region);
db::TrapezoidGenerator tg (btp);
db::MergeOp op (0);
ep.process (tg, op);
m_complex_region.sort (db::box_convert <db::Box> ());
}
void
@ -179,11 +360,16 @@ RecursiveShapeIterator::validate () const
mp_cell = mp_top_cell;
m_trans_stack.clear ();
m_inst_iterators.clear ();
m_inst_quad_id_stack.clear ();
m_inst_array_iterators.clear ();
m_cells.clear ();
m_trans = cplx_trans_type ();
m_current_layer = 0;
m_shape = shape_iterator ();
m_local_region_stack.push_back (m_region);
if (!m_complex_region.empty ()) {
m_local_complex_region_stack.push_back (m_complex_region);
}
if (mp_shapes) {
// Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor)
@ -311,7 +497,33 @@ RecursiveShapeIterator::bbox () const
return box;
}
void
void
RecursiveShapeIterator::next ()
{
if (! at_end ()) {
++m_shape;
// skip shape quad if possible
if (! m_local_complex_region_stack.empty () && m_shape_quad_id != m_shape.quad_id ()) {
while (! m_shape.at_end ()) {
if (is_outside_complex_region (m_shape.quad_box ())) {
m_shape.skip_quad ();
} else {
m_shape_quad_id = m_shape.quad_id ();
break;
}
}
}
if (! mp_shapes && m_shape.at_end ()) {
next_shape ();
}
}
}
void
RecursiveShapeIterator::next_shape () const
{
while (at_end ()) {
@ -365,12 +577,12 @@ RecursiveShapeIterator::next_shape () const
} else {
// no more instances: up and next instance
if (m_inst_iterators.empty ()) {
// nothing left:
return;
}
// no more instances: up and next instance
up ();
++m_inst_array;
@ -394,6 +606,7 @@ RecursiveShapeIterator::down () const
m_inst_iterators.push_back (m_inst);
m_inst_array_iterators.push_back (m_inst_array);
m_inst_quad_id_stack.push_back (m_inst_quad_id);
bool ia = is_inactive ();
mp_cell = &mp_layout->cell (m_inst->cell_index ());
@ -401,6 +614,49 @@ RecursiveShapeIterator::down () const
m_trans = m_trans * m_inst->complex_trans (*m_inst_array);
// don't transform the world region, since transformation of that region might not work properly
box_type new_region = box_type::world ();
// compute the region inside the new cell
if (m_region != m_local_region_stack.front ()) {
new_region = m_trans.inverted () * m_local_region_stack.front ();
}
new_region &= mp_cell->bbox ();
m_local_region_stack.push_back (new_region);
if (! m_local_complex_region_stack.empty ()) {
const box_tree_type &pcl = m_local_complex_region_stack.back ();
m_local_complex_region_stack.push_back (box_tree_type ());
if (! new_region.empty ()) {
// compute a new, reduced complex region for use inside the new cell
db::CellInstArray::complex_trans_type tinst = m_inst->complex_trans (*m_inst_array);
db::CellInstArray::complex_trans_type tinst_inv = tinst.inverted ();
db::Box bb;
for (box_tree_type::touching_iterator b = pcl.begin_touching (new_region.transformed (tinst), db::box_convert<db::Box> ()); ! b.at_end (); ++b) {
db::Box lb = (b->transformed (tinst_inv) & new_region);
if (! lb.empty ()) {
m_local_complex_region_stack.back ().insert (lb);
bb += lb;
}
}
m_local_complex_region_stack.back ().sort (db::box_convert<db::Box> ());
// re-adjust the new local region, so we take into account additional clipping by the complex region.
// in the extreme case, this box is empty:
m_local_region_stack.back () = bb;
}
}
new_cell ();
}
@ -408,20 +664,22 @@ void
RecursiveShapeIterator::up () const
{
m_shape = shape_iterator ();
m_shape_quad_id = 0;
m_inst = m_inst_iterators.back ();
m_inst_array = m_inst_array_iterators.back ();
m_inst_quad_id = m_inst_quad_id_stack.back ();
m_inst_iterators.pop_back ();
m_inst_array_iterators.pop_back ();
m_inst_quad_id_stack.pop_back ();
m_trans = m_trans_stack.back ();
m_trans_stack.pop_back ();
mp_cell = m_cells.back ();
m_cells.pop_back ();
m_local_region = box_type::world ();
if (m_region != m_local_region) {
m_local_region = trans ().inverted () * m_region;
m_local_region_stack.pop_back ();
if (! m_local_complex_region_stack.empty ()) {
m_local_complex_region_stack.pop_back ();
}
}
@ -429,9 +687,23 @@ void
RecursiveShapeIterator::start_shapes () const
{
if (! m_overlapping) {
m_shape = mp_shapes->begin_touching (m_region, m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
m_shape = mp_shapes->begin_touching (m_local_region_stack.back (), m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
} else {
m_shape = mp_shapes->begin_overlapping (m_region, m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
m_shape = mp_shapes->begin_overlapping (m_local_region_stack.back (), m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
}
m_shape_quad_id = 0;
// skip instance quad if possible
if (! m_local_complex_region_stack.empty ()) {
while (! m_shape.at_end ()) {
if (is_outside_complex_region (m_shape.quad_box ())) {
m_shape.skip_quad ();
} else {
m_shape_quad_id = m_shape.quad_id ();
break;
}
}
}
}
@ -441,21 +713,29 @@ RecursiveShapeIterator::new_layer () const
if (int (m_trans_stack.size ()) < m_min_depth || int (m_trans_stack.size ()) > m_max_depth) {
m_shape = shape_iterator ();
} else if (! m_overlapping) {
m_shape = cell ()->shapes (m_layer).begin_touching (m_local_region, m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
m_shape = cell ()->shapes (m_layer).begin_touching (m_local_region_stack.back (), m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
} else {
m_shape = cell ()->shapes (m_layer).begin_overlapping (m_local_region, m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
m_shape = cell ()->shapes (m_layer).begin_overlapping (m_local_region_stack.back (), m_shape_flags, mp_shape_prop_sel, m_shape_inv_prop_sel);
}
m_shape_quad_id = 0;
// skip instance quad if possible
if (! m_local_complex_region_stack.empty ()) {
while (! m_shape.at_end ()) {
if (is_outside_complex_region (m_shape.quad_box ())) {
m_shape.skip_quad ();
} else {
m_shape_quad_id = m_shape.quad_id ();
break;
}
}
}
}
void
RecursiveShapeIterator::new_cell () const
{
// don't transform the world region, since transformation of that region might not work properly
m_local_region = box_type::world ();
if (m_region != m_local_region) {
m_local_region = trans ().inverted () * m_region;
}
if (m_has_layers) {
m_current_layer = 0;
m_layer = m_layers.front ();
@ -469,7 +749,22 @@ RecursiveShapeIterator::new_cell () const
new_layer ();
m_inst = cell ()->begin_touching (m_local_region);
m_inst = cell ()->begin_touching (m_local_region_stack.back ());
m_inst_quad_id = 0;
// skip instance quad if possible
if (! m_local_complex_region_stack.empty ()) {
while (! m_inst.at_end ()) {
if (is_outside_complex_region (m_inst.quad_box ())) {
m_inst.skip_quad ();
} else {
m_inst_quad_id = m_inst.quad_id ();
break;
}
}
}
new_inst ();
}
@ -481,8 +776,26 @@ RecursiveShapeIterator::new_inst () const
// touching instance iterator.
while (! m_inst.at_end ()) {
if (m_local_region != box_type::world ()) {
m_inst_array = m_inst->cell_inst ().begin_touching (m_local_region, m_box_convert);
// skip instance quad if possible
if (! m_local_complex_region_stack.empty () && m_inst_quad_id != m_inst.quad_id ()) {
while (! m_inst.at_end ()) {
if (is_outside_complex_region (m_inst.quad_box ())) {
m_inst.skip_quad ();
} else {
m_inst_quad_id = m_inst.quad_id ();
break;
}
}
if (m_inst.at_end ()) {
break;
}
}
if (m_local_region_stack.back () != box_type::world ()) {
m_inst_array = m_inst->cell_inst ().begin_touching (m_local_region_stack.back (), m_box_convert);
} else {
m_inst_array = m_inst->cell_inst ().begin ();
}
@ -496,5 +809,15 @@ RecursiveShapeIterator::new_inst () const
}
}
bool
RecursiveShapeIterator::is_outside_complex_region (const db::Box &box) const
{
if (m_overlapping) {
return m_local_complex_region_stack.back ().begin_overlapping (box, db::box_convert<db::Box> ()).at_end ();
} else {
return m_local_complex_region_stack.back ().begin_touching (box, db::box_convert<db::Box> ()).at_end ();
}
}
}

View File

@ -36,6 +36,8 @@
namespace db
{
class Region;
/**
* @brief An iterator delivering shapes that touch or overlap the given region recursively
*
@ -50,6 +52,7 @@ class DB_PUBLIC RecursiveShapeIterator
public:
typedef db::Layout layout_type;
typedef db::Box box_type;
typedef db::Region region_type;
typedef db::Cell cell_type;
typedef db::Cell::touching_iterator inst_iterator;
typedef db::CellInstArray::iterator inst_array_iterator;
@ -57,6 +60,7 @@ public:
typedef db::Shape shape_type;
typedef db::Shapes shapes_type;
typedef db::ICplxTrans cplx_trans_type;
typedef db::box_tree<db::Box, db::Box, db::box_convert<db::Box>, 20, 20> box_tree_type;
/**
* @brief Default constructor
@ -84,6 +88,33 @@ public:
*/
RecursiveShapeIterator (const shapes_type &shapes, const box_type &region, bool overlapping = false);
/**
* @brief Standard constructor iterating a single shape container
*
* @param shapes The shape container to iterate
* @param region The complex region from which to select the shapes
* @param overlapping Specify overlapping mode
*
* This iterator will iterate the shapes from the given shapes container using
* the given search region in overlapping or touching mode. It allows specification of a complex
* search region.
*/
RecursiveShapeIterator (const shapes_type &shapes, const region_type &region, bool overlapping = false);
/**
* @brief Standard constructor iterating a single shape container
*
* @param shapes The shape container to iterate
* @param region The basic region from which to select the shapes
* @param excl_region A complex region that will be excluded from the rectangular region
* @param overlapping Specify overlapping mode
*
* This iterator will iterate the shapes from the given shapes container using
* the given search region in overlapping or touching mode. It allows specification of a complex
* search region using a basic region and a complex region that is excluded from the search.
*/
RecursiveShapeIterator (const shapes_type &shapes, const box_type &region, const region_type &excl_region, bool overlapping = false);
/**
* @brief Standard constructor
*
@ -99,6 +130,39 @@ public:
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type &region, bool overlapping = false);
/**
* @brief Standard constructor
*
* @param layout The layout from which to get the cell hierarchy
* @param cell The starting cell
* @param layer The layer from which to deliver the shapes
* @param region The complex region from which to select the shapes
* @param overlapping Specify overlapping mode
*
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
* overlap the given region by at least one database unit. It allows specification of a complex
* search region.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type &region, bool overlapping = false);
/**
* @brief Standard constructor
*
* @param layout The layout from which to get the cell hierarchy
* @param cell The starting cell
* @param layer The layer from which to deliver the shapes
* @param region The region from which to select the shapes
* @param excl_region A complex region that will be excluded from the rectangular region
* @param overlapping Specify overlapping mode
*
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
* overlap the given region by at least one database unit. It allows specification of a complex
* search region using a basic region and a complex region that is excluded from the search.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type &region, const region_type &excl_region, bool overlapping = false);
/**
* @brief Standard constructor for "world" iteration
*
@ -125,6 +189,39 @@ public:
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type &region, bool overlapping = false);
/**
* @brief Standard constructor with a layer selection
*
* @param layout The layout from which to get the cell hierarchy
* @param cell The starting cell
* @param layers The layers from which to deliver the shapes
* @param region The complex region from which to select the shapes
* @param overlapping Specify overlapping mode
*
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
* overlap the given region by at least one database unit. It allows specification of a complex
* search region.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type &region, bool overlapping = false);
/**
* @brief Standard constructor with a layer selection
*
* @param layout The layout from which to get the cell hierarchy
* @param cell The starting cell
* @param layers The layers from which to deliver the shapes
* @param region The region from which to select the shapes
* @param excl_region A complex region that will be excluded from the rectangular region
* @param overlapping Specify overlapping mode
*
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
* overlap the given region by at least one database unit. It allows specification of a complex
* search region using a basic region and a complex region that is excluded from the search.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type &region, const region_type &excl_region, bool overlapping = false);
/**
* @brief Standard constructor with a layer selection
*
@ -140,6 +237,39 @@ public:
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type &region, bool overlapping = false);
/**
* @brief Standard constructor with a layer selection
*
* @param layout The layout from which to get the cell hierarchy
* @param cell The starting cell
* @param layers The layers from which to deliver the shapes
* @param region The complex region from which to select the shapes
* @param overlapping Specify overlapping mode
*
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
* overlap the given region by at least one database unit. It allows specification of a complex
* search region.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type &region, bool overlapping = false);
/**
* @brief Standard constructor with a layer selection
*
* @param layout The layout from which to get the cell hierarchy
* @param cell The starting cell
* @param layers The layers from which to deliver the shapes
* @param region The region from which to select the shapes
* @param excl_region A complex region that will be excluded from the rectangular region
* @param overlapping Specify overlapping mode
*
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
* overlap the given region by at least one database unit. It allows specification of a complex
* search region using a basic region and a complex region that is excluded from the search.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type &region, const region_type &excl_region, bool overlapping = false);
/**
* @brief Standard constructor for "world" iteration with a layer set
*
@ -487,15 +617,7 @@ public:
/**
* @brief Increment the iterator
*/
void next ()
{
if (! at_end ()) {
++m_shape;
if (! mp_shapes) {
next_shape ();
}
}
}
void next ();
/**
* @brief Comparison of iterators - equality
@ -547,9 +669,9 @@ private:
const shapes_type *mp_shapes;
box_type m_region;
box_tree_type m_complex_region;
db::box_convert<db::CellInst> m_box_convert;
mutable box_type m_local_region;
mutable inst_iterator m_inst;
mutable inst_array_iterator m_inst_array;
mutable std::map<db::cell_index_type, bool> m_empty_cells_cache;
@ -562,9 +684,16 @@ private:
mutable std::vector<inst_iterator> m_inst_iterators;
mutable std::vector<inst_array_iterator> m_inst_array_iterators;
mutable std::vector<const cell_type *> m_cells;
mutable std::vector<box_tree_type> m_local_complex_region_stack;
mutable std::vector<box_type> m_local_region_stack;
mutable bool m_needs_reinit;
mutable size_t m_inst_quad_id;
mutable std::vector<size_t> m_inst_quad_id_stack;
mutable size_t m_shape_quad_id;
void init ();
void init_complex_region (const box_type &box, const region_type &excl_region);
void init_complex_region (const region_type &excl_region);
void validate () const;
void start_shapes () const;
void next_shape () const;
@ -574,6 +703,8 @@ private:
void up () const;
void down () const;
bool is_outside_complex_region (const db::Box &box) const;
bool is_inactive () const
{
return (reinterpret_cast<size_t> (mp_cell) & size_t (1)) != 0;