A couple of enhancements and bugfixes found during issue-1059 research (#1062)

* Opportunity fix: library selection box listed libraries with technology even though no technology is selected.

* Opportunity: show PCell errors on new error layer. Previously, errors were only shown when the PCell had at least a single layer parameter

The error text is drawn together with guiding shapes. Disabling guiding shapes will
turn off error display.

* Opportunity: fixed an issue when reloading a library immediately after loading a layout: in this case, the library connection got lost and cells were substituted by static ones

* Opportunity: added a layout cleanup for the following case: a layout is loaded without the library present - giving defunct cells. Then the library is registered and defunct cells are reconnected.
This commit is contained in:
Matthias Köfferlein 2022-04-10 18:44:24 +02:00 committed by GitHub
parent cb527cc50b
commit 3615b50fc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 91 additions and 17 deletions

View File

@ -355,6 +355,7 @@ Layout::Layout (db::Manager *manager)
m_properties_repository (this),
m_guiding_shape_layer (-1),
m_waste_layer (-1),
m_error_layer (-1),
m_do_cleanup (false),
m_editable (db::default_editable_mode ())
{
@ -372,6 +373,7 @@ Layout::Layout (bool editable, db::Manager *manager)
m_properties_repository (this),
m_guiding_shape_layer (-1),
m_waste_layer (-1),
m_error_layer (-1),
m_do_cleanup (false),
m_editable (editable)
{
@ -393,6 +395,7 @@ Layout::Layout (const db::Layout &layout)
m_properties_repository (this),
m_guiding_shape_layer (-1),
m_waste_layer (-1),
m_error_layer (-1),
m_do_cleanup (false),
m_editable (layout.m_editable)
{
@ -458,6 +461,7 @@ Layout::clear ()
m_guiding_shape_layer = -1;
m_waste_layer = -1;
m_error_layer = -1;
m_lib_proxy_map.clear ();
m_meta_info.clear ();
@ -474,6 +478,7 @@ Layout::operator= (const Layout &d)
m_guiding_shape_layer = d.m_guiding_shape_layer;
m_waste_layer = d.m_waste_layer;
m_error_layer = d.m_error_layer;
m_editable = d.m_editable;
m_pcell_ids = d.m_pcell_ids;
@ -1946,6 +1951,19 @@ Layout::get_layer (const db::LayerProperties &lp)
}
}
unsigned int
Layout::error_layer () const
{
if (m_error_layer < 0) {
// create the waste layer (since that layer is cached we can do
// this in a "const" fashion.
db::Layout *self = const_cast<db::Layout *> (this);
self->m_error_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE"));
}
return (unsigned int) m_error_layer;
}
unsigned int
Layout::waste_layer () const
{
@ -2555,8 +2573,15 @@ Layout::restore_proxies (ImportLayerMapping *layer_mapping)
}
}
bool needs_cleanup = false;
for (std::vector<db::ColdProxy *>::const_iterator p = cold_proxies.begin (); p != cold_proxies.end (); ++p) {
recover_proxy_as ((*p)->cell_index (), (*p)->context_info (), layer_mapping);
if (recover_proxy_as ((*p)->cell_index (), (*p)->context_info (), layer_mapping)) {
needs_cleanup = true;
}
}
if (needs_cleanup) {
cleanup ();
}
}

View File

@ -1709,6 +1709,13 @@ public:
*/
unsigned int waste_layer () const;
/**
* @brief Gets the error layer
*
* The error layer is used to display error messages.
*/
unsigned int error_layer () const;
/**
* @brief Set the properties for a specified layer
*/
@ -1891,6 +1898,7 @@ private:
lib_proxy_map m_lib_proxy_map;
int m_guiding_shape_layer;
int m_waste_layer;
int m_error_layer;
bool m_do_cleanup;
bool m_editable;
meta_info m_meta_info;

View File

@ -183,7 +183,6 @@ LibraryManager::register_lib (Library *library)
if (found) {
// substitute
old_lib = m_libs [l->second];
m_libs [l->second] = 0;
m_lib_by_name.erase (l);
}
@ -193,10 +192,19 @@ LibraryManager::register_lib (Library *library)
}
if (old_lib) {
old_lib->remap_to (library);
{
// reset the library pointer only after "remap_to" -> this function may need lib_by_id.
tl::MutexLocker locker (&m_lock);
m_libs [old_lib->get_id ()] = 0;
}
old_lib->set_id (std::numeric_limits<lib_id_type>::max ());
delete old_lib;
old_lib = 0;
}
// take care of cold referrers - these may not get valid

View File

