mirror of https://github.com/KLayout/klayout.git
Merge remote-tracking branch 'origin/master' into macos-build
This commit is contained in:
commit
be08e1a714
|
|
@ -343,7 +343,6 @@ Object::class_name () const
|
|||
void
|
||||
Object::from_string (const char *s)
|
||||
{
|
||||
printf("@@@ %s\n", s); fflush(stdout);
|
||||
tl::Extractor ex (s);
|
||||
while (! ex.at_end ()) {
|
||||
|
||||
|
|
|
|||
|
|
@ -1035,7 +1035,7 @@ public:
|
|||
|
||||
value_type operator* () const
|
||||
{
|
||||
return value_type (*(dynamic_cast<const ant::Object *> (m_iter->first->ptr ())), m_services[m_service]->view ());
|
||||
return value_type (*(static_cast<const ant::Object *> (m_iter->first->ptr ())), m_services[m_service]->view ());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -183,6 +183,13 @@ to create the \\LayerInfo object, i.e. like this:
|
|||
|
||||
The default implementation does nothing. All parameters not set in this method will receive their default value.
|
||||
|
||||
If you use a parameter called "layer" for example, the parameter getter will hide the
|
||||
"layer" argument. Use "_layer" for the argument in this case (same for "layout", "shape" or "cell):
|
||||
|
||||
@code
|
||||
set_layer layout.get_info(_layer)
|
||||
@/code
|
||||
|
||||
@method transformation_from_shape_impl
|
||||
|
||||
@brief Gets the initial PCell instance transformation when creating from a shape
|
||||
|
|
@ -230,6 +237,13 @@ module RBA
|
|||
|
||||
# provide accessors for the current layout and cell (for prod)
|
||||
attr_reader :layout, :cell, :shape, :layer
|
||||
|
||||
# provide fallback accessors in case of a name clash with a
|
||||
# parameter
|
||||
def _layer; @layer; end
|
||||
def _layout; @layout; end
|
||||
def _cell; @cell; end
|
||||
def _shape; @shape; end
|
||||
|
||||
# define a parameter
|
||||
# name -> the short name of the parameter
|
||||
|
|
@ -246,6 +260,12 @@ module RBA
|
|||
# set_{name} -> write accessor ({name}= does not work because the
|
||||
# Ruby confuses that method with variables)
|
||||
# {name}_layer -> read accessor for the layer index for TypeLayer parameters
|
||||
# in addition, fallback accessors are defined which can be used if
|
||||
# the parameter's name clashes with another name:
|
||||
# param_{name}
|
||||
# set_param_{name}
|
||||
# param_{name}_layer
|
||||
|
||||
def param(name, type, description, args = {})
|
||||
|
||||
# create accessor methods for the parameters
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class MyPCell(pya.PCellDeclarationHelper):
|
|||
def __init__(self):
|
||||
|
||||
# Important: initialize the super class
|
||||
super(Circle, self).__init__()
|
||||
super(MyPCell, self).__init__()
|
||||
|
||||
# your initialization: add parameters with name, type, description and
|
||||
# optional other values
|
||||
|
|
@ -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):
|
||||
"""
|
||||
|
|
@ -321,7 +332,38 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
|
|||
gets the parameters
|
||||
"""
|
||||
return self._param_decls
|
||||
|
||||
def get_values(self):
|
||||
"""
|
||||
gets the temporary parameter values
|
||||
"""
|
||||
v = self._param_values
|
||||
self._param_values = None
|
||||
return v
|
||||
|
||||
def init_values(self, values = None, layers = None):
|
||||
"""
|
||||
initializes the temporary parameter values
|
||||
"values" are the original values. If "None" is given, the
|
||||
default values will be used.
|
||||
"layers" are the layer indexes corresponding to the layer
|
||||
parameters.
|
||||
"""
|
||||
if not values:
|
||||
self._param_values = []
|
||||
for pd in self._param_decls:
|
||||
self._param_values.append(pd.default)
|
||||
else:
|
||||
self._param_values = values
|
||||
self._layers = layers
|
||||
|
||||
def finish(self):
|
||||
"""
|
||||
Needs to be called at the end of produce() after init_values was used
|
||||
"""
|
||||
self._param_values = None
|
||||
self._layers = None
|
||||
|
||||
def get_layers(self, parameters):
|
||||
"""
|
||||
get the layer definitions
|
||||
|
|
@ -335,25 +377,23 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
|
|||
"""
|
||||
coerce parameters (make consistent)
|
||||
"""
|
||||
self._param_values = parameters
|
||||
self.init_values(parameters)
|
||||
self.layout = layout
|
||||
self.coerce_parameters_impl()
|
||||
self.layout = None
|
||||
return self._param_values
|
||||
return self.get_values()
|
||||
|
||||
def produce(self, layout, layers, parameters, cell):
|
||||
"""
|
||||
coerce parameters (make consistent)
|
||||
"""
|
||||
self._layers = layers
|
||||
self.init_values(parameters, layers)
|
||||
self.cell = cell
|
||||
self._param_values = parameters
|
||||
self.layout = layout
|
||||
self.produce_impl()
|
||||
self._layers = None
|
||||
self.cell = None
|
||||
self._param_values = None
|
||||
self.layout = None
|
||||
self.finish()
|
||||
|
||||
def can_create_from_shape(self, layout, shape, layer):
|
||||
"""
|
||||
|
|
@ -386,17 +426,16 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
|
|||
produce a helper for parameters_from_shape
|
||||
with this helper, the implementation can use the parameter setters
|
||||
"""
|
||||
self._param_values = []
|
||||
for pd in self._param_decls:
|
||||
self._param_values.append(pd.default)
|
||||
self.init_values()
|
||||
self.layout = layout
|
||||
self.shape = shape
|
||||
self.layer = layer
|
||||
self.parameters_from_shape_impl()
|
||||
param = self.get_values()
|
||||
self.layout = None
|
||||
self.shape = None
|
||||
self.layer = None
|
||||
return self._param_values
|
||||
return param
|
||||
|
||||
def display_text_impl(self):
|
||||
"""
|
||||
|
|
@ -432,7 +471,7 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
|
|||
"""
|
||||
default implementation
|
||||
"""
|
||||
return pya.Trans.new
|
||||
return pya.Trans()
|
||||
|
||||
# import the Type... constants from PCellParameterDeclaration
|
||||
for k in dir(pya.PCellParameterDeclaration):
|
||||
|
|
|
|||
|
|
@ -110,6 +110,18 @@ OASISReader::OASISReader (tl::InputStream &s)
|
|||
{
|
||||
m_progress.set_format (tl::to_string (QObject::tr ("%.0f MB")));
|
||||
m_progress.set_unit (1024 * 1024);
|
||||
m_first_cellname = 0;
|
||||
m_first_propname = 0;
|
||||
m_first_propstring = 0;
|
||||
m_first_textstring = 0;
|
||||
m_first_layername = 0;
|
||||
m_in_table = NotInTable;
|
||||
m_table_cellname = 0;
|
||||
m_table_propname = 0;
|
||||
m_table_propstring = 0;
|
||||
m_table_textstring = 0;
|
||||
m_table_layername = 0;
|
||||
m_table_start = 0;
|
||||
}
|
||||
|
||||
OASISReader::~OASISReader ()
|
||||
|
|
@ -197,6 +209,16 @@ OASISReader::get_long ()
|
|||
}
|
||||
}
|
||||
|
||||
inline unsigned long
|
||||
OASISReader::get_ulong_for_divider ()
|
||||
{
|
||||
unsigned long l = get_ulong ();
|
||||
if (l == 0) {
|
||||
error (tl::to_string (QObject::tr ("Divider must not be zero")));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
inline unsigned long
|
||||
OASISReader::get_ulong ()
|
||||
{
|
||||
|
|
@ -295,21 +317,21 @@ OASISReader::get_real ()
|
|||
|
||||
} else if (t == 2) {
|
||||
|
||||
return 1.0 / double (get_ulong ());
|
||||
return 1.0 / double (get_ulong_for_divider ());
|
||||
|
||||
} else if (t == 3) {
|
||||
|
||||
return -1.0 / double (get_ulong ());
|
||||
return -1.0 / double (get_ulong_for_divider ());
|
||||
|
||||
} else if (t == 4) {
|
||||
|
||||
double d = double (get_ulong ());
|
||||
return d / double (get_ulong ());
|
||||
return d / double (get_ulong_for_divider ());
|
||||
|
||||
} else if (t == 5) {
|
||||
|
||||
double d = double (get_ulong ());
|
||||
return -d / double (get_ulong ());
|
||||
return -d / double (get_ulong_for_divider ());
|
||||
|
||||
} else if (t == 6) {
|
||||
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ private:
|
|||
unsigned long long get_ulong_long ();
|
||||
long get_long ();
|
||||
unsigned long get_ulong ();
|
||||
unsigned long get_ulong_for_divider ();
|
||||
int get_int ();
|
||||
unsigned int get_uint ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,6 +276,8 @@ RecursiveShapeIterator::init ()
|
|||
m_shape_inv_prop_sel = false;
|
||||
m_inst_quad_id = 0;
|
||||
m_shape_quad_id = 0;
|
||||
mp_cell = 0;
|
||||
m_current_layer = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -883,8 +883,6 @@ static bool cell_has_prop_id (const db::Cell *c)
|
|||
|
||||
static void delete_cell_property (db::Cell *c, const tl::Variant &key)
|
||||
{
|
||||
check_is_editable (c);
|
||||
|
||||
db::properties_id_type id = c->prop_id ();
|
||||
if (id == 0) {
|
||||
return;
|
||||
|
|
@ -911,8 +909,6 @@ static void delete_cell_property (db::Cell *c, const tl::Variant &key)
|
|||
|
||||
static void set_cell_property (db::Cell *c, const tl::Variant &key, const tl::Variant &value)
|
||||
{
|
||||
check_is_editable (c);
|
||||
|
||||
db::properties_id_type id = c->prop_id ();
|
||||
|
||||
db::Layout *layout = c->layout ();
|
||||
|
|
@ -1110,13 +1106,11 @@ static void move_or_copy_from_other_cell (db::Cell *cell, db::Cell *src_cell, un
|
|||
|
||||
static void move_from_other_cell (db::Cell *cell, db::Cell *src_cell, unsigned int src_layer, unsigned int dest_layer)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
move_or_copy_from_other_cell (cell, src_cell, src_layer, dest_layer, true);
|
||||
}
|
||||
|
||||
static void copy_from_other_cell (db::Cell *cell, db::Cell *src_cell, unsigned int src_layer, unsigned int dest_layer)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
move_or_copy_from_other_cell (cell, src_cell, src_layer, dest_layer, false);
|
||||
}
|
||||
|
||||
|
|
@ -1158,7 +1152,6 @@ write_options (const db::Cell *cell, const std::string &filename, const db::Save
|
|||
static void
|
||||
clear_all (db::Cell *cell)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
cell->clear_shapes ();
|
||||
cell->clear_insts ();
|
||||
}
|
||||
|
|
@ -1166,7 +1159,6 @@ clear_all (db::Cell *cell)
|
|||
static void
|
||||
delete_cell (db::Cell *cell)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
db::Layout *layout = cell->layout ();
|
||||
if (layout) {
|
||||
layout->delete_cell (cell->cell_index ());
|
||||
|
|
@ -1176,7 +1168,6 @@ delete_cell (db::Cell *cell)
|
|||
static void
|
||||
prune_subcells (db::Cell *cell, int levels)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
db::Layout *layout = cell->layout ();
|
||||
if (layout) {
|
||||
layout->prune_subcells (cell->cell_index (), levels);
|
||||
|
|
@ -1192,7 +1183,6 @@ prune_subcells0 (db::Cell *cell)
|
|||
static void
|
||||
prune_cell (db::Cell *cell, int levels)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
db::Layout *layout = cell->layout ();
|
||||
if (layout) {
|
||||
layout->prune_cell (cell->cell_index (), levels);
|
||||
|
|
@ -1208,7 +1198,6 @@ prune_cell0 (db::Cell *cell)
|
|||
static void
|
||||
flatten (db::Cell *cell, int levels, bool prune)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
db::Layout *layout = cell->layout ();
|
||||
if (layout) {
|
||||
layout->flatten (*cell, levels, prune);
|
||||
|
|
@ -1288,8 +1277,6 @@ begin_shapes_rec_overlapping_um (const db::Cell *cell, unsigned int layer, db::D
|
|||
|
||||
static void copy_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db::LayerMapping &layer_mapping)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot copy shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1318,8 +1305,6 @@ static void copy_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db:
|
|||
|
||||
static void copy_shapes1 (db::Cell *cell, const db::Cell &source_cell)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot copy shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1344,8 +1329,6 @@ static void copy_shapes1 (db::Cell *cell, const db::Cell &source_cell)
|
|||
|
||||
static void copy_instances (db::Cell *cell, const db::Cell &source_cell)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot copy instances within the same cell")));
|
||||
}
|
||||
|
|
@ -1360,8 +1343,6 @@ static void copy_instances (db::Cell *cell, const db::Cell &source_cell)
|
|||
|
||||
static std::vector<db::cell_index_type> copy_tree (db::Cell *cell, const db::Cell &source_cell)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot copy shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1393,8 +1374,6 @@ static std::vector<db::cell_index_type> copy_tree (db::Cell *cell, const db::Cel
|
|||
|
||||
static void copy_tree_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db::CellMapping &cm)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot copy shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1421,8 +1400,6 @@ static void copy_tree_shapes2 (db::Cell *cell, const db::Cell &source_cell, cons
|
|||
|
||||
static void copy_tree_shapes3 (db::Cell *cell, const db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot copy shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1446,8 +1423,6 @@ static void copy_tree_shapes3 (db::Cell *cell, const db::Cell &source_cell, cons
|
|||
|
||||
static void move_shapes2 (db::Cell *cell, db::Cell &source_cell, const db::LayerMapping &layer_mapping)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot move shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1478,8 +1453,6 @@ static void move_shapes2 (db::Cell *cell, db::Cell &source_cell, const db::Layer
|
|||
|
||||
static void move_shapes1 (db::Cell *cell, db::Cell &source_cell)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot move shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1505,8 +1478,6 @@ static void move_shapes1 (db::Cell *cell, db::Cell &source_cell)
|
|||
|
||||
static void move_instances (db::Cell *cell, db::Cell &source_cell)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot move instances within the same cell")));
|
||||
}
|
||||
|
|
@ -1523,8 +1494,6 @@ static void move_instances (db::Cell *cell, db::Cell &source_cell)
|
|||
|
||||
static std::vector<db::cell_index_type> move_tree (db::Cell *cell, db::Cell &source_cell)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot move shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1558,8 +1527,6 @@ static std::vector<db::cell_index_type> move_tree (db::Cell *cell, db::Cell &sou
|
|||
|
||||
static void move_tree_shapes2 (db::Cell *cell, db::Cell &source_cell, const db::CellMapping &cm)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot move shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1586,8 +1553,6 @@ static void move_tree_shapes2 (db::Cell *cell, db::Cell &source_cell, const db::
|
|||
|
||||
static void move_tree_shapes3 (db::Cell *cell, db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (cell == &source_cell) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Cannot move shapes within the same cell")));
|
||||
}
|
||||
|
|
@ -1612,8 +1577,6 @@ static void move_tree_shapes3 (db::Cell *cell, db::Cell &source_cell, const db::
|
|||
static void
|
||||
fill_region1 (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (fc_box.empty () || fc_box.width () == 0 || fc_box.height () == 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid fill cell footprint (empty or zero width/height)")));
|
||||
}
|
||||
|
|
@ -1624,8 +1587,6 @@ static void
|
|||
fill_region2 (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin,
|
||||
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons)
|
||||
{
|
||||
check_is_editable (cell);
|
||||
|
||||
if (fc_box.empty () || fc_box.width () == 0 || fc_box.height () == 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid fill cell footprint (empty or zero width/height)")));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ struct A : public db::Object
|
|||
void redo (db::Op *op) throw ()
|
||||
{
|
||||
AO *aop = dynamic_cast<AO *> (op);
|
||||
tl_assert (aop != 0);
|
||||
x += aop->d;
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +163,7 @@ struct B : public db::Object
|
|||
void redo (db::Op *op) throw ()
|
||||
{
|
||||
BO *bop = dynamic_cast<BO *> (op);
|
||||
tl_assert (bop != 0);
|
||||
x += bop->d;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3922,9 +3922,9 @@ CODE
|
|||
n = $1.to_i - 1
|
||||
view = RBA::LayoutView::current
|
||||
view || raise("No view open")
|
||||
(n >= 0 && view.cellviews > n) || raise("Invalid layout index @#{n}")
|
||||
(n >= 0 && view.cellviews > n) || raise("Invalid layout index @#{n + 1}")
|
||||
cv = view.cellview(n)
|
||||
cv.is_valid? || raise("Invalid layout @#{n}")
|
||||
cv.is_valid? || raise("Invalid layout @#{n + 1}")
|
||||
@def_source = make_source(cv.layout, cv.cell)
|
||||
else
|
||||
layout = RBA::Layout::new
|
||||
|
|
@ -4016,9 +4016,9 @@ CODE
|
|||
n = $1.to_i - 1
|
||||
view = RBA::LayoutView::current
|
||||
view || raise("No view open")
|
||||
(n >= 0 && view.cellviews > n) || raise("Invalid layout index @#{n}")
|
||||
(n >= 0 && view.cellviews > n) || raise("Invalid layout index @#{n + 1}")
|
||||
cv = view.cellview(n)
|
||||
cv.is_valid? || raise("Invalid layout @#{n}")
|
||||
cv.is_valid? || raise("Invalid layout @#{n + 1}")
|
||||
return make_source(cv.layout, cv.cell)
|
||||
else
|
||||
layout = RBA::Layout::new
|
||||
|
|
@ -4173,9 +4173,9 @@ CODE
|
|||
n = $1.to_i - 1
|
||||
view = RBA::LayoutView::current
|
||||
view || raise("No view open")
|
||||
(n >= 0 && view.cellviews > n) || raise("Invalid layout index @#{n}")
|
||||
(n >= 0 && view.cellviews > n) || raise("Invalid layout index @#{n + 1}")
|
||||
cv = view.cellview(n)
|
||||
cv.is_valid? || raise("Invalid layout @#{n}")
|
||||
cv.is_valid? || raise("Invalid layout @#{n + 1}")
|
||||
@output_layout = cv.layout
|
||||
@output_cell = cellname ? (@output_layout.cell(cellname.to_s) || @output_layout.create_cell(cellname.to_s)) : cv.cell
|
||||
@output_layout_file = nil
|
||||
|
|
@ -4694,11 +4694,20 @@ CODE
|
|||
|
||||
else
|
||||
|
||||
output = @output_layout || @def_layout
|
||||
output || raise("No output layout specified")
|
||||
|
||||
output_cell = @output_cell || @def_cell
|
||||
output_cell || raise("No output cell specified")
|
||||
if @output_layout
|
||||
output = @output_layout
|
||||
if @output_cell
|
||||
output_cell = @output_cell
|
||||
elsif @def_cell
|
||||
output_cell = @output_layout.cell(@def_cell.name) || @output_layout.create_cell(@def_cell.name)
|
||||
end
|
||||
output_cell || raise("No output cell specified (see 'target' instruction)")
|
||||
else
|
||||
output = @def_layout
|
||||
output || raise("No output layout specified")
|
||||
output_cell = @output_cell || @def_cell
|
||||
output_cell || raise("No output cell specified")
|
||||
end
|
||||
|
||||
info = nil
|
||||
if args.size == 1
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1092,7 +1092,7 @@ Net::Net ()
|
|||
}
|
||||
|
||||
Net::Net (const NetTracer &tracer, const db::ICplxTrans &trans, const db::Layout &layout, db::cell_index_type cell_index, const std::string &layout_filename, const std::string &layout_name, const NetTracerData &data)
|
||||
: m_name (tracer.name ()), m_incomplete (tracer.incomplete ())
|
||||
: m_name (tracer.name ()), m_incomplete (tracer.incomplete ()), m_trace_path (false)
|
||||
{
|
||||
m_dbu = layout.dbu ();
|
||||
m_top_cell_name = layout.cell_name (cell_index);
|
||||
|
|
|
|||
|
|
@ -607,11 +607,30 @@ RS274XMacroAperture::do_produce_flash ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
RS274XMacroAperture::read_exposure (tl::Extractor &ex, bool &clear, bool &clear_set)
|
||||
{
|
||||
int pol = int (floor (read_expr (ex) + 0.5));
|
||||
|
||||
if (pol == 0) {
|
||||
clear = true;
|
||||
} else if (pol == 1) {
|
||||
clear = false;
|
||||
} else if (pol == 2) {
|
||||
clear = !clear_set || !clear;
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid exposure code '%d'")), pol);
|
||||
}
|
||||
|
||||
clear_set = true;
|
||||
}
|
||||
|
||||
void
|
||||
RS274XMacroAperture::do_produce_flash_internal ()
|
||||
{
|
||||
tl::Extractor ex (m_def.c_str ());
|
||||
bool clear = false;
|
||||
bool clear_set = false;
|
||||
|
||||
while (! ex.at_end ()) {
|
||||
|
||||
|
|
@ -640,18 +659,7 @@ RS274XMacroAperture::do_produce_flash_internal ()
|
|||
if (code == 1) {
|
||||
|
||||
ex.expect (",");
|
||||
int pol = (read_expr (ex) > 0.5);
|
||||
|
||||
if (pol == 0) {
|
||||
clear = true;
|
||||
} else if (pol == 1) {
|
||||
clear = false;
|
||||
} else if (pol == 2) {
|
||||
clear = !clear;
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid exposure code '%d'")), pol);
|
||||
}
|
||||
|
||||
read_exposure (ex, clear, clear_set);
|
||||
ex.expect (",");
|
||||
double d = read_expr (ex, true);
|
||||
ex.expect (",");
|
||||
|
|
@ -670,18 +678,7 @@ RS274XMacroAperture::do_produce_flash_internal ()
|
|||
} else if (code == 2 || code == 20) {
|
||||
|
||||
ex.expect (",");
|
||||
int pol = (read_expr (ex) > 0.5);
|
||||
|
||||
if (pol == 0) {
|
||||
clear = true;
|
||||
} else if (pol == 1) {
|
||||
clear = false;
|
||||
} else if (pol == 2) {
|
||||
clear = !clear;
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid exposure code '%d'")), pol);
|
||||
}
|
||||
|
||||
read_exposure (ex, clear, clear_set);
|
||||
ex.expect (",");
|
||||
double w = read_expr (ex, true);
|
||||
ex.expect (",");
|
||||
|
|
@ -723,18 +720,7 @@ RS274XMacroAperture::do_produce_flash_internal ()
|
|||
} else if (code == 21 || code == 22) {
|
||||
|
||||
ex.expect (",");
|
||||
int pol = (read_expr (ex) > 0.5);
|
||||
|
||||
if (pol == 0) {
|
||||
clear = true;
|
||||
} else if (pol == 1) {
|
||||
clear = false;
|
||||
} else if (pol == 2) {
|
||||
clear = !clear;
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid exposure code '%d'")), pol);
|
||||
}
|
||||
|
||||
read_exposure (ex, clear, clear_set);
|
||||
ex.expect (",");
|
||||
double w = read_expr (ex, true);
|
||||
ex.expect (",");
|
||||
|
|
@ -766,18 +752,7 @@ RS274XMacroAperture::do_produce_flash_internal ()
|
|||
} else if (code == 4) {
|
||||
|
||||
ex.expect (",");
|
||||
int pol = (read_expr (ex) > 0.5);
|
||||
|
||||
if (pol == 0) {
|
||||
clear = true;
|
||||
} else if (pol == 1) {
|
||||
clear = false;
|
||||
} else if (pol == 2) {
|
||||
clear = !clear;
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid exposure code '%d'")), pol);
|
||||
}
|
||||
|
||||
read_exposure (ex, clear, clear_set);
|
||||
ex.expect (",");
|
||||
int n = int (read_expr (ex) + 0.5);
|
||||
if (n < 1) {
|
||||
|
|
@ -854,18 +829,7 @@ RS274XMacroAperture::do_produce_flash_internal ()
|
|||
} else if (code == 5) {
|
||||
|
||||
ex.expect (",");
|
||||
int pol = (read_expr (ex) > 0.5);
|
||||
|
||||
if (pol == 0) {
|
||||
clear = true;
|
||||
} else if (pol == 1) {
|
||||
clear = false;
|
||||
} else if (pol == 2) {
|
||||
clear = !clear;
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Invalid exposure code '%d'")), pol);
|
||||
}
|
||||
|
||||
read_exposure (ex, clear, clear_set);
|
||||
ex.expect (",");
|
||||
int n = int (read_expr (ex) + 0.5);
|
||||
if (n < 3) {
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ private:
|
|||
double read_atom (tl::Extractor &ex);
|
||||
double read_dot_expr (tl::Extractor &ex);
|
||||
double read_expr (tl::Extractor &ex, bool length = false);
|
||||
void read_exposure (tl::Extractor &ex, bool &clear, bool &clear_set);
|
||||
void do_produce_flash_internal ();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -524,7 +524,6 @@ private:
|
|||
ArgType m_ret_type;
|
||||
bool m_const : 1;
|
||||
bool m_static : 1;
|
||||
bool m_is_predicate : 1;
|
||||
bool m_protected : 1;
|
||||
unsigned int m_argsize;
|
||||
std::vector<MethodSynonym> m_method_synonyms;
|
||||
|
|
|
|||
|
|
@ -697,12 +697,14 @@ static size_t make_id ()
|
|||
Object::Object ()
|
||||
: m_trans (1.0), mp_data (0), m_id (make_id ()), m_min_value (0.0), m_max_value (1.0), m_min_value_set (false), m_max_value_set (false), m_visible (true), m_z_position (0)
|
||||
{
|
||||
m_updates_enabled = false;
|
||||
mp_pixel_data = 0;
|
||||
}
|
||||
|
||||
Object::Object (size_t w, size_t h, const db::DCplxTrans &trans, bool color)
|
||||
: m_trans (trans), m_id (make_id ()), m_min_value (0.0), m_max_value (1.0), m_min_value_set (false), m_max_value_set (false), m_visible (true), m_z_position (0)
|
||||
{
|
||||
m_updates_enabled = false;
|
||||
mp_pixel_data = 0;
|
||||
|
||||
mp_data = new DataHeader (w, h, color, false);
|
||||
|
|
|
|||
|
|
@ -211,10 +211,12 @@ ProgressReporter::set_visible (bool vis)
|
|||
// actual operation
|
||||
tl::DeferredMethodScheduler::enable (!vis);
|
||||
|
||||
if (!vis) {
|
||||
mp_pb->progress_remove_widget ();
|
||||
} else if (mp_pb->progress_wants_widget () && mp_objects.front ()) {
|
||||
mp_pb->progress_add_widget (mp_objects.front ()->progress_widget ());
|
||||
if (mp_pb) {
|
||||
if (!vis) {
|
||||
mp_pb->progress_remove_widget ();
|
||||
} else if (mp_pb->progress_wants_widget () && mp_objects.front ()) {
|
||||
mp_pb->progress_add_widget (mp_objects.front ()->progress_widget ());
|
||||
}
|
||||
}
|
||||
|
||||
m_pw_visible = vis;
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ SaltGrainPropertiesDialog::dependency_changed (QTreeWidgetItem *item, int column
|
|||
m_update_enabled = false;
|
||||
|
||||
std::string name = tl::to_string (item->data (0, Qt::UserRole).toString ().simplified ());
|
||||
SaltGrain *g = mp_salt->grain_by_name (name);
|
||||
SaltGrain *g = mp_salt ? mp_salt->grain_by_name (name) : 0;
|
||||
|
||||
if (column == 0 && mp_salt) {
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ static lay::Technology *create_technology (const std::string &name)
|
|||
{
|
||||
lay::Technology *tech = new lay::Technology ();
|
||||
tech->set_name (name);
|
||||
lay::Technologies::instance ()->add (tech);
|
||||
lay::Technologies::instance ()->add_new (tech);
|
||||
return tech;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,11 +88,13 @@ save_dialog_state (QWidget *w)
|
|||
|
||||
}
|
||||
|
||||
for (QList<QObject *>::const_iterator c = w->children ().begin (); c != w->children ().end (); ++c) {
|
||||
if (dynamic_cast <QWidget *> (*c)) {
|
||||
std::string cs = save_dialog_state (dynamic_cast <QWidget *> (*c));
|
||||
if (! cs.empty ()) {
|
||||
s += cs;
|
||||
if (w) {
|
||||
for (QList<QObject *>::const_iterator c = w->children ().begin (); c != w->children ().end (); ++c) {
|
||||
if (dynamic_cast <QWidget *> (*c)) {
|
||||
std::string cs = save_dialog_state (dynamic_cast <QWidget *> (*c));
|
||||
if (! cs.empty ()) {
|
||||
s += cs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ Technologies::Technologies ()
|
|||
Technologies::Technologies (const Technologies &other)
|
||||
: tl::Object ()
|
||||
{
|
||||
m_changed = false;
|
||||
m_in_update = false;
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
|
|
@ -115,19 +117,30 @@ Technologies::load_from_xml (const std::string &s)
|
|||
}
|
||||
|
||||
void
|
||||
Technologies::add (Technology *technology)
|
||||
Technologies::add_tech (Technology *tech, bool replace_same)
|
||||
{
|
||||
for (tl::stable_vector<Technology>::iterator t = m_technologies.begin (); technology && t != m_technologies.end (); ++t) {
|
||||
if (t->name () == technology->name ()) {
|
||||
*t = *technology;
|
||||
delete technology;
|
||||
technology = 0;
|
||||
if (! tech) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::auto_ptr<Technology> tech_ptr (tech);
|
||||
|
||||
Technology *t = 0;
|
||||
for (tl::stable_vector<Technology>::iterator i = m_technologies.begin (); !t && i != m_technologies.end (); ++i) {
|
||||
if (i->name () == tech->name ()) {
|
||||
t = i.operator-> ();
|
||||
}
|
||||
}
|
||||
|
||||
if (technology) {
|
||||
m_technologies.push_back (technology);
|
||||
technology->technology_changed_with_sender_event.add (this, &Technologies::technology_changed);
|
||||
if (t) {
|
||||
if (replace_same) {
|
||||
*t = *tech;
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("A technology with this name already exists: %1").arg (tl::to_qstring (tech->name ()))));
|
||||
}
|
||||
} else {
|
||||
m_technologies.push_back (tech_ptr.release ());
|
||||
tech->technology_changed_with_sender_event.add (this, &Technologies::technology_changed);
|
||||
}
|
||||
|
||||
technologies_changed ();
|
||||
|
|
@ -218,6 +231,7 @@ Technologies::technology_by_name (const std::string &name)
|
|||
}
|
||||
}
|
||||
|
||||
tl_assert (! m_technologies.empty ());
|
||||
return &*m_technologies.begin ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,22 @@ public:
|
|||
* The container becomes owner of the technology object.
|
||||
* Replaces a technology with the name of the given technology.
|
||||
*/
|
||||
void add (Technology *technology);
|
||||
void add (Technology *technology)
|
||||
{
|
||||
add_tech (technology, true /*replace*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a technology with a new name
|
||||
*
|
||||
* Like \add, but throws an exception if a technology with this name
|
||||
* already exists. Takes over ownership over the technology object.
|
||||
* The technology object is discarded if an exception is thrown.
|
||||
*/
|
||||
void add_new (Technology *technology)
|
||||
{
|
||||
add_tech (technology, false /*throws exception on same name*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove a technology with the given name from the setup
|
||||
|
|
@ -233,6 +248,8 @@ private:
|
|||
tl::stable_vector<Technology> m_technologies;
|
||||
bool m_changed;
|
||||
bool m_in_update;
|
||||
|
||||
void add_tech (Technology *technology, bool replace_same);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -915,26 +915,28 @@ void Macro::install_doc () const
|
|||
|
||||
if (cls == 0) {
|
||||
tl::error << tl::to_string (QObject::tr ("Reading class doc from ")) << path () << ": " << tl::to_string (QObject::tr ("@method without preceeding @class"));
|
||||
}
|
||||
} else {
|
||||
|
||||
std::string n;
|
||||
ex.read_word_or_quoted (n);
|
||||
std::string n;
|
||||
ex.read_word_or_quoted (n);
|
||||
|
||||
std::string doc;
|
||||
while (++i < lines.size ()) {
|
||||
std::string l = tl::trim (lines [i]);
|
||||
if (l.find ("@method") == 0 || l.find ("@static_method") == 0) {
|
||||
break;
|
||||
std::string doc;
|
||||
while (++i < lines.size ()) {
|
||||
std::string l = tl::trim (lines [i]);
|
||||
if (l.find ("@method") == 0 || l.find ("@static_method") == 0) {
|
||||
break;
|
||||
}
|
||||
if (! doc.empty ()) {
|
||||
doc += "\n";
|
||||
}
|
||||
doc += lines [i];
|
||||
}
|
||||
if (! doc.empty ()) {
|
||||
doc += "\n";
|
||||
}
|
||||
doc += lines [i];
|
||||
}
|
||||
--i;
|
||||
--i;
|
||||
|
||||
ExternalMethod *meth = new ExternalMethod (n, doc, false, st);
|
||||
cls->add_method (meth);
|
||||
ExternalMethod *meth = new ExternalMethod (n, doc, false, st);
|
||||
cls->add_method (meth);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1945,7 +1945,11 @@ property_setter_impl (int mid, PyObject *self, PyObject *value)
|
|||
|
||||
if (meth->is_signal ()) {
|
||||
|
||||
if (PyObject_IsInstance (value, (PyObject *) PYASignal::cls)) {
|
||||
if (!p) {
|
||||
|
||||
// TODO: Static signals?
|
||||
|
||||
} else if (PyObject_IsInstance (value, (PyObject *) PYASignal::cls)) {
|
||||
|
||||
// assigning a signal to a signal works if it applies to the same handler -
|
||||
// this simplifies the implementation of += and -=.
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ public:
|
|||
|
||||
bool compare (const ValueBase *other) const
|
||||
{
|
||||
return m_value < dynamic_cast<const Value<C> *> (other)->m_value;
|
||||
return m_value < static_cast<const Value<C> *> (other)->m_value;
|
||||
}
|
||||
|
||||
std::string to_string () const;
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ public:
|
|||
++lb0;
|
||||
}
|
||||
--lb;
|
||||
if (lb != m_index_map.end () && i2 < lb->first.second) {
|
||||
if (i2 < lb->first.second) {
|
||||
// the last one is overlapping above i2: cut it
|
||||
lb->first.first = i2;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -424,17 +424,20 @@ JobBase::schedule (Task *task)
|
|||
{
|
||||
m_lock.lock ();
|
||||
|
||||
// Don't allow tasks to be scheduled while stopping or exiting (waiting for m_queue_empty_condition)
|
||||
if (m_stopping) {
|
||||
m_lock.unlock ();
|
||||
throw TaskTerminatedException ();
|
||||
}
|
||||
|
||||
// Add the task to the task queue
|
||||
m_task_list.put (task);
|
||||
// Don't allow tasks to be scheduled while stopping or exiting (waiting for m_queue_empty_condition)
|
||||
delete task;
|
||||
|
||||
} else {
|
||||
|
||||
// Add the task to the task queue
|
||||
m_task_list.put (task);
|
||||
|
||||
if (m_running) {
|
||||
m_task_available_condition.wakeAll ();
|
||||
}
|
||||
|
||||
if (m_running) {
|
||||
m_task_available_condition.wakeAll ();
|
||||
}
|
||||
|
||||
m_lock.unlock ();
|
||||
|
|
|
|||
|
|
@ -1298,7 +1298,7 @@ Variant::can_convert_to_long () const
|
|||
case t_double:
|
||||
return m_var.m_double <= std::numeric_limits<long>::max () && m_var.m_double >= std::numeric_limits<long>::min ();
|
||||
case t_float:
|
||||
return m_var.m_float <= std::numeric_limits<long>::max () && m_var.m_float >= std::numeric_limits<long>::min ();
|
||||
return m_var.m_float <= float (std::numeric_limits<long>::max ()) && m_var.m_float >= float (std::numeric_limits<long>::min ());
|
||||
#if defined(HAVE_64BIT_COORD)
|
||||
case t_int128:
|
||||
return m_var.m_int128 <= __int128 (std::numeric_limits<long>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<long>::min ());
|
||||
|
|
|
|||
|
|
@ -52,20 +52,25 @@ class BoxPCell(pya.PCellDeclaration):
|
|||
|
||||
# create the shape
|
||||
cell.shapes(layers[0]).insert(pya.Box(-w / 2, -h / 2, w / 2, h / 2))
|
||||
|
||||
def can_create_from_shape(self, layout, shape, layer):
|
||||
return shape.is_box()
|
||||
|
||||
def transformation_from_shape(self, layout, shape, layer):
|
||||
return pya.Trans(shape.box.center() - pya.Point())
|
||||
|
||||
def parameters_from_shape(self, layout, shape, layer):
|
||||
return [ layout.get_info(layer), shape.box.width() * layout.dbu, shape.box.height() * layout.dbu ]
|
||||
|
||||
|
||||
class PCellTestLib(pya.Library):
|
||||
|
||||
boxpcell = None
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# set the description
|
||||
self.description = "PCell test lib"
|
||||
|
||||
# create the PCell declarations
|
||||
boxpcell = BoxPCell()
|
||||
self.layout().register_pcell("Box", boxpcell)
|
||||
self.layout().register_pcell("Box", BoxPCell())
|
||||
|
||||
sb_index = self.layout().add_cell("StaticBox")
|
||||
l10 = self.layout().insert_layer(pya.LayerInfo(10, 0))
|
||||
|
|
@ -75,6 +80,60 @@ class PCellTestLib(pya.Library):
|
|||
# register us with the name "MyLib"
|
||||
self.register("PCellTestLib")
|
||||
|
||||
|
||||
# A PCell based on the declaration helper
|
||||
|
||||
class BoxPCell2(pya.PCellDeclarationHelper):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
super(BoxPCell2, self).__init__()
|
||||
|
||||
self.param("layer", self.TypeLayer, "Layer", default = pya.LayerInfo(0, 0))
|
||||
self.param("width", self.TypeDouble, "Width", default = 1.0)
|
||||
self.param("height", self.TypeDouble, "Height", default = 1.0)
|
||||
|
||||
def display_text_impl(self):
|
||||
# provide a descriptive text for the cell
|
||||
return "Box2(L=" + str(self.layer) + ",W=" + ('%.3f' % self.width) + ",H=" + ('%.3f' % self.height) + ")"
|
||||
|
||||
def produce_impl(self):
|
||||
|
||||
dbu = self.layout.dbu
|
||||
|
||||
# fetch the parameters
|
||||
l = self.layer_layer
|
||||
w = self.width / self.layout.dbu
|
||||
h = self.height / self.layout.dbu
|
||||
|
||||
# create the shape
|
||||
self.cell.shapes(l).insert(pya.Box(-w / 2, -h / 2, w / 2, h / 2))
|
||||
|
||||
def can_create_from_shape_impl(self):
|
||||
return self.shape.is_box()
|
||||
|
||||
def transformation_from_shape_impl(self):
|
||||
return pya.Trans(self.shape.box.center() - pya.Point())
|
||||
|
||||
def parameters_from_shape_impl(self):
|
||||
self.layer = self.layout.get_info(self.layer)
|
||||
self.width = self.shape.box.width() * self.layout.dbu
|
||||
self.height = self.shape.box.height() * self.layout.dbu
|
||||
|
||||
class PCellTestLib2(pya.Library):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# set the description
|
||||
self.description = "PCell test lib2"
|
||||
|
||||
# create the PCell declarations
|
||||
self.layout().register_pcell("Box2", BoxPCell2())
|
||||
|
||||
# register us with the name "MyLib"
|
||||
self.register("PCellTestLib2")
|
||||
|
||||
|
||||
def inspect_LayerInfo(self):
|
||||
return "<" + str(self) + ">"
|
||||
|
||||
|
|
@ -233,6 +292,75 @@ class DBPCellTests(unittest.TestCase):
|
|||
pcell_inst.cell_index = new_id
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-500,-100;500,100)")
|
||||
|
||||
l10 = ly.layer(10, 0)
|
||||
c1.shapes(l10).insert(pya.Box(0, 10, 100, 210))
|
||||
l11 = ly.layer(11, 0)
|
||||
c1.shapes(l11).insert(pya.Text("hello", pya.Trans()))
|
||||
self.assertEqual(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), False)
|
||||
self.assertEqual(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), True)
|
||||
self.assertEqual(repr(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10)), "[<10/0>, 1.0, 2.0]")
|
||||
self.assertEqual(str(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10)), "r0 50,110")
|
||||
|
||||
|
||||
def test_1a(self):
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib2()
|
||||
|
||||
ly = pya.Layout(True)
|
||||
ly.dbu = 0.01
|
||||
|
||||
li1 = find_layer(ly, "1/0")
|
||||
self.assertEqual(li1 == None, True)
|
||||
|
||||
ci1 = ly.add_cell("c1")
|
||||
c1 = ly.cell(ci1)
|
||||
|
||||
lib = pya.Library.library_by_name("PCellTestLib2")
|
||||
self.assertEqual(lib != None, True)
|
||||
pcell_decl = lib.layout().pcell_declaration("Box2")
|
||||
|
||||
param = [ pya.LayerInfo(1, 0) ] # rest is filled with defaults
|
||||
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl.id(), param)
|
||||
pcell_var = ly.cell(pcell_var_id)
|
||||
pcell_inst = c1.insert(pya.CellInstArray(pcell_var_id, pya.Trans()))
|
||||
self.assertEqual(pcell_var.basic_name(), "Box2")
|
||||
self.assertEqual(pcell_var.pcell_parameters().__repr__(), "[<1/0>, 1.0, 1.0]")
|
||||
self.assertEqual(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)")
|
||||
self.assertEqual(nh(pcell_var.pcell_parameters_by_name()), "{'height': 1.0, 'layer': <1/0>, 'width': 1.0}")
|
||||
self.assertEqual(pcell_var.pcell_parameter("height").__repr__(), "1.0")
|
||||
self.assertEqual(c1.pcell_parameters(pcell_inst).__repr__(), "[<1/0>, 1.0, 1.0]")
|
||||
self.assertEqual(nh(c1.pcell_parameters_by_name(pcell_inst)), "{'height': 1.0, 'layer': <1/0>, 'width': 1.0}")
|
||||
self.assertEqual(c1.pcell_parameter(pcell_inst, "height").__repr__(), "1.0")
|
||||
self.assertEqual(nh(pcell_inst.pcell_parameters_by_name()), "{'height': 1.0, 'layer': <1/0>, 'width': 1.0}")
|
||||
self.assertEqual(pcell_inst["height"].__repr__(), "1.0")
|
||||
self.assertEqual(pcell_inst.pcell_parameter("height").__repr__(), "1.0")
|
||||
self.assertEqual(pcell_var.pcell_declaration().__repr__(), pcell_decl.__repr__())
|
||||
self.assertEqual(c1.pcell_declaration(pcell_inst).__repr__(), pcell_decl.__repr__())
|
||||
self.assertEqual(pcell_inst.pcell_declaration().__repr__(), pcell_decl.__repr__())
|
||||
|
||||
li1 = find_layer(ly, "1/0")
|
||||
self.assertEqual(li1 == None, False)
|
||||
pcell_inst.change_pcell_parameter("height", 2.0)
|
||||
self.assertEqual(nh(pcell_inst.pcell_parameters_by_name()), "{'height': 2.0, 'layer': <1/0>, 'width': 1.0}")
|
||||
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-50,-100;50,100)")
|
||||
|
||||
param = { "layer": pya.LayerInfo(2, 0), "width": 2, "height": 1 }
|
||||
li2 = ly.layer(2, 0)
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li2).shape().__str__(), "box (-100,-50;100,50)")
|
||||
|
||||
l10 = ly.layer(10, 0)
|
||||
c1.shapes(l10).insert(pya.Box(0, 10, 100, 210))
|
||||
l11 = ly.layer(11, 0)
|
||||
c1.shapes(l11).insert(pya.Text("hello", pya.Trans()))
|
||||
self.assertEqual(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), False)
|
||||
self.assertEqual(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), True)
|
||||
self.assertEqual(repr(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10)), "[<10/0>, 1.0, 2.0]")
|
||||
self.assertEqual(str(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10)), "r0 50,110")
|
||||
|
||||
|
||||
def test_2(self):
|
||||
|
||||
# instantiate and register the library
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -61,6 +61,18 @@ class BoxPCell < RBA::PCellDeclaration
|
|||
|
||||
end
|
||||
|
||||
def can_create_from_shape(layout, shape, layer)
|
||||
return shape.is_box?
|
||||
end
|
||||
|
||||
def transformation_from_shape(layout, shape, layer)
|
||||
return RBA::Trans::new(shape.box.center - RBA::Point::new)
|
||||
end
|
||||
|
||||
def parameters_from_shape(layout, shape, layer)
|
||||
return [ layout.get_info(layer), shape.box.width * layout.dbu, shape.box.height * layout.dbu ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class PCellTestLib < RBA::Library
|
||||
|
|
@ -85,6 +97,72 @@ class PCellTestLib < RBA::Library
|
|||
|
||||
end
|
||||
|
||||
# A PCell based on the declaration helper
|
||||
|
||||
class BoxPCell2 < RBA::PCellDeclarationHelper
|
||||
|
||||
def initialize
|
||||
|
||||
super()
|
||||
|
||||
param("layer", BoxPCell2::TypeLayer, "Layer", :default => RBA::LayerInfo::new(0, 0))
|
||||
param("width", BoxPCell2::TypeDouble, "Width", :default => 1.0)
|
||||
param("height", BoxPCell2::TypeDouble, "Height", :default => 1.0)
|
||||
|
||||
end
|
||||
|
||||
def display_text_impl
|
||||
# provide a descriptive text for the cell
|
||||
return "Box2(L=" + layer.to_s + ",W=" + ('%.3f' % width) + ",H=" + ('%.3f' % height) + ")"
|
||||
end
|
||||
|
||||
def produce_impl
|
||||
|
||||
# fetch the parameters
|
||||
l = layer_layer
|
||||
w = width / layout.dbu
|
||||
h = height / layout.dbu
|
||||
|
||||
# create the shape
|
||||
cell.shapes(l).insert(RBA::Box::new(-w / 2, -h / 2, w / 2, h / 2))
|
||||
|
||||
end
|
||||
|
||||
def can_create_from_shape_impl
|
||||
return self.shape.is_box?
|
||||
end
|
||||
|
||||
def transformation_from_shape_impl
|
||||
return RBA::Trans::new(shape.box.center - RBA::Point::new)
|
||||
end
|
||||
|
||||
def parameters_from_shape_impl
|
||||
# NOTE: because there is one parameter called "layer" already, we need to use
|
||||
# the "_layer" fallback to access the argument to this method
|
||||
set_layer(_layout.get_info(_layer))
|
||||
set_width(shape.box.width * _layout.dbu)
|
||||
set_height(shape.box.height * _layout.dbu)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class PCellTestLib2 < RBA::Library
|
||||
|
||||
def initialize
|
||||
|
||||
# set the description
|
||||
description = "PCell test lib2"
|
||||
|
||||
# create the PCell declarations
|
||||
layout.register_pcell("Box2", BoxPCell2::new)
|
||||
|
||||
# register us with the name "MyLib"
|
||||
self.register("PCellTestLib2")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# A helper for testing: provide an inspect method
|
||||
class RBA::LayerInfo
|
||||
def inspect
|
||||
|
|
@ -115,8 +193,7 @@ class DBPCell_TestClass < TestBase
|
|||
ly = RBA::Layout::new(true)
|
||||
ly.dbu = 0.01
|
||||
|
||||
li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" }
|
||||
assert_equal(li1 == nil, true)
|
||||
li1 = ly.layer(1, 0)
|
||||
|
||||
ci1 = ly.add_cell("c1")
|
||||
c1 = ly.cell(ci1)
|
||||
|
|
@ -241,10 +318,84 @@ class DBPCell_TestClass < TestBase
|
|||
pcell_inst.cell_index = new_id
|
||||
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
|
||||
|
||||
#ly.destroy
|
||||
l10 = ly.layer(10, 0)
|
||||
c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210))
|
||||
l11 = ly.layer(11, 0)
|
||||
c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new))
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false)
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true)
|
||||
assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]")
|
||||
assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110")
|
||||
|
||||
ly.destroy
|
||||
|
||||
ensure
|
||||
#tl.delete
|
||||
tl.delete
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_1a
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib2::new
|
||||
|
||||
begin
|
||||
|
||||
ly = RBA::Layout::new(true)
|
||||
ly.dbu = 0.01
|
||||
|
||||
ci1 = ly.add_cell("c1")
|
||||
c1 = ly.cell(ci1)
|
||||
|
||||
lib = RBA::Library.library_by_name("PCellTestLib2")
|
||||
assert_equal(lib != nil, true)
|
||||
pcell_decl = lib.layout().pcell_declaration("Box2")
|
||||
|
||||
param = [ RBA::LayerInfo::new(1, 0) ] # rest is filled with defaults
|
||||
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl.id(), param)
|
||||
pcell_var = ly.cell(pcell_var_id)
|
||||
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
|
||||
assert_equal(pcell_var.basic_name, "Box2")
|
||||
assert_equal(pcell_var.pcell_parameters().inspect, "[<1/0>, 1.0, 1.0]")
|
||||
assert_equal(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)")
|
||||
assert_equal(norm_hash(pcell_var.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"width\"=>1.0}")
|
||||
assert_equal(pcell_var.pcell_parameter("height").inspect(), "1.0")
|
||||
assert_equal(c1.pcell_parameters(pcell_inst).inspect(), "[<1/0>, 1.0, 1.0]")
|
||||
assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"height\"=>1.0, \"layer\"=><1/0>, \"width\"=>1.0}")
|
||||
assert_equal(c1.pcell_parameter(pcell_inst, "height").inspect(), "1.0")
|
||||
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"width\"=>1.0}")
|
||||
assert_equal(pcell_inst["height"].inspect(), "1.0")
|
||||
assert_equal(pcell_inst.pcell_parameter("height").inspect(), "1.0")
|
||||
assert_equal(pcell_var.pcell_declaration().inspect(), pcell_decl.inspect)
|
||||
assert_equal(c1.pcell_declaration(pcell_inst).inspect(), pcell_decl.inspect)
|
||||
assert_equal(pcell_inst.pcell_declaration().inspect(), pcell_decl.inspect)
|
||||
|
||||
li1 = ly.layer(1, 0)
|
||||
assert_equal(li1 == nil, false)
|
||||
pcell_inst.change_pcell_parameter("height", 2.0)
|
||||
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>2.0, \"layer\"=><1/0>, \"width\"=>1.0}")
|
||||
|
||||
assert_equal(ly.begin_shapes(c1.cell_index(), li1).shape().to_s, "box (-50,-100;50,100)")
|
||||
|
||||
param = { "layer" => RBA::LayerInfo::new(2, 0), "width" => 2, "height" => 1 }
|
||||
li2 = ly.layer(2, 0)
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
assert_equal(ly.begin_shapes(c1.cell_index(), li2).shape().to_s, "box (-100,-50;100,50)")
|
||||
|
||||
l10 = ly.layer(10, 0)
|
||||
c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210))
|
||||
l11 = ly.layer(11, 0)
|
||||
c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new))
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false)
|
||||
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true)
|
||||
assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]")
|
||||
assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110")
|
||||
|
||||
ly.destroy
|
||||
|
||||
ensure
|
||||
tl.delete
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue