mirror of https://github.com/KLayout/klayout.git
Refactoring, primary goal is to centralize the definition of PCellDeclarationHelper in Python
This commit is contained in:
parent
8b7e2b2b40
commit
068849a634
|
|
@ -8,6 +8,10 @@
|
|||
<doc>@class [db] PCellDeclarationHelper < PCellDeclaration
|
||||
@brief A helper class to simplify the declaration of a PCell (Python version)
|
||||
|
||||
NOTE: in the following, "pya" can be replaced by "klayout.db" which is
|
||||
the canonical module and the preferred way of addressing the
|
||||
external Python library.
|
||||
|
||||
This class provides adds some convenience to the PCell declaration based
|
||||
on PCellDeclaration. PCellDeclaration is a C++ object which is less
|
||||
convenient to use than a Ruby-based approach. In particular this class
|
||||
|
|
@ -252,314 +256,7 @@ This method must return a \\Trans object. The default implementation returns a u
|
|||
<interpreter>python</interpreter>
|
||||
<dsl-interpreter-name/>
|
||||
<text>
|
||||
import pya
|
||||
|
||||
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 _PCellDeclarationHelper(pya.PCellDeclaration):
|
||||
"""
|
||||
A helper class that somewhat simplifies the implementation
|
||||
of a PCell
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
initialize this instance
|
||||
"""
|
||||
# "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 = pya.PCellParameterDeclaration(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 "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 "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):
|
||||
"""
|
||||
implementation of display_text
|
||||
"""
|
||||
self._param_values = parameters
|
||||
try:
|
||||
text = self.display_text_impl()
|
||||
finally:
|
||||
self._param_values = None
|
||||
return text
|
||||
|
||||
def get_parameters(self):
|
||||
"""
|
||||
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, states = 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.
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
Needs to be called at the end of an implementation
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
gets the layer definitions
|
||||
"""
|
||||
layers = []
|
||||
for i in self._layer_param_index:
|
||||
layers.append(parameters[i])
|
||||
return layers
|
||||
|
||||
def callback(self, layout, name, states):
|
||||
"""
|
||||
callback (change state on parameter change)
|
||||
"""
|
||||
self.init_values(states = states)
|
||||
self.layout = layout
|
||||
try:
|
||||
self.callback_impl(name)
|
||||
finally:
|
||||
self.finish()
|
||||
|
||||
def coerce_parameters(self, layout, parameters):
|
||||
"""
|
||||
coerce parameters (make consistent)
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
produces the layout
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
produce a helper for can_create_from_shape
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
produce a helper for parameters_from_shape
|
||||
"""
|
||||
self.layout = layout
|
||||
self.shape = shape
|
||||
self.layer = layer
|
||||
try:
|
||||
t = self.transformation_from_shape_impl()
|
||||
finally:
|
||||
self.finish()
|
||||
return t
|
||||
|
||||
def parameters_from_shape(self, layout, shape, layer):
|
||||
"""
|
||||
produce a helper for parameters_from_shape
|
||||
with this helper, the implementation can use the parameter setters
|
||||
"""
|
||||
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 pya.Trans()
|
||||
|
||||
# import the Type... constants from PCellParameterDeclaration
|
||||
for k in dir(pya.PCellParameterDeclaration):
|
||||
if k.startswith("Type"):
|
||||
setattr(_PCellDeclarationHelper, k, getattr(pya.PCellParameterDeclaration, k))
|
||||
|
||||
# Inject the PCellDeclarationHelper into pya module for consistency:
|
||||
setattr(pya, "PCellDeclarationHelper", _PCellDeclarationHelper)
|
||||
|
||||
# No code provided here. This macro is supplied to provide the documentation.
|
||||
# The basic code is located in klayout.db.pcell_declaration_helper now.
|
||||
</text>
|
||||
</klayout-macro>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,31 @@
|
|||
import functools
|
||||
from typing import Type
|
||||
import klayout.dbcore
|
||||
from klayout.dbcore import *
|
||||
|
||||
from klayout.db.pcell_declaration_helper import PCellDeclarationHelper
|
||||
import sys
|
||||
from ..dbcore import __all__
|
||||
from ..dbcore import *
|
||||
|
||||
__all__ = klayout.dbcore.__all__ + ["PCellDeclarationHelper"] # type: ignore
|
||||
from .pcell_declaration_helper import *
|
||||
|
||||
# establish the PCellDeclarationHelper using the mixin provided by _pcell_declaration_helper
|
||||
class PCellDeclarationHelper(_PCellDeclarationHelperMixin, PCellDeclaration):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def _make_parameter_declaration(self, name, value_type, description):
|
||||
return PCellParameterDeclaration(name, value_type, description)
|
||||
def _make_default_trans(self):
|
||||
return Trans()
|
||||
|
||||
# import the Type... constants from PCellParameterDeclaration
|
||||
for k in dir(PCellParameterDeclaration):
|
||||
if k.startswith("Type"):
|
||||
setattr(PCellDeclarationHelper, k, getattr(PCellParameterDeclaration, k))
|
||||
|
||||
# If class has from_s, to_s, and assign, use them to
|
||||
# enable serialization.
|
||||
for name, cls in klayout.dbcore.__dict__.items():
|
||||
if not isinstance(cls, type):
|
||||
continue
|
||||
if hasattr(cls, 'from_s') and hasattr(cls, 'to_s') and hasattr(cls, 'assign'):
|
||||
cls.__getstate__ = cls.to_s # type: ignore
|
||||
def _setstate(self, str):
|
||||
cls = self.__class__
|
||||
self.assign(cls.from_s(str))
|
||||
cls.__setstate__ = _setstate # type: ignore
|
||||
for name in __all__:
|
||||
cls = globals()[name]
|
||||
if hasattr(cls, 'from_s') and hasattr(cls, 'to_s') and hasattr(cls, 'assign'):
|
||||
cls.__getstate__ = cls.to_s # type: ignore
|
||||
def _setstate(self, str):
|
||||
cls = self.__class__
|
||||
self.assign(cls.from_s(str))
|
||||
cls.__setstate__ = _setstate # type: ignore
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
from klayout.db import Trans, PCellDeclaration, PCellParameterDeclaration
|
||||
|
||||
|
||||
class _PCellDeclarationHelperLayerDescriptor(object):
|
||||
"""
|
||||
|
|
@ -43,16 +41,17 @@ class _PCellDeclarationHelperParameterDescriptor(object):
|
|||
else:
|
||||
self.value = value
|
||||
|
||||
class _PCellDeclarationHelper(PCellDeclaration):
|
||||
class _PCellDeclarationHelperMixin:
|
||||
"""
|
||||
A helper class that somewhat simplifies the implementation
|
||||
of a PCell
|
||||
A mixin class that somewhat simplifies the implementation of a PCell
|
||||
Needed to build PCellDeclarationHelper
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
initialize this instance
|
||||
initializes this instance
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
# "private" attributes
|
||||
self._param_decls = []
|
||||
self._param_values = None
|
||||
|
|
@ -93,7 +92,7 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
self._layer_param_index.append(param_index)
|
||||
|
||||
# store the parameter declarations
|
||||
pdecl = PCellParameterDeclaration(name, value_type, description)
|
||||
pdecl = self._make_parameter_declaration(name, value_type, description)
|
||||
self._param_decls.append(pdecl)
|
||||
|
||||
# set additional attributes of the parameters
|
||||
|
|
@ -116,24 +115,33 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def display_text(self, parameters):
|
||||
"""
|
||||
implementation of display_text
|
||||
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._param_values = None
|
||||
self.finish()
|
||||
return text
|
||||
|
||||
def get_parameters(self):
|
||||
"""
|
||||
gets the parameters
|
||||
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
|
||||
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
|
||||
|
|
@ -141,7 +149,8 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def init_values(self, values = None, layers = None, states = None):
|
||||
"""
|
||||
initializes the temporary parameter values
|
||||
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
|
||||
|
|
@ -161,7 +170,7 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def finish(self):
|
||||
"""
|
||||
Needs to be called at the end of an implementation
|
||||
Is called at the end of an implementation of a PCellDeclaration method
|
||||
"""
|
||||
self._param_values = None
|
||||
self._param_states = None
|
||||
|
|
@ -173,7 +182,9 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def get_layers(self, parameters):
|
||||
"""
|
||||
gets the layer definitions
|
||||
Reimplements PCellDeclaration.get_layers.
|
||||
|
||||
Gets the layer definitions from all layer parameters.
|
||||
"""
|
||||
layers = []
|
||||
for i in self._layer_param_index:
|
||||
|
|
@ -182,7 +193,10 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def callback(self, layout, name, states):
|
||||
"""
|
||||
callback (change state on parameter change)
|
||||
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
|
||||
|
|
@ -193,7 +207,10 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def coerce_parameters(self, layout, parameters):
|
||||
"""
|
||||
coerce parameters (make consistent)
|
||||
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
|
||||
|
|
@ -206,7 +223,10 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def produce(self, layout, layers, parameters, cell):
|
||||
"""
|
||||
produces the layout
|
||||
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
|
||||
|
|
@ -218,7 +238,10 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def can_create_from_shape(self, layout, shape, layer):
|
||||
"""
|
||||
produce a helper for can_create_from_shape
|
||||
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
|
||||
|
|
@ -231,21 +254,28 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
|
||||
def transformation_from_shape(self, layout, shape, layer):
|
||||
"""
|
||||
produce a helper for parameters_from_shape
|
||||
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):
|
||||
"""
|
||||
produce a helper for parameters_from_shape
|
||||
with this helper, the implementation can use the parameter setters
|
||||
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
|
||||
|
|
@ -298,13 +328,10 @@ class _PCellDeclarationHelper(PCellDeclaration):
|
|||
"""
|
||||
default implementation
|
||||
"""
|
||||
return Trans()
|
||||
return None
|
||||
|
||||
# import the Type... constants from PCellParameterDeclaration
|
||||
for k in dir(PCellParameterDeclaration):
|
||||
if k.startswith("Type"):
|
||||
setattr(_PCellDeclarationHelper, k, getattr(PCellParameterDeclaration, k))
|
||||
|
||||
# Inject the PCellDeclarationHelper into module for consistency:
|
||||
PCellDeclarationHelper = _PCellDeclarationHelper
|
||||
__all__ = [ "_PCellDeclarationHelperLayerDescriptor",
|
||||
"_PCellDeclarationHelperParameterDescriptor",
|
||||
"_PCellDeclarationHelperMixin" ]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import klayout.dbcore # enables stream reader plugins
|
||||
import klayout.laycore
|
||||
|
||||
from klayout.laycore import *
|
||||
from ..dbcore import Layout # enables stream reader plugins
|
||||
|
||||
from ..laycore import __all__
|
||||
from ..laycore import *
|
||||
|
||||
__all__ = klayout.laycore.__all__
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import klayout.libcore
|
||||
from klayout.libcore import *
|
||||
|
||||
__all__ = klayout.libcore.__all__
|
||||
from ..libcore import __all__
|
||||
from ..libcore import *
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import klayout.rdbcore
|
||||
from klayout.rdbcore import *
|
||||
|
||||
__all__ = klayout.rdbcore.__all__
|
||||
from ..rdbcore import __all__
|
||||
from ..rdbcore import *
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import klayout.tlcore
|
||||
from klayout.tlcore import *
|
||||
|
||||
__all__ = klayout.tlcore.__all__
|
||||
from ..tlcore import __all__
|
||||
from ..tlcore import *
|
||||
|
||||
|
|
|
|||
|
|
@ -2,3 +2,20 @@
|
|||
# pull everything from the generic klayout.pya package into pya
|
||||
from klayout.pya import __all__
|
||||
from klayout.pya import *
|
||||
|
||||
from klayout.db.pcell_declaration_helper import *
|
||||
|
||||
# establish the PCellDeclarationHelper using the mixin provided by _pcell_declaration_helper
|
||||
class PCellDeclarationHelper(_PCellDeclarationHelperMixin, PCellDeclaration):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def _make_parameter_declaration(self, name, value_type, description):
|
||||
return PCellParameterDeclaration(name, value_type, description)
|
||||
def _make_default_trans(self):
|
||||
return Trans()
|
||||
|
||||
# import the Type... constants from PCellParameterDeclaration
|
||||
for k in dir(PCellParameterDeclaration):
|
||||
if k.startswith("Type"):
|
||||
setattr(PCellDeclarationHelper, k, getattr(PCellParameterDeclaration, k))
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ PYMODTEST (bridge, "bridge.py")
|
|||
|
||||
PYMODTEST (import_tl, "import_tl.py")
|
||||
PYMODTEST (import_db, "import_db.py")
|
||||
PYMODTEST (klayout_db_tests, "klayout_db_tests.py")
|
||||
PYMODTEST (import_rdb, "import_rdb.py")
|
||||
PYMODTEST (import_lay, "import_lay.py")
|
||||
PYMODTEST (import_lib, "import_lib.py")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,502 @@
|
|||
# KLayout Layout Viewer
|
||||
# Copyright (C) 2006-2023 Matthias Koefferlein
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
import klayout.db
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
class BoxPCell(klayout.db.PCellDeclaration):
|
||||
|
||||
def display_text(self, parameters):
|
||||
# provide a descriptive text for the cell
|
||||
return "Box(L=" + str(parameters[0]) + ",W=" + ('%.3f' % parameters[1]) + ",H=" + ('%.3f' % parameters[2]) + ")"
|
||||
|
||||
def get_parameters(self):
|
||||
|
||||
# prepare a set of parameter declarations
|
||||
param = []
|
||||
|
||||
param.append(klayout.db.PCellParameterDeclaration("l", klayout.db.PCellParameterDeclaration.TypeLayer, "Layer", klayout.db.LayerInfo(0, 0)))
|
||||
param.append(klayout.db.PCellParameterDeclaration("w", klayout.db.PCellParameterDeclaration.TypeDouble, "Width", 1.0))
|
||||
param.append(klayout.db.PCellParameterDeclaration("h", klayout.db.PCellParameterDeclaration.TypeDouble, "Height", 1.0))
|
||||
|
||||
return param
|
||||
|
||||
|
||||
def get_layers(self, parameters):
|
||||
return [ parameters[0] ]
|
||||
|
||||
def produce(self, layout, layers, parameters, cell):
|
||||
|
||||
dbu = layout.dbu
|
||||
|
||||
# fetch the parameters
|
||||
l = parameters[0]
|
||||
w = parameters[1] / layout.dbu
|
||||
h = parameters[2] / layout.dbu
|
||||
|
||||
# create the shape
|
||||
cell.shapes(layers[0]).insert(klayout.db.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 klayout.db.Trans(shape.box.center() - klayout.db.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(klayout.db.Library):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# set the description
|
||||
self.description = "PCell test lib"
|
||||
|
||||
# create the PCell declarations
|
||||
self.layout().register_pcell("Box", BoxPCell())
|
||||
|
||||
sb_index = self.layout().add_cell("StaticBox")
|
||||
l10 = self.layout().insert_layer(klayout.db.LayerInfo(10, 0))
|
||||
sb_cell = self.layout().cell(sb_index)
|
||||
sb_cell.shapes(l10).insert(klayout.db.Box(0, 0, 100, 200))
|
||||
|
||||
# register us with the name "MyLib"
|
||||
self.register("PCellTestLib")
|
||||
|
||||
|
||||
# A PCell based on the declaration helper
|
||||
|
||||
class BoxPCell2(klayout.db.PCellDeclarationHelper):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
super(BoxPCell2, self).__init__()
|
||||
|
||||
self.param("layer", self.TypeLayer, "Layer", default = klayout.db.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 wants_lazy_evaluation(self):
|
||||
return True
|
||||
|
||||
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(klayout.db.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 klayout.db.Trans(self.shape.box.center() - klayout.db.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(klayout.db.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) + ">"
|
||||
|
||||
klayout.db.LayerInfo.__repr__ = inspect_LayerInfo
|
||||
|
||||
def find_layer(ly, lp):
|
||||
|
||||
for li in ly.layer_indices():
|
||||
if str(ly.get_info(li)) == lp:
|
||||
return li
|
||||
return None
|
||||
|
||||
|
||||
def nh(h):
|
||||
"""
|
||||
Returns a normalized hash representation
|
||||
"""
|
||||
v = []
|
||||
for k in sorted(h):
|
||||
v.append(repr(k) + ": " + repr(h[k]))
|
||||
return "{" + (", ".join(v)) + "}"
|
||||
|
||||
class DBPCellTests(unittest.TestCase):
|
||||
|
||||
def test_1(self):
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib()
|
||||
|
||||
ly = klayout.db.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 = klayout.db.Library.library_by_name("NoLib")
|
||||
self.assertEqual(lib == None, True)
|
||||
lib = klayout.db.Library.library_by_name("PCellTestLib")
|
||||
self.assertEqual(lib != None, True)
|
||||
pcell_decl = lib.layout().pcell_declaration("x")
|
||||
self.assertEqual(pcell_decl == None, True)
|
||||
pcell_decl = lib.layout().pcell_declaration("Box")
|
||||
self.assertEqual(pcell_decl != None, True)
|
||||
pcell_decl_id = lib.layout().pcell_id("Box")
|
||||
self.assertEqual(pcell_decl.id(), pcell_decl_id)
|
||||
self.assertEqual(":".join(lib.layout().pcell_names()), "Box")
|
||||
self.assertEqual(lib.layout().pcell_ids(), [ pcell_decl_id ])
|
||||
self.assertEqual(lib.layout().pcell_declaration(pcell_decl_id).id(), pcell_decl_id)
|
||||
|
||||
param = [ klayout.db.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(klayout.db.CellInstArray(pcell_var_id, klayout.db.Trans()))
|
||||
self.assertEqual(pcell_var.layout().__repr__(), ly.__repr__())
|
||||
self.assertEqual(pcell_var.library().__repr__(), lib.__repr__())
|
||||
self.assertEqual(pcell_var.is_pcell_variant(), True)
|
||||
self.assertEqual(pcell_var.display_title(), "PCellTestLib.Box(L=1/0,W=1.000,H=1.000)")
|
||||
self.assertEqual(pcell_var.basic_name(), "Box")
|
||||
self.assertEqual(pcell_var.pcell_declaration().wants_lazy_evaluation(), False)
|
||||
self.assertEqual(c1.is_pcell_variant(), False)
|
||||
self.assertEqual(c1.is_pcell_variant(pcell_inst), True)
|
||||
self.assertEqual(pcell_var.pcell_id(), pcell_decl_id)
|
||||
self.assertEqual(pcell_var.pcell_library().__repr__(), lib.__repr__())
|
||||
self.assertEqual(pcell_var.pcell_parameters().__repr__(), "[<1/0>, 1.0, 1.0]")
|
||||
self.assertEqual(nh(pcell_var.pcell_parameters_by_name()), "{'h': 1.0, 'l': <1/0>, 'w': 1.0}")
|
||||
self.assertEqual(pcell_var.pcell_parameter("h").__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)), "{'h': 1.0, 'l': <1/0>, 'w': 1.0}")
|
||||
self.assertEqual(c1.pcell_parameter(pcell_inst, "h").__repr__(), "1.0")
|
||||
self.assertEqual(nh(pcell_inst.pcell_parameters_by_name()), "{'h': 1.0, 'l': <1/0>, 'w': 1.0}")
|
||||
self.assertEqual(pcell_inst["h"].__repr__(), "1.0")
|
||||
self.assertEqual(pcell_inst["i"].__repr__(), "None")
|
||||
self.assertEqual(pcell_inst.pcell_parameter("h").__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__())
|
||||
|
||||
pcell_inst.change_pcell_parameter("h", 2.0)
|
||||
self.assertEqual(nh(pcell_inst.pcell_parameters_by_name()), "{'h': 2.0, 'l': <1/0>, 'w': 1.0}")
|
||||
pcell_inst.set_property("abc", "a property")
|
||||
self.assertEqual(pcell_inst.property("abc").__repr__(), "'a property'")
|
||||
|
||||
c1.clear()
|
||||
|
||||
param = [ klayout.db.LayerInfo(1, 0), 5.0, 10.0 ]
|
||||
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
|
||||
pcell_var = ly.cell(pcell_var_id)
|
||||
pcell_inst = c1.insert(klayout.db.CellInstArray(pcell_var_id, klayout.db.Trans()))
|
||||
self.assertEqual(pcell_var.layout().__repr__(), ly.__repr__())
|
||||
self.assertEqual(pcell_var.library().__repr__(), lib.__repr__())
|
||||
self.assertEqual(pcell_var.is_pcell_variant(), True)
|
||||
self.assertEqual(pcell_var.display_title(), "PCellTestLib.Box(L=1/0,W=5.000,H=10.000)")
|
||||
self.assertEqual(pcell_var.basic_name(), "Box")
|
||||
self.assertEqual(c1.is_pcell_variant(), False)
|
||||
self.assertEqual(c1.is_pcell_variant(pcell_inst), True)
|
||||
self.assertEqual(pcell_var.pcell_id(), pcell_decl_id)
|
||||
self.assertEqual(pcell_var.pcell_library().__repr__(), lib.__repr__())
|
||||
self.assertEqual(pcell_var.pcell_parameters().__repr__(), "[<1/0>, 5.0, 10.0]")
|
||||
self.assertEqual(c1.pcell_parameters(pcell_inst).__repr__(), "[<1/0>, 5.0, 10.0]")
|
||||
self.assertEqual(pcell_inst.pcell_parameters().__repr__(), "[<1/0>, 5.0, 10.0]")
|
||||
self.assertEqual(pcell_var.pcell_declaration().__repr__(), pcell_decl.__repr__())
|
||||
self.assertEqual(c1.pcell_declaration(pcell_inst).__repr__(), pcell_decl.__repr__())
|
||||
|
||||
li1 = find_layer(ly, "1/0")
|
||||
self.assertEqual(li1 != None, True)
|
||||
self.assertEqual(ly.is_valid_layer(li1), True)
|
||||
self.assertEqual(str(ly.get_info(li1)), "1/0")
|
||||
|
||||
lib_proxy_id = ly.add_lib_cell(lib, lib.layout().cell_by_name("StaticBox"))
|
||||
lib_proxy = ly.cell(lib_proxy_id)
|
||||
self.assertEqual(lib_proxy.display_title(), "PCellTestLib.StaticBox")
|
||||
self.assertEqual(lib_proxy.basic_name(), "StaticBox")
|
||||
self.assertEqual(lib_proxy.layout().__repr__(), ly.__repr__())
|
||||
self.assertEqual(lib_proxy.library().__repr__(), lib.__repr__())
|
||||
self.assertEqual(lib_proxy.is_pcell_variant(), False)
|
||||
self.assertEqual(lib.layout().cell(lib.layout().cell_by_name("StaticBox")).library().__repr__(), "None")
|
||||
|
||||
li2 = find_layer(ly, "10/0")
|
||||
self.assertEqual(li2 != None, True)
|
||||
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-250,-500;250,500)")
|
||||
self.assertEqual(ly.begin_shapes(lib_proxy.cell_index(), li2).shape().__str__(), "box (0,0;10,20)")
|
||||
|
||||
param = { "w": 1, "h": 2 }
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-50,-100;50,100)")
|
||||
|
||||
param = [ klayout.db.LayerInfo(1, 0), 5.0, 5.0 ]
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-250,-250;250,250)")
|
||||
|
||||
pcell_inst.change_pcell_parameters({ "w": 2.0, "h": 10.0 })
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-100,-500;100,500)")
|
||||
|
||||
pcell_inst.change_pcell_parameters([ klayout.db.LayerInfo(1, 0), 5.0, 5.0 ])
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-250,-250;250,250)")
|
||||
|
||||
pcell_inst.change_pcell_parameter("w", 5.0)
|
||||
pcell_inst.change_pcell_parameter("h", 1.0)
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-250,-50;250,50)")
|
||||
|
||||
c1.change_pcell_parameter(pcell_inst, "w", 10.0)
|
||||
c1.change_pcell_parameter(pcell_inst, "h", 2.0)
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-500,-100;500,100)")
|
||||
|
||||
self.assertEqual(ly.cell(pcell_inst.cell_index).is_pcell_variant(), True)
|
||||
self.assertEqual(pcell_inst.is_pcell(), True)
|
||||
new_id = ly.convert_cell_to_static(pcell_inst.cell_index)
|
||||
self.assertEqual(new_id == pcell_inst.cell_index, False)
|
||||
self.assertEqual(ly.cell(new_id).is_pcell_variant(), False)
|
||||
param = [ klayout.db.LayerInfo(1, 0), 5.0, 5.0 ]
|
||||
c1.change_pcell_parameters(pcell_inst, param)
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-250,-250;250,250)")
|
||||
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(klayout.db.Box(0, 10, 100, 210))
|
||||
l11 = ly.layer(11, 0)
|
||||
c1.shapes(l11).insert(klayout.db.Text("hello", klayout.db.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):
|
||||
|
||||
if not "PCellDeclarationHelper" in klayout.db.__dict__:
|
||||
return
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib2()
|
||||
|
||||
ly = klayout.db.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 = klayout.db.Library.library_by_name("PCellTestLib2")
|
||||
self.assertEqual(lib != None, True)
|
||||
pcell_decl = lib.layout().pcell_declaration("Box2")
|
||||
|
||||
param = [ klayout.db.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(klayout.db.CellInstArray(pcell_var_id, klayout.db.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__())
|
||||
self.assertEqual(pcell_decl.wants_lazy_evaluation(), True)
|
||||
|
||||
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": klayout.db.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(klayout.db.Box(0, 10, 100, 210))
|
||||
l11 = ly.layer(11, 0)
|
||||
c1.shapes(l11).insert(klayout.db.Text("hello", klayout.db.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
|
||||
tl = PCellTestLib()
|
||||
|
||||
ly = klayout.db.Layout(True)
|
||||
ly.dbu = 0.01
|
||||
|
||||
ci1 = ly.add_cell("c1")
|
||||
c1 = ly.cell(ci1)
|
||||
|
||||
lib = klayout.db.Library.library_by_name("PCellTestLib")
|
||||
pcell_decl_id = lib.layout().pcell_id("Box")
|
||||
|
||||
param = [ klayout.db.LayerInfo(1, 0), 10.0, 2.0 ]
|
||||
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
|
||||
pcell_var = ly.cell(pcell_var_id)
|
||||
pcell_inst = c1.insert(klayout.db.CellInstArray(pcell_var_id, klayout.db.Trans()))
|
||||
|
||||
li1 = find_layer(ly, "1/0")
|
||||
self.assertEqual(li1 != None, True)
|
||||
self.assertEqual(ly.is_valid_layer(li1), True)
|
||||
self.assertEqual(str(ly.get_info(li1)), "1/0")
|
||||
|
||||
self.assertEqual(pcell_inst.is_pcell(), True)
|
||||
|
||||
self.assertEqual(ly.begin_shapes(pcell_inst.cell_index, li1).shape().__str__(), "box (-500,-100;500,100)")
|
||||
pcell_inst.convert_to_static()
|
||||
self.assertEqual(pcell_inst.is_pcell(), False)
|
||||
self.assertEqual(ly.begin_shapes(pcell_inst.cell_index, li1).shape().__str__(), "box (-500,-100;500,100)")
|
||||
pcell_inst.convert_to_static()
|
||||
self.assertEqual(pcell_inst.is_pcell(), False)
|
||||
self.assertEqual(ly.begin_shapes(pcell_inst.cell_index, li1).shape().__str__(), "box (-500,-100;500,100)")
|
||||
|
||||
def test_3(self):
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib()
|
||||
|
||||
ly = klayout.db.Layout(True)
|
||||
ly.dbu = 0.01
|
||||
|
||||
c1 = ly.create_cell("c1")
|
||||
|
||||
lib = klayout.db.Library.library_by_name("PCellTestLib")
|
||||
pcell_decl_id = lib.layout().pcell_id("Box")
|
||||
|
||||
param = { "w": 4.0, "h": 8.0, "l": klayout.db.LayerInfo(1, 0) }
|
||||
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
|
||||
pcell_var = ly.cell(pcell_var_id)
|
||||
pcell_inst = c1.insert(klayout.db.CellInstArray(pcell_var_id, klayout.db.Trans()))
|
||||
|
||||
self.assertEqual(ly.begin_shapes(c1.cell_index(), ly.layer(1, 0)).shape().__str__(), "box (-200,-400;200,400)")
|
||||
|
||||
def test_4(self):
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib()
|
||||
|
||||
lib = klayout.db.Library.library_by_name("PCellTestLib")
|
||||
pcell_decl_id = lib.layout().pcell_id("Box")
|
||||
|
||||
param = { "w": 4.0, "h": 8.0, "l": klayout.db.LayerInfo(1, 0) }
|
||||
pcell_var_id = lib.layout().add_pcell_variant(pcell_decl_id, param)
|
||||
|
||||
self.assertEqual(lib.layout().begin_shapes(pcell_var_id, lib.layout().layer(1, 0)).shape().__str__(), "box (-2000,-4000;2000,4000)")
|
||||
|
||||
def test_5(self):
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib()
|
||||
|
||||
lib = klayout.db.Library.library_by_name("PCellTestLib")
|
||||
pcell_decl_id = lib.layout().pcell_id("Box")
|
||||
|
||||
param = { "w": 3.0, "h": 7.0, "l": klayout.db.LayerInfo(2, 0) }
|
||||
pcell_var_id = lib.layout().add_pcell_variant(pcell_decl_id, param)
|
||||
|
||||
self.assertEqual(lib.layout().begin_shapes(pcell_var_id, lib.layout().layer(2, 0)).shape().__str__(), "box (-1500,-3500;1500,3500)")
|
||||
|
||||
|
||||
def test_6(self):
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib()
|
||||
|
||||
lib = klayout.db.Library.library_by_name("PCellTestLib")
|
||||
|
||||
param = { "w": 3.0, "h": 8.0, "l": klayout.db.LayerInfo(3, 0) }
|
||||
pcell_var = lib.layout().create_cell("Box", param)
|
||||
|
||||
self.assertEqual(lib.layout().begin_shapes(pcell_var.cell_index(), lib.layout().layer(3, 0)).shape().__str__(), "box (-1500,-4000;1500,4000)")
|
||||
|
||||
|
||||
def test_7(self):
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib()
|
||||
|
||||
ly = klayout.db.Layout(True)
|
||||
ly.dbu = 0.01
|
||||
|
||||
param = { "w": 4.0, "h": 8.0, "l": klayout.db.LayerInfo(4, 0) }
|
||||
cell = ly.create_cell("Box", "PCellTestLib", param)
|
||||
|
||||
self.assertEqual(ly.begin_shapes(cell, ly.layer(4, 0)).shape().__str__(), "box (-200,-400;200,400)")
|
||||
|
||||
def test_8(self):
|
||||
|
||||
# instantiate and register the library
|
||||
tl = PCellTestLib()
|
||||
|
||||
lib = klayout.db.Library.library_by_name("PCellTestLib")
|
||||
ly = klayout.db.Layout(True)
|
||||
ly.dbu = 0.01
|
||||
|
||||
param = { "w": 2.0, "h": 6.0, "l": klayout.db.LayerInfo(5, 0) }
|
||||
pcell_var = lib.layout().create_cell("Box", param)
|
||||
pcell_var.name = "BOXVAR"
|
||||
|
||||
cell = ly.create_cell("BOXVAR", "PCellTestLib")
|
||||
|
||||
self.assertEqual(cell.begin_shapes_rec(ly.layer(5, 0)).shape().__str__(), "box (-100,-300;100,300)")
|
||||
|
||||
# run unit tests
|
||||
if __name__ == '__main__':
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(DBPCellTests)
|
||||
|
||||
if not unittest.TextTestRunner(verbosity = 1).run(suite).wasSuccessful():
|
||||
sys.exit(1)
|
||||
|
||||
Loading…
Reference in New Issue