Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 1307 #1480

Merged
merged 14 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/db/db/built-in-pymacros/pcell_declaration_helper.lym
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ for k in dir(pya.PCellParameterDeclaration):

# Inject the PCellDeclarationHelper into pya module for consistency:
setattr(pya, "PCellDeclarationHelper", _PCellDeclarationHelper)
pya.__all__.append("PCellDeclarationHelper")

</text>
</klayout-macro>
9 changes: 5 additions & 4 deletions src/db/db/dbCell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ Cell::box_type Cell::ms_empty_box = Cell::box_type ();

Cell::Cell (cell_index_type ci, db::Layout &l)
: db::Object (l.manager ()),
m_cell_index (ci), mp_layout (&l), m_instances (this), m_prop_id (0), m_hier_levels (0), m_bbox_needs_update (false), m_ghost_cell (false),
m_cell_index (ci), mp_layout (&l), m_instances (this), m_prop_id (0), m_hier_levels (0),
m_bbox_needs_update (false), m_ghost_cell (false),
mp_last (0), mp_next (0)
{
// .. nothing yet
Expand Down Expand Up @@ -700,7 +701,7 @@ Cell::clear_parent_insts (size_t sz)
void
Cell::sort_child_insts ()
{
m_instances.sort_child_insts ();
m_instances.sort_child_insts (false);
}

std::pair<bool, db::pcell_id_type>
Expand Down Expand Up @@ -744,9 +745,9 @@ Cell::change_pcell_parameters (const instance_type &ref, const std::vector<tl::V
}

void
Cell::sort_inst_tree ()
Cell::sort_inst_tree (bool force)
{
m_instances.sort_inst_tree (mp_layout);
m_instances.sort_inst_tree (mp_layout, force);

// update the number of hierarchy levels
m_hier_levels = count_hier_levels ();
Expand Down
6 changes: 3 additions & 3 deletions src/db/db/dbCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -1076,7 +1076,7 @@ class DB_PUBLIC Cell
db::properties_id_type m_prop_id;

// packed fields
unsigned int m_hier_levels : 29;
unsigned int m_hier_levels : 30;
bool m_bbox_needs_update : 1;
bool m_ghost_cell : 1;

Expand Down Expand Up @@ -1147,9 +1147,9 @@ class DB_PUBLIC Cell
* This will sort the cell instance list. As a prerequesite
* the cell's bounding boxes must have been computed.
*
* @param layers The maximum number of layers in the child cells
* @param force Force sorting, even if not strictly needed
*/
void sort_inst_tree ();
void sort_inst_tree (bool force);
};

/**
Expand Down
131 changes: 79 additions & 52 deletions src/db/db/dbInstances.cc
Original file line number Diff line number Diff line change
Expand Up @@ -940,20 +940,34 @@ Instances::operator= (const Instances &d)

m_parent_insts = d.m_parent_insts;

set_instance_by_cell_index_needs_made (true);
set_instance_tree_needs_sort (true);

}
return *this;
}

bool
Instances::is_editable () const
{
return mp_cell && mp_cell->layout () ? mp_cell->layout ()->is_editable () : true;
return cell () && cell ()->layout () ? cell ()->layout ()->is_editable () : true;
}

db::Layout *
Instances::layout () const
{
return mp_cell ? mp_cell->layout () : 0;
return cell () ? cell ()->layout () : 0;
}

void
Instances::invalidate_insts ()
{
if (cell ()) {
cell ()->invalidate_insts ();
}

set_instance_by_cell_index_needs_made (true);
set_instance_tree_needs_sort (true);
}

template <class Tag, class ET, class I>
Expand All @@ -962,14 +976,15 @@ Instances::erase_positions (Tag tag, ET editable_tag, I first, I last)
{
typedef instances_editable_traits<ET> editable_traits;

if (mp_cell) {
mp_cell->invalidate_insts (); // HINT: must come before the change is done!
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
invalidate_insts (); // HINT: must come before the change is done!

if (cell ()) {
if (cell ()->manager () && cell ()->manager ()->transacting ()) {
check_is_editable_for_undo_redo (this);
if (! is_editable ()) {
throw tl::Exception (tl::to_string (tr ("No undo/redo support for non-editable instance lists in 'erase_positions'")));
}
mp_cell->manager ()->queue (mp_cell, new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, first, last, true /*dummy*/));
cell ()->manager ()->queue (cell (), new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, first, last, true /*dummy*/));
}
}

