mirror of https://github.com/KLayout/klayout.git
Merge pull request #1910 from KLayout/bugfix/issue-1907
Bugfix/issue 1907
This commit is contained in:
commit
926dac96c6
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1749,8 +1749,49 @@ Layout::end_top_cells () const
|
|||
return m_top_down_list.begin () + m_top_cells;
|
||||
}
|
||||
|
||||
void
|
||||
Layout::start_changes ()
|
||||
{
|
||||
tl::MutexLocker locker (&lock ());
|
||||
++m_invalid;
|
||||
}
|
||||
|
||||
void
|
||||
Layout::end_changes ()
|
||||
{
|
||||
tl::MutexLocker locker (&lock ());
|
||||
if (m_invalid > 0) {
|
||||
if (--m_invalid == 0) {
|
||||
force_update_no_lock ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::end_changes_no_update ()
|
||||
{
|
||||
tl::MutexLocker locker (&lock ());
|
||||
if (m_invalid > 0) {
|
||||
--m_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::force_update ()
|
||||
{
|
||||
// NOTE: the assumption is that either one thread is writing or
|
||||
// multiple threads are reading. Hence, we do not need to lock hier_dirty() or bboxes_dirty().
|
||||
// We still do double checking as another thread might do the update as well.
|
||||
if (! hier_dirty () && ! bboxes_dirty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
tl::MutexLocker locker (&lock ());
|
||||
force_update_no_lock ();
|
||||
}
|
||||
|
||||
void
|
||||
Layout::force_update_no_lock () const
|
||||
{
|
||||
if (hier_dirty () || bboxes_dirty ()) {
|
||||
|
||||
|
|
@ -1776,22 +1817,17 @@ Layout::force_update ()
|
|||
void
|
||||
Layout::update () const
|
||||
{
|
||||
if (! under_construction () && (hier_dirty () || bboxes_dirty ())) {
|
||||
// NOTE: the assumption is that either one thread is writing or
|
||||
// multiple threads are reading. Hence, we do not need to lock hier_dirty() or bboxes_dirty().
|
||||
// We still do double checking as another thread might do the update as well.
|
||||
if (under_construction () || (! hier_dirty () && ! bboxes_dirty ())) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
m_invalid = std::numeric_limits<unsigned int>::max (); // prevent recursion
|
||||
|
||||
db::LayoutStateModel *state_model = const_cast<db::LayoutStateModel *> ((const db::LayoutStateModel *) this);
|
||||
state_model->update ();
|
||||
|
||||
m_invalid = 0;
|
||||
|
||||
} catch (...) {
|
||||
m_invalid = 0;
|
||||
throw;
|
||||
}
|
||||
tl::MutexLocker locker (&lock ());
|
||||
|
||||
if (! under_construction ()) {
|
||||
force_update_no_lock ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -624,7 +624,7 @@ public:
|
|||
* @brief Gets the lock for the layout object
|
||||
* This is a generic lock that can be used to lock modifications against multiple threads.
|
||||
*/
|
||||
tl::Mutex &lock ()
|
||||
tl::Mutex &lock () const
|
||||
{
|
||||
return m_lock;
|
||||
}
|
||||
|
|
@ -1791,34 +1791,18 @@ public:
|
|||
* an operation, the start/end_changes method pair does not
|
||||
* need to be called.
|
||||
*/
|
||||
void start_changes ()
|
||||
{
|
||||
++m_invalid;
|
||||
}
|
||||
void start_changes ();
|
||||
|
||||
/**
|
||||
* @brief Cancel the "in changes" state (see "start_changes")
|
||||
*/
|
||||
void end_changes ()
|
||||
{
|
||||
if (m_invalid > 0) {
|
||||
--m_invalid;
|
||||
if (! m_invalid) {
|
||||
update ();
|
||||
}
|
||||
}
|
||||
}
|
||||
void end_changes ();
|
||||
|
||||
/**
|
||||
* @brief Cancel the "in changes" state (see "start_changes")
|
||||
* This version does not force an update
|
||||
*/
|
||||
void end_changes_no_update ()
|
||||
{
|
||||
if (m_invalid > 0) {
|
||||
--m_invalid;
|
||||
}
|
||||
}
|
||||
void end_changes_no_update ();
|
||||
|
||||
/**
|
||||
* @brief Tell if the layout object is under construction
|
||||
|
|
@ -2168,7 +2152,7 @@ private:
|
|||
std::map<db::cell_index_type, meta_info_map> m_meta_info_by_cell;
|
||||
|
||||
std::string m_tech_name;
|
||||
tl::Mutex m_lock;
|
||||
mutable tl::Mutex m_lock;
|
||||
|
||||
/**
|
||||
* @brief Sort the cells topologically
|
||||
|
|
@ -2211,6 +2195,11 @@ private:
|
|||
* @brief Recovers a proxy without considering the library from context_info
|
||||
*/
|
||||
db::Cell *recover_proxy_no_lib (const LayoutOrCellContextInfo &context_info);
|
||||
|
||||
/**
|
||||
* @brief Does an update without checking under_construction() and no Mutex
|
||||
*/
|
||||
void force_update_no_lock () const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -29,13 +29,14 @@ namespace db
|
|||
{
|
||||
|
||||
LayoutStateModel::LayoutStateModel (bool busy)
|
||||
: m_hier_dirty (false), m_hier_generation_id (0), m_all_bboxes_dirty (false), m_busy (busy)
|
||||
: m_hier_dirty (false), m_hier_generation_id (0), m_all_bboxes_dirty (false), m_some_bboxes_dirty (false), m_busy (busy)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
LayoutStateModel::LayoutStateModel (const LayoutStateModel &d)
|
||||
: m_hier_dirty (d.m_hier_dirty), m_hier_generation_id (d.m_hier_generation_id), m_bboxes_dirty (d.m_bboxes_dirty), m_all_bboxes_dirty (d.m_all_bboxes_dirty), m_busy (d.m_busy)
|
||||
: m_hier_dirty (d.m_hier_dirty), m_hier_generation_id (d.m_hier_generation_id), m_bboxes_dirty (d.m_bboxes_dirty),
|
||||
m_all_bboxes_dirty (d.m_all_bboxes_dirty), m_some_bboxes_dirty (d.m_some_bboxes_dirty), m_busy (d.m_busy)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -47,6 +48,7 @@ LayoutStateModel::operator= (const LayoutStateModel &d)
|
|||
m_hier_generation_id = d.m_hier_generation_id;
|
||||
m_bboxes_dirty = d.m_bboxes_dirty;
|
||||
m_all_bboxes_dirty = d.m_all_bboxes_dirty;
|
||||
m_some_bboxes_dirty = d.m_some_bboxes_dirty;
|
||||
m_busy = d.m_busy;
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -84,6 +86,7 @@ LayoutStateModel::invalidate_bboxes (unsigned int index)
|
|||
m_bboxes_dirty.resize (index + 1, false);
|
||||
}
|
||||
m_bboxes_dirty [index] = true;
|
||||
m_some_bboxes_dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -91,7 +94,7 @@ LayoutStateModel::invalidate_bboxes (unsigned int index)
|
|||
bool
|
||||
LayoutStateModel::bboxes_dirty () const
|
||||
{
|
||||
return ! m_bboxes_dirty.empty () || m_all_bboxes_dirty;
|
||||
return m_some_bboxes_dirty || m_all_bboxes_dirty;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -100,6 +103,7 @@ LayoutStateModel::update ()
|
|||
if (bboxes_dirty () || m_hier_dirty) {
|
||||
do_update ();
|
||||
m_bboxes_dirty.clear ();
|
||||
m_some_bboxes_dirty = false;
|
||||
m_all_bboxes_dirty = false;
|
||||
m_hier_dirty = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ private:
|
|||
bool m_hier_dirty;
|
||||
size_t m_hier_generation_id;
|
||||
std::vector<bool> m_bboxes_dirty;
|
||||
bool m_all_bboxes_dirty;
|
||||
bool m_all_bboxes_dirty, m_some_bboxes_dirty;
|
||||
bool m_busy;
|
||||
|
||||
void do_invalidate_hier ();
|
||||
|
|
|
|||
|
|
@ -330,7 +330,11 @@ OriginalLayerRegion::begin_merged_iter () const
|
|||
bool
|
||||
OriginalLayerRegion::empty () const
|
||||
{
|
||||
return m_iter.at_end ();
|
||||
// NOTE: we should to make sure the iterator isn't validated as this would spoil the usability or OriginalLayerRegion upon
|
||||
// layout changes
|
||||
db::RecursiveShapeIterator iter = m_iter;
|
||||
|
||||
return iter.at_end ();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ RecursiveInstanceIterator &RecursiveInstanceIterator::operator= (const Recursive
|
|||
|
||||
m_box_convert = d.m_box_convert;
|
||||
|
||||
m_locker = d.m_locker;
|
||||
m_inst = d.m_inst;
|
||||
m_inst_array = d.m_inst_array;
|
||||
m_empty_cells_cache = d.m_empty_cells_cache;
|
||||
|
|
@ -175,7 +176,7 @@ RecursiveInstanceIterator::set_region (const box_type ®ion)
|
|||
{
|
||||
if (m_region != region || mp_complex_region.get () != 0) {
|
||||
init_region (region);
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +184,7 @@ void
|
|||
RecursiveInstanceIterator::set_region (const region_type ®ion)
|
||||
{
|
||||
init_region (region);
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -196,7 +197,7 @@ RecursiveInstanceIterator::confine_region (const box_type ®ion)
|
|||
} else {
|
||||
init_region (m_region & region);
|
||||
}
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -209,7 +210,7 @@ RecursiveInstanceIterator::confine_region (const region_type ®ion)
|
|||
} else {
|
||||
init_region (region & region_type (m_region));
|
||||
}
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -218,7 +219,7 @@ RecursiveInstanceIterator::enable_all_targets ()
|
|||
if (! m_all_targets) {
|
||||
m_all_targets = true;
|
||||
m_targets.clear ();
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +229,7 @@ RecursiveInstanceIterator::set_targets (const std::set<db::cell_index_type> &tgt
|
|||
if (m_all_targets || m_targets != tgt) {
|
||||
m_targets = tgt;
|
||||
m_all_targets = false;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +265,8 @@ RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const
|
|||
m_needs_reinit = false;
|
||||
|
||||
// re-initialize
|
||||
m_locker = db::LayoutLocker ();
|
||||
|
||||
mp_cell = mp_top_cell;
|
||||
m_trans_stack.clear ();
|
||||
m_inst_iterators.clear ();
|
||||
|
|
@ -310,6 +313,17 @@ RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const
|
|||
next_instance (receiver);
|
||||
|
||||
}
|
||||
|
||||
if (mp_layout && ! at_end ()) {
|
||||
m_locker = db::LayoutLocker (const_cast <db::Layout *> (mp_layout.get ()), true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::reset ()
|
||||
{
|
||||
m_needs_reinit = true;
|
||||
m_locker = db::LayoutLocker ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -320,7 +334,7 @@ RecursiveInstanceIterator::reset_selection ()
|
|||
m_start.clear ();
|
||||
m_stop.clear ();
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -335,7 +349,7 @@ RecursiveInstanceIterator::unselect_cells (const std::set<db::cell_index_type> &
|
|||
m_start.erase (*c);
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -350,7 +364,7 @@ RecursiveInstanceIterator::unselect_all_cells ()
|
|||
m_stop.insert (c->cell_index ());
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -365,7 +379,7 @@ RecursiveInstanceIterator::select_cells (const std::set<db::cell_index_type> &ce
|
|||
m_stop.erase (*c);
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -380,7 +394,7 @@ RecursiveInstanceIterator::select_all_cells ()
|
|||
m_start.insert (c->cell_index ());
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -441,6 +455,7 @@ void
|
|||
RecursiveInstanceIterator::next (RecursiveInstanceReceiver *receiver)
|
||||
{
|
||||
if (! at_end ()) {
|
||||
|
||||
++m_inst_array;
|
||||
if (! m_inst_array.at_end ()) {
|
||||
new_inst_member (receiver);
|
||||
|
|
@ -449,6 +464,12 @@ RecursiveInstanceIterator::next (RecursiveInstanceReceiver *receiver)
|
|||
new_inst (receiver);
|
||||
}
|
||||
next_instance (receiver);
|
||||
|
||||
if (at_end ()) {
|
||||
// Take this opportunity the release the layout lock.
|
||||
// This way, the shape iterator can be held further, without blocking the layout.
|
||||
m_locker = db::LayoutLocker ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ public:
|
|||
{
|
||||
if (m_max_depth != depth) {
|
||||
m_max_depth = depth;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ public:
|
|||
{
|
||||
if (m_min_depth != depth) {
|
||||
m_min_depth = depth;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -262,17 +262,14 @@ public:
|
|||
{
|
||||
if (m_overlapping != f) {
|
||||
m_overlapping = f;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the iterator
|
||||
*/
|
||||
void reset ()
|
||||
{
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
void reset ();
|
||||
|
||||
/**
|
||||
* @brief Gets the selected target cells
|
||||
|
|
@ -552,6 +549,7 @@ private:
|
|||
std::unique_ptr<region_type> mp_complex_region;
|
||||
db::box_convert<db::CellInst> m_box_convert;
|
||||
|
||||
mutable db::LayoutLocker m_locker;
|
||||
mutable inst_iterator m_inst;
|
||||
mutable inst_array_iterator m_inst_array;
|
||||
mutable instance_element_type m_combined_instance;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ RecursiveShapeIterator &RecursiveShapeIterator::operator= (const RecursiveShapeI
|
|||
|
||||
m_box_convert = d.m_box_convert;
|
||||
|
||||
m_locker = d.m_locker;
|
||||
m_inst = d.m_inst;
|
||||
m_inst_array = d.m_inst_array;
|
||||
m_empty_cells_cache = d.m_empty_cells_cache;
|
||||
|
|
@ -340,7 +341,7 @@ RecursiveShapeIterator::set_global_trans (const cplx_trans_type &tr)
|
|||
{
|
||||
if (m_global_trans != tr) {
|
||||
m_global_trans = tr;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +361,7 @@ RecursiveShapeIterator::set_region (const box_type ®ion)
|
|||
{
|
||||
if (m_region != region || mp_complex_region.get () != 0) {
|
||||
init_region (region);
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -368,7 +369,7 @@ void
|
|||
RecursiveShapeIterator::set_region (const region_type ®ion)
|
||||
{
|
||||
init_region (region);
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -381,7 +382,7 @@ RecursiveShapeIterator::confine_region (const box_type ®ion)
|
|||
} else {
|
||||
init_region (m_region & region);
|
||||
}
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -394,7 +395,7 @@ RecursiveShapeIterator::confine_region (const region_type ®ion)
|
|||
} else {
|
||||
init_region (region & region_type (m_region));
|
||||
}
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -404,7 +405,7 @@ RecursiveShapeIterator::set_layer (unsigned int layer)
|
|||
m_has_layers = false;
|
||||
m_layers.clear ();
|
||||
m_layer = layer;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -415,7 +416,7 @@ RecursiveShapeIterator::set_layers (const std::vector<unsigned int> &layers)
|
|||
m_has_layers = true;
|
||||
m_layers = layers;
|
||||
m_layer = 0;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -451,6 +452,8 @@ RecursiveShapeIterator::validate (RecursiveShapeReceiver *receiver) const
|
|||
m_needs_reinit = false;
|
||||
|
||||
// re-initialize
|
||||
m_locker = db::LayoutLocker ();
|
||||
|
||||
mp_cell = mp_top_cell;
|
||||
m_trans_stack.clear ();
|
||||
m_inst_iterators.clear ();
|
||||
|
|
@ -502,9 +505,20 @@ RecursiveShapeIterator::validate (RecursiveShapeReceiver *receiver) const
|
|||
new_cell (receiver);
|
||||
next_shape (receiver);
|
||||
}
|
||||
|
||||
if (mp_layout && ! at_end ()) {
|
||||
m_locker = db::LayoutLocker (const_cast<db::Layout *> (mp_layout.get ()), true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
RecursiveShapeIterator::reset ()
|
||||
{
|
||||
m_needs_reinit = true;
|
||||
m_locker = db::LayoutLocker ();
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::reset_selection ()
|
||||
{
|
||||
if (mp_layout) {
|
||||
|
|
@ -512,7 +526,7 @@ RecursiveShapeIterator::reset_selection ()
|
|||
m_start.clear ();
|
||||
m_stop.clear ();
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -527,7 +541,7 @@ RecursiveShapeIterator::unselect_cells (const std::set<db::cell_index_type> &cel
|
|||
m_start.erase (*c);
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -542,7 +556,7 @@ RecursiveShapeIterator::unselect_all_cells ()
|
|||
m_stop.insert (c->cell_index ());
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -557,7 +571,7 @@ RecursiveShapeIterator::select_cells (const std::set<db::cell_index_type> &cells
|
|||
m_stop.erase (*c);
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -572,7 +586,7 @@ RecursiveShapeIterator::select_all_cells ()
|
|||
m_start.insert (c->cell_index ());
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -688,6 +702,12 @@ RecursiveShapeIterator::next (RecursiveShapeReceiver *receiver)
|
|||
next_shape (receiver);
|
||||
}
|
||||
|
||||
if (at_end ()) {
|
||||
// Take this opportunity the release the layout lock.
|
||||
// This way, the shape iterator can be held further, without blocking the layout.
|
||||
m_locker = db::LayoutLocker ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ public:
|
|||
{
|
||||
if (m_max_depth != depth) {
|
||||
m_max_depth = depth;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -288,7 +288,7 @@ public:
|
|||
{
|
||||
if (m_min_depth != depth) {
|
||||
m_min_depth = depth;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -433,7 +433,7 @@ public:
|
|||
{
|
||||
if (m_overlapping != f) {
|
||||
m_overlapping = f;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -452,7 +452,7 @@ public:
|
|||
{
|
||||
if (m_for_merged_input != f) {
|
||||
m_for_merged_input = f;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -483,10 +483,7 @@ public:
|
|||
/**
|
||||
* @brief Reset the iterator
|
||||
*/
|
||||
void reset ()
|
||||
{
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
void reset ();
|
||||
|
||||
/**
|
||||
* @brief Select cells
|
||||
|
|
@ -559,7 +556,7 @@ public:
|
|||
{
|
||||
if (m_shape_flags != flags) {
|
||||
m_shape_flags = flags;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -596,7 +593,7 @@ public:
|
|||
{
|
||||
if (mp_shape_prop_sel != prop_sel) {
|
||||
mp_shape_prop_sel = prop_sel;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -610,7 +607,7 @@ public:
|
|||
{
|
||||
if (m_shape_inv_prop_sel != inv) {
|
||||
m_shape_inv_prop_sel = inv;
|
||||
m_needs_reinit = true;
|
||||
reset ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -854,6 +851,7 @@ private:
|
|||
std::unique_ptr<region_type> mp_complex_region;
|
||||
db::box_convert<db::CellInst> m_box_convert;
|
||||
|
||||
mutable db::LayoutLocker m_locker;
|
||||
mutable inst_iterator m_inst;
|
||||
mutable inst_array_iterator m_inst_array;
|
||||
mutable std::map<db::cell_index_type, bool> m_empty_cells_cache;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ Writer::write (db::Layout &layout, tl::OutputStream &stream)
|
|||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Writing file: ")) + stream.path ());
|
||||
|
||||
if (layout.under_construction ()) {
|
||||
tl::warn << tl::to_string (tr ("Cannot properly write a layout that is under construction - forcing update."));
|
||||
layout.force_update ();
|
||||
}
|
||||
|
||||
tl_assert (mp_writer != 0);
|
||||
mp_writer->write (layout, stream, m_options);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -603,6 +603,11 @@ Class<db::RecursiveInstanceIterator> decl_RecursiveInstanceIterator ("db", "Recu
|
|||
"and the target cell of the current instance.\n"
|
||||
"\n"
|
||||
"The RecursiveInstanceIterator class has been introduced in version 0.27.\n"
|
||||
"Starting with version 0.29.9, the recursive instance iterator will lock the layout it acts on while in iterating mode. "
|
||||
"While the iterator is active, the Layout object is maintained in 'under construction mode' (see \\Layout#under_construction). "
|
||||
"This is to prevent layout modifications to interfere with the iterator's operation. Specifically when coding in Ruby, "
|
||||
"pending iterators may block the Layout until the garbage collector cleans up these objects. To avoid this, call \\_destroy "
|
||||
"on the iterator when you no longer need it. The Layout is automatically unlocked when the iterator reaches the end."
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -804,6 +804,11 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"all cells not starting with one of that letters.\n"
|
||||
"\n"
|
||||
"The RecursiveShapeIterator class has been introduced in version 0.18 and has been extended substantially in 0.23.\n"
|
||||
"Starting with version 0.29.9, the recursive shape iterator will lock the layout it acts on while in iterating mode. "
|
||||
"While the iterator is active, the Layout object is maintained in 'under construction mode' (see \\Layout#under_construction). "
|
||||
"This is to prevent layout modifications to interfere with the iterator's operation. Specifically when coding in Ruby, "
|
||||
"pending iterators may block the Layout until the garbage collector cleans up these objects. To avoid this, call \\_destroy "
|
||||
"on the iterator when you no longer need it. The Layout is automatically unlocked when the iterator reaches the end."
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -789,3 +789,70 @@ TEST(6)
|
|||
"CHILD_CELL_3_1_1@r0 *1 120000,0"
|
||||
);
|
||||
}
|
||||
|
||||
// layout locking
|
||||
TEST(7_LayoutLocking)
|
||||
{
|
||||
db::Layout layout;
|
||||
|
||||
layout.insert_layer (0);
|
||||
|
||||
db::Cell &c0 (layout.cell (layout.add_cell ()));
|
||||
db::Cell &c1 (layout.cell (layout.add_cell ()));
|
||||
|
||||
db::Box b (0, 100, 1000, 1200);
|
||||
c1.shapes (0).insert (b);
|
||||
|
||||
db::Trans tt;
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt));
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (2000, -2000))));
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
|
||||
db::RecursiveInstanceIterator iter (layout, c0);
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
|
||||
EXPECT_EQ (iter.at_end (), false);
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
|
||||
EXPECT_EQ (iter.instance ().to_string (), "cell_index=1 r0 *1 0,0");
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
++iter;
|
||||
|
||||
EXPECT_EQ (iter.at_end (), false);
|
||||
|
||||
EXPECT_EQ (iter.instance ().to_string (), "cell_index=1 r0 *1 2000,-2000");
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
++iter;
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
EXPECT_EQ (iter.at_end (), true);
|
||||
|
||||
// reset will restart
|
||||
iter.reset ();
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
|
||||
EXPECT_EQ (iter.at_end (), false);
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
|
||||
// a copy will hold the lock
|
||||
iter.reset ();
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
EXPECT_EQ (iter.at_end (), false);
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
db::RecursiveInstanceIterator iter_copy = iter;
|
||||
|
||||
while (! iter.at_end ()) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
iter_copy = db::RecursiveInstanceIterator ();
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1780,3 +1780,69 @@ TEST(13_ForMergedPerformance)
|
|||
}
|
||||
}
|
||||
|
||||
// layout locking
|
||||
TEST(14_LayoutLocking)
|
||||
{
|
||||
db::Layout layout;
|
||||
|
||||
layout.insert_layer (0);
|
||||
|
||||
db::Cell &c0 (layout.cell (layout.add_cell ()));
|
||||
db::Cell &c1 (layout.cell (layout.add_cell ()));
|
||||
|
||||
db::Box b (0, 100, 1000, 1200);
|
||||
c1.shapes (0).insert (b);
|
||||
|
||||
db::Trans tt;
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt));
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (2000, -2000))));
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
|
||||
db::RecursiveShapeIterator iter (layout, c0, 0);
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
|
||||
EXPECT_EQ (iter.at_end (), false);
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
|
||||
EXPECT_EQ (iter.shape ().to_string (), "box (0,100;1000,1200)");
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
++iter;
|
||||
|
||||
EXPECT_EQ (iter.at_end (), false);
|
||||
|
||||
EXPECT_EQ (iter.shape ().to_string (), "box (0,100;1000,1200)");
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
++iter;
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
EXPECT_EQ (iter.at_end (), true);
|
||||
|
||||
// reset will restart
|
||||
iter.reset ();
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
|
||||
EXPECT_EQ (iter.at_end (), false);
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
|
||||
// a copy will hold the lock
|
||||
iter.reset ();
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
EXPECT_EQ (iter.at_end (), false);
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
db::RecursiveShapeIterator iter_copy = iter;
|
||||
|
||||
while (! iter.at_end ()) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), true);
|
||||
iter_copy = db::RecursiveShapeIterator ();
|
||||
|
||||
EXPECT_EQ (layout.under_construction (), false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,6 +232,16 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
def first_shape(s)
|
||||
|
||||
sdup = s.dup
|
||||
shape = sdup.shape
|
||||
sdup._destroy
|
||||
|
||||
return shape
|
||||
|
||||
end
|
||||
|
||||
def collect(s, l)
|
||||
|
||||
res = []
|
||||
|
|
@ -1042,18 +1052,18 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
c0c = l.cell(l.add_cell("c0"))
|
||||
c0c.copy_shapes(c0)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](0,100;1000,1200)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), 17)
|
||||
|
||||
c0c.clear
|
||||
lm = RBA::LayerMapping::new
|
||||
lm.map(1, 0)
|
||||
c0c.copy_shapes(c0, lm)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), 17)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), nil)
|
||||
|
||||
l2 = RBA::Layout::new
|
||||
l2.dbu = 0.0005
|
||||
|
|
@ -1063,9 +1073,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
layer1 = l2.find_layer(1, 0)
|
||||
layer2 = l2.find_layer(2, 0)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer1), l), "[c0](0,200;2000,2400)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer1)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer2), l), "[c0](2,202;2002,2402)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer2).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer2)).property("p"), 17)
|
||||
|
||||
l2 = RBA::Layout::new
|
||||
l2.dbu = 0.0005
|
||||
|
|
@ -1084,9 +1094,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
layer1 = l2.find_layer(1, 0)
|
||||
layer2 = l2.find_layer(2, 0)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer1), l), "[c0](0,200;2000,2400)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer1)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer2), l), "[c0](2,202;2002,2402)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer2).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer2)).property("p"), 17)
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -1127,9 +1137,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(c0.begin_shapes_rec(0), l), "[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](0,100;1000,1200)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), 17)
|
||||
c0.move_shapes(c0c)
|
||||
assert_equal(collect(c0.begin_shapes_rec(0), 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)")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "[c0](1,101;1001,1201)")
|
||||
|
|
@ -1142,9 +1152,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(c0.begin_shapes_rec(0), 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)")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), 17)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), nil)
|
||||
|
||||
l = ll.dup
|
||||
c0 = l.cell("c0")
|
||||
|
|
@ -1159,9 +1169,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(c0.begin_shapes_rec(0), l), "[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer1), l), "[c0](0,200;2000,2400)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer1)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer2), l), "[c0](2,202;2002,2402)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer2).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer2)).property("p"), 17)
|
||||
|
||||
l = ll.dup
|
||||
c0 = l.cell("c0")
|
||||
|
|
@ -1185,9 +1195,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(c0.begin_shapes_rec(0), l), "[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer1), l), "[c0](0,200;2000,2400)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer1)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer2), l), "[c0](2,202;2002,2402)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer2).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer2)).property("p"), 17)
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -1351,7 +1361,7 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
|
||||
layer1 = l2.find_layer(1, 0)
|
||||
layer2 = l2.find_layer(2, 0)
|
||||
assert_equal(l2.cell("c1").begin_shapes_rec(layer1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(l2.cell("c1").begin_shapes_rec(layer1)).property("p"), 17)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer1), l2), "[c0](0,200;2000,2400)/[c2](200,0;2200,2200)/[c3](2400,0;4400,2200)/[c3](-2400,0;-200,2000)/[c1](0,200;2000,2400)")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer2), l2), "[c0](2,202;2002,2402)")
|
||||
|
||||
|
|
@ -1401,7 +1411,7 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
i0 = nil
|
||||
c0c.each_inst { |i| i.cell_index == l.cell("c1$1").cell_index && i0 = i }
|
||||
assert_equal(i0.property("p"), 18)
|
||||
assert_equal(l.cell("c1$1").begin_shapes_rec(0).shape.property("p"), 17)
|
||||
assert_equal(first_shape(l.cell("c1$1").begin_shapes_rec(0)).property("p"), 17)
|
||||
|
||||
assert_equal(collect(c0.begin_shapes_rec(0), l), "")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "")
|
||||
|
|
@ -1429,7 +1439,7 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
|
||||
layer1 = l2.find_layer(1, 0)
|
||||
layer2 = l2.find_layer(2, 0)
|
||||
assert_equal(l2.cell("c1").begin_shapes_rec(layer1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(l2.cell("c1").begin_shapes_rec(layer1)).property("p"), 17)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer1), l2), "[c0](0,200;2000,2400)/[c2](200,0;2200,2200)/[c3](2400,0;4400,2200)/[c3](-2400,0;-200,2000)/[c1](0,200;2000,2400)")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer2), l2), "[c0](2,202;2002,2402)")
|
||||
|
||||
|
|
@ -1471,16 +1481,16 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
cm.for_single_cell(l, c0c.cell_index, l, c0.cell_index)
|
||||
c0c.copy_tree_shapes(c0, cm)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](0,100;1000,1200)/[c0$1](0,100;1000,1200)/[c0$1](100,0;1100,1100)/[c0$1](-1200,0;-100,1000)/[c0$1](1200,0;2200,1100)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), 17)
|
||||
|
||||
c0c.clear
|
||||
lm = RBA::LayerMapping::new
|
||||
lm.map(1, 0)
|
||||
c0c.copy_tree_shapes(c0, cm, lm)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), 17)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), nil)
|
||||
|
||||
|
|
@ -1488,9 +1498,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
cm.for_single_cell_full(l, c0c.cell_index, l, c0.cell_index)
|
||||
c0c.copy_tree_shapes(c0, cm)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](0,100;1000,1200)/[c2$1](100,0;1100,1100)/[c3$1](1200,0;2200,1100)/[c3$1](-1200,0;-100,1000)/[c1$1](0,100;1000,1200)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), 17)
|
||||
|
||||
i0 = nil
|
||||
c0c.each_inst { |i| i.cell_index == l.cell("c1$1").cell_index && i0 = i }
|
||||
|
|
@ -1505,9 +1515,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
layer1 = l2.find_layer(1, 0)
|
||||
layer2 = l2.find_layer(2, 0)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer1), l), "[c0](0,200;2000,2400)/[c2](200,0;2200,2200)/[c3](2400,0;4400,2200)/[c3](-2400,0;-200,2000)/[c1](0,200;2000,2400)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer1)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer2), l), "[c0](2,202;2002,2402)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer2).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer2)).property("p"), 17)
|
||||
|
||||
i0 = nil
|
||||
c0c.each_inst { |i| i.cell_index == l2.cell("c1").cell_index && i0 = i }
|
||||
|
|
@ -1559,9 +1569,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(c0.begin_shapes_rec(0), l), "")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](0,100;1000,1200)/[c0$1](0,100;1000,1200)/[c0$1](100,0;1100,1100)/[c0$1](-1200,0;-100,1000)/[c0$1](1200,0;2200,1100)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), 17)
|
||||
|
||||
l = ll.dup
|
||||
c0 = l.cell("c0")
|
||||
|
|
@ -1573,9 +1583,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(c0.begin_shapes_rec(0), l), "[c0](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)/[c1](0,100;1000,1200)")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), 17)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), nil)
|
||||
|
||||
l = ll.dup
|
||||
c0 = l.cell("c0")
|
||||
|
|
@ -1586,9 +1596,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(c0.begin_shapes_rec(0), l), "")
|
||||
assert_equal(collect(c0.begin_shapes_rec(1), l), "")
|
||||
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](0,100;1000,1200)/[c2$1](100,0;1100,1100)/[c3$1](1200,0;2200,1100)/[c3$1](-1200,0;-100,1000)/[c1$1](0,100;1000,1200)")
|
||||
assert_equal(c0c.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(1), l), "[c0$1](1,101;1001,1201)")
|
||||
assert_equal(c0c.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(1)).property("p"), 17)
|
||||
|
||||
i0 = nil
|
||||
c0c.each_inst { |i| i.cell_index == l.cell("c1$1").cell_index && i0 = i }
|
||||
|
|
@ -1608,9 +1618,9 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
layer1 = l2.find_layer(1, 0)
|
||||
layer2 = l2.find_layer(2, 0)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer1), l), "[c0](0,200;2000,2400)/[c2](200,0;2200,2200)/[c3](2400,0;4400,2200)/[c3](-2400,0;-200,2000)/[c1](0,200;2000,2400)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer1).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer1)).property("p"), nil)
|
||||
assert_equal(collect(c0c.begin_shapes_rec(layer2), l), "[c0](2,202;2002,2402)")
|
||||
assert_equal(c0c.begin_shapes_rec(layer2).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0c.begin_shapes_rec(layer2)).property("p"), 17)
|
||||
|
||||
i0 = nil
|
||||
c0c.each_inst { |i| i.cell_index == l2.cell("c1").cell_index && i0 = i }
|
||||
|
|
@ -1833,10 +1843,10 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
|
||||
lt.copy_tree_shapes(l, cm)
|
||||
assert_equal(collect(c0t.begin_shapes_rec(0), lt), "[c0](0,100;1000,1200)/[c0](0,100;1000,1200)/[c0](100,0;1100,1100)/[c0](-1200,0;-100,1000)/[c0](1200,0;2200,1100)")
|
||||
assert_equal(c0t.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0t.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(0), lt), "[c9](0,100;1000,1200)")
|
||||
assert_equal(collect(c0t.begin_shapes_rec(1), l), "[c0](1,101;1001,1201)")
|
||||
assert_equal(c0t.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0t.begin_shapes_rec(1)).property("p"), 17)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(1), l), "")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
|
|
@ -1850,10 +1860,10 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
|
||||
lt.copy_tree_shapes(l, cm)
|
||||
assert_equal(collect(c0t.begin_shapes_rec(0), lt), "[c0](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)/[c1](0,100;1000,1200)")
|
||||
assert_equal(c0t.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0t.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(0), lt), "[c1](0,100;1000,1200)")
|
||||
assert_equal(collect(c0t.begin_shapes_rec(1), l), "[c0](1,101;1001,1201)")
|
||||
assert_equal(c0t.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0t.begin_shapes_rec(1)).property("p"), 17)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(1), l), "")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
|
|
@ -1873,7 +1883,7 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
|
||||
lt.copy_tree_shapes(l, cm, lm)
|
||||
assert_equal(collect(c0t.begin_shapes_rec(ll), lt), "[c0](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)/[c1](0,100;1000,1200)")
|
||||
assert_equal(c0t.begin_shapes_rec(ll).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0t.begin_shapes_rec(ll)).property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(ll), lt), "[c1](0,100;1000,1200)")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
|
|
@ -1897,10 +1907,10 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(ls.cell(c9.cell_index).begin_shapes_rec(1), ls), "")
|
||||
|
||||
assert_equal(collect(c0t.begin_shapes_rec(0), lt), "[c0](0,100;1000,1200)/[c0](0,100;1000,1200)/[c0](100,0;1100,1100)/[c0](-1200,0;-100,1000)/[c0](1200,0;2200,1100)")
|
||||
assert_equal(c0t.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0t.begin_shapes_rec(0)).property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(0), lt), "[c9](0,100;1000,1200)")
|
||||
assert_equal(collect(c0t.begin_shapes_rec(1), l), "[c0](1,101;1001,1201)")
|
||||
assert_equal(c0t.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(first_shape(c0t.begin_shapes_rec(1)).property("p"), 17)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(1), l), "")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
|
|
@ -1931,7 +1941,7 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
assert_equal(collect(ls.cell(c9.cell_index).begin_shapes_rec(1), ls), "")
|
||||
|
||||
assert_equal(collect(c0t.begin_shapes_rec(ll), lt), "[c0](0,100;1000,1200)/[c0](0,100;1000,1200)/[c0](100,0;1100,1100)/[c0](-1200,0;-100,1000)/[c0](1200,0;2200,1100)")
|
||||
assert_equal(c0t.begin_shapes_rec(ll).shape.property("p"), nil)
|
||||
assert_equal(first_shape(c0t.begin_shapes_rec(ll)).property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(ll), lt), "[c9](0,100;1000,1200)")
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23,6 +23,16 @@ end
|
|||
|
||||
load("test_prologue.rb")
|
||||
|
||||
def first_shape(s)
|
||||
|
||||
sdup = s.dup
|
||||
shape = sdup.shape
|
||||
sdup._destroy
|
||||
|
||||
return shape
|
||||
|
||||
end
|
||||
|
||||
class BoxPCell < RBA::PCellDeclaration
|
||||
|
||||
def display_text(parameters)
|
||||
|
|
@ -428,30 +438,30 @@ class DBPCell_TestClass < TestBase
|
|||
li2 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "10/0" }
|
||||
assert_equal(li2 != nil, true)
|
||||
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-500;250,500)")
|
||||
assert_equal(ly.begin_shapes(lib_proxy.cell_index, li2).shape.to_s, "box (0,0;10,20)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-250,-500;250,500)")
|
||||
assert_equal(first_shape(ly.begin_shapes(lib_proxy.cell_index, li2)).to_s, "box (0,0;10,20)")
|
||||
|
||||
param = { "w" => 1, "h" => 2 }
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-50,-100;50,100)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-50,-100;50,100)")
|
||||
|
||||
param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ]
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-250,-250;250,250)")
|
||||
|
||||
pcell_inst.change_pcell_parameters({ "w" => 2.0, "h" => 10.0 })
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-100,-500;100,500)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-100,-500;100,500)")
|
||||
|
||||
pcell_inst.change_pcell_parameters([ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ])
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-250,-250;250,250)")
|
||||
|
||||
pcell_inst.change_pcell_parameter("w", 5.0)
|
||||
pcell_inst.change_pcell_parameter("h", 1.0)
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-50;250,50)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-250,-50;250,50)")
|
||||
|
||||
c1.change_pcell_parameter(pcell_inst, "w", 10.0)
|
||||
c1.change_pcell_parameter(pcell_inst, "h", 2.0)
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-500,-100;500,100)")
|
||||
|
||||
assert_equal(ly.cell(pcell_inst.cell_index).is_pcell_variant?, true)
|
||||
assert_equal(pcell_inst.is_pcell?, true)
|
||||
|
|
@ -460,18 +470,18 @@ class DBPCell_TestClass < TestBase
|
|||
assert_equal(ly.cell(new_id).is_pcell_variant?, false)
|
||||
param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ]
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-250,-250;250,250)")
|
||||
pcell_inst.cell_index = new_id
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, li1)).to_s, "box (-500,-100;500,100)")
|
||||
|
||||
l10 = ly.layer(10, 0)
|
||||
c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210))
|
||||
l11 = ly.layer(11, 0)
|
||||
c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new))
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false)
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true)
|
||||
assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]")
|
||||
assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110")
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, first_shape(ly.begin_shapes(c1.cell_index(), l11)), l10), false)
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, first_shape(ly.begin_shapes(c1.cell_index(), l10)), l10), true)
|
||||
assert_equal(pcell_decl.parameters_from_shape(ly, first_shape(ly.begin_shapes(c1.cell_index(), l10)), l10).inspect, "[<10/0>, 1.0, 2.0]")
|
||||
assert_equal(pcell_decl.transformation_from_shape(ly, first_shape(ly.begin_shapes(c1.cell_index(), l10)), l10).to_s, "r0 50,110")
|
||||
|
||||
ly._destroy
|
||||
tl._destroy
|
||||
|
|
@ -522,21 +532,21 @@ class DBPCell_TestClass < TestBase
|
|||
pcell_inst.change_pcell_parameter("height", 2.0)
|
||||
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>2.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}")
|
||||
|
||||
assert_equal(ly.begin_shapes(c1.cell_index(), li1).shape().to_s, "box (-50,-100;50,100)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index(), li1)).to_s, "box (-50,-100;50,100)")
|
||||
|
||||
param = { "layer" => RBA::LayerInfo::new(2, 0), "width" => 2, "height" => 1 }
|
||||
li2 = ly.layer(2, 0)
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
assert_equal(ly.begin_shapes(c1.cell_index(), li2).shape().to_s, "box (-100,-50;100,50)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index(), li2)).to_s, "box (-100,-50;100,50)")
|
||||
|
||||
l10 = ly.layer(10, 0)
|
||||
c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210))
|
||||
l11 = ly.layer(11, 0)
|
||||
c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new))
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false)
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true)
|
||||
assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0, 0]")
|
||||
assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110")
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, first_shape(ly.begin_shapes(c1.cell_index(), l11)), l10), false)
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, first_shape(ly.begin_shapes(c1.cell_index(), l10)), l10), true)
|
||||
assert_equal(pcell_decl.parameters_from_shape(ly, first_shape(ly.begin_shapes(c1.cell_index(), l10)), l10).inspect, "[<10/0>, 1.0, 2.0, 0]")
|
||||
assert_equal(pcell_decl.transformation_from_shape(ly, first_shape(ly.begin_shapes(c1.cell_index(), l10)), l10).to_s, "r0 50,110")
|
||||
|
||||
param2 = c1.pcell_parameters(pcell_inst)
|
||||
param2[3] = -2 # "secret"
|
||||
|
|
@ -594,13 +604,13 @@ class DBPCell_TestClass < TestBase
|
|||
|
||||
assert_equal(pcell_inst.is_pcell?, true)
|
||||
|
||||
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
|
||||
assert_equal(first_shape(ly.begin_shapes(pcell_inst.cell_index, li1)).to_s, "box (-500,-100;500,100)")
|
||||
pcell_inst.convert_to_static
|
||||
assert_equal(pcell_inst.is_pcell?, false)
|
||||
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
|
||||
assert_equal(first_shape(ly.begin_shapes(pcell_inst.cell_index, li1)).to_s, "box (-500,-100;500,100)")
|
||||
pcell_inst.convert_to_static
|
||||
assert_equal(pcell_inst.is_pcell?, false)
|
||||
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
|
||||
assert_equal(first_shape(ly.begin_shapes(pcell_inst.cell_index, li1)).to_s, "box (-500,-100;500,100)")
|
||||
|
||||
ly._destroy
|
||||
tl._destroy
|
||||
|
|
@ -625,7 +635,7 @@ class DBPCell_TestClass < TestBase
|
|||
pcell_var = ly.cell(pcell_var_id)
|
||||
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
|
||||
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, ly.layer(1, 0)).shape.to_s, "box (-200,-400;200,400)")
|
||||
assert_equal(first_shape(ly.begin_shapes(c1.cell_index, ly.layer(1, 0))).to_s, "box (-200,-400;200,400)")
|
||||
|
||||
ly._destroy
|
||||
tl._destroy
|
||||
|
|
@ -643,7 +653,7 @@ class DBPCell_TestClass < TestBase
|
|||
param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) }
|
||||
pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param)
|
||||
|
||||
assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(1, 0)).shape.to_s, "box (-2000,-4000;2000,4000)")
|
||||
assert_equal(first_shape(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(1, 0))).to_s, "box (-2000,-4000;2000,4000)")
|
||||
|
||||
tl._destroy
|
||||
|
||||
|
|
@ -660,7 +670,7 @@ class DBPCell_TestClass < TestBase
|
|||
param = { "w" => 3.0, "h" => 7.0, "l" => RBA::LayerInfo::new(2, 0) }
|
||||
pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param)
|
||||
|
||||
assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(2, 0)).shape.to_s, "box (-1500,-3500;1500,3500)")
|
||||
assert_equal(first_shape(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(2, 0))).to_s, "box (-1500,-3500;1500,3500)")
|
||||
|
||||
tl._destroy
|
||||
|
||||
|
|
@ -676,7 +686,7 @@ class DBPCell_TestClass < TestBase
|
|||
param = { "w" => 3.0, "h" => 8.0, "l" => RBA::LayerInfo::new(3, 0) }
|
||||
pcell_var = lib.layout.create_cell("Box", param)
|
||||
|
||||
assert_equal(lib.layout.begin_shapes(pcell_var.cell_index, lib.layout.layer(3, 0)).shape.to_s, "box (-1500,-4000;1500,4000)")
|
||||
assert_equal(first_shape(lib.layout.begin_shapes(pcell_var.cell_index, lib.layout.layer(3, 0))).to_s, "box (-1500,-4000;1500,4000)")
|
||||
|
||||
tl._destroy
|
||||
|
||||
|
|
@ -693,7 +703,7 @@ class DBPCell_TestClass < TestBase
|
|||
param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(4, 0) }
|
||||
cell = ly.create_cell("Box", "PCellTestLib", param)
|
||||
|
||||
assert_equal(ly.begin_shapes(cell, ly.layer(4, 0)).shape.to_s, "box (-200,-400;200,400)")
|
||||
assert_equal(first_shape(ly.begin_shapes(cell, ly.layer(4, 0))).to_s, "box (-200,-400;200,400)")
|
||||
|
||||
tl._destroy
|
||||
ly._destroy
|
||||
|
|
@ -715,7 +725,7 @@ class DBPCell_TestClass < TestBase
|
|||
|
||||
cell = ly.create_cell("BOXVAR", "PCellTestLib")
|
||||
|
||||
assert_equal(cell.begin_shapes_rec(ly.layer(5, 0)).shape.to_s, "box (-100,-300;100,300)")
|
||||
assert_equal(first_shape(cell.begin_shapes_rec(ly.layer(5, 0))).to_s, "box (-100,-300;100,300)")
|
||||
|
||||
tl._destroy
|
||||
ly._destroy
|
||||
|
|
|
|||
Loading…
Reference in New Issue