mirror of https://github.com/KLayout/klayout.git
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:
parent
cb527cc50b
commit
3615b50fc4
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue