From 6d0fe8542526d529f7ff893f8b529e2b60c722a0 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 11 Feb 2018 00:34:28 +0100 Subject: [PATCH] Fixed #75 (Python PCell issue when parameters are called 'layer') This commit - Ignores exceptions when checking for PCells that accept shapes. Hence a single rogue one does not break the feature. - Prevents errors when parameters named "layer" are present by making the implementation safe against this case. - In addition, guiding shape parameters of type "Path", "Box" etc. (i.e. integer types) are supported too although they are not recommended for portability. --- .../pcell_declaration_helper.lym | 15 ++++++-- src/db/db/dbPCellVariant.cc | 23 +++++++++++++ src/edt/edt/edtMainService.cc | 34 +++++++++++-------- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/db/db/built-in-pymacros/pcell_declaration_helper.lym b/src/db/db/built-in-pymacros/pcell_declaration_helper.lym index 13abeb6c5..c69cbc74a 100644 --- a/src/db/db/built-in-pymacros/pcell_declaration_helper.lym +++ b/src/db/db/built-in-pymacros/pcell_declaration_helper.lym @@ -226,16 +226,27 @@ class _PCellDeclarationHelperLayerDescriptor(object): class _PCellDeclarationHelperParameterDescriptor(object): """ A descriptor object which translates the PCell parameters into class attributes + + In some cases (i.e. can_convert_from_shape), these placeholders are not + connected to real parameters (obj._param_values is None). In this case, + the descriptor acts as a value holder (self.value) """ def __init__(self, param_index): self.param_index = param_index + self.value = None def __get__(self, obj, type = None): - return obj._param_values[self.param_index] + if obj._param_values: + return obj._param_values[self.param_index] + else: + return self.value def __set__(self, obj, value): - obj._param_values[self.param_index] = value + if obj._param_values: + obj._param_values[self.param_index] = value + else: + self.value = value class _PCellDeclarationHelper(pya.PCellDeclaration): """ diff --git a/src/db/db/dbPCellVariant.cc b/src/db/db/dbPCellVariant.cc index 0430996f0..55f67a840 100644 --- a/src/db/db/dbPCellVariant.cc +++ b/src/db/db/dbPCellVariant.cc @@ -186,15 +186,28 @@ PCellVariant::update (ImportLayerMapping *layer_mapping) shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { + + shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(db::Edge (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { + + shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { db::DPoint p = m_parameters[i].to_user (); shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (db::DBox (p, p) * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { + + db::Point p = m_parameters[i].to_user (); + shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (p, p), layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { db::complex_trans dbu_trans (1.0 / layout ()->dbu ()); @@ -202,11 +215,21 @@ PCellVariant::update (ImportLayerMapping *layer_mapping) // Hint: we don't compress the polygon since we don't want to loose information shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { + + db::Polygon poly = m_parameters[i].to_user (); + // Hint: we don't compress the polygon since we don't want to loose information + shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { db::complex_trans dbu_trans (1.0 / layout ()->dbu ()); shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(dbu_trans * m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + } else if (m_parameters[i].is_user ()) { + + shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + } } diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index 59bf0a572..0d98f3872 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -1084,23 +1084,29 @@ MainService::cm_convert_to_pcell () db::Library *lib = db::LibraryManager::instance ().lib (l->second); for (db::Layout::pcell_iterator pc = lib->layout ().begin_pcells (); pc != lib->layout ().end_pcells (); ++pc) { - const db::PCellDeclaration *pc_decl = lib->layout ().pcell_declaration (pc->second); - size_t n = 1000; // 1000 tries max. - for (std::vector::const_iterator es = edt_services.begin (); n > 0 && pc_decl && es != edt_services.end (); ++es) { - for (edt::Service::obj_iterator s = (*es)->selection ().begin (); n > 0 && pc_decl && s != (*es)->selection ().end (); ++s) { - const lay::CellView &cv = view ()->cellview (s->cv_index ()); - if (pc_decl->can_create_from_shape (cv->layout (), s->shape (), s->layer ())) { - --n; - } else { - pc_decl = 0; // stop + try { + + const db::PCellDeclaration *pc_decl = lib->layout ().pcell_declaration (pc->second); + size_t n = 1000; // 1000 tries max. + for (std::vector::const_iterator es = edt_services.begin (); n > 0 && pc_decl && es != edt_services.end (); ++es) { + for (edt::Service::obj_iterator s = (*es)->selection ().begin (); n > 0 && pc_decl && s != (*es)->selection ().end (); ++s) { + const lay::CellView &cv = view ()->cellview (s->cv_index ()); + if (pc_decl->can_create_from_shape (cv->layout (), s->shape (), s->layer ())) { + --n; + } else { + pc_decl = 0; // stop + } } } - } - // We have positive hit - if (pc_decl) { - pcells.push_back (std::make_pair (lib, pc->second)); - items.push_back (tl::to_qstring (lib->get_name () + "." + pc_decl->name ())); + // We have positive hit + if (pc_decl) { + pcells.push_back (std::make_pair (lib, pc->second)); + items.push_back (tl::to_qstring (lib->get_name () + "." + pc_decl->name ())); + } + + } catch (...) { + // ignore errors in can_create_from_shape } }