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.
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)
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
>>> 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
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 (
ComplexNumberProperty) always cast the assigned value to the correct type.
1is passed to a
BoolProperty, it is converted to
Trueis passed to a
IntProperty, it is converted to
1is passed to a
FloatProperty), it is converted to
1is passed to a
ComplexNumberProperty, it is converted to
1.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
ComplexNumberPropertyshould 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 .
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.
Secondly, a number of class methods or attributes which had leading and trailing double underscores where renamed:
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.
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
[[-17 5] [ 10 5] [ 10 14] [ 5 14]]
In Ipkiss 3.0, the magnification will not round the numbers:
[[-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
Ipkiss 3.0 requires a number of new entries in the TECH settings tree:
WG_DEFAULTS. Also, in the baseline technology settings trees (
si_photonics.picazzo), a number of entries were moved
si_photonics settings to the
If you have your own technology file which directly imports
technologies.si_photonics.picazzo.default, then probably your scripts will run as is without modification
If you have copied and altered
technologies.default_ipkissor 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
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 (
ARef) in the
_default_elements()method. When doing so, they will not be recognized as proper Ipkiss 3 child cells (which are defined using
ChildCellProperty). 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 any
In Ipkiss 2.4, waveguides were elements (groups of geometric shapes drawn on layers), hence the ‘waveguide definitions’ like
WgElDefinitionare 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 mix
WaveguideDefinitions(Ipkiss 2.4) in one component.