# 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 a BoolProperty, it is converted to True.

• when True is passed to a IntProperty, it is converted to 1.

• when 1 is passed to a NumberProperty (equivalent to FloatProperty), it is converted to 1.0.

• when 1 is 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 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 .

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 or technologies.si_photonics.picazzo.default, then probably your scripts will run as is without modification

• If 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 *

• 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 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 Netlist or CapheModel 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 mix TraceTemplates (Ipkiss 3.0)and WaveguideDefinitions (Ipkiss 2.4) in one component.