Known changes and backwards incompatibilities in 2024.09
Removal of StackARef
This class has been removed in this release as part of a code base cleanup.
RestrictType does not allow None
i3.RestrictType
and all restrictions derived from it do not allow None as a valid value anymore.
Hence this does not work anymore:
import ipkiss3.all as i3
class ExampleRestrictType(i3.StrongPropertyInitializer):
restricted = i3.DefinitionProperty(restriction=i3.RestrictType(int))
example = ExampleRestrictType(restricted=None)
In order to allow None, explictly pass allow_none=True to the DefinitionProperty instead.
import ipkiss3.all as i3
class ExampleRestrictType(i3.StrongPropertyInitializer):
restricted = i3.DefinitionProperty(restriction=i3.RestrictType(int), allow_none=True)
example = ExampleRestrictType(restricted=None)
In more complex cases when you are building your own restrictions, you may need to add i3.RestrictNone(), e.g. i3.RestrictNone() | i3.RestrictType(allowed_types).
When you inherit from a class and lock a property that had allow_none=True then you’ll need to explicitly set it again. For example:
import ipkiss3.all as i3
class Super(i3.StrongPropertyInitializer):
number_or_none = i3.NumberProperty(allow_none=True)
def _default_number_or_none(self):
return None
class Sub(Super)
number_or_none = i3.NumberProperty(locked=True, allow_none=True)
Deprecated ipkiss core types
Duplication and aliased classes with ipcore.types, ipcore.properties.container_properties, and ipkiss3.core was cleaned up. As a result, several already deprecated classes were removed, some classes were combined into one, and modules have been re-organized.
Removed class |
Equivalent class |
---|---|
In module ipcore.types.typed_dict:
|
Use instead:
|
In module ipcore.properties.container_properties:
|
Use instead:
|
Module ipkiss3.core.types.typed_list was removed:
|
Use classes from ipkiss3.all instead:
|
Module ipkiss3.core.types.typed_dict was removed:
|
Use classes from ipkiss3.all instead:
|
ipkiss3.core.types.named_typed_dict.NamedTypedDict |
ipcore.types.named_typed_dict.OrderedNamedTypedDict |
In module ipkiss3.core.properties.containers.named_typed_dict:
|
Use instead:
|
In module ipkiss3.core.properties.containers.atom_dict:
|
Use instead:
|
In module ipkiss3.core.properties.containers.autonamed_typed_dict:
|
Use instead:
|
Also, ipkiss3.core.moduleloader was removed.
Fixed bug in ShapeRound
A bug in fitting circular bends was fixed. Said bug was introduced in 3.10 and it was only affecting cases where there was not enough space to fit the bend with the desired radius. In those cases, rounded shapes will differ, being correct in 3.9 and 2024.09 (and incorrect in 3.10-3.12).
import ipkiss3.all as i3
pts = [(0.0, 0.0), (0.0, 30.0), (5.0, 35.0), (20.0, 20.0), (10.0, 0.0)]
shape = i3.Shape(pts)
rounded_shape = i3.ShapeRound(original_shape=shape, radius=10)
elements = i3.ElementList()
elements += i3.Boundary(
layer=i3.Layer(1),
shape=rounded_shape,
)
example_path = i3.LayoutCell(name="example_path").Layout(elements=elements)
example_path.visualize()
Boolean operations (2024.09.1)
The number of shape cutting operations performed during boolean operations on elements has been reduced. Note that when exporting to GDSII, shapes of Boundaries and Paths will still be cut where necessary to adhere to the GDSII standard.
One side effect is that when i3.Path is used, closed shapes (a path with the same start and end point) will not be cut anymore before doing the boolean operation itself. As a result, such a closed shape can be cut in a different place. This is XOR equivalent and has no effect on the layout. Also, when using Luceda IPManager for regression testing of your libraries, such cutting differences will be ignored.
This is an example occurrence, going through a boolean operation function but without actually doing a real boolean operation.
import ipkiss3.all as i3
layer0 = i3.Layer(0)
layer1 = i3.Layer(1)
path_shape = i3.Shape([
(5, 0),
(0, 0),
(0, 10),
(10, 10),
(10, 0),
(5, 0),
])
path = i3.Path(
layer=layer0,
shape=path_shape,
line_width=2,
)
elements = i3.ElementList([path])
boolean_elements = i3.get_elements_for_generated_layers(elements, {layer0: layer1})
layout = i3.LayoutCell().Layout(elements=boolean_elements)
layout.visualize()
In 2024.09.0 this gives:
While in 2024.09.1 this gives: