Mitigating the effect of a locked layout: plain iteration of instances now is possible also with a locked layout. Before, the instances were correctly iterated only if the layout could be sorted.

This commit is contained in:
Matthias Koefferlein 2024-10-27 23:42:16 +01:00
parent 946729f14d
commit cdd7058866
3 changed files with 207 additions and 23 deletions

View File

@ -280,12 +280,18 @@ void
instance_iterator<Traits>::release_iter ()
{
if (m_type == TInstance) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()).~stable_iter_wp_type ();
} else {
basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()).~stable_iter_type ();
}
} else if (m_stable) {
if (m_with_props) {
basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()).~stable_unsorted_iter_wp_type ();
} else {
basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()).~stable_unsorted_iter_type ();
}
} else {
if (m_with_props) {
basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()).~iter_wp_type ();
@ -301,12 +307,18 @@ void
instance_iterator<Traits>::make_iter ()
{
if (m_type == TInstance) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
new (&basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())) stable_iter_wp_type ();
} else {
new (&basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())) stable_iter_type ();
}
} else if (m_stable) {
if (m_with_props) {
new (&basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())) stable_unsorted_iter_wp_type ();
} else {
new (&basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())) stable_unsorted_iter_type ();
}
} else {
if (m_with_props) {
new (&basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())) iter_wp_type ();
@ -322,18 +334,24 @@ template <class Traits>
bool
instance_iterator<Traits>::operator== (const instance_iterator<Traits> &d) const
{
if (! (m_type == d.m_type && m_stable == d.m_stable && m_with_props == d.m_with_props)) {
if (! (m_type == d.m_type && m_stable == d.m_stable && m_with_props == d.m_with_props && m_unsorted == d.m_unsorted)) {
return false;
}
if (m_type == TNull) {
return true;
} else {
if (m_stable) {
if (m_with_props) {
if (m_with_props && ! m_unsorted) {
return (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()) == d.basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
return (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()) == d.basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else if (m_stable) {
if (m_with_props) {
return (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()) == d.basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
return (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()) == d.basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else {
if (m_with_props) {
return (basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()) == d.basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()));
@ -355,16 +373,23 @@ instance_iterator<Traits>::operator= (const instance_iterator<Traits> &iter)
m_type = iter.m_type;
m_stable = iter.m_stable;
m_with_props = iter.m_with_props;
m_unsorted = iter.m_unsorted;
m_traits = iter.m_traits;
if (m_type == TInstance) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
new (&basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())) stable_iter_wp_type (iter.basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
new (&basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())) stable_iter_type (iter.basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else if (m_stable) {
if (m_with_props) {
new (&basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())) stable_unsorted_iter_wp_type (iter.basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
new (&basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())) stable_unsorted_iter_type (iter.basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else {
if (m_with_props) {
new (&basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())) iter_wp_type (iter.basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()));
@ -387,12 +412,18 @@ db::Box
instance_iterator<Traits>::quad_box () const
{
if (m_type == TInstance) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
return m_traits.quad_box (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
return m_traits.quad_box (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else if (m_stable) {
if (m_with_props) {
return m_traits.quad_box (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
return m_traits.quad_box (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else {
if (m_with_props) {
return m_traits.quad_box (basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()));
@ -409,12 +440,18 @@ size_t
instance_iterator<Traits>::quad_id () const
{
if (m_type == TInstance) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
return m_traits.quad_id (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
return m_traits.quad_id (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else if (m_stable) {
if (m_with_props) {
return m_traits.quad_id (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
return m_traits.quad_id (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else {
if (m_with_props) {
return m_traits.quad_id (basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()));
@ -431,12 +468,18 @@ void
instance_iterator<Traits>::skip_quad ()
{
if (m_type == TInstance) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
m_traits.skip_quad (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
m_traits.skip_quad (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else if (m_stable) {
if (m_with_props) {
m_traits.skip_quad (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
m_traits.skip_quad (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else {
if (m_with_props) {
m_traits.skip_quad (basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()));
@ -454,12 +497,18 @@ instance_iterator<Traits> &
instance_iterator<Traits>::operator++()
{
if (m_type == TInstance) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
++basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ());
} else {
++basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ());
}
} else if (m_stable) {
if (m_with_props) {
++basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ());
} else {
++basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ());
}
} else {
if (m_with_props) {
++basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ());
@ -478,7 +527,7 @@ void
instance_iterator<Traits>::make_next ()
{
while (true) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
if (! basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()).at_end ()) {
return;
@ -488,6 +537,16 @@ instance_iterator<Traits>::make_next ()
return;
}
}
} else if (m_stable) {
if (m_with_props) {
if (! basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()).at_end ()) {
return;
}
} else {
if (! basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()).at_end ()) {
return;
}
}
} else {
if (m_with_props) {
if (! basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()).at_end ()) {
@ -514,12 +573,18 @@ void
instance_iterator<Traits>::update_ref ()
{
if (m_type == TInstance) {
if (m_stable) {
if (m_stable && ! m_unsorted) {
if (m_with_props) {
m_ref = m_traits.instance_from_stable_iter (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
m_ref = m_traits.instance_from_stable_iter (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else if (m_stable) {
if (m_with_props) {
m_ref = m_traits.instance_from_stable_iter (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()));
} else {
m_ref = m_traits.instance_from_stable_iter (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()));
}
} else {
if (m_with_props) {
m_ref = value_type (m_traits.instances (), *basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()));
@ -551,7 +616,7 @@ void
NormalInstanceIteratorTraits::init (instance_iterator<NormalInstanceIteratorTraits> *iter) const
{
tl_assert (mp_insts != 0);
if (iter->m_stable) {
if (iter->m_stable && ! iter->m_unsorted) {
if (iter->m_with_props) {
cell_inst_wp_array_type::tag tag = cell_inst_wp_array_type::tag ();
iter->basic_iter (tag, InstancesEditableTag ()) = mp_insts->inst_tree (tag, InstancesEditableTag ()).begin_flat ();
@ -559,6 +624,14 @@ NormalInstanceIteratorTraits::init (instance_iterator<NormalInstanceIteratorTrai
cell_inst_array_type::tag tag = cell_inst_array_type::tag ();
iter->basic_iter (tag, InstancesEditableTag ()) = mp_insts->inst_tree (tag, InstancesEditableTag ()).begin_flat ();
}
} else if (iter->m_stable) {
if (iter->m_with_props) {
cell_inst_wp_array_type::tag tag = cell_inst_wp_array_type::tag ();
iter->basic_unsorted_iter (tag, InstancesEditableTag ()) = stable_unsorted_iter_wp_type (mp_insts->inst_tree (tag, InstancesEditableTag ()).begin (), mp_insts->inst_tree (tag, InstancesEditableTag ()).end ());
} else {
cell_inst_array_type::tag tag = cell_inst_array_type::tag ();
iter->basic_unsorted_iter (tag, InstancesEditableTag ()) = stable_unsorted_iter_type (mp_insts->inst_tree (tag, InstancesEditableTag ()).begin (), mp_insts->inst_tree (tag, InstancesEditableTag ()).end ());
}
} else {
if (iter->m_with_props) {
cell_inst_wp_array_type::tag tag = cell_inst_wp_array_type::tag ();

View File

@ -527,7 +527,9 @@ public:
typedef typename IterTraits::iter_wp_type iter_wp_type;
typedef typename IterTraits::stable_iter_type stable_iter_type;
typedef typename IterTraits::stable_iter_wp_type stable_iter_wp_type;
typedef const value_type *pointer;
typedef typename IterTraits::stable_unsorted_iter_type stable_unsorted_iter_type;
typedef typename IterTraits::stable_unsorted_iter_wp_type stable_unsorted_iter_wp_type;
typedef const value_type *pointer;
typedef value_type reference; // operator* returns a value
typedef std::forward_iterator_tag iterator_category;
typedef void difference_type;
@ -541,7 +543,7 @@ public:
* @brief Default ctor
*/
instance_iterator ()
: m_with_props (false), m_stable (false), m_type (TNull), m_traits ()
: m_type (TNull), m_with_props (false), m_stable (false), m_unsorted (false), m_traits ()
{ }
/**
@ -556,7 +558,7 @@ public:
* @brief Constructor
*/
instance_iterator (const IterTraits &traits)
: m_with_props (false), m_stable (traits.instances ()->is_editable ()), m_type (TInstance), m_traits (traits)
: m_type (TInstance), m_with_props (false), m_stable (traits.instances ()->is_editable ()), m_unsorted (traits.instances ()->instance_tree_needs_sort ()), m_traits (traits)
{
make_iter ();
make_next ();
@ -567,7 +569,7 @@ public:
* @brief Copy constructor
*/
instance_iterator (const instance_iterator &iter)
: m_with_props (false), m_stable (false), m_type (TNull), m_traits ()
: m_type (TNull), m_with_props (false), m_stable (false), m_unsorted (false), m_traits ()
{
operator= (iter);
}
@ -661,7 +663,7 @@ public:
*/
stable_iter_type &basic_iter (cell_inst_array_type::tag, InstancesEditableTag)
{
tl_assert (m_type == TInstance && m_stable == true && m_with_props == false);
tl_assert (m_type == TInstance && m_stable == true && m_with_props == false && m_unsorted == false);
return *((stable_iter_type *) m_generic.stable_iter);
}
@ -670,10 +672,28 @@ public:
*/
const stable_iter_type &basic_iter (cell_inst_array_type::tag, InstancesEditableTag) const
{
tl_assert (m_type == TInstance && m_stable == true && m_with_props == false);
tl_assert (m_type == TInstance && m_stable == true && m_with_props == false && m_unsorted == false);
return *((stable_iter_type *) m_generic.stable_iter);
}
/**
* @brief Gets the basic iterator in the editable case without properties and in the unsorted case
*/
stable_unsorted_iter_type &basic_unsorted_iter (cell_inst_array_type::tag, InstancesEditableTag)
{
tl_assert (m_type == TInstance && m_stable == true && m_with_props == false && m_unsorted == true);
return *((stable_unsorted_iter_type *) m_generic.stable_unsorted_iter);
}
/**
* @brief Gets the basic iterator in the editable case without properties and in the unsorted case (const version)
*/
const stable_unsorted_iter_type &basic_unsorted_iter (cell_inst_array_type::tag, InstancesEditableTag) const
{
tl_assert (m_type == TInstance && m_stable == true && m_with_props == false && m_unsorted == true);
return *((stable_unsorted_iter_type *) m_generic.stable_unsorted_iter);
}
/**
* @brief Gets the basic iterator in the non-editable case with properties
*/
@ -697,7 +717,7 @@ public:
*/
stable_iter_wp_type &basic_iter (cell_inst_wp_array_type::tag, InstancesEditableTag)
{
tl_assert (m_type == TInstance && m_stable == true && m_with_props == true);
tl_assert (m_type == TInstance && m_stable == true && m_with_props == true && m_unsorted == false);
return *((stable_iter_wp_type *) m_generic.pstable_iter);
}
@ -706,10 +726,28 @@ public:
*/
const stable_iter_wp_type &basic_iter (cell_inst_wp_array_type::tag, InstancesEditableTag) const
{
tl_assert (m_type == TInstance && m_stable == true && m_with_props == true);
tl_assert (m_type == TInstance && m_stable == true && m_with_props == true && m_unsorted == false);
return *((stable_iter_wp_type *) m_generic.pstable_iter);
}
/**
* @brief Gets the basic iterator in the editable case with properties and in the unsorted case
*/
stable_unsorted_iter_wp_type &basic_unsorted_iter (cell_inst_wp_array_type::tag, InstancesEditableTag)
{
tl_assert (m_type == TInstance && m_stable == true && m_with_props == true && m_unsorted == true);
return *((stable_unsorted_iter_wp_type *) m_generic.pstable_unsorted_iter);
}
/**
* @brief Gets the basic iterator in the editable case with properties and in the unsorted case (const version)
*/
const stable_unsorted_iter_wp_type &basic_unsorted_iter (cell_inst_wp_array_type::tag, InstancesEditableTag) const
{
tl_assert (m_type == TInstance && m_stable == true && m_with_props == true && m_unsorted == true);
return *((stable_unsorted_iter_wp_type *) m_generic.pstable_unsorted_iter);
}
private:
friend struct NormalInstanceIteratorTraits;
friend struct OverlappingInstanceIteratorTraits;
@ -720,11 +758,14 @@ private:
char piter[sizeof (iter_wp_type)];
char stable_iter[sizeof (stable_iter_type)];
char pstable_iter[sizeof (stable_iter_wp_type)];
char stable_unsorted_iter[sizeof (stable_unsorted_iter_type)];
char pstable_unsorted_iter[sizeof (stable_unsorted_iter_wp_type)];
} m_generic;
bool m_with_props : 8;
bool m_stable : 8;
object_type m_type : 16;
bool m_with_props : 1;
bool m_stable : 1;
bool m_unsorted : 1;
value_type m_ref;
IterTraits m_traits;
@ -759,6 +800,8 @@ struct DB_PUBLIC NormalInstanceIteratorTraits
typedef tl::iterator_pair<cell_inst_wp_tree_type::const_iterator> iter_wp_type;
typedef stable_cell_inst_tree_type::flat_iterator stable_iter_type;
typedef stable_cell_inst_wp_tree_type::flat_iterator stable_iter_wp_type;
typedef tl::iterator_pair<stable_cell_inst_tree_type::const_iterator> stable_unsorted_iter_type;
typedef tl::iterator_pair<stable_cell_inst_wp_tree_type::const_iterator> stable_unsorted_iter_wp_type;
NormalInstanceIteratorTraits ();
NormalInstanceIteratorTraits (const instances_type *insts);
@ -804,6 +847,8 @@ struct DB_PUBLIC TouchingInstanceIteratorTraits
typedef cell_inst_wp_tree_type::touching_iterator iter_wp_type;
typedef stable_cell_inst_tree_type::touching_iterator stable_iter_type;
typedef stable_cell_inst_wp_tree_type::touching_iterator stable_iter_wp_type;
typedef stable_iter_type stable_unsorted_iter_type;
typedef stable_iter_wp_type stable_unsorted_iter_wp_type;
TouchingInstanceIteratorTraits ();
TouchingInstanceIteratorTraits (const instances_type *insts, const box_type &box, const layout_type *layout);
@ -855,6 +900,8 @@ struct DB_PUBLIC OverlappingInstanceIteratorTraits
typedef cell_inst_wp_tree_type::overlapping_iterator iter_wp_type;
typedef stable_cell_inst_tree_type::overlapping_iterator stable_iter_type;
typedef stable_cell_inst_wp_tree_type::overlapping_iterator stable_iter_wp_type;
typedef stable_iter_type stable_unsorted_iter_type;
typedef stable_iter_wp_type stable_unsorted_iter_wp_type;
OverlappingInstanceIteratorTraits ();
OverlappingInstanceIteratorTraits (const instances_type *insts, const box_type &box, const layout_type *layout);
@ -1741,6 +1788,7 @@ private:
friend struct NormalInstanceIteratorTraits;
friend struct TouchingInstanceIteratorTraits;
friend struct OverlappingInstanceIteratorTraits;
template <class Traits> friend class instance_iterator;
template <class Inst, class ET> friend class InstOp;
union {
@ -1773,7 +1821,7 @@ private:
}
/**
* @brief Sets a flag indicating that the instance tree needs sorting
* @brief Gets a flag indicating that the instance tree needs sorting
*/
bool instance_tree_needs_sort () const
{

View File

@ -28,6 +28,7 @@
#include "dbTextWriter.h"
#include "dbCellMapping.h"
#include "dbInstElement.h"
#include "dbWriter.h"
#include "tlString.h"
#include "tlUnitTest.h"
@ -872,6 +873,68 @@ TEST(11_FindPath)
EXPECT_EQ (d, "cell_index=1 r90 *1 0,0;cell_index=2 r0 *1 100,200");
}
// Shapes can be flat-iterated even in locked layout
TEST(12_ShapesInLockedLayout)
{
db::Layout l;
db::Cell &top = l.cell (l.add_cell ("TOP"));
unsigned int l1 = l.insert_layer (db::LayerProperties (1, 0));
{
db::LayoutLocker locker (&l);
EXPECT_EQ (l.under_construction (), true);
top.shapes (l1).insert (db::Box (1, 2, 3, 4));
top.shapes (l1).insert (db::Box (10, 20, 30, 40));
top.shapes (l1).insert (db::Box (100, 200, 300, 400));
double a = 0;
for (auto s = top.shapes (l1).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
a += s->area ();
}
EXPECT_EQ (a, 40404.0);
}
EXPECT_EQ (l.under_construction (), false);
double a = 0;
for (auto s = top.shapes (l1).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
a += s->area ();
}
EXPECT_EQ (a, 40404.0);
}
// Instances can be flat-iterated even in locked layout
TEST(13_InstancesInLockedLayout)
{
db::Layout l;
db::Cell &top = l.cell (l.add_cell ("TOP"));
db::Cell &c = l.cell (l.add_cell ("C"));
{
db::LayoutLocker locker (&l);
EXPECT_EQ (l.under_construction (), true);
top.insert (db::CellInstArray (c.cell_index (), db::Trans (db::Vector (10, 20))));
top.insert (db::CellInstArray (c.cell_index (), db::Trans (db::Vector (100, 200))));
top.insert (db::CellInstArray (c.cell_index (), db::Trans (db::Vector (1, 2))));
db::Vector a;
for (auto i = top.begin (); ! i.at_end (); ++i) {
a += i->cell_inst ().front ().disp ();
}
EXPECT_EQ (a.to_string (), "111,222");
}
EXPECT_EQ (l.under_construction (), false);
db::Vector a;
for (auto i = top.begin (); ! i.at_end (); ++i) {
a += i->cell_inst ().front ().disp ();
}
EXPECT_EQ (a.to_string (), "111,222");
}
// issue #1860
TEST(100_UndoOfDeleteLayer)
{