Expand All @@ -983,18 +998,19 @@ Instances::insert (const InstArray &inst)
{
bool editable = is_editable ();

if (mp_cell) {
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
if (cell ()) {
if (cell ()->manager () && cell ()->manager ()->transacting ()) {
check_is_editable_for_undo_redo (this);
if (editable) {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesEditableTag> (true /*insert*/, inst));
cell ()->manager ()->queue (cell (), new db::InstOp<InstArray, InstancesEditableTag> (true /*insert*/, inst));
} else {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesNonEditableTag> (true /*insert*/, inst));
cell ()->manager ()->queue (cell (), new db::InstOp<InstArray, InstancesNonEditableTag> (true /*insert*/, inst));
}
}
mp_cell->invalidate_insts ();
}

invalidate_insts ();

// TODO: simplify this, i.e. through instance_from_pointer
if (editable) {
return instance_type (this, inst_tree (typename InstArray::tag (), InstancesEditableTag ()).insert (inst));
Expand All @@ -1010,14 +1026,14 @@ Instances::insert (I from, I to)
typedef std::iterator_traits<I> it_traits;
typedef typename it_traits::value_type value_type;

if (mp_cell) {
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
if (cell ()) {
if (cell ()->manager () && cell ()->manager ()->transacting ()) {
check_is_editable_for_undo_redo (this);
mp_cell->manager ()->queue (mp_cell, new db::InstOp<typename it_traits::value_type, ET> (true /*insert*/, from, to));
cell ()->manager ()->queue (cell (), new db::InstOp<typename it_traits::value_type, ET> (true /*insert*/, from, to));
}
mp_cell->invalidate_insts ();
}

invalidate_insts ();
inst_tree (typename value_type::tag (), ET ()).insert (from, to);
}

Expand Down Expand Up @@ -1061,20 +1077,21 @@ template <class InstArray>
void
Instances::replace (const InstArray *replace, const InstArray &with)
{
if (mp_cell) {
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
if (cell ()) {
if (cell ()->manager () && cell ()->manager ()->transacting ()) {
check_is_editable_for_undo_redo (this);
if (is_editable ()) {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesEditableTag> (false /*not insert*/, *replace));
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesEditableTag> (true /*insert*/, with));
cell ()->manager ()->queue (cell (), new db::InstOp<InstArray, InstancesEditableTag> (false /*not insert*/, *replace));
cell ()->manager ()->queue (cell (), new db::InstOp<InstArray, InstancesEditableTag> (true /*insert*/, with));
} else {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesNonEditableTag> (false /*not insert*/, *replace));
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesNonEditableTag> (true /*insert*/, with));
cell ()->manager ()->queue (cell (), new db::InstOp<InstArray, InstancesNonEditableTag> (false /*not insert*/, *replace));
cell ()->manager ()->queue (cell (), new db::InstOp<InstArray, InstancesNonEditableTag> (true /*insert*/, with));
}
}
mp_cell->invalidate_insts ();
}

invalidate_insts ();

// HINT: this only works because we know our box trees well:
*((InstArray *)replace) = with;
}
Expand Down Expand Up @@ -1150,11 +1167,12 @@ Instances::erase_inst_by_iter (Tag tag, ET editable_tag, I iter)
throw tl::Exception (tl::to_string (tr ("Trying to erase an object from a list that it does not belong to")));
}

if (mp_cell) {
mp_cell->invalidate_insts ();
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
invalidate_insts ();

if (cell ()) {
if (cell ()->manager () && cell ()->manager ()->transacting ()) {
check_is_editable_for_undo_redo (this);
mp_cell->manager ()->queue (mp_cell, new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, *iter));
cell ()->manager ()->queue (cell (), new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, *iter));
}
}

Expand All @@ -1165,11 +1183,12 @@ template <class Tag, class ET>
void
Instances::erase_inst_by_tag (Tag tag, ET editable_tag, const typename Tag::object_type &obj)
{
if (mp_cell) {
mp_cell->invalidate_insts ();
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
invalidate_insts ();

if (cell ()) {
if (cell ()->manager () && cell ()->manager ()->transacting ()) {
check_is_editable_for_undo_redo (this);
mp_cell->manager ()->queue (mp_cell, new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, obj));
cell ()->manager ()->queue (cell (), new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, obj));
}
}

