klayout/src/pymod/distutils_src/klayout/db/pcell_declaration_helper.py

343 lines
9.8 KiB
Python

from klayout.db import LayerInfo
class _PCellDeclarationHelperLayerDescriptor(object):
"""
A descriptor object which translates the PCell parameters into class attributes
"""
def __init__(self, param_index):
self.param_index = param_index
def __get__(self, obj, type = None):
return obj._layers[self.param_index]
def __set__(self, obj, value):
raise AttributeError("can't change layer attribute")
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, param_name):
self.param_index = param_index
self.param_name = param_name
self.value = None
def __get__(self, obj, type = None):
if obj._param_values:
return obj._param_values[self.param_index]
elif obj._param_states:
return obj._param_states.parameter(self.param_name)
else:
return self.value
def __set__(self, obj, value):
if obj._param_values:
obj._param_values[self.param_index] = value
else:
self.value = value
class _PCellDeclarationHelperMixin:
"""
A mixin class that somewhat simplifies the implementation of a PCell
Needed to build PCellDeclarationHelper
"""
def __init__(self, *args, **kwargs):
"""
initializes this instance
"""
super().__init__(*args, **kwargs)
# "private" attributes
self._param_decls = []
self._param_values = None
self._param_states = None
self._layer_param_index = []
self._layers = []
# public attributes
self.layout = None
self.shape = None
self.layer = None
self.cell = None
def param(self, name, value_type, description, hidden = False, readonly = False, unit = None, default = None, choices = None):
"""
Defines a parameter
name -> the short name of the parameter
type -> the type of the parameter
description -> the description text
named parameters
hidden -> (boolean) true, if the parameter is not shown in the dialog
readonly -> (boolean) true, if the parameter cannot be edited
unit -> the unit string
default -> the default value
choices -> ([ [ d, v ], ...) choice descriptions/value for choice type
this method defines accessor methods for the parameters
{name} -> read accessor
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
"""
# create accessor methods for the parameters
param_index = len(self._param_decls)
setattr(type(self), name, _PCellDeclarationHelperParameterDescriptor(param_index, name))
if value_type == type(self).TypeLayer:
setattr(type(self), name + "_layer", _PCellDeclarationHelperLayerDescriptor(len(self._layer_param_index)))
self._layer_param_index.append(param_index)
# store the parameter declarations
pdecl = self._make_parameter_declaration(name, value_type, description)
self._param_decls.append(pdecl)
# set additional attributes of the parameters
pdecl.hidden = hidden
pdecl.readonly = readonly
if not (default is None):
pdecl.default = default
if not (unit is None):
pdecl.unit = unit
if not (choices is None):
if not isinstance(choices, list) and not isinstance(choices, tuple):
raise TypeError("choices value must be an list/tuple of two-element arrays (description, value)")
for c in choices:
if (not isinstance(choices, list) and not isinstance(choices, tuple)) or len(c) != 2:
raise TypeError("choices value must be an list/tuple of two-element arrays (description, value)")
pdecl.add_choice(c[0],c[1])
# return the declaration object for further operations
return pdecl
def display_text(self, parameters):
"""
Reimplementation of PCellDeclaration.display_text
This function delegates the implementation to self.display_text_impl
after configuring the PCellDeclaration object.
"""
self._param_values = parameters
try:
text = self.display_text_impl()
finally:
self.finish()
return text
def get_parameters(self):
"""
Reimplementation of PCellDeclaration.get_parameters
This function uses the collected parameters to feed the
PCell declaration.
"""
return self._param_decls
def get_values(self):
"""
Gets the temporary parameter values used for the current evaluation
Call this function to get the a current parameter values. This
is an array of variants in the order the parameters are declared.
"""
v = self._param_values
self._param_values = None
return v
def init_values(self, values = None, layers = None, states = None):
"""
initializes the temporary parameter values for the current evaluation
"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.
"""
self._param_values = None
self._param_states = None
if states:
self._param_states = states
elif 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):
"""
Is called at the end of an implementation of a PCellDeclaration method
"""
self._param_values = None
self._param_states = None
self._layers = None
self._cell = None
self._layout = None
self._layer = None
self._shape = None
def get_layers(self, parameters):
"""
Reimplements PCellDeclaration.get_layers.
Gets the layer definitions from all layer parameters.
"""
layers = []
for i in self._layer_param_index:
if parameters[i] is not None:
layers.append(parameters[i])
else:
layers.append(LayerInfo())
return layers
def callback(self, layout, name, states):
"""
Reimplements PCellDeclaration.callback (change state on parameter change)
The function delegates the implementation to callback_impl
after updating the state of this object with the current parameters.
"""
self.init_values(states = states)
self.layout = layout
try:
self.callback_impl(name)
finally:
self.finish()
def coerce_parameters(self, layout, parameters):
"""
Reimplements PCellDeclaration.coerce parameters (make consistent)
The function delegates the implementation to coerce_parameters_impl
after updating the state of this object with the current parameters.
"""
self.init_values(parameters)
self.layout = layout
try:
self.coerce_parameters_impl()
parameters = self.get_values()
finally:
self.finish()
return parameters
def produce(self, layout, layers, parameters, cell):
"""
Reimplements PCellDeclaration.produce (produces the layout)
The function delegates the implementation to produce_impl
after updating the state of this object with the current parameters.
"""
self.init_values(parameters, layers)
self.cell = cell
self.layout = layout
try:
self.produce_impl()
finally:
self.finish()
def can_create_from_shape(self, layout, shape, layer):
"""
Reimplements PCellDeclaration.can_create_from_shape
The function delegates the implementation to can_create_from_shape_impl
after updating the state of this object with the current parameters.
"""
self.layout = layout
self.shape = shape
self.layer = layer
try:
ret = self.can_create_from_shape_impl()
finally:
self.finish()
return ret
def transformation_from_shape(self, layout, shape, layer):
"""
Reimplements PCellDeclaration.transformation_from_shape
The function delegates the implementation to transformation_from_shape_impl
after updating the state of this object with the current parameters.
"""
self.layout = layout
self.shape = shape
self.layer = layer
try:
t = self.transformation_from_shape_impl()
if t is None:
t = self._make_default_trans()
finally:
self.finish()
return t
def parameters_from_shape(self, layout, shape, layer):
"""
Reimplements PCellDeclaration.parameters_from_shape
The function delegates the implementation to parameters_from_shape_impl
after updating the state of this object with the current parameters.
"""
self.init_values()
self.layout = layout
self.shape = shape
self.layer = layer
try:
self.parameters_from_shape_impl()
param = self.get_values()
finally:
self.finish()
return param
def display_text_impl(self):
"""
default implementation
"""
return ""
def coerce_parameters_impl(self):
"""
default implementation
"""
pass
def callback_impl(self, name):
"""
default implementation
"""
pass
def produce_impl(self):
"""
default implementation
"""
pass
def can_create_from_shape_impl(self):
"""
default implementation
"""
return False
def parameters_from_shape_impl(self):
"""
default implementation
"""
pass
def transformation_from_shape_impl(self):
"""
default implementation
"""
return None
__all__ = [ "_PCellDeclarationHelperLayerDescriptor",
"_PCellDeclarationHelperParameterDescriptor",
"_PCellDeclarationHelperMixin" ]