Running Ipkiss 2.4 code in Ipkiss 3
Ipkiss 3.0 has a syntax which is considerably different from the Ipkiss 2.4 syntax, in order to provide features such as netlisting, device models and multiple view of the same type. A compatibility layer has been provided in order to be able to run existing scripts written for Ipkiss 2.4 on an Ipkisss 3.0 installation.
Most regular scripts should be able to run unmodified on the Ipkiss 3.0 installation. Of course, it is not possible to use the new features of 3.0 using a script in 2.4 syntax. For that you will need to port your Ipkiss 2.4 components to Ipkiss 3.0 syntax. Check out the porting guide for instructions on how to do that.
Users who build their own technology settings file, or power users who use Ipkiss base classes to build an advanced framework, will need to apply a number of changes and pay attention to a few Backward incompatible changes in Ipkiss listed in this document.
Property system
The property system received a complete overhaul in Ipkiss 3.0. A number of things have changed which may impact your current code:
Most Ipkiss objects are StrongPropertyInitializer
objects. This has not changed from Ipkiss 2.4 to Ipkiss 3.0, but the underlying type
enforcement and caching mechanisms have changed.
Using properties on objects that don’t inherit from StrongPropertyInitializer
The following was a common pattern in Ipkiss 2.4:
class A(object):
prop = DefinitionProperty(default="abc")
class B(A, StrongPropertyInitializer):
pass
b = B()
print(b.prop) # This would print "abc"
This can be confusing as it might suggest that adding properties to a class
that doesn’t inherit from StrongPropertyInitializer
is okay.
This behavior isn’t supported anymore and will now result in errors, instead you should
write the following:
class A(StrongPropertyInitializer):
prop = DefinitionProperty(default="abc")
class B(A, StrongPropertyInitializer):
pass
b = B()
print(b.prop)
Overriding Properties with normal python attributes
In 2.4 the following behavior was possible:
class A(StrongPropertyInitializer):
p = DefinitionProperty(default=123)
class B(A):
p = 456
This behavior has been changed as it can result in various unexpected side-effects. If you want to override a Property to give it for example a new default value, you must create a new Property. This means that the example above would become:
class A(StrongPropertyInitializer):
p = DefinitionProperty(default=123)
class B(A):
p = DefinitionProperty(default=456)
Implementing Restrictions
If you have defined custom Restrictions you might need to make some modifications. If you have a simple restriction that just implements the validate method, you probably don’t need to change anything. The following restriction is for example perfectly valid code.
class EvenRestriction(_PropertyRestriction):
"""
Restrict to even numbers
"""
def validate(self, value, obj=None):
return (value % 2 == 0)
However when you have a more elaborate restriction with attributes you need to take notice of a few things:
Use slots for your attributes
In your __init__ method, make sure you call the __init__ method of the super class.
Let’s clarify this with an example:
class ModRestriction(_PropertyRestriction):
"""
Restrict to numbers that are multiple of the given modulo.
"""
def __init__(self, modulo):
self.mod = modulo
def validate(self, value, obj=None):
return (value % self.modulo == 0)
This should now become:
class ModRestriction(_PropertyRestriction):
"""
Restrict to numbers that are multiple of the given modulo.
"""
__slots__ = ('mod',)
def __init__(self, modulo):
self.mod = modulo
super(ModRestriction, self).__init__()
def validate(self, value, obj=None):
return (value % self.mod == 0)
Creating classes with definition names that are not declared at first
Consider the following IPKISS 2.4 class:
class MyBaseClass(StrongPropertyInitializer):
p1 = DefinitionProperty(fdef_name="function_that_doesn_exist_yet")
As you can see, this class has one property, p1
, which is defined by calling function_that_doesn_exist_yet
. When creating a new class, the following would succeed in IPKISS 2.4:
>>> a = MyBaseClass()
As you can see, the class is successfully created, even if the function to define p1
does not yet exist. The old IPKISS version would fail when asking the value for p1
:
>>> print a.p1
AttributeError: 'MyBaseClass' object has no attribute 'function_that_doesn_exist_yet'
In IPKISS 3, this error is caught earlier on, at class creation. Example:
>>> a = MyBaseClass()
ipcore.exceptions.exc.IpcoreAttributeException: Required property 'p1' is not found in keyword arguments of '<class 'MyBaseClass'>' initialization.
It calculated that p1
should be required, and since it wasn’t passed during instantiation, it throws an error.
The following would have worked: a = MyBaseClass(p1=4)
.
Of course, the real use case is when a new class inherits from MyBaseClass
, implementing the function_that_doesn_exist_yet
function:
class MyParentClass(MyBaseClass):
def function_that_doesn_exist_yet(self):
return 5
Which, in both IPKISS versions, yields the same behavior, i.e.:
>>> b = MyParentClass()
>>> print b.p1
5
Number properties are cast to the correct type
As of IPKISS 3.0.1, number properties behave slightly different: basic type (bool
, int
, float
, complex
) properties
(such as BoolProperty
, IntProperty
, NumberProperty
and ComplexNumberProperty
) always cast the assigned value to the correct type.
For example:
when
1
is passed to aBoolProperty
, it is converted toTrue
.when
True
is passed to aIntProperty
, it is converted to1
.when
1
is passed to aNumberProperty
(equivalent toFloatProperty
), it is converted to1.0
.when
1
is passed to aComplexNumberProperty
, it is converted to1.0 + 1j
.from ipkiss3 import all as i3 class A(i3.StrongPropertyInitializer): p1 = i3.FloatProperty()
>>> a = A(p1=4) >>> a.p1 4.0
There are several reasons for this slight change in behavior:
Ensuring consistency: a property denoted as a
ComplexNumberProperty
should really contain a complex number, and not possibly an integer value.When IPKISS is interfaced with other frameworks (such as Caphe, OpenAccess, or an EDA tool), enforcing the correct types improves consistency and stability of the overall framework.
(more technical reason: ) atom, the framework upon which IPKISS is based, work with the same principles.
Additional information can be found in :ref:porting301-guide .
Leading and trailing underscores
Ipkiss 3.0 has been made more PEP-8 [1] compliant. As a result, several symbols which were not intended to be used by the user have been renamed. In particular:
Several base classes in Ipkiss had a leading and trailing double underscore. These have been renamed to have a single leading underscore and no trailing underscore. Hence, they are now normal symbols for internal use, and not “magic” names anymore. If you have subclassed from these base classes in order to implement your own functionality, you will need to adapt their names in your code.
Ipkiss 2.4
Ipkiss 3.0
__PropertyRestriction__
_PropertyRestriction
__PropertyRestrictionAnd__
_PropertyRestrictionAnd
__PropertyRestrictionOr__
_PropertyRestrictionOr
__PropertyRestrictionNot__
_PropertyRestrictionNot
__BasePropertyDescriptor__
_BasePropertyDescriptor
__CompoundPropertyProcessor__
_CompoundPropertyProcessor
__Procedure__
_Procedure
__Processor__
_Processor
__StopCriterium__
_StopCriterium
__Element__
_Element
__ShapeElement__
_ShapeElement
__LayerElement__
_LayerElement
__Group__
_Group
__BaseWaveguideElement__
_BaseWaveguideElement
__Aspect__
_Aspect
__Port__
_Port
__InPort__
_InPort
__OutPort__
_OutPort
__OrientedPort__
_OrientedPort
__OutOfPlanePort__
_OutOfPlanePort
Secondly, a number of class methods or attributes which had leading and trailing double underscores where renamed:
Ipkiss 2.4
Ipkiss 3.0
TypedList.__item_type__
TypedList._item_type
PropertyInitializer.__externally_set_properties__
PropertyInitializer._externally_set_properties
PropertyInitializer.__unlocked_properties__
PropertyInitializer._unlocked_properties
The notable exception to this is __name_prefix__
, which was kept since it is a frequently used attribute. This only holds for Ipkiss 2.4 Structures though - for all new-style PCells however,
_name_prefix
should be used to alter the naming prefix of the parametric cell.
Layout
Magnification
In IPKISS 2.4, the magnification function rounds integers. For example (for a more elaborate example, see samples/ipkiss/elements.py):
coordinates = Shape([(-179,54), (101,54), (101,149), (59,149)],
closed = True)
coordinates.magnify((0.0, 0.0), 0.1)
print coordinates.points
would print
[[-17 5]
[ 10 5]
[ 10 14]
[ 5 14]]
In Ipkiss 3.0, the magnification will not round the numbers:
print coordinates.points
yields
[[-17.9 5.4]
[ 10.1 5.4]
[ 10.1 14.9]
[ 5.9 14.9]]
This is equal to the behavior when using Python3 compared to Python2. For example, in Python 2:
>>> print 2/3
0
In Python 3:
>>> print 2/3
0.666
Technology files
Ipkiss 3.0 requires a number of new entries in the TECH settings tree: TECH.PCELLS
, TECH.TRACE
, TECH.DEFAULT_WAVELENGTH
,
WG_DEFAULTS
. Also, in the baseline technology settings trees (default_ipkiss
, si_photonics.ipkiss
and si_photonics.picazzo
), a number of entries were moved
from the si_photonics
settings to the default_ipkiss
settings.
If you have your own technology file which directly imports
technologies.default_ipkiss
ortechnologies.si_photonics.picazzo.default
, then probably your scripts will run as is without modificationIf you have copied and altered
technologies.default_ipkiss
or one of the other files, then some entries will be missing. We provide an extra package which you can import that will give you a large chance of not needing further modifications. Just import it after your tech file as follow:from my_own_tech import * from technologies.compat24.default_ipkiss import *
If you experience problems, contact us for support
Mixing 3.0 and 2.4 syntax
In Ipkiss 2.4, parametric cells were called Structures and only held layout elements and ports. In Ipkiss 3.0, the PCell is the new datastructure encapsulating all information about a parametric cell. A PCell has Views which define the information relevant to specific parts of the design flow: layout, netlist, Caphe model, etc. Hence, the Ipkiss 2.4 syntax is much more limited and suitable for layout information.
Mixing 2.4 and 3.0 syntax within one design is currently not officially supported. Any design doing so will only be fully functional on the layout level.
Advanced users can try it but should consider a few issues.
Ipkiss 2.4 Structures behave like the Layout view of an Ipkiss 3.0 PCell, but don’t have exactly the same API. You can refer to Ipkiss 2.4 Structures from within the Layout view of a PCell using reference elements (
SRef
,ARef
) in the_default_elements()
method. When doing so, they will not be recognized as proper Ipkiss 3 child cells (which are defined usingChildCellProperty
). Neither can they be taken into account for circuit simulation using Caphe. You can also assign an Ipkiss 2.4 Structure object to a ChildCellProperty of a PCell, but that PCell should then not have anyNetlist
orCapheModel
views.In Ipkiss 2.4, waveguides were elements (groups of geometric shapes drawn on layers), hence the ‘waveguide definitions’ like
WgElDefinition
are generating waveguide elements. In Ipkiss 3.0, waveguides are (parametric) cells on their own right. In addition, they are derived from the more generic ‘trace templates’ concept. It is difficult to mixTraceTemplates
(Ipkiss 3.0)andWaveguideDefinitions
(Ipkiss 2.4) in one component.