The problem was essentially the "specific path" which got invalid.
The solution is to establish a better criterion for "path validity"
and use for failsafes against invalid paths.

In addition, the path validation has been modified such that a
better choice is made about the remaining path after a cell gets
deleted.
This commit is contained in:
Matthias Koefferlein
2021-12-26 12:20:54 +01:00
parent 812e26aff9
commit 8e02b400ca
5 changed files with 140 additions and 142 deletions
+4 -4
View File
@@ -501,13 +501,13 @@ CellView::is_valid () const
}
// check, if the path references valid cell indices.
for (specific_cell_path_type::const_iterator pp = m_specific_path.begin (); pp != m_specific_path.end (); ++pp) {
if (! m_layout_href.get ()->layout ().is_valid_cell_index (pp->inst_ptr.cell_index ())) {
for (unspecific_cell_path_type::const_iterator pp = m_unspecific_path.begin (); pp != m_unspecific_path.end (); ++pp) {
if (! m_layout_href.get ()->layout ().is_valid_cell_index (*pp)) {
return false;
}
}
for (unspecific_cell_path_type::const_iterator pp = m_unspecific_path.begin (); pp != m_unspecific_path.end (); ++pp) {
if (! m_layout_href.get ()->layout ().is_valid_cell_index (*pp)) {
for (specific_cell_path_type::const_iterator pp = m_specific_path.begin (); pp != m_specific_path.end (); ++pp) {
if (! pp->inst_ptr.instances () || ! pp->inst_ptr.instances ()->is_valid (pp->inst_ptr) || ! m_layout_href.get ()->layout ().is_valid_cell_index (pp->inst_ptr.cell_index ())) {
return false;
}
}
@@ -836,6 +836,8 @@ HierarchyControlPanel::do_update_content (int cv_index)
if (&m_cellviews [i]->layout () != &mp_view->cellview (i)->layout ()) {
m_needs_update [i] = true;
m_force_close [i] = true;
} else if (! m_cellviews [i].is_valid ()) {
m_needs_update [i] = true;
} else if (m_cellviews [i].combined_unspecific_path () != mp_view->cellview (i).combined_unspecific_path ()) {
m_needs_update [i] = true;
}
+2
View File
@@ -4896,6 +4896,7 @@ LayoutView::select_cell_fit (const cell_path_type &path, int index)
set_min_hier_levels (0);
cancel ();
cellview_iter (index)->set_specific_path (lay::CellView::specific_cell_path_type ());
cellview_iter (index)->set_unspecific_path (path);
set_active_cellview_index (index);
redraw ();
@@ -4985,6 +4986,7 @@ LayoutView::select_cell (const cell_path_type &path, int index)
set_min_hier_levels (0);
cancel ();
cellview_iter (index)->set_specific_path (lay::CellView::specific_cell_path_type ());
cellview_iter (index)->set_unspecific_path (path);
set_active_cellview_index (index);
redraw ();
+38 -48
View File
@@ -42,6 +42,41 @@
namespace lay
{
static void
collect_cells_to_delete (const db::Layout &layout, const db::Cell &cell, std::set<db::cell_index_type> &called)
{
// don't delete proxies - they are deleted later when the layout is cleaned
for (db::Cell::child_cell_iterator cc = cell.begin_child_cells (); ! cc.at_end (); ++cc) {
if (called.find (*cc) == called.end () && !layout.cell (*cc).is_proxy ()) {
called.insert (*cc);
collect_cells_to_delete (layout, layout.cell (*cc), called);
}
}
}
static bool
validate_cell_path (const db::Layout &layout, lay::LayoutView::cell_path_type &path)
{
for (size_t i = 0; i < path.size (); ++i) {
if (! layout.is_valid_cell_index (path [i])) {
if (layout.is_valid_cell_index (path.back ())) {
// use a stub path
path.erase (path.begin (), --path.end ());
} else {
// strip everything that is not valid
path.erase (path.begin () + i, path.end ());
}
return true;
}
}
return false;
}
LayoutViewFunctions::LayoutViewFunctions (db::Manager *manager, LayoutView *view)
: lay::Plugin (view), mp_view (view), mp_manager (manager)
{
@@ -493,18 +528,7 @@ LayoutViewFunctions::cm_cell_replace ()
view ()->commit ();
// If one of the cells in the path was deleted, establish a valid path
bool needs_update = false;
for (size_t i = cell_path.size (); i > 0; ) {
--i;
if (! layout.is_valid_cell_index (cell_path [i])) {
cell_path.erase (cell_path.begin () + i, cell_path.end ());
needs_update = true;
}
}
if (needs_update) {
if (validate_cell_path (layout, cell_path)) {
view ()->select_cell (cell_path, cv_index);
}
@@ -613,36 +637,13 @@ LayoutViewFunctions::cm_cell_convert_to_static ()
view ()->commit ();
// If one of the cells in the path was deleted, establish a valid path
bool needs_update = false;
for (size_t i = cell_path.size (); i > 0; ) {
--i;
if (! layout.is_valid_cell_index (cell_path [i])) {
cell_path.erase (cell_path.begin () + i, cell_path.end ());
needs_update = true;
}
}
if (needs_update) {
if (validate_cell_path (layout, cell_path)) {
view ()->select_cell (cell_path, cv_index);
}
}
}
static void
collect_cells_to_delete (const db::Layout &layout, const db::Cell &cell, std::set<db::cell_index_type> &called)
{
// don't delete proxies - they are deleted later when the layout is cleaned
for (db::Cell::child_cell_iterator cc = cell.begin_child_cells (); ! cc.at_end (); ++cc) {
if (called.find (*cc) == called.end () && !layout.cell (*cc).is_proxy ()) {
called.insert (*cc);
collect_cells_to_delete (layout, layout.cell (*cc), called);
}
}
}
void
LayoutViewFunctions::cm_cell_delete ()
{
@@ -704,18 +705,7 @@ LayoutViewFunctions::cm_cell_delete ()
view ()->commit ();
// If one of the cells in the path was deleted, establish a valid path
bool needs_update = false;
for (size_t i = cell_path.size (); i > 0; ) {
--i;
if (! layout.is_valid_cell_index (cell_path [i])) {
cell_path.erase (cell_path.begin () + i, cell_path.end ());
needs_update = true;
}
}
if (needs_update) {
if (validate_cell_path (layout, cell_path)) {
view ()->select_cell (cell_path, cv_index);
}