mirror of https://github.com/KLayout/klayout.git
RecursiveInstanceIterator: Doc fixes, tests, instance array iteration.
This commit is contained in:
parent
a1bae225e3
commit
0f4a10441d
|
|
@ -115,6 +115,7 @@ SOURCES = \
|
|||
gsiDeclDbPoint.cc \
|
||||
gsiDeclDbPolygon.cc \
|
||||
gsiDeclDbReader.cc \
|
||||
gsiDeclDbRecursiveInstanceIterator.cc \
|
||||
gsiDeclDbRecursiveShapeIterator.cc \
|
||||
gsiDeclDbRegion.cc \
|
||||
gsiDeclDbShape.cc \
|
||||
|
|
|
|||
|
|
@ -45,8 +45,6 @@ RecursiveInstanceIterator &RecursiveInstanceIterator::operator= (const Recursive
|
|||
|
||||
m_max_depth = d.m_max_depth;
|
||||
m_min_depth = d.m_min_depth;
|
||||
m_shape_flags = d.m_shape_flags;
|
||||
m_shape_inv_prop_sel = d.m_shape_inv_prop_sel;
|
||||
m_overlapping = d.m_overlapping;
|
||||
m_start = d.m_start;
|
||||
m_stop = d.m_stop;
|
||||
|
|
@ -91,7 +89,6 @@ RecursiveInstanceIterator::RecursiveInstanceIterator ()
|
|||
m_overlapping = false;
|
||||
m_max_depth = std::numeric_limits<int>::max (); // all
|
||||
m_min_depth = 0;
|
||||
m_shape_inv_prop_sel = false;
|
||||
m_needs_reinit = false;
|
||||
m_inst_quad_id = 0;
|
||||
m_all_targets = true;
|
||||
|
|
@ -139,7 +136,6 @@ RecursiveInstanceIterator::init ()
|
|||
m_needs_reinit = true;
|
||||
m_max_depth = std::numeric_limits<int>::max (); // all
|
||||
m_min_depth = 0; // from the beginning
|
||||
m_shape_inv_prop_sel = false;
|
||||
m_inst_quad_id = 0;
|
||||
mp_cell = 0;
|
||||
m_all_targets = true;
|
||||
|
|
@ -390,6 +386,14 @@ RecursiveInstanceIterator::select_all_cells ()
|
|||
}
|
||||
}
|
||||
|
||||
const RecursiveInstanceIterator::instance_element_type *
|
||||
RecursiveInstanceIterator::operator-> () const
|
||||
{
|
||||
validate (0);
|
||||
m_combined_instance = db::InstElement (*m_inst, m_inst_array);
|
||||
return &m_combined_instance;
|
||||
}
|
||||
|
||||
bool
|
||||
RecursiveInstanceIterator::at_end () const
|
||||
{
|
||||
|
|
@ -438,9 +442,14 @@ void
|
|||
RecursiveInstanceIterator::next (RecursiveInstanceReceiver *receiver)
|
||||
{
|
||||
if (! at_end ()) {
|
||||
++m_inst;
|
||||
new_inst (receiver);
|
||||
next_instance (receiver);
|
||||
++m_inst_array;
|
||||
if (! m_inst_array.at_end ()) {
|
||||
new_inst_member (receiver);
|
||||
} else {
|
||||
++m_inst;
|
||||
new_inst (receiver);
|
||||
next_instance (receiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -474,8 +483,13 @@ RecursiveInstanceIterator::next_instance (RecursiveInstanceReceiver *receiver) c
|
|||
|
||||
if (! m_inst.at_end ()) {
|
||||
if (! needs_visit ()) {
|
||||
++m_inst;
|
||||
new_inst (receiver);
|
||||
++m_inst_array;
|
||||
if (! m_inst_array.at_end ()) {
|
||||
new_inst_member (receiver);
|
||||
} else {
|
||||
++m_inst;
|
||||
new_inst (receiver);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,9 @@ public:
|
|||
typedef db::Instances::overlapping_iterator overlapping_instance_iterator;
|
||||
typedef db::Instances::touching_iterator touching_instance_iterator;
|
||||
typedef db::Instance instance_type;
|
||||
typedef db::InstElement instance_element_type;
|
||||
typedef db::ICplxTrans cplx_trans_type;
|
||||
typedef instance_element_type value_type;
|
||||
typedef db::box_tree<db::Box, db::Box, db::box_convert<db::Box>, 20, 20> box_tree_type;
|
||||
|
||||
/**
|
||||
|
|
@ -416,7 +418,7 @@ public:
|
|||
* Returns the instance currently referred to by the recursive iterator.
|
||||
* This instance is not transformed yet and is located in the current cell.
|
||||
*/
|
||||
instance_type instance () const
|
||||
instance_element_type instance () const
|
||||
{
|
||||
return *operator-> ();
|
||||
}
|
||||
|
|
@ -426,7 +428,7 @@ public:
|
|||
*
|
||||
* The access operator is identical to the instance method.
|
||||
*/
|
||||
instance_type operator* () const
|
||||
instance_element_type operator* () const
|
||||
{
|
||||
return *operator-> ();
|
||||
}
|
||||
|
|
@ -436,11 +438,7 @@ public:
|
|||
*
|
||||
* The access operator is identical to the instance method.
|
||||
*/
|
||||
const instance_type *operator-> () const
|
||||
{
|
||||
validate (0);
|
||||
return m_inst.operator-> ();
|
||||
}
|
||||
const instance_element_type *operator-> () const;
|
||||
|
||||
/**
|
||||
* @brief End of iterator predicate
|
||||
|
|
@ -509,7 +507,7 @@ public:
|
|||
/**
|
||||
* @brief The instance path
|
||||
*/
|
||||
std::vector<db::InstElement> path () const;
|
||||
std::vector<instance_element_type> path () const;
|
||||
|
||||
/**
|
||||
* @brief Push-mode delivery
|
||||
|
|
@ -541,8 +539,6 @@ public:
|
|||
private:
|
||||
int m_max_depth;
|
||||
int m_min_depth;
|
||||
unsigned int m_shape_flags;
|
||||
bool m_shape_inv_prop_sel;
|
||||
bool m_overlapping;
|
||||
std::set<db::cell_index_type> m_start, m_stop;
|
||||
std::set<db::cell_index_type> m_targets;
|
||||
|
|
@ -557,6 +553,7 @@ private:
|
|||
|
||||
mutable inst_iterator m_inst;
|
||||
mutable inst_array_iterator m_inst_array;
|
||||
mutable instance_element_type m_combined_instance;
|
||||
mutable std::map<db::cell_index_type, bool> m_empty_cells_cache;
|
||||
mutable const cell_type *mp_cell;
|
||||
mutable cplx_trans_type m_trans;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#include "dbCellMapping.h"
|
||||
#include "dbPCellDeclaration.h"
|
||||
#include "dbSaveLayoutOptions.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbRecursiveInstanceIterator.h"
|
||||
#include "dbWriter.h"
|
||||
#include "dbHash.h"
|
||||
#include "tlStream.h"
|
||||
|
|
@ -1204,6 +1206,56 @@ begin_shapes_rec_overlapping_um (const db::Cell *cell, unsigned int layer, db::D
|
|||
return db::RecursiveShapeIterator (*layout, *cell, layer, db::CplxTrans (layout->dbu ()).inverted () * region, true);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec (const db::Cell *cell)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec_touching (const db::Cell *cell, db::Box region)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell, region, false);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec_touching_um (const db::Cell *cell, db::DBox region)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell, db::CplxTrans (layout->dbu ()).inverted () * region, false);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec_overlapping (const db::Cell *cell, db::Box region)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell, region, true);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec_overlapping_um (const db::Cell *cell, db::DBox region)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell, db::CplxTrans (layout->dbu ()).inverted () * region, true);
|
||||
}
|
||||
|
||||
static void copy_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db::LayerMapping &layer_mapping)
|
||||
{
|
||||
cell->copy_shapes (source_cell, layer_mapping);
|
||||
|
|
@ -1833,6 +1885,54 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec", &begin_instances_rec,
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec_touching", &begin_instances_rec_touching, gsi::arg ("region"),
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell\n"
|
||||
"@param region The search region\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"This version gives an iterator delivering instances whose bounding box touches the given region.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec_touching", &begin_instances_rec_touching_um, gsi::arg ("region"),
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell using a region search, with the region given in micrometer units\n"
|
||||
"@param region The search region as \\DBox object in micrometer units\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"This version gives an iterator delivering instances whose bounding box touches the given region.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec_overlapping", &begin_instances_rec_overlapping, gsi::arg ("region"),
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell using a region search\n"
|
||||
"@param region The search region\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"This version gives an iterator delivering instances whose bounding box overlaps the given region.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec_overlapping", &begin_instances_rec_overlapping_um, gsi::arg ("region"),
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell using a region search, with the region given in micrometer units\n"
|
||||
"@param region The search region as \\DBox object in micrometer units\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"This version gives an iterator delivering instances whose bounding box overlaps the given region.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("copy_shapes", ©_shapes1, gsi::arg ("source_cell"),
|
||||
"@brief Copies the shapes from the given cell into this cell\n"
|
||||
"@param source_cell The cell from where to copy shapes\n"
|
||||
|
|
|
|||
|
|
@ -1716,9 +1716,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.24.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes", &begin_shapes, gsi::arg ("cell_index"), gsi::arg ("layer"),
|
||||
gsi::method_ext ("#begin_shapes", &begin_shapes, gsi::arg ("cell_index"), gsi::arg ("layer"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer\n"
|
||||
"@param cell_index The index of the initial (top) cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1726,9 +1728,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.18.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_touching", &begin_shapes_touching, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_touching", &begin_shapes_touching, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search\n"
|
||||
"@param cell_index The index of the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1738,9 +1742,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version gives an iterator delivering shapes whose bounding box touches the given region.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_touching instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.18.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_touching", &begin_shapes_touching2, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_touching", &begin_shapes_touching2, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search\n"
|
||||
"@param cell The cell object for the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1751,9 +1757,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This version gives an iterator delivering shapes whose bounding box touches the given region.\n"
|
||||
"It is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_touching instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.24.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_overlapping", &begin_shapes_overlapping, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_overlapping", &begin_shapes_overlapping, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search\n"
|
||||
"@param cell_index The index of the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1763,9 +1771,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version gives an iterator delivering shapes whose bounding box overlaps the given region.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_overlapping instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.18.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_overlapping", &begin_shapes_overlapping2, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_overlapping", &begin_shapes_overlapping2, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search\n"
|
||||
"@param cell The cell object for the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1776,9 +1786,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This version gives an iterator delivering shapes whose bounding box overlaps the given region.\n"
|
||||
"It is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_overlapping instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.24.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_touching", &begin_shapes_touching_um, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_touching", &begin_shapes_touching_um, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search, the region given in micrometer units\n"
|
||||
"@param cell_index The index of the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1788,9 +1800,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version gives an iterator delivering shapes whose bounding box touches the given region.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_touching instead.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_touching", &begin_shapes_touching2_um, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_touching", &begin_shapes_touching2_um, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search, the region given in micrometer units\n"
|
||||
"@param cell The cell object for the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1801,9 +1815,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This version gives an iterator delivering shapes whose bounding box touches the given region.\n"
|
||||
"It is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_touching instead.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_overlapping", &begin_shapes_overlapping_um, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_overlapping", &begin_shapes_overlapping_um, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search, the region given in micrometer units\n"
|
||||
"@param cell_index The index of the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1813,9 +1829,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version gives an iterator delivering shapes whose bounding box overlaps the given region.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_overlapping instead.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_overlapping", &begin_shapes_overlapping2_um, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_overlapping", &begin_shapes_overlapping2_um, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search, the region given in micrometer units\n"
|
||||
"@param cell The cell object for the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1826,6 +1844,8 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This version gives an iterator delivering shapes whose bounding box overlaps the given region.\n"
|
||||
"It is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_overlapping instead.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("#write", &write_options2, gsi::arg ("filename"), gsi::arg ("gzip"), gsi::arg ("options"),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,558 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "gsiDecl.h"
|
||||
#include "dbRecursiveInstanceIterator.h"
|
||||
#include "dbRegion.h"
|
||||
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// db::RecursiveInstanceIterator binding
|
||||
|
||||
static db::RecursiveInstanceIterator *new_si1 (const db::Layout &layout, const db::Cell &cell)
|
||||
{
|
||||
return new db::RecursiveInstanceIterator (layout, cell);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator *new_si2 (const db::Layout &layout, const db::Cell &cell, const db::Box &box, bool overlapping)
|
||||
{
|
||||
return new db::RecursiveInstanceIterator (layout, cell, box, overlapping);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator *new_si2a (const db::Layout &layout, const db::Cell &cell, const db::Region ®ion, bool overlapping)
|
||||
{
|
||||
return new db::RecursiveInstanceIterator (layout, cell, region, overlapping);
|
||||
}
|
||||
|
||||
static db::DCplxTrans si_dtrans (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
tl_assert (ly != 0);
|
||||
return db::CplxTrans (ly->dbu ()) * r->trans () * db::VCplxTrans (1.0 / ly->dbu ());
|
||||
}
|
||||
|
||||
static void set_targets1 (db::RecursiveInstanceIterator *r, const std::vector<db::cell_index_type> &cells)
|
||||
{
|
||||
std::set<db::cell_index_type> cc;
|
||||
cc.insert (cells.begin (), cells.end ());
|
||||
r->set_targets (cc);
|
||||
}
|
||||
|
||||
static db::DCplxTrans inst_dtrans (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
tl_assert (ly != 0);
|
||||
return db::CplxTrans (ly->dbu ()) * (*r)->complex_trans () * db::VCplxTrans (1.0 / ly->dbu ());
|
||||
}
|
||||
|
||||
static db::ICplxTrans inst_trans (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
return (*r)->complex_trans ();
|
||||
}
|
||||
|
||||
static db::Cell *inst_cell (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
tl_assert (ly != 0);
|
||||
return const_cast<db::Cell *> (&ly->cell ((*r)->inst_ptr.cell_index ()));
|
||||
}
|
||||
|
||||
static void set_targets2 (db::RecursiveInstanceIterator *r, const std::string &pattern)
|
||||
{
|
||||
tl::GlobPattern p (pattern);
|
||||
std::set<db::cell_index_type> cc;
|
||||
for (db::Layout::const_iterator ci = r->layout ()->begin (); ci != r->layout ()->end (); ++ci) {
|
||||
if (p.match (r->layout ()->cell_name (ci->cell_index ()))) {
|
||||
cc.insert (ci->cell_index ());
|
||||
}
|
||||
}
|
||||
|
||||
r->set_targets (cc);
|
||||
}
|
||||
|
||||
static void select_cells1 (db::RecursiveInstanceIterator *r, const std::vector<db::cell_index_type> &cells)
|
||||
{
|
||||
std::set<db::cell_index_type> cc;
|
||||
cc.insert (cells.begin (), cells.end ());
|
||||
r->select_cells (cc);
|
||||
}
|
||||
|
||||
static void select_cells2 (db::RecursiveInstanceIterator *r, const std::string &pattern)
|
||||
{
|
||||
tl::GlobPattern p (pattern);
|
||||
std::set<db::cell_index_type> cc;
|
||||
for (db::Layout::const_iterator ci = r->layout ()->begin (); ci != r->layout ()->end (); ++ci) {
|
||||
if (p.match (r->layout ()->cell_name (ci->cell_index ()))) {
|
||||
cc.insert (ci->cell_index ());
|
||||
}
|
||||
}
|
||||
|
||||
r->select_cells (cc);
|
||||
}
|
||||
|
||||
static void unselect_cells1 (db::RecursiveInstanceIterator *r, const std::vector<db::cell_index_type> &cells)
|
||||
{
|
||||
std::set<db::cell_index_type> cc;
|
||||
cc.insert (cells.begin (), cells.end ());
|
||||
r->unselect_cells (cc);
|
||||
}
|
||||
|
||||
static void unselect_cells2 (db::RecursiveInstanceIterator *r, const std::string &pattern)
|
||||
{
|
||||
tl::GlobPattern p (pattern);
|
||||
std::set<db::cell_index_type> cc;
|
||||
for (db::Layout::const_iterator ci = r->layout ()->begin (); ci != r->layout ()->end (); ++ci) {
|
||||
if (p.match (r->layout ()->cell_name (ci->cell_index ()))) {
|
||||
cc.insert (ci->cell_index ());
|
||||
}
|
||||
}
|
||||
|
||||
r->unselect_cells (cc);
|
||||
}
|
||||
|
||||
static db::Region complex_region (const db::RecursiveInstanceIterator *iter)
|
||||
{
|
||||
if (iter->has_complex_region ()) {
|
||||
return iter->complex_region ();
|
||||
} else {
|
||||
return db::Region (iter->region ());
|
||||
}
|
||||
}
|
||||
|
||||
Class<db::RecursiveInstanceIterator> decl_RecursiveInstanceIterator ("db", "RecursiveInstanceIterator",
|
||||
gsi::constructor ("new", &new_si1, gsi::arg ("layout"), gsi::arg ("cell"),
|
||||
"@brief Creates a recursive instance iterator.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive instance iterator which delivers the instances of "
|
||||
"the given cell plus its children.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si2, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("box"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive instance iterator with a search region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param box The search region\n"
|
||||
"@param overlapping If set to true, instances overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive instance iterator which delivers the instances of "
|
||||
"the given cell plus its children.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"box\" parameter. If \"overlapping\" is true, instances whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, instances whose "
|
||||
"bounding box touches the search region are reported. The bounding box of instances is measured taking all layers "
|
||||
"of the target cell into account.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si2a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("region"), gsi::arg ("overlapping"),
|
||||
"@brief Creates a recursive instance iterator with a search region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param region The search region\n"
|
||||
"@param overlapping If set to true, instances overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive instance iterator which delivers the instances of "
|
||||
"the given cell plus its children.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"region\" parameter. The region needs to be a rectilinear region.\n"
|
||||
"If \"overlapping\" is true, instances whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, instances whose "
|
||||
"bounding box touches the search region are reported. The bounding box of instances is measured taking all layers "
|
||||
"of the target cell into account.\n"
|
||||
) +
|
||||
gsi::method ("max_depth=", (void (db::RecursiveInstanceIterator::*) (int)) &db::RecursiveInstanceIterator::max_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
"A depth of 0 instructs the iterator to deliver only instances from the initial cell.\n"
|
||||
"A higher depth instructs the iterator to look deeper.\n"
|
||||
"The depth must be specified before the instances are being retrieved.\n"
|
||||
) +
|
||||
gsi::method ("max_depth", (int (db::RecursiveInstanceIterator::*) () const) &db::RecursiveInstanceIterator::max_depth,
|
||||
"@brief Gets the maximum hierarchy depth\n"
|
||||
"\n"
|
||||
"See \\max_depth= for a description of that attribute.\n"
|
||||
) +
|
||||
gsi::method ("min_depth=", (void (db::RecursiveInstanceIterator::*) (int)) &db::RecursiveInstanceIterator::min_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the minimum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
"A depth of 0 instructs the iterator to deliver instances from the top level.\n"
|
||||
"1 instructs to deliver instances from the first child level.\n"
|
||||
"The minimum depth must be specified before the instances are being retrieved.\n"
|
||||
) +
|
||||
gsi::method ("min_depth", (int (db::RecursiveInstanceIterator::*) () const) &db::RecursiveInstanceIterator::min_depth,
|
||||
"@brief Gets the minimum hierarchy depth\n"
|
||||
"\n"
|
||||
"See \\min_depth= for a description of that attribute.\n"
|
||||
) +
|
||||
gsi::method ("reset", &db::RecursiveInstanceIterator::reset,
|
||||
"@brief Resets the iterator to the initial state\n"
|
||||
) +
|
||||
gsi::method ("reset_selection", &db::RecursiveInstanceIterator::reset_selection,
|
||||
"@brief Resets the selection to the default state\n"
|
||||
"\n"
|
||||
"In the initial state, the top cell and its children are selected. Child cells can be switched on and off "
|
||||
"together with their sub-hierarchy using \\select_cells and \\unselect_cells.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method ("layout", &db::RecursiveInstanceIterator::layout,
|
||||
"@brief Gets the layout this iterator is connected to\n"
|
||||
) +
|
||||
gsi::method ("top_cell", &db::RecursiveInstanceIterator::top_cell,
|
||||
"@brief Gets the top cell this iterator is connected to\n"
|
||||
) +
|
||||
gsi::method ("region", &db::RecursiveInstanceIterator::region,
|
||||
"@brief Gets the basic region that is iterator is using\n"
|
||||
"The basic region is the overall box the region iterator iterates over. "
|
||||
"There may be an additional complex region that confines the region iterator. "
|
||||
"See \\complex_region for this attribute.\n"
|
||||
) +
|
||||
gsi::method_ext ("complex_region", &complex_region,
|
||||
"@brief Gets the complex region that is iterator is using\n"
|
||||
"The complex region is the effective region (a \\Region object) that the "
|
||||
"iterator is selecting from the layout. This region can be a single box "
|
||||
"or a complex region.\n"
|
||||
) +
|
||||
gsi::method ("region=", (void (db::RecursiveInstanceIterator::*)(const db::RecursiveInstanceIterator::box_type &)) &db::RecursiveInstanceIterator::set_region, gsi::arg ("box_region"),
|
||||
"@brief Sets the rectangular region that is iterator is iterating over\n"
|
||||
"See \\region for a description of this attribute.\n"
|
||||
"Setting a simple region will reset the complex region to a rectangle and reset the iterator to "
|
||||
"the beginning of the sequence."
|
||||
) +
|
||||
gsi::method ("region=", (void (db::RecursiveInstanceIterator::*)(const db::RecursiveInstanceIterator::region_type &)) &db::RecursiveInstanceIterator::set_region, gsi::arg ("complex_region"),
|
||||
"@brief Sets the complex region that is iterator is using\n"
|
||||
"See \\complex_region for a description of this attribute. Setting the complex region will "
|
||||
"reset the basic region (see \\region) to the bounding box of the complex region and "
|
||||
"reset the iterator to the beginning of the sequence.\n"
|
||||
) +
|
||||
gsi::method ("confine_region", (void (db::RecursiveInstanceIterator::*)(const db::RecursiveInstanceIterator::box_type &)) &db::RecursiveInstanceIterator::confine_region, gsi::arg ("box_region"),
|
||||
"@brief Confines the region that is iterator is iterating over\n"
|
||||
"This method is similar to setting the region (see \\region=), but will confine any region (complex or simple) already set. "
|
||||
"Essentially it does a logical AND operation between the existing and given region. "
|
||||
"Hence this method can only reduce a region, not extend it.\n"
|
||||
) +
|
||||
gsi::method ("confine_region", (void (db::RecursiveInstanceIterator::*)(const db::RecursiveInstanceIterator::region_type &)) &db::RecursiveInstanceIterator::confine_region, gsi::arg ("complex_region"),
|
||||
"@brief Confines the region that is iterator is iterating over\n"
|
||||
"This method is similar to setting the region (see \\region=), but will confine any region (complex or simple) already set. "
|
||||
"Essentially it does a logical AND operation between the existing and given region. "
|
||||
"Hence this method can only reduce a region, not extend it.\n"
|
||||
) +
|
||||
gsi::method ("overlapping?", &db::RecursiveInstanceIterator::overlapping,
|
||||
"@brief Gets a flag indicating whether overlapping instances are selected when a region is used\n"
|
||||
) +
|
||||
gsi::method ("overlapping=", &db::RecursiveInstanceIterator::set_overlapping, gsi::arg ("region"),
|
||||
"@brief Sets a flag indicating whether overlapping instances are selected when a region is used\n"
|
||||
"\n"
|
||||
"If this flag is false, instances touching the search region are returned.\n"
|
||||
) +
|
||||
gsi::method ("unselect_all_cells", &db::RecursiveInstanceIterator::unselect_all_cells,
|
||||
"@brief Unselects all cells.\n"
|
||||
"\n"
|
||||
"This method will set the \"unselected\" mark on all cells. The effect is "
|
||||
"that subsequent calls of \\select_cells will select only the specified cells, not "
|
||||
"their children, because they are still unselected.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method ("select_all_cells", &db::RecursiveInstanceIterator::select_all_cells,
|
||||
"@brief Selects all cells.\n"
|
||||
"\n"
|
||||
"This method will set the \"selected\" mark on all cells. The effect is "
|
||||
"that subsequent calls of \\unselect_cells will unselect only the specified cells, not "
|
||||
"their children, because they are still unselected.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("unselect_cells", &unselect_cells1, gsi::arg ("cells"),
|
||||
"@brief Unselects the given cells.\n"
|
||||
"\n"
|
||||
"This method will sets the \"unselected\" mark on the given cells. "
|
||||
"That means that these cells or their child cells will not be visited, unless "
|
||||
"they are marked as \"selected\" again with the \\select_cells method.\n"
|
||||
"\n"
|
||||
"The cells are given as a list of cell indexes.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("unselect_cells", &unselect_cells2, gsi::arg ("cells"),
|
||||
"@brief Unselects the given cells.\n"
|
||||
"\n"
|
||||
"This method will sets the \"unselected\" mark on the given cells. "
|
||||
"That means that these cells or their child cells will not be visited, unless "
|
||||
"they are marked as \"selected\" again with the \\select_cells method.\n"
|
||||
"\n"
|
||||
"The cells are given as a glob pattern.\n"
|
||||
"A glob pattern follows the syntax of "
|
||||
"file names on the shell (i.e. \"A*\" are all cells starting with a letter \"A\").\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("select_cells", &select_cells1, gsi::arg ("cells"),
|
||||
"@brief Unselects the given cells.\n"
|
||||
"\n"
|
||||
"This method will sets the \"selected\" mark on the given cells. "
|
||||
"That means that these cells or their child cells are visited, unless "
|
||||
"they are marked as \"unselected\" again with the \\unselect_cells method.\n"
|
||||
"\n"
|
||||
"The cells are given as a list of cell indexes.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("select_cells", &select_cells2, gsi::arg ("cells"),
|
||||
"@brief Unselects the given cells.\n"
|
||||
"\n"
|
||||
"This method will sets the \"selected\" mark on the given cells. "
|
||||
"That means that these cells or their child cells are visited, unless "
|
||||
"they are marked as \"unselected\" again with the \\unselect_cells method.\n"
|
||||
"\n"
|
||||
"The cells are given as a glob pattern.\n"
|
||||
"A glob pattern follows the syntax of "
|
||||
"file names on the shell (i.e. \"A*\" are all cells starting with a letter \"A\").\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("targets=", &set_targets1, gsi::arg ("cells"),
|
||||
"@brief Specifies the target cells.\n"
|
||||
"\n"
|
||||
"If target cells are specified, only instances of these cells are delivered. "
|
||||
"This version takes a list of cell indexes for the targets. "
|
||||
"By default, no target cell list is present and the instances of all cells "
|
||||
"are delivered by the iterator. See \\all_targets_enabled? and \\enable_all_targets for "
|
||||
"a description of this mode. Once a target list is specified, the iteration is "
|
||||
"confined to the cells from this list."
|
||||
"\n"
|
||||
"The cells are given as a list of cell indexes.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("targets=", &set_targets2, gsi::arg ("cells"),
|
||||
"@brief Specifies the target cells.\n"
|
||||
"\n"
|
||||
"If target cells are specified, only instances of these cells are delivered. "
|
||||
"This version takes a cell list as a glob pattern. "
|
||||
"A glob pattern follows the syntax of "
|
||||
"file names on the shell (i.e. \"A*\" are all cells starting with a letter \"A\").\n"
|
||||
"Use the curly-bracket notation to list different cells, e.g \"{A,B,C}\" for cells A, B and C.\n"
|
||||
"\n"
|
||||
"By default, no target cell list is present and the instances of all cells "
|
||||
"are delivered by the iterator. See \\all_targets_enabled? and \\enable_all_targets for "
|
||||
"a description of this mode. Once a target list is specified, the iteration is "
|
||||
"confined to the cells from this list."
|
||||
"\n"
|
||||
"The cells are given as a list of cell indexes.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method ("targets", &db::RecursiveInstanceIterator::targets,
|
||||
"@brief Gets the list of target cells\n"
|
||||
"See \\targets= for a description of the target cell concept. "
|
||||
"This method returns a list of cell indexes of the selected target cells."
|
||||
) +
|
||||
gsi::method ("all_targets_enabled?", &db::RecursiveInstanceIterator::all_targets_enabled,
|
||||
"@brief Gets a value indicating whether instances of all cells are reported\n"
|
||||
"See \\targets= for a description of the target cell concept. "
|
||||
) +
|
||||
gsi::method ("enable_all_targets", &db::RecursiveInstanceIterator::enable_all_targets,
|
||||
"@brief Enables 'all targets' mode in which instances of all cells are reported\n"
|
||||
"See \\targets= for a description of the target cell concept. "
|
||||
) +
|
||||
gsi::method ("trans", &db::RecursiveInstanceIterator::trans,
|
||||
"@brief Gets the accumulated transformation of the current instance parent cell to the top cell\n"
|
||||
"\n"
|
||||
"This transformation represents how the current instance is seen in the top cell.\n"
|
||||
) +
|
||||
gsi::method_ext ("dtrans", &gsi::si_dtrans,
|
||||
"@brief Gets the accumulated transformation of the current instance parent cell to the top cell\n"
|
||||
"\n"
|
||||
"This transformation represents how the current instance is seen in the top cell.\n"
|
||||
"This version returns the micon-unit transformation.\n"
|
||||
) +
|
||||
gsi::method ("at_end?", &db::RecursiveInstanceIterator::at_end,
|
||||
"@brief End of iterator predicate\n"
|
||||
"\n"
|
||||
"Returns true, if the iterator is at the end of the sequence\n"
|
||||
) +
|
||||
gsi::method ("cell", &db::RecursiveInstanceIterator::cell,
|
||||
"@brief Gets the cell the current instance sits in\n"
|
||||
) +
|
||||
gsi::method ("cell_index", &db::RecursiveInstanceIterator::cell_index,
|
||||
"@brief Gets the index of the cell the current instance sits in\n"
|
||||
"This is equivalent to 'cell.cell_index'."
|
||||
) +
|
||||
gsi::method_ext ("inst_trans", &inst_trans,
|
||||
"@brief Gets the integer-unit transformation of the current instance\n"
|
||||
"This is the transformation of the current instance inside its parent.\n"
|
||||
"'trans * inst_trans' gives the full transformation how the current cell is seen in the top cell.\n"
|
||||
"See also \\inst_dtrans and \\inst_cell.\n"
|
||||
) +
|
||||
gsi::method_ext ("inst_dtrans", &inst_dtrans,
|
||||
"@brief Gets the micron-unit transformation of the current instance\n"
|
||||
"This is the transformation of the current instance inside its parent.\n"
|
||||
"'dtrans * inst_dtrans' gives the full micron-unit transformation how the current cell is seen in the top cell.\n"
|
||||
"See also \\inst_trans and \\inst_cell.\n"
|
||||
) +
|
||||
gsi::method_ext ("inst_cell", &inst_cell,
|
||||
"@brief Gets the target cell of the current instance\n"
|
||||
"This is the cell the current instance refers to. It is one of the \\targets if a target list is given.\n"
|
||||
) +
|
||||
gsi::method ("current_inst_element", &db::RecursiveInstanceIterator::instance,
|
||||
"@brief Gets the current instance\n"
|
||||
"\n"
|
||||
"This is the instance/array element the iterator currently refers to.\n"
|
||||
"This is a \\InstElement object representing the current instance and the array element the iterator currently points at.\n"
|
||||
"\n"
|
||||
"See \\inst_trans, \\inst_dtrans and \\inst_cell for convenience methods to access the details of the current element.\n"
|
||||
) +
|
||||
gsi::method ("next", (void (db::RecursiveInstanceIterator::*) ()) &db::RecursiveInstanceIterator::next,
|
||||
"@brief Increments the iterator\n"
|
||||
"This moves the iterator to the next instance inside the search scope."
|
||||
) +
|
||||
gsi::method ("path", &db::RecursiveInstanceIterator::path,
|
||||
"@brief Gets the instantatiation path of the instance addressed currently\n"
|
||||
"\n"
|
||||
"This attribute is a sequence of \\InstElement objects describing the cell instance path from the initial "
|
||||
"cell to the current instance. The path is empty if the current instance is in the top cell.\n"
|
||||
) +
|
||||
gsi::method ("==", &db::RecursiveInstanceIterator::operator==, gsi::arg ("other"),
|
||||
"@brief Comparison of iterators - equality\n"
|
||||
"\n"
|
||||
"Two iterators are equal if they point to the same instance.\n"
|
||||
) +
|
||||
gsi::method ("!=", &db::RecursiveInstanceIterator::operator!=, gsi::arg ("other"),
|
||||
"@brief Comparison of iterators - inequality\n"
|
||||
"\n"
|
||||
"Two iterators are not equal if they do not point to the same instance.\n"
|
||||
),
|
||||
"@brief An iterator delivering instances recursively\n"
|
||||
"\n"
|
||||
"The iterator can be obtained from a cell and optionally a region.\n"
|
||||
"It simplifies retrieval of instances while considering\n"
|
||||
"subcells as well.\n"
|
||||
"Some options can be specified in addition, i.e. the hierarchy level to which to look into.\n"
|
||||
"The search can be confined to instances of certain cells (see \\targets=) or to certain regions. "
|
||||
"Subtrees can be selected for traversal or excluded from it (see \\select_cells).\n"
|
||||
"\n"
|
||||
"This is some sample code:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# prints the effective instances of cell \"A\" as seen from the initial cell \"cell\"\n"
|
||||
"iter = cell.begin_instances_rec\n"
|
||||
"iter.targets = \"A\"\n"
|
||||
"while !iter.at_end?\n"
|
||||
" puts \"Instance of #{iter.inst_cell.name} in #{cell.name}: \" + (iter.dtrans * iter.inst_dtrans).to_s\n"
|
||||
" iter.next\n"
|
||||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Here, a target cell is specified which confines the search to instances of this particular cell.\n"
|
||||
"'iter.dtrans' gives us the accumulated transformation of all parents up to the top cell. "
|
||||
"'iter.inst_dtrans' gives us the transformation from the current instance. "
|
||||
"'iter.inst_cell' finally gives us the target cell of the current instance (which is always 'A' in our case).\n"
|
||||
"\n"
|
||||
"\\Cell offers three methods to get these iterators: begin_instances_rec, begin_instances_rec_touching and begin_instances_rec_overlapping.\n"
|
||||
"\\Cell#begin_instances_rec will deliver a standard recursive instance iterator which starts from the given cell and iterates "
|
||||
"over all child cells. \\Cell#begin_instances_rec_touching creates a RecursiveInstanceIterator which delivers the instances "
|
||||
"whose bounding boxed touch the given search box. \\Layout#begin_instances_rec_overlapping gives an iterator which delivers all instances whose bounding box "
|
||||
"overlaps the search box.\n"
|
||||
"\n"
|
||||
"A RecursiveInstanceIterator object can also be created directly, like this:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"iter = RBA::RecursiveInstanceIterator::new(layout, cell [, options ])\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"\"layout\" is the layout object, \"cell\" the \\Cell object of the initial cell.\n"
|
||||
"\n"
|
||||
"The recursive instance iterator can be confined to a maximum hierarchy depth. By using \\max_depth=, the "
|
||||
"iterator will restrict the search depth to the given depth in the cell tree.\n"
|
||||
"In the same way, the iterator can be configured to start from a certain hierarchy depth using \\min_depth=. "
|
||||
"The hierarchy depth always applies to the parent of the instances iterated.\n"
|
||||
"\n"
|
||||
"In addition, the recursive instance iterator supports selection and exclusion of subtrees. For that purpose "
|
||||
"it keeps flags per cell telling it for which cells to turn instance delivery on and off. The \\select_cells method "
|
||||
"sets the \"start delivery\" flag while \\unselect_cells sets the \"stop delivery\" flag. In effect, using "
|
||||
"\\unselect_cells will exclude that cell plus the subtree from delivery. Parts of that subtree can be "
|
||||
"turned on again using \\select_cells. For the cells selected that way, the instances of these cells and their "
|
||||
"child cells are delivered, even if their parent was unselected.\n"
|
||||
"\n"
|
||||
"To get instances from a specific cell, i.e. \"MACRO\" plus its child cells, unselect the top cell first "
|
||||
"and the select the desired cell again:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# deliver all instances inside \"MACRO\" and the sub-hierarchy:\n"
|
||||
"iter = RBA::RecursiveInstanceIterator::new(layout, cell)\n"
|
||||
"iter.unselect_cells(cell.cell_index)\n"
|
||||
"iter.select_cells(\"MACRO\")\n"
|
||||
"...\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"The \\unselect_all_cells and \\select_all_cells methods turn on the \"stop\" and \"start\" flag "
|
||||
"for all cells respectively. If you use \\unselect_all_cells and use \\select_cells for a specific cell, "
|
||||
"the iterator will deliver only the instances of the selected cell, not its children. Those are still "
|
||||
"unselected by \\unselect_all_cells:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# deliver all instance inside \"MACRO\" but not of child cells:\n"
|
||||
"iter = RBA::RecursiveInstanceIterator::new(layout, cell)\n"
|
||||
"iter.unselect_all_cells\n"
|
||||
"iter.select_cells(\"MACRO\")\n"
|
||||
"...\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Cell selection is done using cell indexes or glob pattern. Glob pattern are equivalent to the usual "
|
||||
"file name wildcards used on various command line shells. For example \"A*\" matches all cells starting with "
|
||||
"an \"A\". The curly brace notation and character classes are supported as well. For example \"C{125,512}\" matches "
|
||||
"\"C125\" and \"C512\" and \"[ABC]*\" matches all cells starting with an \"A\", a \"B\" or \"C\". \"[^ABC]*\" matches "
|
||||
"all cells not starting with one of that letters.\n"
|
||||
"\n"
|
||||
"To confine instance iteration to instances of certain cells, use the \\targets feature:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# deliver all instance of \"INV1\":\n"
|
||||
"iter = RBA::RecursiveInstanceIterator::new(layout, cell)\n"
|
||||
"iter.targets = \"INV1\"\n"
|
||||
"...\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Targets can be specified either as lists of cell indexes or through a glob pattern.\n"
|
||||
"\n"
|
||||
"Instances are always delivered depth-first with child instances before their parents. A default recursive instance "
|
||||
"iterator will first deliver leaf cells, followed by the parent of these cells.\n"
|
||||
"\n"
|
||||
"When a search region is used, instances whose bounding box touch or overlap (depending on 'overlapping' flag) will "
|
||||
"be reported. The instance bounding box taken as reference is computed using all layers of the layout.\n"
|
||||
"\n"
|
||||
"The iterator will deliver the individual elements of instance arrays, confined to the search region if one is given. "
|
||||
"Consequently the return value (\\current_inst_element) is an \\InstElement "
|
||||
"object which is basically a combination of an \\Instance object and information about the current array element.\n"
|
||||
"\\inst_cell, \\inst_trans and \\inst_dtrans are methods provided for convenience to access the current array member's transformation "
|
||||
"and the target cell of the current instance.\n"
|
||||
"\n"
|
||||
"The RecursiveInstanceIterator class has been introduced in version 0.27.\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
|
@ -123,89 +123,89 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
gsi::constructor ("new", &new_si1, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"),
|
||||
"@brief Creates a recursive, single-layer shape iterator.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"the given cell plus its children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si2, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"),
|
||||
"@brief Creates a recursive, multi-layer shape iterator.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layers The layer indexes from which the shapes are taken\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"the given cell plus its children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"While iterating use the \\layer method to retrieve the layer of the current shape.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si3, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("box"), gsi::arg ("overlapping"),
|
||||
gsi::constructor ("new", &new_si3, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("box"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive, single-layer shape iterator with a region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"@param box The search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"the given cell plus its children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"box\" parameter. If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si3a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"), gsi::arg ("overlapping"),
|
||||
gsi::constructor ("new", &new_si3a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive, single-layer shape iterator with a region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"@param region The search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"the given cell plus its children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"region\" parameter. The region needs to be a rectilinear region.\n"
|
||||
"If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.25.\n"
|
||||
"This constructor has been introduced in version 0.25. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si4, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"), gsi::arg ("box"), gsi::arg ("overlapping"),
|
||||
gsi::constructor ("new", &new_si4, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"), gsi::arg ("box"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive, multi-layer shape iterator with a region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layers The layer indexes from which the shapes are taken\n"
|
||||
"@param box The search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"the given cell plus its children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"While iterating use the \\layer method to retrieve the layer of the current shape.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"box\" parameter. If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si4a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"), gsi::arg ("region"), gsi::arg ("overlapping"),
|
||||
gsi::constructor ("new", &new_si4a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"), gsi::arg ("region"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive, multi-layer shape iterator with a region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layers The layer indexes from which the shapes are taken\n"
|
||||
"@param region The search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"the given cell plus its children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"While iterating use the \\layer method to retrieve the layer of the current shape.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"region\" parameter. The region needs to be a rectilinear region.\n"
|
||||
|
|
@ -213,10 +213,10 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("max_depth=", (void (db::RecursiveShapeIterator::*) (int)) &db::RecursiveShapeIterator::max_depth, gsi::arg ("depth"),
|
||||
"@brief Specify the maximum hierarchy depth to look into\n"
|
||||
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
"A depth of 0 instructs the iterator to deliver only shapes from the initial cell.\n"
|
||||
"The depth must be specified before the shapes are being retrieved.\n"
|
||||
|
|
@ -229,7 +229,23 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::method ("reset", &db::RecursiveShapeIterator::reset,
|
||||
gsi::method ("min_depth=", (void (db::RecursiveShapeIterator::*) (int)) &db::RecursiveShapeIterator::min_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the minimum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
"A depth of 0 instructs the iterator to deliver shapes from the top level.\n"
|
||||
"1 instructs to deliver shapes from the first child level.\n"
|
||||
"The minimum depth must be specified before the shapes are being retrieved.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("min_depth", (int (db::RecursiveShapeIterator::*) () const) &db::RecursiveShapeIterator::min_depth,
|
||||
"@brief Gets the minimum hierarchy depth\n"
|
||||
"\n"
|
||||
"See \\min_depth= for a description of that attribute.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("reset", &db::RecursiveShapeIterator::reset,
|
||||
"@brief Resets the iterator to the initial state\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
|
|
@ -237,7 +253,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
gsi::method ("reset_selection", &db::RecursiveShapeIterator::reset_selection,
|
||||
"@brief Resets the selection to the default state\n"
|
||||
"\n"
|
||||
"In the initial state, the top cell and it's children are selected. Child cells can be switched on and off "
|
||||
"In the initial state, the top cell and its children are selected. Child cells can be switched on and off "
|
||||
"together with their sub-hierarchy using \\select_cells and \\unselect_cells.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
|
|
@ -436,7 +452,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"@brief Gets the current cell's index \n"
|
||||
) +
|
||||
gsi::method ("next", (void (db::RecursiveShapeIterator::*) ()) &db::RecursiveShapeIterator::next,
|
||||
"@brief Increment the iterator\n"
|
||||
"@brief Increments the iterator\n"
|
||||
"This moves the iterator to the next shape inside the search scope."
|
||||
) +
|
||||
gsi::method ("layer", &db::RecursiveShapeIterator::layer,
|
||||
|
|
@ -462,12 +478,12 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"\n"
|
||||
"Two iterators are not equal if they do not point to the same shape.\n"
|
||||
),
|
||||
"@brief An iterator delivering shapes that touch or overlap the given region recursively\n"
|
||||
"@brief An iterator delivering shapes recursively\n"
|
||||
"\n"
|
||||
"The iterator can be obtained from a layout, specifying a starting cell, a layer and optionally a region.\n"
|
||||
"The iterator can be obtained from a cell, a layer and optionally a region.\n"
|
||||
"It simplifies retrieval of shapes from a geometrical region while considering\n"
|
||||
"subcells as well.\n"
|
||||
"Some options can be specified, i.e. the level to which to look into or\n"
|
||||
"Some options can be specified in addition, i.e. the level to which to look into or\n"
|
||||
"shape classes and shape properties. The shapes are retrieved by using the \\shape method,\n"
|
||||
"\\next moves to the next shape and \\at_end tells, if the iterator has move shapes to deliver.\n"
|
||||
"\n"
|
||||
|
|
@ -475,7 +491,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"\n"
|
||||
"@code\n"
|
||||
"# print the polygon-like objects as seen from the initial cell \"cell\"\n"
|
||||
"iter = layout.begin_shapes(cell_index, layer)\n"
|
||||
"iter = cell.begin_shapes_rec(layer)\n"
|
||||
"while !iter.at_end?\n"
|
||||
" if iter.shape.renders_polygon?\n"
|
||||
" polygon = iter.shape.polygon.transformed(iter.itrans)\n"
|
||||
|
|
@ -485,10 +501,10 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"\\Layout offers three methods to get these iterators: begin_shapes, begin_shapes_touching and begin_shapes_overlapping.\n"
|
||||
"\\Layout#begin_shapes will deliver a standard recursive shape iterator which starts from the given cell and iterates "
|
||||
"over all child cells. \\Layout#begin_shapes_touching delivers a RecursiveShapeIterator which delivers the shapes "
|
||||
"whose bounding boxed touch the given search box. \\Layout#begin_shapes_overlapping delivers all shapes whose bounding box "
|
||||
"\\Cell offers three methods to get these iterators: begin_shapes_rec, begin_shapes_rec_touching and begin_shapes_rec_overlapping.\n"
|
||||
"\\Cell#begin_shapes_rec will deliver a standard recursive shape iterator which starts from the given cell and iterates "
|
||||
"over all child cells. \\Cell#begin_shapes_rec_touching delivers a RecursiveShapeIterator which delivers the shapes "
|
||||
"whose bounding boxed touch the given search box. \\Cell#begin_shapes_rec_overlapping delivers all shapes whose bounding box "
|
||||
"overlaps the search box.\n"
|
||||
"\n"
|
||||
"A RecursiveShapeIterator object can also be created explicitly. This allows some more options, i.e. using "
|
||||
|
|
@ -510,7 +526,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"sets the \"start delivery\" flag while \\unselect_cells sets the \"stop delivery\" flag. In effect, using "
|
||||
"\\unselect_cells will exclude that cell plus the subtree from delivery. Parts of that subtree can be "
|
||||
"turned on again using \\select_cells. For the cells selected that way, the shapes of these cells and their "
|
||||
"child cells are delivered, even if their parents was unselected.\n"
|
||||
"child cells are delivered, even if their parent was unselected.\n"
|
||||
"\n"
|
||||
"To get shapes from a specific cell, i.e. \"MACRO\" plus its child cells, unselect the top cell first "
|
||||
"and the select the desired cell again:\n"
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ std::string collect(db::RecursiveInstanceIterator &s, const db::Layout &layout)
|
|||
} else {
|
||||
res += "[]";
|
||||
}
|
||||
res += s->to_string (true);
|
||||
res += s->inst_ptr.to_string (true);
|
||||
++s;
|
||||
}
|
||||
return res;
|
||||
|
|
@ -126,13 +126,13 @@ TEST(1)
|
|||
x = collect_with_copy(i1_12, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
||||
|
||||
db::RecursiveInstanceIterator i1_22 (g, c0, db::Box (0, 0, 100, 100));
|
||||
db::RecursiveInstanceIterator i1_22 (g, c0, db::Box (0, 0, 2000, 100));
|
||||
i1_22.min_depth(1);
|
||||
i1_22.max_depth(1);
|
||||
x = collect(i1_22, g);
|
||||
EXPECT_EQ (x, "");
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
x = collect_with_copy(i1_22, g);
|
||||
EXPECT_EQ (x, "");
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
|
||||
db::RecursiveInstanceIterator i1o (g, c0, db::Box (0, 0, 100, 100), true);
|
||||
x = collect(i1o, g);
|
||||
|
|
@ -350,7 +350,7 @@ TEST(2)
|
|||
std::set<db::Box> selected_boxes2;
|
||||
|
||||
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box, true); !iter.at_end (); ++iter) {
|
||||
selected_boxes.insert (iter.trans () * iter->bbox ());
|
||||
selected_boxes.insert (iter.trans () * iter->inst_ptr.bbox ());
|
||||
}
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
|
|
@ -382,7 +382,7 @@ TEST(2)
|
|||
reg.insert (search_box2);
|
||||
|
||||
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg, true); !iter.at_end (); ++iter) {
|
||||
selected_boxes.insert (iter.trans () * iter->bbox ());
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
|
|
@ -451,7 +451,7 @@ TEST(3)
|
|||
int n = 0;
|
||||
for ( ; !iter.at_end (); ++iter) {
|
||||
++n;
|
||||
selected_boxes.insert (iter.trans () * iter->bbox ());
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
int nn = 0;
|
||||
|
|
@ -487,7 +487,7 @@ TEST(3)
|
|||
reg.insert (search_box2);
|
||||
|
||||
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg, true); !iter.at_end (); ++iter) {
|
||||
selected_boxes.insert (iter.trans () * iter->bbox ());
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
|
|
@ -556,7 +556,7 @@ TEST(4)
|
|||
int n = 0;
|
||||
for ( ; !iter.at_end (); ++iter) {
|
||||
++n;
|
||||
selected_boxes.insert (iter.trans () * iter->bbox ());
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
int nn = 0;
|
||||
|
|
@ -592,7 +592,7 @@ TEST(4)
|
|||
reg.insert (search_box2);
|
||||
|
||||
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg); !iter.at_end (); ++iter) {
|
||||
selected_boxes.insert (iter.trans () * iter->bbox ());
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,8 @@ RUBYTEST (dbInstElementTest, "dbInstElementTest.rb")
|
|||
RUBYTEST (dbLayerMapping, "dbLayerMapping.rb")
|
||||
RUBYTEST (dbLibrary, "dbLibrary.rb")
|
||||
RUBYTEST (dbLayout, "dbLayout.rb")
|
||||
RUBYTEST (dbRecursiveShapeIterator, "dbRecursiveShapeIterator.rb")
|
||||
RUBYTEST (dbRecursiveInstanceIterator, "dbRecursiveInstanceIterator.rb")
|
||||
RUBYTEST (dbLayoutTest, "dbLayoutTest.rb")
|
||||
RUBYTEST (dbLayoutDiff, "dbLayoutDiff.rb")
|
||||
RUBYTEST (dbLayoutQuery, "dbLayoutQuery.rb")
|
||||
|
|
|
|||
|
|
@ -335,212 +335,6 @@ class DBLayout_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
def test_5
|
||||
|
||||
# Recursive shape iterator tests
|
||||
|
||||
l = RBA::Layout.new
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
l.insert_layer_at(1, RBA::LayerInfo.new(2, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
c2 = l.cell(l.add_cell("c2"))
|
||||
c3 = l.cell(l.add_cell("c3"))
|
||||
|
||||
b = RBA::Box.new(0, 100, 1000, 1200)
|
||||
c0.shapes(0).insert(b)
|
||||
c1.shapes(0).insert(b)
|
||||
c2.shapes(0).insert(b)
|
||||
c3.shapes(0).insert(b)
|
||||
|
||||
bb = RBA::Box.new(1, 101, 1001, 1201)
|
||||
c3.shapes(1).insert(bb)
|
||||
|
||||
tt = RBA::Trans.new
|
||||
c0.insert(RBA::CellInstArray.new(c1.cell_index, tt))
|
||||
c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100))))
|
||||
c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1)))
|
||||
c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0))))
|
||||
|
||||
i1 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 100))
|
||||
i1copy = i1.dup
|
||||
assert_equal(i1copy.overlapping?, false)
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
i1.reset
|
||||
assert_equal(dcollect(i1, l), "[c0](0,0.1;1,1.2)/[c1](0,0.1;1,1.2)/[c2](0.1,0;1.1,1.1)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1 = l.begin_shapes_touching(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.100))
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1 = c0.begin_shapes_rec_touching(0, RBA::Box.new(0, 0, 100, 100))
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1 = c0.begin_shapes_rec_touching(0, RBA::DBox.new(0, 0, 0.100, 0.100))
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 100));
|
||||
assert_equal(collect(i1o, l), "");
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.100));
|
||||
assert_equal(collect(i1o, l), "");
|
||||
i1copy.overlapping = true
|
||||
assert_equal(i1copy.overlapping?, true)
|
||||
assert_equal(collect(i1copy, l), "");
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 101));
|
||||
assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.101));
|
||||
assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1copy.region = RBA::Box.new(0, 0, 100, 101)
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1copy.region = RBA::Region::new(RBA::Box.new(0, 0, 100, 101))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1copy.region = RBA::Box.new(-1000, -1000, 1100, 1101)
|
||||
i1copy.confine_region(RBA::Box.new(0, 0, 100, 101))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1copy.region = RBA::Box.new(-1000, -1000, 1100, 1101)
|
||||
i1copy.confine_region(RBA::Region::new(RBA::Box.new(0, 0, 100, 101)))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 101, 101));
|
||||
assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)");
|
||||
i1o = c0.begin_shapes_rec_overlapping(0, RBA::Box.new(0, 0, 101, 101));
|
||||
assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)");
|
||||
|
||||
i2 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 100, 100));
|
||||
assert_equal(collect(i2, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)");
|
||||
i2o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(-100, 0, 100, 100));
|
||||
assert_equal(collect(i2o, l), "");
|
||||
i2o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(-101, 0, 101, 101));
|
||||
assert_equal(collect(i2o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)");
|
||||
|
||||
i4 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 2000, 100));
|
||||
i4_copy = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 2000, 100));
|
||||
i4.max_depth = 0;
|
||||
assert_equal(collect(i4, l), "[c0](0,100;1000,1200)");
|
||||
|
||||
assert_equal(i4 == i4, true);
|
||||
assert_equal(i4 != i4, false);
|
||||
assert_equal(i4 == i4_copy, false);
|
||||
assert_equal(i4 != i4_copy, true);
|
||||
i4 = i4_copy.dup;
|
||||
assert_equal(i4 == i4_copy, true);
|
||||
assert_equal(i4 != i4_copy, false);
|
||||
i4.max_depth = 1;
|
||||
assert_equal(collect(i4, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)");
|
||||
|
||||
i4.assign(i4_copy);
|
||||
assert_equal(collect(i4, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)");
|
||||
|
||||
i5 = l.begin_shapes(c0.cell_index, 0);
|
||||
assert_equal(collect(i5, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)");
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new
|
||||
assert_equal(collect(ii, l), "")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c1, 0)
|
||||
assert_equal(collect(ii, l), "[c1](0,100;1000,1200)")
|
||||
assert_equal(ii.top_cell.name, "c1")
|
||||
assert_equal(ii.layout == l, true)
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1])
|
||||
ic = ii.dup
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)")
|
||||
assert_equal(collect(ic, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 100), false)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 100), true)
|
||||
assert_equal(collect(ii, l), "")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 101), true)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 100), false)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 101), false)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 101), true)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c0, 0)
|
||||
assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
|
||||
ii.reset
|
||||
ii.unselect_cells("c0")
|
||||
ii.select_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)")
|
||||
|
||||
ii.reset_selection
|
||||
ii.unselect_cells("c*")
|
||||
ii.select_cells([ c2.cell_index ])
|
||||
assert_equal(collect(ii, l), "[c2](100,0;1100,1100)")
|
||||
|
||||
ii.reset_selection
|
||||
ii.unselect_all_cells
|
||||
ii.select_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c2](100,0;1100,1100)")
|
||||
|
||||
ii.reset_selection
|
||||
ii.select_all_cells
|
||||
ii.unselect_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
|
||||
ii.reset_selection
|
||||
ii.select_cells("c*")
|
||||
ii.unselect_cells([ c1.cell_index, c2.cell_index ])
|
||||
assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
|
||||
end
|
||||
|
||||
def test_5x
|
||||
|
||||
# Recursive shape iterator tests
|
||||
|
||||
l = RBA::Layout.new
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
l.insert_layer_at(1, RBA::LayerInfo.new(2, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
c2 = l.cell(l.add_cell("c2"))
|
||||
c3 = l.cell(l.add_cell("c3"))
|
||||
|
||||
b = RBA::Box.new(0, 100, 1000, 1200)
|
||||
c3.shapes(0).insert(b)
|
||||
|
||||
bb = RBA::Box.new(1, 101, 1001, 1201)
|
||||
c3.shapes(1).insert(bb)
|
||||
|
||||
tt = RBA::Trans.new
|
||||
c0.insert(RBA::CellInstArray.new(c1.cell_index, tt))
|
||||
c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100))))
|
||||
c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1), RBA::Vector::new(10, 20), RBA::Vector::new(11, 21), 2, 3))
|
||||
c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0))))
|
||||
|
||||
res = []
|
||||
i = l.begin_shapes(c0.cell_index, 0)
|
||||
while !i.at_end?
|
||||
res << i.shape.box.transformed(i.trans).to_s + " " + i.path.collect { |e| "[" + l.cell(e.cell_inst.cell_index).name + " #" + e.ia.to_s + "," + e.ib.to_s + " -> " + e.specific_trans.to_s + "]" }.join("")
|
||||
i.next
|
||||
end
|
||||
|
||||
assert_equal(res.join("\n") + "\n", <<"END")
|
||||
(1200,0;2200,1100) [c2 #-1,-1 -> r0 100,-100][c3 #-1,-1 -> r0 1100,0]
|
||||
(-1200,0;-100,1000) [c3 #0,0 -> r90 0,0]
|
||||
(-1190,20;-90,1020) [c3 #1,0 -> r90 10,20]
|
||||
(-1189,21;-89,1021) [c3 #0,1 -> r90 11,21]
|
||||
(-1179,41;-79,1041) [c3 #1,1 -> r90 21,41]
|
||||
(-1178,42;-78,1042) [c3 #0,2 -> r90 22,42]
|
||||
(-1168,62;-68,1062) [c3 #1,2 -> r90 32,62]
|
||||
END
|
||||
|
||||
end
|
||||
|
||||
def collect_hier(l)
|
||||
|
||||
s = ""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
# encoding: UTF-8
|
||||
|
||||
# KLayout Layout Viewer
|
||||
# Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
if !$:.member?(File::dirname($0))
|
||||
$:.push(File::dirname($0))
|
||||
end
|
||||
|
||||
load("test_prologue.rb")
|
||||
|
||||
class DBLayout_TestClass < TestBase
|
||||
|
||||
def collect(s, l)
|
||||
|
||||
res = []
|
||||
while !s.at_end?
|
||||
r = "[#{s.inst_cell.name}]"
|
||||
r += (s.trans * s.inst_trans).to_s
|
||||
res.push(r)
|
||||
s.next
|
||||
end
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
||||
def dcollect(s, l)
|
||||
|
||||
res = []
|
||||
while !s.at_end?
|
||||
r = "[#{s.inst_cell.name}]"
|
||||
r += (s.dtrans * s.inst_dtrans).to_s
|
||||
res.push(r)
|
||||
s.next
|
||||
end
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
||||
def test_1
|
||||
|
||||
# Recursive instance iterator tests
|
||||
|
||||
l = RBA::Layout.new
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
l.insert_layer_at(1, RBA::LayerInfo.new(2, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
c2 = l.cell(l.add_cell("c2"))
|
||||
c3 = l.cell(l.add_cell("c3"))
|
||||
|
||||
b = RBA::Box.new(0, 100, 1000, 1200)
|
||||
c0.shapes(0).insert(b)
|
||||
c1.shapes(0).insert(b)
|
||||
c2.shapes(0).insert(b)
|
||||
c3.shapes(0).insert(b)
|
||||
|
||||
bb = RBA::Box.new(1, 101, 1001, 1201)
|
||||
c3.shapes(1).insert(bb)
|
||||
|
||||
tt = RBA::Trans.new
|
||||
c0.insert(RBA::CellInstArray.new(c1.cell_index, tt))
|
||||
c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100))))
|
||||
c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1)))
|
||||
c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0))))
|
||||
|
||||
i1 = c0.begin_instances_rec_touching(RBA::Box.new(0, 0, 100, 100))
|
||||
i1copy = i1.dup
|
||||
assert_equal(i1copy.overlapping?, false)
|
||||
assert_equal(collect(i1, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100")
|
||||
i1.reset
|
||||
assert_equal(dcollect(i1, l), "[c1]r0 *1 0,0/[c2]r0 *1 0.1,-0.1")
|
||||
assert_equal(collect(i1copy, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100")
|
||||
|
||||
i1 = c0.begin_instances_rec_touching(RBA::DBox.new(0, 0, 0.100, 0.100))
|
||||
assert_equal(collect(i1, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100")
|
||||
|
||||
i1o = c0.begin_instances_rec_overlapping(RBA::Box.new(0, 0, 100, 100));
|
||||
assert_equal(collect(i1o, l), "");
|
||||
i1o = c0.begin_instances_rec_overlapping(RBA::DBox.new(0, 0, 0.100, 0.100));
|
||||
assert_equal(collect(i1o, l), "");
|
||||
i1copy.overlapping = true
|
||||
assert_equal(i1copy.overlapping?, true)
|
||||
assert_equal(collect(i1copy, l), "");
|
||||
i1o = c0.begin_instances_rec_overlapping(RBA::Box.new(0, 0, 100, 101));
|
||||
assert_equal(collect(i1o, l), "[c1]r0 *1 0,0");
|
||||
i1o = c0.begin_instances_rec_overlapping(RBA::DBox.new(0, 0, 0.100, 0.101));
|
||||
assert_equal(collect(i1o, l), "[c1]r0 *1 0,0");
|
||||
i1copy.region = RBA::Box.new(0, 0, 100, 101)
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c1]r0 *1 0,0");
|
||||
i1copy.region = RBA::Region::new(RBA::Box.new(0, 0, 100, 101))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c1]r0 *1 0,0");
|
||||
i1copy.region = RBA::Box.new(-1000, -1000, 1100, 1101)
|
||||
i1copy.confine_region(RBA::Box.new(0, 0, 100, 101))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c1]r0 *1 0,0");
|
||||
i1copy.region = RBA::Box.new(-1000, -1000, 1100, 1101)
|
||||
i1copy.confine_region(RBA::Region::new(RBA::Box.new(0, 0, 100, 101)))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c1]r0 *1 0,0");
|
||||
i1o = c0.begin_instances_rec_overlapping(RBA::Box.new(0, 0, 101, 101));
|
||||
assert_equal(collect(i1o, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100");
|
||||
i1o = c0.begin_instances_rec_overlapping(RBA::Box.new(0, 0, 101, 101));
|
||||
assert_equal(collect(i1o, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100");
|
||||
|
||||
i2 = c0.begin_instances_rec_touching(RBA::Box.new(-100, 0, 100, 100));
|
||||
assert_equal(collect(i2, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100/[c3]r90 *1 0,0");
|
||||
i2o = c0.begin_instances_rec_overlapping(RBA::Box.new(-100, 0, 100, 100));
|
||||
assert_equal(collect(i2o, l), "");
|
||||
i2o = c0.begin_instances_rec_overlapping(RBA::Box.new(-101, 0, 101, 101));
|
||||
assert_equal(collect(i2o, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100/[c3]r90 *1 0,0");
|
||||
|
||||
i4 = c0.begin_instances_rec_touching(RBA::Box.new(-100, 0, 2000, 100));
|
||||
i4_copy = c0.begin_instances_rec_touching(RBA::Box.new(-100, 0, 2000, 100));
|
||||
i4.max_depth = 0;
|
||||
assert_equal(collect(i4, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100/[c3]r90 *1 0,0");
|
||||
|
||||
assert_equal(i4 == i4, true);
|
||||
assert_equal(i4 != i4, false);
|
||||
assert_equal(i4 == i4_copy, false);
|
||||
assert_equal(i4 != i4_copy, true);
|
||||
i4 = i4_copy.dup
|
||||
assert_equal(i4 == i4_copy, true);
|
||||
assert_equal(i4 != i4_copy, false);
|
||||
i4.max_depth = 1;
|
||||
assert_equal(i4.max_depth, 1)
|
||||
assert_equal(collect(i4, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100/[c3]r90 *1 0,0");
|
||||
i4.min_depth = 1;
|
||||
assert_equal(i4.min_depth, 1)
|
||||
assert_equal(collect(i4, l), "[c3]r0 *1 1200,-100");
|
||||
|
||||
i4.assign(i4_copy);
|
||||
assert_equal(collect(i4, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100/[c3]r90 *1 0,0");
|
||||
|
||||
i5 = c0.begin_instances_rec
|
||||
assert_equal(collect(i5, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100/[c3]r90 *1 0,0");
|
||||
|
||||
ii = RBA::RecursiveInstanceIterator::new
|
||||
assert_equal(collect(ii, l), "")
|
||||
|
||||
ii = RBA::RecursiveInstanceIterator::new(l, c2)
|
||||
assert_equal(collect(ii, l), "[c3]r0 *1 1100,0")
|
||||
assert_equal(ii.top_cell.name, "c2")
|
||||
assert_equal(ii.layout == l, true)
|
||||
|
||||
ii = RBA::RecursiveInstanceIterator::new(l, c0, RBA::Box.new(-100, 0, 2000, 100), false)
|
||||
assert_equal(collect(ii, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100/[c3]r90 *1 0,0")
|
||||
|
||||
ii = RBA::RecursiveInstanceIterator::new(l, c0, RBA::Box.new(-100, 0, 2000, 100), true)
|
||||
assert_equal(collect(ii, l), "[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100")
|
||||
|
||||
ii = RBA::RecursiveInstanceIterator::new(l, c0, RBA::Box.new(-100, 0, 2000, 101), true)
|
||||
assert_equal(collect(ii, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100")
|
||||
|
||||
ii = RBA::RecursiveInstanceIterator::new(l, c0, RBA::Region::new(RBA::Box.new(-100, 0, 2000, 101)), true)
|
||||
assert_equal(collect(ii, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100")
|
||||
|
||||
ii = RBA::RecursiveInstanceIterator::new(l, c0)
|
||||
assert_equal(collect(ii, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100/[c3]r90 *1 0,0")
|
||||
|
||||
ii.reset
|
||||
ii.unselect_cells("c0")
|
||||
ii.select_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c3]r0 *1 1200,-100")
|
||||
|
||||
ii.reset_selection
|
||||
ii.unselect_cells("c*")
|
||||
ii.select_cells([ c2.cell_index ])
|
||||
assert_equal(collect(ii, l), "[c3]r0 *1 1200,-100")
|
||||
|
||||
ii.reset_selection
|
||||
ii.unselect_all_cells
|
||||
ii.select_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c3]r0 *1 1200,-100")
|
||||
|
||||
ii.reset_selection
|
||||
ii.select_all_cells
|
||||
ii.unselect_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100/[c3]r90 *1 0,0")
|
||||
|
||||
ii.reset_selection
|
||||
ii.select_cells("c*")
|
||||
ii.unselect_cells([ c1.cell_index, c2.cell_index ])
|
||||
assert_equal(collect(ii, l), "[c1]r0 *1 0,0/[c2]r0 *1 100,-100/[c3]r90 *1 0,0")
|
||||
|
||||
ii = RBA::RecursiveInstanceIterator::new(l, c0)
|
||||
assert_equal(ii.all_targets_enabled?, true)
|
||||
ii.targets = "c3"
|
||||
assert_equal(ii.all_targets_enabled?, false)
|
||||
assert_equal(collect(ii, l), "[c3]r0 *1 1200,-100/[c3]r90 *1 0,0")
|
||||
ii.enable_all_targets
|
||||
assert_equal(ii.all_targets_enabled?, true)
|
||||
assert_equal(collect(ii, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c2]r0 *1 100,-100/[c3]r90 *1 0,0")
|
||||
ii.targets = [ c3.cell_index, c1.cell_index ]
|
||||
assert_equal(ii.all_targets_enabled?, false)
|
||||
assert_equal(collect(ii, l), "[c1]r0 *1 0,0/[c3]r0 *1 1200,-100/[c3]r90 *1 0,0")
|
||||
|
||||
end
|
||||
|
||||
def test_2
|
||||
|
||||
# Recursive instance iterator tests
|
||||
|
||||
l = RBA::Layout.new
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
l.insert_layer_at(1, RBA::LayerInfo.new(2, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
c2 = l.cell(l.add_cell("c2"))
|
||||
c3 = l.cell(l.add_cell("c3"))
|
||||
|
||||
b = RBA::Box.new(0, 100, 1000, 1200)
|
||||
c3.shapes(0).insert(b)
|
||||
|
||||
bb = RBA::Box.new(1, 101, 1001, 1201)
|
||||
c3.shapes(1).insert(bb)
|
||||
|
||||
tt = RBA::Trans.new
|
||||
c0.insert(RBA::CellInstArray.new(c1.cell_index, tt))
|
||||
c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100))))
|
||||
c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1), RBA::Vector::new(10, 20), RBA::Vector::new(11, 21), 2, 3))
|
||||
c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0))))
|
||||
|
||||
res = []
|
||||
i = c0.begin_instances_rec
|
||||
while !i.at_end?
|
||||
res << i.inst_cell.bbox.transformed(i.trans * i.inst_trans).to_s + " " + (i.path + [ i.current_inst_element ]).collect { |e| "[" + l.cell(e.cell_inst.cell_index).name + " #" + e.ia.to_s + "," + e.ib.to_s + " -> " + e.specific_trans.to_s + "]" }.join("")
|
||||
i.next
|
||||
end
|
||||
|
||||
assert_equal(res.join("\n") + "\n", <<"END")
|
||||
() [c1 #-1,-1 -> r0 0,0]
|
||||
(1200,0;2201,1101) [c2 #-1,-1 -> r0 100,-100][c3 #-1,-1 -> r0 1100,0]
|
||||
(1200,0;2201,1101) [c2 #-1,-1 -> r0 100,-100]
|
||||
(-1201,0;-100,1001) [c3 #0,0 -> r90 0,0]
|
||||
(-1191,20;-90,1021) [c3 #1,0 -> r90 10,20]
|
||||
(-1190,21;-89,1022) [c3 #0,1 -> r90 11,21]
|
||||
(-1180,41;-79,1042) [c3 #1,1 -> r90 21,41]
|
||||
(-1179,42;-78,1043) [c3 #0,2 -> r90 22,42]
|
||||
(-1169,62;-68,1063) [c3 #1,2 -> r90 32,62]
|
||||
END
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
# encoding: UTF-8
|
||||
|
||||
# KLayout Layout Viewer
|
||||
# Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
if !$:.member?(File::dirname($0))
|
||||
$:.push(File::dirname($0))
|
||||
end
|
||||
|
||||
load("test_prologue.rb")
|
||||
|
||||
class DBRecursiveShapeIterator_TestClass < TestBase
|
||||
|
||||
def collect(s, l)
|
||||
|
||||
res = []
|
||||
while !s.at_end?
|
||||
r = "[#{l.cell_name(s.cell_index)}]"
|
||||
if s.shape.is_box?
|
||||
box = s.shape.box
|
||||
r += box.transformed(s.trans).to_s
|
||||
else
|
||||
r += "X";
|
||||
end
|
||||
s.next
|
||||
res.push(r)
|
||||
end
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
||||
def dcollect(s, l)
|
||||
|
||||
res = []
|
||||
while !s.at_end?
|
||||
r = "[#{l.cell_name(s.cell_index)}]"
|
||||
if s.shape.is_box?
|
||||
box = s.shape.dbox
|
||||
r += box.transformed(s.dtrans).to_s
|
||||
else
|
||||
r += "X";
|
||||
end
|
||||
s.next
|
||||
res.push(r)
|
||||
end
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
||||
def test_1
|
||||
|
||||
# Recursive shape iterator tests
|
||||
|
||||
l = RBA::Layout.new
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
l.insert_layer_at(1, RBA::LayerInfo.new(2, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
c2 = l.cell(l.add_cell("c2"))
|
||||
c3 = l.cell(l.add_cell("c3"))
|
||||
|
||||
b = RBA::Box.new(0, 100, 1000, 1200)
|
||||
c0.shapes(0).insert(b)
|
||||
c1.shapes(0).insert(b)
|
||||
c2.shapes(0).insert(b)
|
||||
c3.shapes(0).insert(b)
|
||||
|
||||
bb = RBA::Box.new(1, 101, 1001, 1201)
|
||||
c3.shapes(1).insert(bb)
|
||||
|
||||
tt = RBA::Trans.new
|
||||
c0.insert(RBA::CellInstArray.new(c1.cell_index, tt))
|
||||
c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100))))
|
||||
c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1)))
|
||||
c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0))))
|
||||
|
||||
i1 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 100))
|
||||
i1copy = i1.dup
|
||||
assert_equal(i1copy.overlapping?, false)
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
i1.reset
|
||||
assert_equal(dcollect(i1, l), "[c0](0,0.1;1,1.2)/[c1](0,0.1;1,1.2)/[c2](0.1,0;1.1,1.1)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1 = l.begin_shapes_touching(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.100))
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1 = c0.begin_shapes_rec_touching(0, RBA::Box.new(0, 0, 100, 100))
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1 = c0.begin_shapes_rec_touching(0, RBA::DBox.new(0, 0, 0.100, 0.100))
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 100));
|
||||
assert_equal(collect(i1o, l), "");
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.100));
|
||||
assert_equal(collect(i1o, l), "");
|
||||
i1copy.overlapping = true
|
||||
assert_equal(i1copy.overlapping?, true)
|
||||
assert_equal(collect(i1copy, l), "");
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 101));
|
||||
assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.101));
|
||||
assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1copy.region = RBA::Box.new(0, 0, 100, 101)
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1copy.region = RBA::Region::new(RBA::Box.new(0, 0, 100, 101))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1copy.region = RBA::Box.new(-1000, -1000, 1100, 1101)
|
||||
i1copy.confine_region(RBA::Box.new(0, 0, 100, 101))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1copy.region = RBA::Box.new(-1000, -1000, 1100, 1101)
|
||||
i1copy.confine_region(RBA::Region::new(RBA::Box.new(0, 0, 100, 101)))
|
||||
assert_equal(i1copy.region.to_s, "(0,0;100,101)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)");
|
||||
i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 101, 101));
|
||||
assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)");
|
||||
i1o = c0.begin_shapes_rec_overlapping(0, RBA::Box.new(0, 0, 101, 101));
|
||||
assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)");
|
||||
|
||||
i2 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 100, 100));
|
||||
assert_equal(collect(i2, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)");
|
||||
i2o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(-100, 0, 100, 100));
|
||||
assert_equal(collect(i2o, l), "");
|
||||
i2o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(-101, 0, 101, 101));
|
||||
assert_equal(collect(i2o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)");
|
||||
|
||||
i4 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 2000, 100));
|
||||
i4_copy = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 2000, 100));
|
||||
i4.max_depth = 0;
|
||||
assert_equal(collect(i4, l), "[c0](0,100;1000,1200)");
|
||||
|
||||
assert_equal(i4 == i4, true);
|
||||
assert_equal(i4 != i4, false);
|
||||
assert_equal(i4 == i4_copy, false);
|
||||
assert_equal(i4 != i4_copy, true);
|
||||
i4 = i4_copy.dup;
|
||||
assert_equal(i4 == i4_copy, true);
|
||||
assert_equal(i4 != i4_copy, false);
|
||||
i4.max_depth = 1;
|
||||
assert_equal(collect(i4, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)");
|
||||
|
||||
i4.assign(i4_copy);
|
||||
assert_equal(collect(i4, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)");
|
||||
|
||||
i5 = l.begin_shapes(c0.cell_index, 0);
|
||||
assert_equal(collect(i5, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)");
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new
|
||||
assert_equal(collect(ii, l), "")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c1, 0)
|
||||
assert_equal(collect(ii, l), "[c1](0,100;1000,1200)")
|
||||
assert_equal(ii.top_cell.name, "c1")
|
||||
assert_equal(ii.layout == l, true)
|
||||
|
||||
ii.max_depth = 2
|
||||
assert_equal(ii.max_depth, 2)
|
||||
ii.min_depth = 1
|
||||
assert_equal(ii.min_depth, 1)
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1])
|
||||
ic = ii.dup
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)")
|
||||
assert_equal(collect(ic, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 100), false)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 100), true)
|
||||
assert_equal(collect(ii, l), "")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 101), true)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 100), false)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 101), false)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 101), true)
|
||||
assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)")
|
||||
|
||||
ii = RBA::RecursiveShapeIterator::new(l, c0, 0)
|
||||
assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
|
||||
ii.reset
|
||||
ii.unselect_cells("c0")
|
||||
ii.select_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)")
|
||||
|
||||
ii.reset_selection
|
||||
ii.unselect_cells("c*")
|
||||
ii.select_cells([ c2.cell_index ])
|
||||
assert_equal(collect(ii, l), "[c2](100,0;1100,1100)")
|
||||
|
||||
ii.reset_selection
|
||||
ii.unselect_all_cells
|
||||
ii.select_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c2](100,0;1100,1100)")
|
||||
|
||||
ii.reset_selection
|
||||
ii.select_all_cells
|
||||
ii.unselect_cells("c2")
|
||||
assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
|
||||
ii.reset_selection
|
||||
ii.select_cells("c*")
|
||||
ii.unselect_cells([ c1.cell_index, c2.cell_index ])
|
||||
assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
|
||||
end
|
||||
|
||||
def test_2
|
||||
|
||||
# Recursive shape iterator tests
|
||||
|
||||
l = RBA::Layout.new
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
l.insert_layer_at(1, RBA::LayerInfo.new(2, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
c2 = l.cell(l.add_cell("c2"))
|
||||
c3 = l.cell(l.add_cell("c3"))
|
||||
|
||||
b = RBA::Box.new(0, 100, 1000, 1200)
|
||||
c3.shapes(0).insert(b)
|
||||
|
||||
bb = RBA::Box.new(1, 101, 1001, 1201)
|
||||
c3.shapes(1).insert(bb)
|
||||
|
||||
tt = RBA::Trans.new
|
||||
c0.insert(RBA::CellInstArray.new(c1.cell_index, tt))
|
||||
c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100))))
|
||||
c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1), RBA::Vector::new(10, 20), RBA::Vector::new(11, 21), 2, 3))
|
||||
c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0))))
|
||||
|
||||
res = []
|
||||
i = l.begin_shapes(c0.cell_index, 0)
|
||||
while !i.at_end?
|
||||
res << i.shape.box.transformed(i.trans).to_s + " " + i.path.collect { |e| "[" + l.cell(e.cell_inst.cell_index).name + " #" + e.ia.to_s + "," + e.ib.to_s + " -> " + e.specific_trans.to_s + "]" }.join("")
|
||||
i.next
|
||||
end
|
||||
|
||||
assert_equal(res.join("\n") + "\n", <<"END")
|
||||
(1200,0;2200,1100) [c2 #-1,-1 -> r0 100,-100][c3 #-1,-1 -> r0 1100,0]
|
||||
(-1200,0;-100,1000) [c3 #0,0 -> r90 0,0]
|
||||
(-1190,20;-90,1020) [c3 #1,0 -> r90 10,20]
|
||||
(-1189,21;-89,1021) [c3 #0,1 -> r90 11,21]
|
||||
(-1179,41;-79,1041) [c3 #1,1 -> r90 21,41]
|
||||
(-1178,42;-78,1042) [c3 #0,2 -> r90 22,42]
|
||||
(-1168,62;-68,1062) [c3 #1,2 -> r90 32,62]
|
||||
END
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
Loading…
Reference in New Issue