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.
This commit is contained in:
Matthias Koefferlein 2018-02-11 00:34:28 +01:00
parent 6a762db29b
commit 6d0fe85425
3 changed files with 56 additions and 16 deletions

View File

@ -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):
"""

View File

@ -186,15 +186,28 @@ PCellVariant::update (ImportLayerMapping *layer_mapping)
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (m_parameters[i].to_user<db::DBox> () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::Box> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(m_parameters[i].to_user<db::Box> (), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::DEdge> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(db::Edge (m_parameters[i].to_user<db::DEdge> () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::Edge> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(m_parameters[i].to_user<db::Edge> (), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::DPoint> ()) {
db::DPoint p = m_parameters[i].to_user<db::DPoint> ();
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> ()) {
db::Point p = m_parameters[i].to_user<db::Point> ();
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::DPolygon> ()) {
db::complex_trans<db::DCoord, db::Coord> 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> ()) {
db::Polygon poly = m_parameters[i].to_user<db::Polygon> ();
// 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::DPath> ()) {
db::complex_trans<db::DCoord, db::Coord> dbu_trans (1.0 / layout ()->dbu ());
shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(dbu_trans * m_parameters[i].to_user<db::DPath> (), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::Path> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(m_parameters[i].to_user<db::Path> (), layout ()->properties_repository ().properties_id (props)));
}
}

View File

@ -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<edt::Service *>::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<edt::Service *>::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
}
}