pyedb 0.53.0__py3-none-any.whl → 0.54.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_ports_sources.py +6 -8
- pyedb/configuration/configuration.py +2 -1
- pyedb/dotnet/database/cell/hierarchy/model.py +1 -1
- pyedb/dotnet/database/cell/layout.py +1 -1
- pyedb/dotnet/database/cell/layout_obj.py +3 -3
- pyedb/dotnet/database/cell/primitive/path.py +1 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +8 -8
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +24 -26
- pyedb/dotnet/database/components.py +24 -24
- pyedb/dotnet/database/definition/component_def.py +3 -3
- pyedb/dotnet/database/definition/component_model.py +1 -1
- pyedb/dotnet/database/definition/package_def.py +1 -1
- pyedb/dotnet/database/dotnet/database.py +43 -38
- pyedb/dotnet/database/dotnet/primitive.py +16 -16
- pyedb/dotnet/database/edb_data/hfss_extent_info.py +6 -6
- pyedb/dotnet/database/edb_data/layer_data.py +14 -14
- pyedb/dotnet/database/edb_data/padstacks_data.py +12 -12
- pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
- pyedb/dotnet/database/edb_data/sources.py +6 -6
- pyedb/dotnet/database/edb_data/variables.py +7 -3
- pyedb/dotnet/database/geometry/point_data.py +1 -1
- pyedb/dotnet/database/geometry/polygon_data.py +2 -4
- pyedb/dotnet/database/hfss.py +7 -7
- pyedb/dotnet/database/materials.py +2 -2
- pyedb/dotnet/database/modeler.py +8 -11
- pyedb/dotnet/database/nets.py +1 -1
- pyedb/dotnet/database/padstack.py +72 -1
- pyedb/dotnet/database/sim_setup_data/data/settings.py +24 -0
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +26 -1
- pyedb/dotnet/database/siwave.py +5 -5
- pyedb/dotnet/database/stackup.py +74 -77
- pyedb/dotnet/database/utilities/heatsink.py +4 -4
- pyedb/dotnet/database/utilities/obj_base.py +1 -1
- pyedb/dotnet/database/utilities/value.py +116 -0
- pyedb/dotnet/edb.py +43 -43
- pyedb/generic/design_types.py +12 -3
- pyedb/grpc/__init__.py +0 -0
- pyedb/grpc/database/components.py +53 -17
- pyedb/grpc/database/definition/materials.py +23 -30
- pyedb/grpc/database/definition/package_def.py +15 -15
- pyedb/grpc/database/definition/padstack_def.py +51 -51
- pyedb/grpc/database/geometry/arc_data.py +7 -5
- pyedb/grpc/database/geometry/point_3d_data.py +8 -7
- pyedb/grpc/database/geometry/polygon_data.py +3 -2
- pyedb/grpc/database/hierarchy/component.py +43 -38
- pyedb/grpc/database/hierarchy/pin_pair_model.py +15 -14
- pyedb/grpc/database/hierarchy/pingroup.py +9 -9
- pyedb/grpc/database/layers/stackup_layer.py +45 -44
- pyedb/grpc/database/layout/layout.py +9 -8
- pyedb/grpc/database/layout/voltage_regulator.py +7 -7
- pyedb/grpc/database/layout_validation.py +13 -12
- pyedb/grpc/database/modeler.py +51 -54
- pyedb/grpc/database/nets.py +42 -31
- pyedb/grpc/database/padstacks.py +270 -175
- pyedb/grpc/database/ports/ports.py +5 -6
- pyedb/grpc/database/primitive/bondwire.py +8 -7
- pyedb/grpc/database/primitive/circle.py +4 -4
- pyedb/grpc/database/primitive/padstack_instance.py +18 -18
- pyedb/grpc/database/primitive/path.py +7 -7
- pyedb/grpc/database/primitive/polygon.py +3 -3
- pyedb/grpc/database/primitive/primitive.py +13 -17
- pyedb/grpc/database/primitive/rectangle.py +13 -13
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +10 -0
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +17 -1
- pyedb/grpc/database/siwave.py +30 -24
- pyedb/grpc/database/source_excitations.py +333 -229
- pyedb/grpc/database/stackup.py +164 -147
- pyedb/grpc/database/terminal/bundle_terminal.py +17 -7
- pyedb/grpc/database/terminal/edge_terminal.py +10 -0
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +15 -4
- pyedb/grpc/database/terminal/pingroup_terminal.py +11 -10
- pyedb/grpc/database/terminal/point_terminal.py +4 -3
- pyedb/grpc/database/terminal/terminal.py +9 -9
- pyedb/grpc/database/utility/value.py +109 -0
- pyedb/grpc/edb.py +59 -38
- pyedb/grpc/edb_init.py +0 -7
- {pyedb-0.53.0.dist-info → pyedb-0.54.0.dist-info}/METADATA +3 -3
- {pyedb-0.53.0.dist-info → pyedb-0.54.0.dist-info}/RECORD +84 -81
- {pyedb-0.53.0.dist-info → pyedb-0.54.0.dist-info}/WHEEL +0 -0
- {pyedb-0.53.0.dist-info → pyedb-0.54.0.dist-info}/licenses/LICENSE +0 -0
pyedb/grpc/database/stackup.py
CHANGED
|
@@ -31,6 +31,7 @@ from collections import OrderedDict
|
|
|
31
31
|
import json
|
|
32
32
|
import logging
|
|
33
33
|
import math
|
|
34
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
34
35
|
import warnings
|
|
35
36
|
|
|
36
37
|
from ansys.edb.core.definition.die_property import DieOrientation as GrpcDieOrientation
|
|
@@ -49,11 +50,11 @@ from ansys.edb.core.layer.layer_collection import LayerCollection as GrpcLayerCo
|
|
|
49
50
|
from ansys.edb.core.layer.layer_collection import LayerTypeSet as GrpcLayerTypeSet
|
|
50
51
|
from ansys.edb.core.layer.stackup_layer import StackupLayer as GrpcStackupLayer
|
|
51
52
|
from ansys.edb.core.layout.mcad_model import McadModel as GrpcMcadModel
|
|
52
|
-
from ansys.edb.core.utility.value import Value as GrpcValue
|
|
53
53
|
|
|
54
54
|
from pyedb.generic.general_methods import ET, generate_unique_name
|
|
55
55
|
from pyedb.grpc.database.layers.layer import Layer
|
|
56
56
|
from pyedb.grpc.database.layers.stackup_layer import StackupLayer
|
|
57
|
+
from pyedb.grpc.database.utility.value import Value
|
|
57
58
|
from pyedb.misc.aedtlib_personalib_install import write_pretty_xml
|
|
58
59
|
|
|
59
60
|
colors = None
|
|
@@ -104,7 +105,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
104
105
|
"""
|
|
105
106
|
self._pedb.layout.layer_collection = self
|
|
106
107
|
|
|
107
|
-
def add_layer_top(self, name, layer_type="signal", **kwargs):
|
|
108
|
+
def add_layer_top(self, name: str, layer_type: str = "signal", **kwargs) -> Union["Layer", None]:
|
|
108
109
|
"""Add a layer on top of the stackup.
|
|
109
110
|
|
|
110
111
|
Parameters
|
|
@@ -130,10 +131,10 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
130
131
|
>>> top_layer = edb.stackup.add_layer_top("NewTopLayer", layer_type="signal", thickness="0.1mm",
|
|
131
132
|
... material="copper")
|
|
132
133
|
"""
|
|
133
|
-
thickness =
|
|
134
|
+
thickness = Value(0.0)
|
|
134
135
|
if "thickness" in kwargs:
|
|
135
|
-
thickness =
|
|
136
|
-
elevation =
|
|
136
|
+
thickness = Value(kwargs["thickness"])
|
|
137
|
+
elevation = Value(0.0)
|
|
137
138
|
_layer_type = GrpcLayerType.SIGNAL_LAYER
|
|
138
139
|
if layer_type.lower() == "dielectric":
|
|
139
140
|
_layer_type = GrpcLayerType.DIELECTRIC_LAYER
|
|
@@ -142,7 +143,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
142
143
|
)
|
|
143
144
|
return self._layer_collection.add_layer_top(layer)
|
|
144
145
|
|
|
145
|
-
def add_layer_bottom(self, name, layer_type="signal", **kwargs):
|
|
146
|
+
def add_layer_bottom(self, name: str, layer_type: str = "signal", **kwargs) -> Union["Layer", None]:
|
|
146
147
|
"""Add a layer at the bottom of the stackup.
|
|
147
148
|
|
|
148
149
|
Parameters
|
|
@@ -169,11 +170,11 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
169
170
|
>>> bot_layer = edb.stackup.add_layer_bottom("NewBottomLayer", layer_type="signal", thickness="0.1mm",
|
|
170
171
|
... material="copper")
|
|
171
172
|
"""
|
|
172
|
-
thickness =
|
|
173
|
+
thickness = Value(0.0)
|
|
173
174
|
layer_type_map = {"dielectric": GrpcLayerType.DIELECTRIC_LAYER, "signal": GrpcLayerType.SIGNAL_LAYER}
|
|
174
175
|
if "thickness" in kwargs:
|
|
175
|
-
thickness =
|
|
176
|
-
elevation =
|
|
176
|
+
thickness = Value(kwargs["thickness"])
|
|
177
|
+
elevation = Value(0.0)
|
|
177
178
|
if "type" in kwargs:
|
|
178
179
|
_layer_type = layer_type_map[kwargs["type"]]
|
|
179
180
|
else:
|
|
@@ -189,7 +190,9 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
189
190
|
layer.set_fill_material(kwargs["fill_material"])
|
|
190
191
|
return self._layer_collection.add_layer_bottom(layer)
|
|
191
192
|
|
|
192
|
-
def add_layer_below(
|
|
193
|
+
def add_layer_below(
|
|
194
|
+
self, name: str, base_layer_name: str, layer_type: str = "signal", **kwargs
|
|
195
|
+
) -> Union["Layer", None]:
|
|
193
196
|
"""Add a layer below a specified layer.
|
|
194
197
|
|
|
195
198
|
Parameters
|
|
@@ -216,10 +219,10 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
216
219
|
>>> edb = Edb()
|
|
217
220
|
>>> new_layer = edb.stackup.add_layer_below("NewLayer", "TopLayer", layer_type="dielectric", thickness="0.05mm")
|
|
218
221
|
"""
|
|
219
|
-
thickness =
|
|
222
|
+
thickness = Value(0.0)
|
|
220
223
|
if "thickness" in kwargs:
|
|
221
|
-
thickness =
|
|
222
|
-
elevation =
|
|
224
|
+
thickness = Value(kwargs["thickness"])
|
|
225
|
+
elevation = Value(0.0)
|
|
223
226
|
if "type" in kwargs:
|
|
224
227
|
_l_map = {"signal": GrpcLayerType.SIGNAL_LAYER, "dielectric": GrpcLayerType.DIELECTRIC_LAYER}
|
|
225
228
|
_layer_type = _l_map[kwargs["type"]]
|
|
@@ -236,7 +239,9 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
236
239
|
)
|
|
237
240
|
return self._layer_collection.add_layer_below(layer, base_layer_name)
|
|
238
241
|
|
|
239
|
-
def add_layer_above(
|
|
242
|
+
def add_layer_above(
|
|
243
|
+
self, name: str, base_layer_name: str, layer_type: str = "signal", **kwargs
|
|
244
|
+
) -> Union["Layer", None]:
|
|
240
245
|
"""Add a layer above a specified layer.
|
|
241
246
|
|
|
242
247
|
Parameters
|
|
@@ -263,10 +268,10 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
263
268
|
>>> edb = Edb()
|
|
264
269
|
>>> new_layer = edb.stackup.add_layer_above("NewLayer", "BottomLayer", layer_type="signal", thickness="0.05mm")
|
|
265
270
|
"""
|
|
266
|
-
thickness =
|
|
271
|
+
thickness = Value(0.0)
|
|
267
272
|
if "thickness" in kwargs:
|
|
268
|
-
thickness =
|
|
269
|
-
elevation =
|
|
273
|
+
thickness = Value(kwargs["thickness"])
|
|
274
|
+
elevation = Value(0.0)
|
|
270
275
|
_layer_type = GrpcLayerType.SIGNAL_LAYER
|
|
271
276
|
if layer_type.lower() == "dielectric":
|
|
272
277
|
_layer_type = GrpcLayerType.DIELECTRIC_LAYER
|
|
@@ -275,7 +280,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
275
280
|
)
|
|
276
281
|
return self._layer_collection.add_layer_above(layer, base_layer_name)
|
|
277
282
|
|
|
278
|
-
def add_document_layer(self, name, layer_type="user", **kwargs):
|
|
283
|
+
def add_document_layer(self, name: str, layer_type: str = "user", **kwargs: Any) -> Optional["Layer"]:
|
|
279
284
|
"""Add a document layer.
|
|
280
285
|
|
|
281
286
|
Parameters
|
|
@@ -318,7 +323,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
318
323
|
return self.layers
|
|
319
324
|
|
|
320
325
|
@property
|
|
321
|
-
def non_stackup_layers(self):
|
|
326
|
+
def non_stackup_layers(self) -> Dict[str, Layer]:
|
|
322
327
|
"""Retrieve the dictionary of non-stackup layers.
|
|
323
328
|
|
|
324
329
|
Returns
|
|
@@ -337,7 +342,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
337
342
|
}
|
|
338
343
|
|
|
339
344
|
@property
|
|
340
|
-
def all_layers(self):
|
|
345
|
+
def all_layers(self) -> Dict[str, Layer]:
|
|
341
346
|
"""Retrieve all layers.
|
|
342
347
|
|
|
343
348
|
Returns
|
|
@@ -354,7 +359,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
354
359
|
return {layer.name: Layer(self._pedb, layer) for layer in self.get_layers(GrpcLayerTypeSet.ALL_LAYER_SET)}
|
|
355
360
|
|
|
356
361
|
@property
|
|
357
|
-
def signal_layers(self):
|
|
362
|
+
def signal_layers(self) -> Dict[str, StackupLayer]:
|
|
358
363
|
"""Retrieve the dictionary of signal layers.
|
|
359
364
|
|
|
360
365
|
Returns
|
|
@@ -373,7 +378,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
373
378
|
}
|
|
374
379
|
|
|
375
380
|
@property
|
|
376
|
-
def dielectric_layers(self):
|
|
381
|
+
def dielectric_layers(self) -> Dict[str, StackupLayer]:
|
|
377
382
|
"""Retrieve the dictionary of dielectric layers.
|
|
378
383
|
|
|
379
384
|
Returns
|
|
@@ -393,7 +398,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
393
398
|
}
|
|
394
399
|
|
|
395
400
|
@property
|
|
396
|
-
def layers_by_id(self):
|
|
401
|
+
def layers_by_id(self) -> List[List[Union[int, str]]]:
|
|
397
402
|
"""Retrieve the list of layers with their IDs.
|
|
398
403
|
|
|
399
404
|
Returns
|
|
@@ -410,7 +415,7 @@ class LayerCollection(GrpcLayerCollection):
|
|
|
410
415
|
return [[obj.id, name] for name, obj in self.all_layers.items()]
|
|
411
416
|
|
|
412
417
|
@property
|
|
413
|
-
def layers(self):
|
|
418
|
+
def layers(self) -> Dict[str, StackupLayer]:
|
|
414
419
|
"""Retrieve the dictionary of stackup layers (signal and dielectric).
|
|
415
420
|
|
|
416
421
|
Returns
|
|
@@ -486,7 +491,7 @@ class Stackup(LayerCollection):
|
|
|
486
491
|
return self._pedb.logger
|
|
487
492
|
|
|
488
493
|
@property
|
|
489
|
-
def thickness(self):
|
|
494
|
+
def thickness(self) -> float:
|
|
490
495
|
"""Retrieve the stackup thickness.
|
|
491
496
|
|
|
492
497
|
Returns
|
|
@@ -503,7 +508,7 @@ class Stackup(LayerCollection):
|
|
|
503
508
|
return self.get_layout_thickness()
|
|
504
509
|
|
|
505
510
|
@property
|
|
506
|
-
def num_layers(self):
|
|
511
|
+
def num_layers(self) -> int:
|
|
507
512
|
"""Retrieve the number of layers in the stackup.
|
|
508
513
|
|
|
509
514
|
Returns
|
|
@@ -521,14 +526,14 @@ class Stackup(LayerCollection):
|
|
|
521
526
|
|
|
522
527
|
def create_symmetric_stackup(
|
|
523
528
|
self,
|
|
524
|
-
layer_count,
|
|
525
|
-
inner_layer_thickness="17um",
|
|
526
|
-
outer_layer_thickness="50um",
|
|
527
|
-
dielectric_thickness="100um",
|
|
528
|
-
dielectric_material="FR4_epoxy",
|
|
529
|
-
soldermask=True,
|
|
530
|
-
soldermask_thickness="20um",
|
|
531
|
-
) -> bool:
|
|
529
|
+
layer_count: int,
|
|
530
|
+
inner_layer_thickness: str = "17um",
|
|
531
|
+
outer_layer_thickness: str = "50um",
|
|
532
|
+
dielectric_thickness: str = "100um",
|
|
533
|
+
dielectric_material: str = "FR4_epoxy",
|
|
534
|
+
soldermask: bool = True,
|
|
535
|
+
soldermask_thickness: str = "20um",
|
|
536
|
+
) -> bool:
|
|
532
537
|
"""Create a symmetric stackup.
|
|
533
538
|
|
|
534
539
|
Parameters
|
|
@@ -649,7 +654,7 @@ class Stackup(LayerCollection):
|
|
|
649
654
|
return True
|
|
650
655
|
|
|
651
656
|
@property
|
|
652
|
-
def mode(self):
|
|
657
|
+
def mode(self) -> str:
|
|
653
658
|
"""Stackup mode.
|
|
654
659
|
|
|
655
660
|
Returns
|
|
@@ -683,7 +688,9 @@ class Stackup(LayerCollection):
|
|
|
683
688
|
super(LayerCollection, self.__class__).mode.__set__(self, GrpcLayerCollectionMode.MULTIZONE)
|
|
684
689
|
self.update_layout()
|
|
685
690
|
|
|
686
|
-
def _set_layout_stackup(
|
|
691
|
+
def _set_layout_stackup(
|
|
692
|
+
self, layer_clone: GrpcStackupLayer, operation: str, base_layer: Optional[str] = None, method: int = 1
|
|
693
|
+
) -> None:
|
|
687
694
|
"""Internal method. Apply stackup change into EDB.
|
|
688
695
|
|
|
689
696
|
Parameters
|
|
@@ -738,23 +745,25 @@ class Stackup(LayerCollection):
|
|
|
738
745
|
self._pedb.layout.layer_collection = lc
|
|
739
746
|
return True
|
|
740
747
|
|
|
741
|
-
def _create_stackup_layer(
|
|
748
|
+
def _create_stackup_layer(
|
|
749
|
+
self, layer_name: str, thickness: Union[str, float], layer_type: str = "signal", material: str = "copper"
|
|
750
|
+
) -> StackupLayer:
|
|
742
751
|
if layer_type == "signal":
|
|
743
752
|
_layer_type = GrpcLayerType.SIGNAL_LAYER
|
|
744
753
|
else:
|
|
745
754
|
_layer_type = GrpcLayerType.DIELECTRIC_LAYER
|
|
746
755
|
material = "FR4_epoxy"
|
|
747
|
-
thickness =
|
|
756
|
+
thickness = Value(thickness, self._pedb.active_db)
|
|
748
757
|
layer = StackupLayer.create(
|
|
749
758
|
name=layer_name,
|
|
750
759
|
layer_type=_layer_type,
|
|
751
760
|
thickness=thickness,
|
|
752
|
-
elevation=
|
|
761
|
+
elevation=Value(0),
|
|
753
762
|
material=material,
|
|
754
763
|
)
|
|
755
764
|
return layer
|
|
756
765
|
|
|
757
|
-
def _create_nonstackup_layer(self, layer_name, layer_type):
|
|
766
|
+
def _create_nonstackup_layer(self, layer_name: str, layer_type: str):
|
|
758
767
|
if layer_type == "conducting": # pragma: no cover
|
|
759
768
|
_layer_type = GrpcLayerType.CONDUCTING_LAYER
|
|
760
769
|
elif layer_type == "airlines": # pragma: no cover
|
|
@@ -791,7 +800,7 @@ class Stackup(LayerCollection):
|
|
|
791
800
|
result = Layer.create(layer_name, _layer_type)
|
|
792
801
|
return result
|
|
793
802
|
|
|
794
|
-
def add_outline_layer(self,
|
|
803
|
+
def add_outline_layer(self, name: str = "Outline") -> bool:
|
|
795
804
|
"""Add an outline layer named "Outline" if it is not present.
|
|
796
805
|
|
|
797
806
|
Returns
|
|
@@ -809,18 +818,18 @@ class Stackup(LayerCollection):
|
|
|
809
818
|
|
|
810
819
|
def add_layer(
|
|
811
820
|
self,
|
|
812
|
-
layer_name,
|
|
813
|
-
base_layer=None,
|
|
814
|
-
method="add_on_top",
|
|
815
|
-
layer_type="signal",
|
|
816
|
-
material="copper",
|
|
817
|
-
fillMaterial="FR4_epoxy",
|
|
818
|
-
thickness="35um",
|
|
819
|
-
etch_factor=None,
|
|
820
|
-
is_negative=False,
|
|
821
|
-
enable_roughness=False,
|
|
822
|
-
elevation=None,
|
|
823
|
-
):
|
|
821
|
+
layer_name: str,
|
|
822
|
+
base_layer: Optional[str] = None,
|
|
823
|
+
method: str = "add_on_top",
|
|
824
|
+
layer_type: str = "signal",
|
|
825
|
+
material: str = "copper",
|
|
826
|
+
fillMaterial: str = "FR4_epoxy",
|
|
827
|
+
thickness: Union[str, float] = "35um",
|
|
828
|
+
etch_factor: Optional[float] = None,
|
|
829
|
+
is_negative: bool = False,
|
|
830
|
+
enable_roughness: bool = False,
|
|
831
|
+
elevation: Optional[float] = None,
|
|
832
|
+
) -> bool:
|
|
824
833
|
"""Insert a layer into stackup.
|
|
825
834
|
|
|
826
835
|
Parameters
|
|
@@ -906,7 +915,7 @@ class Stackup(LayerCollection):
|
|
|
906
915
|
new_layer.negative = is_negative
|
|
907
916
|
l1 = len(self.layers)
|
|
908
917
|
if method == "add_at_elevation" and elevation:
|
|
909
|
-
new_layer.lower_elevation =
|
|
918
|
+
new_layer.lower_elevation = Value(elevation)
|
|
910
919
|
if etch_factor:
|
|
911
920
|
new_layer.etch_factor = etch_factor
|
|
912
921
|
if enable_roughness:
|
|
@@ -920,7 +929,7 @@ class Stackup(LayerCollection):
|
|
|
920
929
|
return self.non_stackup_layers[layer_name]
|
|
921
930
|
return self.layers[layer_name]
|
|
922
931
|
|
|
923
|
-
def remove_layer(self, name):
|
|
932
|
+
def remove_layer(self, name: str) -> bool:
|
|
924
933
|
"""Remove a layer from stackup.
|
|
925
934
|
|
|
926
935
|
Parameters
|
|
@@ -941,7 +950,7 @@ class Stackup(LayerCollection):
|
|
|
941
950
|
self._pedb.layout.layer_collection = new_layer_collection
|
|
942
951
|
return True
|
|
943
952
|
|
|
944
|
-
def export(self, fpath, file_format="xml", include_material_with_layer=False):
|
|
953
|
+
def export(self, fpath: str, file_format: str = "xml", include_material_with_layer: bool = False) -> bool:
|
|
945
954
|
"""Export stackup definition to a file.
|
|
946
955
|
|
|
947
956
|
Parameters
|
|
@@ -1013,7 +1022,7 @@ class Stackup(LayerCollection):
|
|
|
1013
1022
|
self._logger.warning("Method export_stackup is deprecated. Use .export.")
|
|
1014
1023
|
return self.export(fpath, file_format=file_format, include_material_with_layer=include_material_with_layer)
|
|
1015
1024
|
|
|
1016
|
-
def _export_layer_stackup_to_csv_xlsx(self, fpath=None, file_format=None):
|
|
1025
|
+
def _export_layer_stackup_to_csv_xlsx(self, fpath: Optional[str] = None, file_format: Optional[str] = None) -> bool:
|
|
1017
1026
|
if not pd:
|
|
1018
1027
|
self._pedb.logger.error("Pandas is needed. Please, install it first.")
|
|
1019
1028
|
return False
|
|
@@ -1042,7 +1051,9 @@ class Stackup(LayerCollection):
|
|
|
1042
1051
|
df.to_excel(fpath)
|
|
1043
1052
|
return True
|
|
1044
1053
|
|
|
1045
|
-
def _export_layer_stackup_to_json(
|
|
1054
|
+
def _export_layer_stackup_to_json(
|
|
1055
|
+
self, output_file: Optional[str] = None, include_material_with_layer: bool = False
|
|
1056
|
+
) -> bool:
|
|
1046
1057
|
if not include_material_with_layer:
|
|
1047
1058
|
material_out = {}
|
|
1048
1059
|
for material_name, material in self._pedb.materials.materials.items():
|
|
@@ -1073,7 +1084,7 @@ class Stackup(LayerCollection):
|
|
|
1073
1084
|
else:
|
|
1074
1085
|
return False
|
|
1075
1086
|
|
|
1076
|
-
def limits(self, only_metals=False):
|
|
1087
|
+
def limits(self, only_metals: bool = False) -> Tuple[str, str]:
|
|
1077
1088
|
"""Retrieve stackup limits.
|
|
1078
1089
|
|
|
1079
1090
|
Parameters
|
|
@@ -1102,7 +1113,7 @@ class Stackup(LayerCollection):
|
|
|
1102
1113
|
lower_layer_lower_elevation = res[3]
|
|
1103
1114
|
return upper_layer.name, upper_layer_top_elevationm, lower_layer.name, lower_layer_lower_elevation
|
|
1104
1115
|
|
|
1105
|
-
def flip_design(self):
|
|
1116
|
+
def flip_design(self) -> bool:
|
|
1106
1117
|
"""Flip the current design of a layout.
|
|
1107
1118
|
|
|
1108
1119
|
Returns
|
|
@@ -1124,8 +1135,8 @@ class Stackup(LayerCollection):
|
|
|
1124
1135
|
max_elevation = 0.0
|
|
1125
1136
|
for layer in lc.get_layers(GrpcLayerTypeSet.STACKUP_LAYER_SET):
|
|
1126
1137
|
if "RadBox" not in layer.name: # Ignore RadBox
|
|
1127
|
-
lower_elevation = layer.clone().lower_elevation
|
|
1128
|
-
upper_elevation = layer.Clone().upper_elevation
|
|
1138
|
+
lower_elevation = Value(layer.clone().lower_elevation) * 1.0e6
|
|
1139
|
+
upper_elevation = Value(layer.Clone().upper_elevation) * 1.0e6
|
|
1129
1140
|
max_elevation = max([max_elevation, lower_elevation, upper_elevation])
|
|
1130
1141
|
|
|
1131
1142
|
non_stackup_layers = []
|
|
@@ -1135,9 +1146,9 @@ class Stackup(LayerCollection):
|
|
|
1135
1146
|
non_stackup_layers.append(cloned_layer)
|
|
1136
1147
|
continue
|
|
1137
1148
|
if "RadBox" not in cloned_layer.name and not cloned_layer.is_via_layer:
|
|
1138
|
-
upper_elevation = cloned_layer.upper_elevation
|
|
1149
|
+
upper_elevation = Value(cloned_layer.upper_elevation) * 1.0e6
|
|
1139
1150
|
updated_lower_el = max_elevation - upper_elevation
|
|
1140
|
-
val =
|
|
1151
|
+
val = Value(f"{updated_lower_el}um")
|
|
1141
1152
|
cloned_layer.lower_elevation = val
|
|
1142
1153
|
if cloned_layer.top_bottom_association == GrpcTopBottomAssociation.TOP_ASSOCIATED:
|
|
1143
1154
|
cloned_layer.top_bottom_association = GrpcTopBottomAssociation.BOTTOM_ASSOCIATED
|
|
@@ -1202,7 +1213,7 @@ class Stackup(LayerCollection):
|
|
|
1202
1213
|
except:
|
|
1203
1214
|
return False
|
|
1204
1215
|
|
|
1205
|
-
def get_layout_thickness(self):
|
|
1216
|
+
def get_layout_thickness(self) -> float:
|
|
1206
1217
|
"""Return the layout thickness.
|
|
1207
1218
|
|
|
1208
1219
|
Returns
|
|
@@ -1219,7 +1230,7 @@ class Stackup(LayerCollection):
|
|
|
1219
1230
|
thickness = abs(top_layer.upper_elevation - bottom_layer.lower_elevation)
|
|
1220
1231
|
return round(thickness, 7)
|
|
1221
1232
|
|
|
1222
|
-
def _get_solder_height(self, layer_name):
|
|
1233
|
+
def _get_solder_height(self, layer_name) -> float:
|
|
1223
1234
|
height = 0.0
|
|
1224
1235
|
for _, val in self._pedb.components.instances.items():
|
|
1225
1236
|
try:
|
|
@@ -1235,11 +1246,11 @@ class Stackup(LayerCollection):
|
|
|
1235
1246
|
comp_prop = val.component_property
|
|
1236
1247
|
port_property = comp_prop.port_property
|
|
1237
1248
|
port_property.reference_size_auto = False
|
|
1238
|
-
port_property.reference_size = (
|
|
1249
|
+
port_property.reference_size = (Value(0.0), Value(0.0))
|
|
1239
1250
|
comp_prop.port_property = port_property
|
|
1240
1251
|
val.component_property = comp_prop
|
|
1241
1252
|
|
|
1242
|
-
def adjust_solder_dielectrics(self):
|
|
1253
|
+
def adjust_solder_dielectrics(self) -> bool:
|
|
1243
1254
|
"""Adjust the stack-up by adding or modifying dielectric layers that contain solder balls.
|
|
1244
1255
|
|
|
1245
1256
|
This method identifies the solder-ball height and adjusts the dielectric thickness on top (or bottom)
|
|
@@ -1279,13 +1290,13 @@ class Stackup(LayerCollection):
|
|
|
1279
1290
|
|
|
1280
1291
|
def place_in_layout(
|
|
1281
1292
|
self,
|
|
1282
|
-
edb,
|
|
1283
|
-
angle=0.0,
|
|
1284
|
-
offset_x=0.0,
|
|
1285
|
-
offset_y=0.0,
|
|
1286
|
-
flipped_stackup=True,
|
|
1287
|
-
place_on_top=True,
|
|
1288
|
-
):
|
|
1293
|
+
edb: "Edb",
|
|
1294
|
+
angle: float = 0.0,
|
|
1295
|
+
offset_x: float = 0.0,
|
|
1296
|
+
offset_y: float = 0.0,
|
|
1297
|
+
flipped_stackup: bool = True,
|
|
1298
|
+
place_on_top: bool = True,
|
|
1299
|
+
) -> bool:
|
|
1289
1300
|
"""Place current cell into another cell using layer placement method.
|
|
1290
1301
|
|
|
1291
1302
|
Flip the current layer stackup of a layout if requested.
|
|
@@ -1339,9 +1350,9 @@ class Stackup(LayerCollection):
|
|
|
1339
1350
|
elif flipped_stackup:
|
|
1340
1351
|
self.flip_design()
|
|
1341
1352
|
edb_cell = edb.active_cell
|
|
1342
|
-
_angle =
|
|
1343
|
-
_offset_x =
|
|
1344
|
-
_offset_y =
|
|
1353
|
+
_angle = Value(angle * math.pi / 180.0)
|
|
1354
|
+
_offset_x = Value(offset_x)
|
|
1355
|
+
_offset_y = Value(offset_y)
|
|
1345
1356
|
|
|
1346
1357
|
if edb_cell.name not in self._pedb.cell_names:
|
|
1347
1358
|
list_cells = self._pedb.copy_cells([edb_cell.api_object])
|
|
@@ -1367,14 +1378,14 @@ class Stackup(LayerCollection):
|
|
|
1367
1378
|
|
|
1368
1379
|
def place_in_layout_3d_placement(
|
|
1369
1380
|
self,
|
|
1370
|
-
edb,
|
|
1371
|
-
angle=0.0,
|
|
1372
|
-
offset_x=0.0,
|
|
1373
|
-
offset_y=0.0,
|
|
1374
|
-
flipped_stackup=True,
|
|
1375
|
-
place_on_top=True,
|
|
1376
|
-
solder_height=0,
|
|
1377
|
-
):
|
|
1381
|
+
edb: "Edb",
|
|
1382
|
+
angle: float = 0.0,
|
|
1383
|
+
offset_x: float = 0.0,
|
|
1384
|
+
offset_y: float = 0.0,
|
|
1385
|
+
flipped_stackup: bool = True,
|
|
1386
|
+
place_on_top: bool = True,
|
|
1387
|
+
solder_height: float = 0,
|
|
1388
|
+
) -> bool:
|
|
1378
1389
|
"""Place current cell into another cell using 3D placement method.
|
|
1379
1390
|
|
|
1380
1391
|
Flip the current layer stackup of a layout if requested.
|
|
@@ -1437,13 +1448,13 @@ class Stackup(LayerCollection):
|
|
|
1437
1448
|
solder_height = max(lay_solder_height, solder_height)
|
|
1438
1449
|
self._remove_solder_pec(lay.name)
|
|
1439
1450
|
|
|
1440
|
-
rotation =
|
|
1451
|
+
rotation = Value(0.0)
|
|
1441
1452
|
if flipped_stackup:
|
|
1442
|
-
rotation =
|
|
1453
|
+
rotation = Value(math.pi)
|
|
1443
1454
|
|
|
1444
1455
|
edb_cell = edb.active_cell
|
|
1445
|
-
_offset_x =
|
|
1446
|
-
_offset_y =
|
|
1456
|
+
_offset_x = Value(offset_x)
|
|
1457
|
+
_offset_y = Value(offset_y)
|
|
1447
1458
|
|
|
1448
1459
|
if edb_cell.name not in self._pedb.cell_names:
|
|
1449
1460
|
list_cells = self._pedb.copy_cells(edb_cell)
|
|
@@ -1479,10 +1490,10 @@ class Stackup(LayerCollection):
|
|
|
1479
1490
|
elevation = target_bottom_elevation - source_stack_top_elevation
|
|
1480
1491
|
solder_height = -solder_height
|
|
1481
1492
|
|
|
1482
|
-
h_stackup =
|
|
1493
|
+
h_stackup = Value(elevation + solder_height)
|
|
1483
1494
|
|
|
1484
|
-
zero_data =
|
|
1485
|
-
one_data =
|
|
1495
|
+
zero_data = Value(0.0)
|
|
1496
|
+
one_data = Value(1.0)
|
|
1486
1497
|
point3d_t = GrpcPoint3DData(_offset_x, _offset_y, h_stackup)
|
|
1487
1498
|
point_loc = GrpcPoint3DData(zero_data, zero_data, zero_data)
|
|
1488
1499
|
point_from = GrpcPoint3DData(one_data, zero_data, zero_data)
|
|
@@ -1498,15 +1509,15 @@ class Stackup(LayerCollection):
|
|
|
1498
1509
|
|
|
1499
1510
|
def place_instance(
|
|
1500
1511
|
self,
|
|
1501
|
-
component_edb,
|
|
1502
|
-
angle=0.0,
|
|
1503
|
-
offset_x=0.0,
|
|
1504
|
-
offset_y=0.0,
|
|
1505
|
-
offset_z=0.0,
|
|
1506
|
-
flipped_stackup=True,
|
|
1507
|
-
place_on_top=True,
|
|
1508
|
-
solder_height=0,
|
|
1509
|
-
):
|
|
1512
|
+
component_edb: "Edb",
|
|
1513
|
+
angle: float = 0.0,
|
|
1514
|
+
offset_x: float = 0.0,
|
|
1515
|
+
offset_y: float = 0.0,
|
|
1516
|
+
offset_z: float = 0.0,
|
|
1517
|
+
flipped_stackup: bool = True,
|
|
1518
|
+
place_on_top: bool = True,
|
|
1519
|
+
solder_height: float = 0,
|
|
1520
|
+
) -> GrpcCellInstance:
|
|
1510
1521
|
"""Place a component instance in the layout using 3D placement.
|
|
1511
1522
|
|
|
1512
1523
|
Parameters
|
|
@@ -1563,8 +1574,8 @@ class Stackup(LayerCollection):
|
|
|
1563
1574
|
solder_height = max(lay_solder_height, solder_height)
|
|
1564
1575
|
component_edb.stackup._remove_solder_pec(lay.name)
|
|
1565
1576
|
edb_cell = component_edb.active_cell
|
|
1566
|
-
_offset_x =
|
|
1567
|
-
_offset_y =
|
|
1577
|
+
_offset_x = Value(offset_x)
|
|
1578
|
+
_offset_y = Value(offset_y)
|
|
1568
1579
|
|
|
1569
1580
|
if edb_cell.name not in self._pedb.cell_names:
|
|
1570
1581
|
list_cells = self._pedb.copy_cells(edb_cell)
|
|
@@ -1574,12 +1585,12 @@ class Stackup(LayerCollection):
|
|
|
1574
1585
|
edb_cell = cell
|
|
1575
1586
|
# Keep Cell Independent
|
|
1576
1587
|
edb_cell.is_black_box = True
|
|
1577
|
-
rotation =
|
|
1588
|
+
rotation = Value(0.0)
|
|
1578
1589
|
if flipped_stackup:
|
|
1579
|
-
rotation =
|
|
1590
|
+
rotation = Value(math.pi)
|
|
1580
1591
|
|
|
1581
|
-
_offset_x =
|
|
1582
|
-
_offset_y =
|
|
1592
|
+
_offset_x = Value(offset_x)
|
|
1593
|
+
_offset_y = Value(offset_y)
|
|
1583
1594
|
|
|
1584
1595
|
instance_name = generate_unique_name(edb_cell.name, n=2)
|
|
1585
1596
|
|
|
@@ -1613,8 +1624,8 @@ class Stackup(LayerCollection):
|
|
|
1613
1624
|
|
|
1614
1625
|
h_stackup = elevation + solder_height
|
|
1615
1626
|
|
|
1616
|
-
zero_data =
|
|
1617
|
-
one_data =
|
|
1627
|
+
zero_data = Value(0.0)
|
|
1628
|
+
one_data = Value(1.0)
|
|
1618
1629
|
point3d_t = GrpcPoint3DData(_offset_x, _offset_y, h_stackup)
|
|
1619
1630
|
point_loc = GrpcPoint3DData(zero_data, zero_data, zero_data)
|
|
1620
1631
|
point_from = GrpcPoint3DData(one_data, zero_data, zero_data)
|
|
@@ -1630,12 +1641,12 @@ class Stackup(LayerCollection):
|
|
|
1630
1641
|
|
|
1631
1642
|
def place_a3dcomp_3d_placement(
|
|
1632
1643
|
self,
|
|
1633
|
-
a3dcomp_path,
|
|
1634
|
-
angle=0.0,
|
|
1635
|
-
offset_x=0.0,
|
|
1636
|
-
offset_y=0.0,
|
|
1637
|
-
offset_z=0.0,
|
|
1638
|
-
place_on_top=True,
|
|
1644
|
+
a3dcomp_path: str,
|
|
1645
|
+
angle: float = 0.0,
|
|
1646
|
+
offset_x: float = 0.0,
|
|
1647
|
+
offset_y: float = 0.0,
|
|
1648
|
+
offset_z: float = 0.0,
|
|
1649
|
+
place_on_top: bool = True,
|
|
1639
1650
|
) -> bool:
|
|
1640
1651
|
"""Place a 3D component into the current layout.
|
|
1641
1652
|
|
|
@@ -1679,13 +1690,13 @@ class Stackup(LayerCollection):
|
|
|
1679
1690
|
res = stackup_target.get_top_bottom_stackup_layers(GrpcLayerTypeSet.SIGNAL_LAYER_SET)
|
|
1680
1691
|
target_top_elevation = res[1]
|
|
1681
1692
|
target_bottom_elevation = res[3]
|
|
1682
|
-
flip_angle =
|
|
1693
|
+
flip_angle = Value("0deg")
|
|
1683
1694
|
if place_on_top:
|
|
1684
1695
|
elevation = target_top_elevation + offset_z
|
|
1685
1696
|
else:
|
|
1686
|
-
flip_angle =
|
|
1697
|
+
flip_angle = Value("180deg")
|
|
1687
1698
|
elevation = target_bottom_elevation - offset_z
|
|
1688
|
-
h_stackup =
|
|
1699
|
+
h_stackup = Value(elevation)
|
|
1689
1700
|
location = GrpcPoint3DData(offset_x, offset_y, h_stackup)
|
|
1690
1701
|
mcad_model = GrpcMcadModel.create_3d_comp(layout=self._pedb.active_layout, filename=a3dcomp_path)
|
|
1691
1702
|
if mcad_model.is_null: # pragma: no cover
|
|
@@ -1698,14 +1709,14 @@ class Stackup(LayerCollection):
|
|
|
1698
1709
|
|
|
1699
1710
|
mcad_model.cell_instance.placement_3d = True
|
|
1700
1711
|
transform_rotation = mcad_model.cell_instance.transform3d.create_from_axis_and_angle(
|
|
1701
|
-
axis=rotation_axis_from, angle=flip_angle
|
|
1712
|
+
axis=rotation_axis_from, angle=Value(flip_angle)
|
|
1702
1713
|
)
|
|
1703
1714
|
mcad_model.cell_instance.transform3d = transform_rotation
|
|
1704
1715
|
transform_translation = mcad_model.cell_instance.transform3d.create_from_offset(offset=location)
|
|
1705
1716
|
mcad_model.cell_instance.transform3d = transform_translation
|
|
1706
1717
|
return True
|
|
1707
1718
|
|
|
1708
|
-
def residual_copper_area_per_layer(self):
|
|
1719
|
+
def residual_copper_area_per_layer(self) -> Dict[str, float]:
|
|
1709
1720
|
"""Report residual copper area per layer in percentage.
|
|
1710
1721
|
|
|
1711
1722
|
Returns
|
|
@@ -1734,7 +1745,7 @@ class Stackup(LayerCollection):
|
|
|
1734
1745
|
temp_data = {name: area / outline_area * 100 for name, area in temp_data.items()}
|
|
1735
1746
|
return temp_data
|
|
1736
1747
|
|
|
1737
|
-
def _import_dict(self, json_dict, rename=False):
|
|
1748
|
+
def _import_dict(self, json_dict: Dict[str, Any], rename: bool = False) -> bool:
|
|
1738
1749
|
"""Import stackup from a dictionary.
|
|
1739
1750
|
|
|
1740
1751
|
Parameters
|
|
@@ -1888,7 +1899,7 @@ class Stackup(LayerCollection):
|
|
|
1888
1899
|
|
|
1889
1900
|
return True
|
|
1890
1901
|
|
|
1891
|
-
def _import_json(self, file_path, rename=False):
|
|
1902
|
+
def _import_json(self, file_path: str, rename: bool = False) -> bool:
|
|
1892
1903
|
"""Import stackup from a JSON file.
|
|
1893
1904
|
|
|
1894
1905
|
Parameters
|
|
@@ -1908,7 +1919,7 @@ class Stackup(LayerCollection):
|
|
|
1908
1919
|
json_dict = json.load(f) # pragma: no cover
|
|
1909
1920
|
return self._import_dict(json_dict, rename)
|
|
1910
1921
|
|
|
1911
|
-
def _import_csv(self, file_path):
|
|
1922
|
+
def _import_csv(self, file_path: str) -> bool:
|
|
1912
1923
|
"""Import stackup definition from a CSV file.
|
|
1913
1924
|
|
|
1914
1925
|
Parameters
|
|
@@ -1956,7 +1967,13 @@ class Stackup(LayerCollection):
|
|
|
1956
1967
|
self._pedb.layout.layer_collection = lc_new
|
|
1957
1968
|
return True
|
|
1958
1969
|
|
|
1959
|
-
def _set(
|
|
1970
|
+
def _set(
|
|
1971
|
+
self,
|
|
1972
|
+
layers: Optional[Dict] = None,
|
|
1973
|
+
materials: Optional[Dict] = None,
|
|
1974
|
+
roughness: Optional[Dict] = None,
|
|
1975
|
+
non_stackup_layers: Optional[Dict] = None,
|
|
1976
|
+
) -> bool:
|
|
1960
1977
|
"""Update stackup information.
|
|
1961
1978
|
|
|
1962
1979
|
Parameters
|
|
@@ -2087,7 +2104,7 @@ class Stackup(LayerCollection):
|
|
|
2087
2104
|
|
|
2088
2105
|
return True
|
|
2089
2106
|
|
|
2090
|
-
def _get(self):
|
|
2107
|
+
def _get(self) -> Tuple[Dict, Dict, Dict, Dict]:
|
|
2091
2108
|
"""Get stackup information from layout.
|
|
2092
2109
|
|
|
2093
2110
|
Returns
|
|
@@ -2116,27 +2133,27 @@ class Stackup(LayerCollection):
|
|
|
2116
2133
|
roughness_models[name] = {}
|
|
2117
2134
|
model = val.get_roughness_model("top")
|
|
2118
2135
|
if model.type.name.endswith("GroissRoughnessModel"):
|
|
2119
|
-
roughness_models[name]["GroissSurfaceRoughness"] = {"Roughness": model.get_Roughness
|
|
2136
|
+
roughness_models[name]["GroissSurfaceRoughness"] = {"Roughness": Value(model.get_Roughness)}
|
|
2120
2137
|
else:
|
|
2121
2138
|
roughness_models[name]["HuraySurfaceRoughness"] = {
|
|
2122
|
-
"HallHuraySurfaceRatio": model.get_nodule_radius()
|
|
2123
|
-
"NoduleRadius": model.get_surface_ratio()
|
|
2139
|
+
"HallHuraySurfaceRatio": Value(model.get_nodule_radius()),
|
|
2140
|
+
"NoduleRadius": Value(model.get_surface_ratio()),
|
|
2124
2141
|
}
|
|
2125
2142
|
model = val.get_roughness_model("bottom")
|
|
2126
2143
|
if model.type.name.endswith("GroissRoughnessModel"):
|
|
2127
|
-
roughness_models[name]["GroissBottomSurfaceRoughness"] = {"Roughness": model.get_roughness()
|
|
2144
|
+
roughness_models[name]["GroissBottomSurfaceRoughness"] = {"Roughness": Value(model.get_roughness())}
|
|
2128
2145
|
else:
|
|
2129
2146
|
roughness_models[name]["HurayBottomSurfaceRoughness"] = {
|
|
2130
|
-
"HallHuraySurfaceRatio": model.get_nodule_radius()
|
|
2131
|
-
"NoduleRadius": model.get_surface_ratio()
|
|
2147
|
+
"HallHuraySurfaceRatio": Value(model.get_nodule_radius()),
|
|
2148
|
+
"NoduleRadius": Value(model.get_surface_ratio()),
|
|
2132
2149
|
}
|
|
2133
2150
|
model = val.get_roughness_model("side")
|
|
2134
2151
|
if model.ToString().endswith("GroissRoughnessModel"):
|
|
2135
|
-
roughness_models[name]["GroissSideSurfaceRoughness"] = {"Roughness": model.get_roughness()
|
|
2152
|
+
roughness_models[name]["GroissSideSurfaceRoughness"] = {"Roughness": Value(model.get_roughness())}
|
|
2136
2153
|
else:
|
|
2137
2154
|
roughness_models[name]["HuraySideSurfaceRoughness"] = {
|
|
2138
|
-
"HallHuraySurfaceRatio": model.get_nodule_radius()
|
|
2139
|
-
"NoduleRadius": model.get_surface_ratio()
|
|
2155
|
+
"HallHuraySurfaceRatio": Value(model.get_nodule_radius()),
|
|
2156
|
+
"NoduleRadius": Value(model.get_surface_ratio()),
|
|
2140
2157
|
}
|
|
2141
2158
|
|
|
2142
2159
|
non_stackup_layers = OrderedDict()
|
|
@@ -2159,7 +2176,7 @@ class Stackup(LayerCollection):
|
|
|
2159
2176
|
|
|
2160
2177
|
return layers, materials, roughness_models, non_stackup_layers
|
|
2161
2178
|
|
|
2162
|
-
def _add_materials_from_dictionary(self, material_dict):
|
|
2179
|
+
def _add_materials_from_dictionary(self, material_dict: Dict[str, Dict]) -> bool:
|
|
2163
2180
|
materials = self.self._pedb.materials.materials
|
|
2164
2181
|
for name, material_properties in material_dict.items():
|
|
2165
2182
|
if "Conductivity" in material_properties:
|
|
@@ -2172,7 +2189,7 @@ class Stackup(LayerCollection):
|
|
|
2172
2189
|
)
|
|
2173
2190
|
return True
|
|
2174
2191
|
|
|
2175
|
-
def _import_xml(self, file_path, rename=False):
|
|
2192
|
+
def _import_xml(self, file_path: str, rename: bool = False) -> bool:
|
|
2176
2193
|
"""Read external XML file and convert into JSON format.
|
|
2177
2194
|
|
|
2178
2195
|
Parameters
|
|
@@ -2243,7 +2260,7 @@ class Stackup(LayerCollection):
|
|
|
2243
2260
|
cfg = {"stackup": stackup_dict}
|
|
2244
2261
|
return self._pedb.configuration.load(cfg, apply_file=True)
|
|
2245
2262
|
|
|
2246
|
-
def _export_xml(self, file_path):
|
|
2263
|
+
def _export_xml(self, file_path: str) -> bool:
|
|
2247
2264
|
"""Export stackup information to an external XML file.
|
|
2248
2265
|
|
|
2249
2266
|
Parameters
|
|
@@ -2293,7 +2310,7 @@ class Stackup(LayerCollection):
|
|
|
2293
2310
|
write_pretty_xml(root, file_path)
|
|
2294
2311
|
return True
|
|
2295
2312
|
|
|
2296
|
-
def load(self, file_path, rename=False):
|
|
2313
|
+
def load(self, file_path: Union[str, Dict], rename: bool = False) -> bool:
|
|
2297
2314
|
"""Import stackup from a file.
|
|
2298
2315
|
|
|
2299
2316
|
Supported formats: XML, CSV, JSON.
|
|
@@ -2332,14 +2349,14 @@ class Stackup(LayerCollection):
|
|
|
2332
2349
|
|
|
2333
2350
|
def plot(
|
|
2334
2351
|
self,
|
|
2335
|
-
save_plot=None,
|
|
2336
|
-
size=(2000, 1500),
|
|
2337
|
-
plot_definitions=None,
|
|
2338
|
-
first_layer=None,
|
|
2339
|
-
last_layer=None,
|
|
2340
|
-
scale_elevation=True,
|
|
2341
|
-
show=True,
|
|
2342
|
-
):
|
|
2352
|
+
save_plot: Optional[str] = None,
|
|
2353
|
+
size: Tuple[int, int] = (2000, 1500),
|
|
2354
|
+
plot_definitions: Optional[Union[str, List[str]]] = None,
|
|
2355
|
+
first_layer: Optional[Union[str, "Layer"]] = None,
|
|
2356
|
+
last_layer: Optional[Union[str, "Layer"]] = None,
|
|
2357
|
+
scale_elevation: bool = True,
|
|
2358
|
+
show: bool = True,
|
|
2359
|
+
) -> Any:
|
|
2343
2360
|
"""Plot the current stackup and optionally overlap padstack definitions.
|
|
2344
2361
|
|
|
2345
2362
|
Only supports 'Laminate' and 'Overlapping' stackup types.
|