@ -159,6 +159,11 @@ LibraryProxy::get_layer_indices (db::Layout &layout, db::ImportLayerMapping *lay
// map guiding shape layer
m_layer_indices.push_back ((int) layout.guiding_shape_layer ());
} else if (i == lib->layout ().error_layer ()) {
// map guiding shape layer
m_layer_indices.push_back ((int) layout.error_layer ());
} else if (! lib->layout ().is_valid_layer (i) || cell.bbox (i).empty ()) {
m_layer_indices.push_back (-1);

View File

@ -160,10 +160,8 @@ PCellVariant::update (ImportLayerMapping *layer_mapping)
m_display_name = header->declaration ()->get_display_name (m_parameters);
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
if (! layer_ids.empty ()) {
// put error messages into layout as text objects
shapes (layer_ids [0]).insert (db::Text (ex.msg (), db::Trans ()));
}
// put error messages into layout as text objects on error layer
shapes (layout ()->error_layer ()).insert (db::Text (ex.msg (), db::Trans ()));
}
// produce the shape parameters on the guiding shape layer so they can be edited

View File

@ -607,7 +607,7 @@ EditorOptionsInst::setup (lay::Dispatcher *root)
if (m_cv_index >= 0 && view ()->cellview (m_cv_index).is_valid ()) {
techname = view ()->cellview (m_cv_index)->tech_name ();
}
mp_ui->lib_cbx->set_technology_filter (techname, ! techname.empty ());
mp_ui->lib_cbx->set_technology_filter (techname, true);
// cell name
std::string s;

View File

@ -17,7 +17,7 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="margin" stdset="0">
<number>9</number>
</property>
<item>
@ -29,7 +29,7 @@
<bool>true</bool>
</property>
<layout class="QGridLayout">
<property name="margin">
<property name="margin" stdset="0">
<number>9</number>
</property>
<property name="spacing">
@ -47,7 +47,7 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
@ -84,7 +84,7 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
@ -122,7 +122,7 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
@ -220,13 +220,13 @@
<item>
<widget class="QGroupBox" name="pcell_gs_group">
<property name="title">
<string>Show PCell guiding shapes</string>
<string>Show PCell guiding and error shapes</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout">
<property name="margin">
<property name="margin" stdset="0">
<number>9</number>
</property>
<property name="spacing">

View File

@ -160,6 +160,21 @@ void render_cell_inst (const db::Layout &layout, const db::CellInstArray &inst,
}
{
// render error layer
db::RecursiveShapeIterator shapes (layout, cell, layout.error_layer ());
while (! shapes.at_end ()) {
for (db::CellInstArray::iterator arr = inst.begin (); ! arr.at_end (); ++arr) {
r.draw (*shapes, tr * inst.complex_trans (*arr) * shapes.trans (), fill, contour, 0 /*use vertex for origin*/, text);
}
++shapes;
}
}
// render the origins
if (render_origins && vertex) {

View File

@ -359,7 +359,7 @@ RedrawThreadWorker::perform_task (tl::Task *task)
}
}
// draw the guiding shapes
// draw the guiding and error shapes
for (std::set< std::pair<db::DCplxTrans, int> >::const_iterator b = m_box_variants.begin (); b != m_box_variants.end (); ++b) {
const lay::CellView &cv = m_cellviews [b->second];
@ -374,8 +374,6 @@ RedrawThreadWorker::perform_task (tl::Task *task)
// draw one level more to show the guiding shapes as part of the instance
m_to_level += 1; // TODO: modifying this basic setting is a hack!
m_layer = mp_layout->guiding_shape_layer ();
// configure renderer ..
mp_renderer->draw_texts (m_text_visible);
mp_renderer->draw_properties (false);
@ -384,13 +382,30 @@ RedrawThreadWorker::perform_task (tl::Task *task)
mp_renderer->set_font (db::Font (m_text_font));
mp_renderer->apply_text_trans (m_apply_text_trans);
bool f = m_text_lazy_rendering;
try {
m_text_lazy_rendering = false;
m_layer = mp_layout->guiding_shape_layer ();
iterate_variants (m_redraw_region, cv.cell_index (), trans, &RedrawThreadWorker::draw_layer);
iterate_variants (text_redraw_regions, cv.cell_index (), trans, &RedrawThreadWorker::draw_text_layer);
m_layer = mp_layout->error_layer ();
iterate_variants (m_redraw_region, cv.cell_index (), trans, &RedrawThreadWorker::draw_layer);
iterate_variants (text_redraw_regions, cv.cell_index (), trans, &RedrawThreadWorker::draw_text_layer);
m_text_lazy_rendering = f;
m_to_level -= 1;
} catch (...) {
m_text_lazy_rendering = f;
m_to_level -= 1;
throw;
}
}