Expand Down Expand Up @@ -1197,16 +1216,17 @@ template <class ET>
void
Instances::clear_insts (ET editable_tag)
{
if (mp_cell) {
mp_cell->invalidate_insts ();
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
invalidate_insts ();

if (cell ()) {
if (cell ()->manager () && cell ()->manager ()->transacting ()) {
check_is_editable_for_undo_redo (this);
const Instances *const_this = this;
if (! const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).empty ()) {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<cell_inst_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).end ()));
cell ()->manager ()->queue (cell (), new db::InstOp<cell_inst_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).end ()));
}
if (! const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).empty ()) {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<cell_inst_wp_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).end ()));
cell ()->manager ()->queue (cell (), new db::InstOp<cell_inst_wp_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).end ()));
}
}
}
Expand All @@ -1227,9 +1247,7 @@ Instances::clear_insts ()
void
Instances::clear (Instances::cell_inst_array_type::tag)
{
if (mp_cell) {
mp_cell->invalidate_insts ();
}
invalidate_insts ();

if (m_generic.any) {
if (is_editable ()) {
Expand All @@ -1244,9 +1262,7 @@ Instances::clear (Instances::cell_inst_array_type::tag)
void
Instances::clear (Instances::cell_inst_wp_array_type::tag)
{
if (mp_cell) {
mp_cell->invalidate_insts ();
}
invalidate_insts ();

if (m_generic_wp.any) {
if (is_editable ()) {
Expand Down Expand Up @@ -1371,8 +1387,13 @@ struct cell_inst_compare_f
};

void
Instances::sort_child_insts ()
Instances::sort_child_insts (bool force)
{
if (! force && ! instance_by_cell_index_needs_made ()) {
return;
}
set_instance_by_cell_index_needs_made (false);

m_insts_by_cell_index = sorted_inst_vector ();
m_insts_by_cell_index.reserve (cell_instances ());

Expand Down Expand Up @@ -1406,15 +1427,20 @@ Instances::sort_child_insts ()
}

void
Instances::sort_inst_tree (const Layout *g)
Instances::sort_inst_tree (const Layout *g, bool force)
{
if (! force && ! instance_tree_needs_sort ()) {
return;
}
set_instance_tree_needs_sort (false);

if (m_generic.any) {
if (is_editable ()) {
m_generic.stable_tree->sort (cell_inst_array_box_converter (*g));
} else {
m_generic.unstable_tree->sort (cell_inst_array_box_converter (*g));
// since we use unstable instance trees in non-editable mode, we need to resort the child instances in this case
sort_child_insts ();
sort_child_insts (true);
}
}
if (m_generic_wp.any) {
Expand All @@ -1423,7 +1449,7 @@ Instances::sort_inst_tree (const Layout *g)
} else {
m_generic_wp.unstable_tree->sort (cell_inst_wp_array_box_converter (*g));
// since we use unstable instance trees in non-editable mode, we need to resort the child instances in this case
sort_child_insts ();
sort_child_insts (true);
}
}

Expand Down Expand Up @@ -1603,16 +1629,17 @@ void Instances::apply_op (const Op &op, ET editable_tag)
bool has_insts = ! const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).empty ();
bool has_wp_insts = ! const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).empty ();

if (mp_cell) {
mp_cell->invalidate_insts ();
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
invalidate_insts ();

if (cell ()) {
if (cell ()->manager () && cell ()->manager ()->transacting ()) {
check_is_editable_for_undo_redo (this);
transacting = true;
if (has_insts) {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<cell_inst_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).end ()));
cell ()->manager ()->queue (cell (), new db::InstOp<cell_inst_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).end ()));
}
if (has_wp_insts) {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<cell_inst_wp_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).end ()));
cell ()->manager ()->queue (cell (), new db::InstOp<cell_inst_wp_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).end ()));
}
}
}
Expand All @@ -1637,10 +1664,10 @@ void Instances::apply_op (const Op &op, ET editable_tag)

if (transacting) {
if (has_insts) {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<cell_inst_array_type, ET> (true /*insert*/, const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).end ()));
cell ()->manager ()->queue (cell (), new db::InstOp<cell_inst_array_type, ET> (true /*insert*/, const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).end ()));
}
if (has_wp_insts) {
mp_cell->manager ()->queue (mp_cell, new db::InstOp<cell_inst_wp_array_type, ET> (true /*insert*/, const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).end ()));
cell ()->manager ()->queue (cell (), new db::InstOp<cell_inst_wp_array_type, ET> (true /*insert*/, const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_wp_array_type::tag (), editable_tag).end ()));
}
}
}
Expand Down
Loading
Loading