pyedb 0.56.0__py3-none-any.whl → 0.58.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_data.py +3 -0
- pyedb/configuration/cfg_pin_groups.py +2 -0
- pyedb/configuration/cfg_terminals.py +232 -0
- pyedb/configuration/configuration.py +146 -3
- pyedb/dotnet/clr_module.py +1 -2
- pyedb/dotnet/database/Variables.py +30 -22
- pyedb/dotnet/database/cell/hierarchy/component.py +2 -8
- pyedb/dotnet/database/cell/layout.py +5 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +2 -2
- pyedb/dotnet/database/cell/terminal/bundle_terminal.py +12 -0
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +38 -0
- pyedb/dotnet/database/components.py +15 -19
- pyedb/dotnet/database/dotnet/database.py +1 -0
- pyedb/dotnet/database/edb_data/control_file.py +19 -8
- pyedb/dotnet/database/edb_data/nets_data.py +3 -3
- pyedb/dotnet/database/edb_data/padstacks_data.py +39 -14
- pyedb/dotnet/database/edb_data/ports.py +0 -25
- pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
- pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +18 -19
- pyedb/dotnet/database/edb_data/simulation_configuration.py +3 -3
- pyedb/dotnet/database/edb_data/sources.py +21 -2
- pyedb/dotnet/database/general.py +1 -6
- pyedb/dotnet/database/hfss.py +9 -8
- pyedb/dotnet/database/layout_validation.py +14 -3
- pyedb/dotnet/database/materials.py +1 -3
- pyedb/dotnet/database/modeler.py +7 -3
- pyedb/dotnet/database/nets.py +27 -19
- pyedb/dotnet/database/padstack.py +4 -2
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +54 -1
- pyedb/dotnet/database/siwave.py +4 -3
- pyedb/dotnet/database/stackup.py +55 -58
- pyedb/dotnet/database/utilities/heatsink.py +0 -1
- pyedb/dotnet/database/utilities/hfss_simulation_setup.py +81 -0
- pyedb/dotnet/database/utilities/simulation_setup.py +7 -5
- pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +1 -0
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +264 -13
- pyedb/dotnet/edb.py +65 -47
- pyedb/exceptions.py +1 -2
- pyedb/extensions/create_cell_array.py +67 -49
- pyedb/generic/data_handlers.py +13 -23
- pyedb/generic/design_types.py +9 -35
- pyedb/generic/filesystem.py +4 -2
- pyedb/generic/general_methods.py +28 -41
- pyedb/generic/plot.py +8 -23
- pyedb/generic/process.py +78 -10
- pyedb/grpc/database/_typing.py +0 -0
- pyedb/grpc/database/components.py +14 -13
- pyedb/grpc/database/control_file.py +27 -40
- pyedb/grpc/database/definition/materials.py +1 -1
- pyedb/grpc/database/definition/package_def.py +6 -3
- pyedb/grpc/database/definition/padstack_def.py +14 -12
- pyedb/grpc/database/hfss.py +1 -4
- pyedb/grpc/database/hierarchy/component.py +5 -13
- pyedb/grpc/database/hierarchy/pingroup.py +16 -3
- pyedb/grpc/database/layers/layer.py +1 -2
- pyedb/grpc/database/layers/stackup_layer.py +42 -19
- pyedb/grpc/database/layout/layout.py +43 -27
- pyedb/grpc/database/layout/voltage_regulator.py +6 -1
- pyedb/grpc/database/layout_validation.py +5 -2
- pyedb/grpc/database/modeler.py +254 -252
- pyedb/grpc/database/net/differential_pair.py +9 -2
- pyedb/grpc/database/net/extended_net.py +24 -9
- pyedb/grpc/database/net/net.py +14 -5
- pyedb/grpc/database/net/net_class.py +24 -7
- pyedb/grpc/database/nets.py +11 -43
- pyedb/grpc/database/padstacks.py +67 -119
- pyedb/grpc/database/primitive/bondwire.py +3 -67
- pyedb/grpc/database/primitive/circle.py +42 -3
- pyedb/grpc/database/primitive/padstack_instance.py +58 -31
- pyedb/grpc/database/primitive/path.py +160 -11
- pyedb/grpc/database/primitive/polygon.py +73 -7
- pyedb/grpc/database/primitive/primitive.py +2 -2
- pyedb/grpc/database/primitive/rectangle.py +105 -4
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +0 -2
- pyedb/grpc/database/simulation_setup/hfss_settings_options.py +0 -4
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +79 -0
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +1 -0
- pyedb/grpc/database/simulation_setup/sweep_data.py +1 -3
- pyedb/grpc/database/siwave.py +6 -13
- pyedb/grpc/database/source_excitations.py +46 -63
- pyedb/grpc/database/stackup.py +55 -60
- pyedb/grpc/database/terminal/bundle_terminal.py +10 -3
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +9 -11
- pyedb/grpc/database/terminal/pingroup_terminal.py +8 -1
- pyedb/grpc/database/terminal/point_terminal.py +30 -0
- pyedb/grpc/database/terminal/terminal.py +35 -10
- pyedb/grpc/database/utility/heat_sink.py +0 -1
- pyedb/grpc/database/utility/hfss_extent_info.py +2 -2
- pyedb/grpc/database/utility/xml_control_file.py +19 -8
- pyedb/grpc/edb.py +63 -32
- pyedb/grpc/edb_init.py +1 -0
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +6 -2
- pyedb/ipc2581/ecad/cad_data/step.py +1 -1
- pyedb/ipc2581/ipc2581.py +8 -7
- pyedb/libraries/common.py +3 -4
- pyedb/libraries/rf_libraries/base_functions.py +7 -16
- pyedb/libraries/rf_libraries/planar_antennas.py +3 -21
- pyedb/misc/aedtlib_personalib_install.py +2 -2
- pyedb/misc/downloads.py +19 -3
- pyedb/misc/misc.py +5 -2
- pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +3 -2
- pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +0 -1
- pyedb/misc/utilities.py +0 -1
- pyedb/modeler/geometry_operators.py +3 -2
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/METADATA +6 -7
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/RECORD +110 -108
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/WHEEL +0 -0
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -155,7 +155,7 @@ class LayoutValidation:
|
|
|
155
155
|
Examples
|
|
156
156
|
--------
|
|
157
157
|
|
|
158
|
-
>>> renamed_nets = edb.layout_validation.disjoint_nets(["GND","Net2"])
|
|
158
|
+
>>> renamed_nets = edb.layout_validation.disjoint_nets(["GND", "Net2"])
|
|
159
159
|
"""
|
|
160
160
|
|
|
161
161
|
if not net_list:
|
|
@@ -208,8 +208,11 @@ class LayoutValidation:
|
|
|
208
208
|
if isinstance(obj_dict[el], Primitive):
|
|
209
209
|
if not obj_dict[el].is_void:
|
|
210
210
|
sum += obj_dict[el].area()
|
|
211
|
-
except:
|
|
212
|
-
|
|
211
|
+
except Exception as e:
|
|
212
|
+
self._pedb.logger.warning(
|
|
213
|
+
f"A(n) {type(e).__name__} error occurred while calculating area "
|
|
214
|
+
f"for element {elem} - Default value of 0 is used: {str(e)}"
|
|
215
|
+
)
|
|
213
216
|
return sum
|
|
214
217
|
|
|
215
218
|
if order_by_area:
|
|
@@ -336,3 +339,11 @@ class LayoutValidation:
|
|
|
336
339
|
if fix:
|
|
337
340
|
obj.aedt_name = f"via_{obj.id}"
|
|
338
341
|
self._pedb.logger.info(f"Found {counts}/{len(pds)} padstacks have no name.")
|
|
342
|
+
|
|
343
|
+
@execution_timer("empty_pin_group")
|
|
344
|
+
def delete_empty_pin_groups(self):
|
|
345
|
+
for name, pg in self._pedb.siwave.pin_groups.items():
|
|
346
|
+
pins = pg.pins
|
|
347
|
+
if len(pins) == 0:
|
|
348
|
+
pg.delete()
|
|
349
|
+
self._pedb.logger.info(f"Pin group {name} deleted because it has no pins.")
|
|
@@ -243,9 +243,7 @@ class Material(object):
|
|
|
243
243
|
if self.__dc_model and value:
|
|
244
244
|
self.__dc_model.SetDCRelativePermitivity(value)
|
|
245
245
|
else:
|
|
246
|
-
self.__edb.logger.error(
|
|
247
|
-
f"DC permittivity cannot be updated in material without DC model or value {value}." f""
|
|
248
|
-
)
|
|
246
|
+
self.__edb.logger.error(f"DC permittivity cannot be updated in material without DC model or value {value}.")
|
|
249
247
|
|
|
250
248
|
@property
|
|
251
249
|
def dielectric_model_frequency(self):
|
pyedb/dotnet/database/modeler.py
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"""
|
|
24
24
|
This module contains these classes: `EdbLayout` and `Shape`.
|
|
25
25
|
"""
|
|
26
|
+
|
|
26
27
|
import math
|
|
27
28
|
import warnings
|
|
28
29
|
|
|
@@ -355,8 +356,11 @@ class Modeler(object):
|
|
|
355
356
|
bounding_box.Item2.X.ToDouble(),
|
|
356
357
|
bounding_box.Item2.Y.ToDouble(),
|
|
357
358
|
]
|
|
358
|
-
except:
|
|
359
|
-
|
|
359
|
+
except Exception as e:
|
|
360
|
+
self._logger.warning(
|
|
361
|
+
f"A(n) {type(e).__name__} error occurred while retrieving bounding box for polygon {polygon} - "
|
|
362
|
+
f"Empty list is returned: {str(e)}"
|
|
363
|
+
)
|
|
360
364
|
return bounding
|
|
361
365
|
|
|
362
366
|
def get_polygon_points(self, polygon):
|
|
@@ -383,7 +387,7 @@ class Modeler(object):
|
|
|
383
387
|
--------
|
|
384
388
|
|
|
385
389
|
>>> poly = database.modeler.get_polygons_by_layer("GND")
|
|
386
|
-
>>> points
|
|
390
|
+
>>> points = database.modeler.get_polygon_points(poly[0])
|
|
387
391
|
|
|
388
392
|
"""
|
|
389
393
|
points = []
|
pyedb/dotnet/database/nets.py
CHANGED
|
@@ -308,22 +308,30 @@ class EdbNets(CommonNets):
|
|
|
308
308
|
val_value = cmp.rlc_values
|
|
309
309
|
if refdes in exception_list:
|
|
310
310
|
pass
|
|
311
|
-
elif
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
311
|
+
elif val_type == "Inductor":
|
|
312
|
+
if val_value[1] is None:
|
|
313
|
+
continue
|
|
314
|
+
elif (
|
|
315
|
+
not self._pedb.edb_value(val_value[1]).ToDouble()
|
|
316
|
+
<= self._pedb.edb_value(inductor_below).ToDouble()
|
|
317
|
+
):
|
|
318
|
+
continue
|
|
319
|
+
elif val_type == "Resistor":
|
|
320
|
+
if val_value[0] is None:
|
|
321
|
+
continue
|
|
322
|
+
elif (
|
|
323
|
+
not self._pedb.edb_value(val_value[0]).ToDouble()
|
|
324
|
+
<= self._pedb.edb_value(resistor_below).ToDouble()
|
|
325
|
+
):
|
|
326
|
+
continue
|
|
327
|
+
elif val_type == "Capacitor":
|
|
328
|
+
if val_value[2] is None:
|
|
329
|
+
continue
|
|
330
|
+
elif (
|
|
331
|
+
not self._pedb.edb_value(val_value[2]).ToDouble()
|
|
332
|
+
>= self._pedb.edb_value(capacitor_above).ToDouble()
|
|
333
|
+
):
|
|
334
|
+
continue
|
|
327
335
|
else:
|
|
328
336
|
continue
|
|
329
337
|
|
|
@@ -575,7 +583,7 @@ class EdbNets(CommonNets):
|
|
|
575
583
|
Examples
|
|
576
584
|
--------
|
|
577
585
|
|
|
578
|
-
>>> deleted_nets = database.nets.delete(["Net1","Net2"])
|
|
586
|
+
>>> deleted_nets = database.nets.delete(["Net1", "Net2"])
|
|
579
587
|
"""
|
|
580
588
|
warnings.warn("Use :func:`delete` method instead.", DeprecationWarning)
|
|
581
589
|
return self.delete(netlist=netlist)
|
|
@@ -596,7 +604,7 @@ class EdbNets(CommonNets):
|
|
|
596
604
|
Examples
|
|
597
605
|
--------
|
|
598
606
|
|
|
599
|
-
>>> deleted_nets = database.nets.delete(["Net1","Net2"])
|
|
607
|
+
>>> deleted_nets = database.nets.delete(["Net1", "Net2"])
|
|
600
608
|
"""
|
|
601
609
|
if isinstance(netlist, str):
|
|
602
610
|
netlist = [netlist]
|
|
@@ -733,7 +741,7 @@ class EdbNets(CommonNets):
|
|
|
733
741
|
Examples
|
|
734
742
|
--------
|
|
735
743
|
|
|
736
|
-
>>> renamed_nets = database.nets.find_and_fix_disjoint_nets(["GND","Net2"])
|
|
744
|
+
>>> renamed_nets = database.nets.find_and_fix_disjoint_nets(["GND", "Net2"])
|
|
737
745
|
"""
|
|
738
746
|
warnings.warn("Use new function :func:`edb.layout_validation.disjoint_nets` instead.", DeprecationWarning)
|
|
739
747
|
return self._pedb.layout_validation.disjoint_nets(
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"""
|
|
24
24
|
This module contains the `EdbPadstacks` class.
|
|
25
25
|
"""
|
|
26
|
+
|
|
26
27
|
from collections import defaultdict
|
|
27
28
|
import math
|
|
28
29
|
from typing import Dict, List
|
|
@@ -708,8 +709,9 @@ class EdbPadstacks(object):
|
|
|
708
709
|
)
|
|
709
710
|
else: # pragma no cover
|
|
710
711
|
self._logger.error(
|
|
711
|
-
"Failed to reassign anti-pad value {} on Pads-stack definition {},"
|
|
712
|
-
|
|
712
|
+
"Failed to reassign anti-pad value {} on Pads-stack definition {}, layer{}".format(
|
|
713
|
+
str(value), padstack.edb_padstack.GetName(), layer
|
|
714
|
+
)
|
|
713
715
|
)
|
|
714
716
|
all_succeed = False
|
|
715
717
|
padstack.edb_padstack.SetData(cloned_padstack_data)
|
|
@@ -349,7 +349,7 @@ class AdvancedSettings(SettingsBase):
|
|
|
349
349
|
``True`` if automatic mesh is used, ``False`` otherwise.
|
|
350
350
|
"""
|
|
351
351
|
warnings.warn(
|
|
352
|
-
"`automatic_mesh` is deprecated.
|
|
352
|
+
"`automatic_mesh` is deprecated. Use `mesh_automatic` instead.",
|
|
353
353
|
DeprecationWarning,
|
|
354
354
|
)
|
|
355
355
|
return self.sim_setup_info.simulation_settings.AdvancedSettings.MeshAutoMatic
|
|
@@ -713,6 +713,19 @@ class DCAdvancedSettings(SettingsBase):
|
|
|
713
713
|
def max_num_pass(self):
|
|
714
714
|
"""Maximum number of passes.
|
|
715
715
|
|
|
716
|
+
deprecated: Use `max_num_passes` instead.
|
|
717
|
+
|
|
718
|
+
Returns
|
|
719
|
+
-------
|
|
720
|
+
int
|
|
721
|
+
"""
|
|
722
|
+
warnings.warn("`max_num_pass` is deprecated. Use `max_num_passes` instead.", DeprecationWarning)
|
|
723
|
+
return self.max_num_passes
|
|
724
|
+
|
|
725
|
+
@property
|
|
726
|
+
def max_num_passes(self):
|
|
727
|
+
"""Maximum number of passes.
|
|
728
|
+
|
|
716
729
|
Returns
|
|
717
730
|
-------
|
|
718
731
|
int
|
|
@@ -723,6 +736,19 @@ class DCAdvancedSettings(SettingsBase):
|
|
|
723
736
|
def min_num_pass(self):
|
|
724
737
|
"""Minimum number of passes.
|
|
725
738
|
|
|
739
|
+
deprecated: Use `min_num_passes` instead.
|
|
740
|
+
|
|
741
|
+
Returns
|
|
742
|
+
-------
|
|
743
|
+
int
|
|
744
|
+
"""
|
|
745
|
+
warnings.warn("`min_num_pass` is deprecated. Use `min_num_passes` instead.", DeprecationWarning)
|
|
746
|
+
return self.sim_setup_info
|
|
747
|
+
|
|
748
|
+
@property
|
|
749
|
+
def min_num_passes(self):
|
|
750
|
+
"""Minimum number of passes.
|
|
751
|
+
|
|
726
752
|
Returns
|
|
727
753
|
-------
|
|
728
754
|
int
|
|
@@ -753,6 +779,19 @@ class DCAdvancedSettings(SettingsBase):
|
|
|
753
779
|
def num_bondwire_sides(self):
|
|
754
780
|
"""Number of bondwire sides.
|
|
755
781
|
|
|
782
|
+
deprecated: Use `num_bw_sides` instead.
|
|
783
|
+
|
|
784
|
+
Returns
|
|
785
|
+
-------
|
|
786
|
+
int
|
|
787
|
+
"""
|
|
788
|
+
warnings.warn("`num_bondwire_sides` is deprecated. Use `num_bw_sides` instead.", DeprecationWarning)
|
|
789
|
+
return self.num_bw_sides
|
|
790
|
+
|
|
791
|
+
@property
|
|
792
|
+
def num_bw_sides(self):
|
|
793
|
+
"""Number of bondwire sides.
|
|
794
|
+
|
|
756
795
|
Returns
|
|
757
796
|
-------
|
|
758
797
|
int
|
|
@@ -794,6 +833,20 @@ class DCAdvancedSettings(SettingsBase):
|
|
|
794
833
|
def refine_bondwires(self):
|
|
795
834
|
"""Whether to refine mesh along bondwires.
|
|
796
835
|
|
|
836
|
+
deprecated: Use `refine_bws` instead.
|
|
837
|
+
|
|
838
|
+
Returns
|
|
839
|
+
-------
|
|
840
|
+
bool
|
|
841
|
+
``True`` if refine bondwires is used, ``False`` otherwise.
|
|
842
|
+
"""
|
|
843
|
+
warnings.warn("`refine_bondwires` is deprecated. Use `refine_bws` instead.", DeprecationWarning)
|
|
844
|
+
return self.refine_bws
|
|
845
|
+
|
|
846
|
+
@property
|
|
847
|
+
def refine_bws(self):
|
|
848
|
+
"""Whether to refine mesh along bondwires.
|
|
849
|
+
|
|
797
850
|
Returns
|
|
798
851
|
-------
|
|
799
852
|
bool
|
pyedb/dotnet/database/siwave.py
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
This module contains these classes: ``CircuitPort``, ``CurrentSource``, ``EdbSiwave``,
|
|
25
25
|
``PinGroup``, ``ResistorSource``, ``Source``, ``SourceType``, and ``VoltageSource``.
|
|
26
26
|
"""
|
|
27
|
+
|
|
27
28
|
import os
|
|
28
29
|
import time
|
|
29
30
|
|
|
@@ -483,8 +484,8 @@ class EdbSiwave(object):
|
|
|
483
484
|
|
|
484
485
|
>>> from pyedb import Edb
|
|
485
486
|
>>> edbapp = Edb("myaedbfolder", "project name", "release version")
|
|
486
|
-
>>> pins =edbapp.components.get_pin_from_component("U2A5")
|
|
487
|
-
>>> edbapp.siwave.create_resistor_on_pin(pins[0], pins[1],50,"res_name")
|
|
487
|
+
>>> pins = edbapp.components.get_pin_from_component("U2A5")
|
|
488
|
+
>>> edbapp.siwave.create_resistor_on_pin(pins[0], pins[1], 50, "res_name")
|
|
488
489
|
"""
|
|
489
490
|
resistor = ResistorSource()
|
|
490
491
|
resistor.positive_node.net = pos_pin.net_name
|
|
@@ -625,7 +626,7 @@ class EdbSiwave(object):
|
|
|
625
626
|
|
|
626
627
|
>>> from pyedb import Edb
|
|
627
628
|
>>> edbapp = Edb("myaedbfolder", "project name", "release version")
|
|
628
|
-
>>> edb.siwave.create_voltage_source_on_net("U2A5","V1P5_S3","U2A5","GND",3.3,0,"source_name")
|
|
629
|
+
>>> edb.siwave.create_voltage_source_on_net("U2A5", "V1P5_S3", "U2A5", "GND", 3.3, 0, "source_name")
|
|
629
630
|
"""
|
|
630
631
|
if not negative_component_name:
|
|
631
632
|
negative_component_name = positive_component_name
|
pyedb/dotnet/database/stackup.py
CHANGED
|
@@ -33,6 +33,11 @@ import logging
|
|
|
33
33
|
import math
|
|
34
34
|
import warnings
|
|
35
35
|
|
|
36
|
+
from defusedxml.ElementTree import parse as defused_parse
|
|
37
|
+
import matplotlib.colors as colors
|
|
38
|
+
import numpy as np
|
|
39
|
+
import pandas as pd
|
|
40
|
+
|
|
36
41
|
from pyedb.dotnet.database.edb_data.layer_data import (
|
|
37
42
|
LayerEdbClass,
|
|
38
43
|
StackupLayerEdbClass,
|
|
@@ -42,24 +47,6 @@ from pyedb.dotnet.database.general import convert_py_list_to_net_list
|
|
|
42
47
|
from pyedb.generic.general_methods import ET, generate_unique_name
|
|
43
48
|
from pyedb.misc.aedtlib_personalib_install import write_pretty_xml
|
|
44
49
|
|
|
45
|
-
colors = None
|
|
46
|
-
pd = None
|
|
47
|
-
np = None
|
|
48
|
-
try:
|
|
49
|
-
import matplotlib.colors as colors
|
|
50
|
-
except ImportError:
|
|
51
|
-
colors = None
|
|
52
|
-
|
|
53
|
-
try:
|
|
54
|
-
import numpy as np
|
|
55
|
-
except ImportError:
|
|
56
|
-
np = None
|
|
57
|
-
|
|
58
|
-
try:
|
|
59
|
-
import pandas as pd
|
|
60
|
-
except ImportError:
|
|
61
|
-
pd = None
|
|
62
|
-
|
|
63
50
|
logger = logging.getLogger(__name__)
|
|
64
51
|
|
|
65
52
|
|
|
@@ -473,9 +460,6 @@ class Stackup(LayerCollection):
|
|
|
473
460
|
-------
|
|
474
461
|
bool
|
|
475
462
|
"""
|
|
476
|
-
if not np:
|
|
477
|
-
self._pedb.logger.error("Numpy is needed. Please, install it first.")
|
|
478
|
-
return False
|
|
479
463
|
if not layer_count % 2 == 0:
|
|
480
464
|
return False
|
|
481
465
|
|
|
@@ -973,10 +957,6 @@ class Stackup(LayerCollection):
|
|
|
973
957
|
return self.export(fpath, file_format=file_format, include_material_with_layer=include_material_with_layer)
|
|
974
958
|
|
|
975
959
|
def _export_layer_stackup_to_csv_xlsx(self, fpath=None, file_format=None):
|
|
976
|
-
if not pd:
|
|
977
|
-
self._pedb.logger.error("Pandas is needed. Please, install it first.")
|
|
978
|
-
return False
|
|
979
|
-
|
|
980
960
|
data = {
|
|
981
961
|
"Type": [],
|
|
982
962
|
"Material": [],
|
|
@@ -1137,7 +1117,7 @@ class Stackup(LayerCollection):
|
|
|
1137
1117
|
|
|
1138
1118
|
Examples
|
|
1139
1119
|
--------
|
|
1140
|
-
>>> edb = Edb(edbpath=targetfile,
|
|
1120
|
+
>>> edb = Edb(edbpath=targetfile, edbversion="2021.2")
|
|
1141
1121
|
>>> edb.stackup.flip_design()
|
|
1142
1122
|
>>> edb.save()
|
|
1143
1123
|
>>> edb.close_edb()
|
|
@@ -1227,8 +1207,11 @@ class Stackup(LayerCollection):
|
|
|
1227
1207
|
sball_prop = cmp_prop.GetSolderBallProperty().Clone()
|
|
1228
1208
|
sball_prop.SetPlacement(self._pedb.definition.SolderballPlacement.AbovePadstack)
|
|
1229
1209
|
cmp_prop.SetSolderBallProperty(sball_prop)
|
|
1230
|
-
except:
|
|
1231
|
-
|
|
1210
|
+
except Exception as e:
|
|
1211
|
+
self._logger.warning(
|
|
1212
|
+
f"A(n) {type(e).__name__} error occurred while attempting to update "
|
|
1213
|
+
f"SolderBallProperty for component {cmp}: {str(e)}"
|
|
1214
|
+
)
|
|
1232
1215
|
if cmp_type == self._pedb.definition.ComponentType.IC:
|
|
1233
1216
|
die_prop = cmp_prop.GetDieProperty().Clone()
|
|
1234
1217
|
chip_orientation = die_prop.GetOrientation()
|
|
@@ -1356,22 +1339,28 @@ class Stackup(LayerCollection):
|
|
|
1356
1339
|
|
|
1357
1340
|
Examples
|
|
1358
1341
|
--------
|
|
1359
|
-
>>> edb1 = Edb(edbpath=targetfile1,
|
|
1342
|
+
>>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
|
|
1360
1343
|
>>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
|
|
1361
1344
|
|
|
1362
1345
|
>>> hosting_cmp = edb1.components.get_component_by_name("U100")
|
|
1363
1346
|
>>> mounted_cmp = edb2.components.get_component_by_name("BGA")
|
|
1364
1347
|
|
|
1365
1348
|
>>> vector, rotation, solder_ball_height = edb1.components.get_component_placement_vector(
|
|
1366
|
-
...
|
|
1367
|
-
...
|
|
1368
|
-
...
|
|
1369
|
-
...
|
|
1370
|
-
...
|
|
1371
|
-
...
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
...
|
|
1349
|
+
... mounted_component=mounted_cmp,
|
|
1350
|
+
... hosting_component=hosting_cmp,
|
|
1351
|
+
... mounted_component_pin1="A12",
|
|
1352
|
+
... mounted_component_pin2="A14",
|
|
1353
|
+
... hosting_component_pin1="A12",
|
|
1354
|
+
... hosting_component_pin2="A14",
|
|
1355
|
+
... )
|
|
1356
|
+
>>> edb2.stackup.place_in_layout(
|
|
1357
|
+
... edb1.active_cell,
|
|
1358
|
+
... angle=0.0,
|
|
1359
|
+
... offset_x=vector[0],
|
|
1360
|
+
... offset_y=vector[1],
|
|
1361
|
+
... flipped_stackup=False,
|
|
1362
|
+
... place_on_top=True,
|
|
1363
|
+
... )
|
|
1375
1364
|
"""
|
|
1376
1365
|
# if flipped_stackup and place_on_top or (not flipped_stackup and not place_on_top):
|
|
1377
1366
|
self.adjust_solder_dielectrics()
|
|
@@ -1453,13 +1442,18 @@ class Stackup(LayerCollection):
|
|
|
1453
1442
|
|
|
1454
1443
|
Examples
|
|
1455
1444
|
--------
|
|
1456
|
-
>>> edb1 = Edb(edbpath=targetfile1,
|
|
1445
|
+
>>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
|
|
1457
1446
|
>>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
|
|
1458
1447
|
>>> hosting_cmp = edb1.components.get_component_by_name("U100")
|
|
1459
1448
|
>>> mounted_cmp = edb2.components.get_component_by_name("BGA")
|
|
1460
|
-
>>> edb2.stackup.place_in_layout(
|
|
1461
|
-
...
|
|
1462
|
-
...
|
|
1449
|
+
>>> edb2.stackup.place_in_layout(
|
|
1450
|
+
... edb1.active_cell,
|
|
1451
|
+
... angle=0.0,
|
|
1452
|
+
... offset_x="1mm",
|
|
1453
|
+
... offset_y="2mm",
|
|
1454
|
+
... flipped_stackup=False,
|
|
1455
|
+
... place_on_top=True,
|
|
1456
|
+
... )
|
|
1463
1457
|
"""
|
|
1464
1458
|
_angle = angle * math.pi / 180.0
|
|
1465
1459
|
|
|
@@ -1592,13 +1586,18 @@ class Stackup(LayerCollection):
|
|
|
1592
1586
|
|
|
1593
1587
|
Examples
|
|
1594
1588
|
--------
|
|
1595
|
-
>>> edb1 = Edb(edbpath=targetfile1,
|
|
1589
|
+
>>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
|
|
1596
1590
|
>>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
|
|
1597
1591
|
>>> hosting_cmp = edb1.components.get_component_by_name("U100")
|
|
1598
1592
|
>>> mounted_cmp = edb2.components.get_component_by_name("BGA")
|
|
1599
|
-
>>> edb1.stackup.place_instance(
|
|
1600
|
-
...
|
|
1601
|
-
...
|
|
1593
|
+
>>> edb1.stackup.place_instance(
|
|
1594
|
+
... edb2,
|
|
1595
|
+
... angle=0.0,
|
|
1596
|
+
... offset_x="1mm",
|
|
1597
|
+
... offset_y="2mm",
|
|
1598
|
+
... flipped_stackup=False,
|
|
1599
|
+
... place_on_top=True,
|
|
1600
|
+
... )
|
|
1602
1601
|
"""
|
|
1603
1602
|
_angle = angle * math.pi / 180.0
|
|
1604
1603
|
|
|
@@ -1736,11 +1735,16 @@ class Stackup(LayerCollection):
|
|
|
1736
1735
|
|
|
1737
1736
|
Examples
|
|
1738
1737
|
--------
|
|
1739
|
-
>>> edb1 = Edb(edbpath=targetfile1,
|
|
1738
|
+
>>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
|
|
1740
1739
|
>>> a3dcomp_path = "connector.a3dcomp"
|
|
1741
|
-
>>> edb1.stackup.place_a3dcomp_3d_placement(
|
|
1742
|
-
...
|
|
1743
|
-
...
|
|
1740
|
+
>>> edb1.stackup.place_a3dcomp_3d_placement(
|
|
1741
|
+
... a3dcomp_path,
|
|
1742
|
+
... angle=0.0,
|
|
1743
|
+
... offset_x="1mm",
|
|
1744
|
+
... offset_y="2mm",
|
|
1745
|
+
... flipped_stackup=False,
|
|
1746
|
+
... place_on_top=True,
|
|
1747
|
+
... )
|
|
1744
1748
|
"""
|
|
1745
1749
|
zero_data = self._edb_value(0.0)
|
|
1746
1750
|
one_data = self._edb_value(1.0)
|
|
@@ -1795,7 +1799,7 @@ class Stackup(LayerCollection):
|
|
|
1795
1799
|
|
|
1796
1800
|
Examples
|
|
1797
1801
|
--------
|
|
1798
|
-
>>> edb = Edb(edbpath=targetfile1,
|
|
1802
|
+
>>> edb = Edb(edbpath=targetfile1, edbversion="2021.2")
|
|
1799
1803
|
>>> edb.stackup.residual_copper_area_per_layer()
|
|
1800
1804
|
"""
|
|
1801
1805
|
temp_data = {name: 0 for name, _ in self.signal_layers.items()}
|
|
@@ -1972,10 +1976,6 @@ class Stackup(LayerCollection):
|
|
|
1972
1976
|
file_path : str
|
|
1973
1977
|
File path to the CSV file.
|
|
1974
1978
|
"""
|
|
1975
|
-
if not pd:
|
|
1976
|
-
self._pedb.logger.error("Pandas is needed. You must install it first.")
|
|
1977
|
-
return False
|
|
1978
|
-
|
|
1979
1979
|
df = pd.read_csv(file_path, index_col=0)
|
|
1980
1980
|
|
|
1981
1981
|
for name in self.layers.keys(): # pragma: no cover
|
|
@@ -2242,9 +2242,6 @@ class Stackup(LayerCollection):
|
|
|
2242
2242
|
``True`` when successful, ``False`` when failed.
|
|
2243
2243
|
"""
|
|
2244
2244
|
|
|
2245
|
-
if not colors:
|
|
2246
|
-
self._pedb.logger.error("Matplotlib is needed. Please, install it first.")
|
|
2247
|
-
return False
|
|
2248
2245
|
tree = ET.parse(file_path)
|
|
2249
2246
|
root = tree.getroot()
|
|
2250
2247
|
stackup = root.find("Stackup")
|
|
@@ -382,6 +382,87 @@ class HfssSimulationSetup(SimulationSetup):
|
|
|
382
382
|
return False
|
|
383
383
|
return True
|
|
384
384
|
|
|
385
|
+
def auto_mesh_operation(
|
|
386
|
+
self,
|
|
387
|
+
trace_ratio_seeding: float = 3,
|
|
388
|
+
signal_via_side_number: int = 12,
|
|
389
|
+
power_ground_via_side_number: int = 6,
|
|
390
|
+
) -> bool:
|
|
391
|
+
"""
|
|
392
|
+
Automatically create and apply a length-based mesh operation for all nets in the design.
|
|
393
|
+
|
|
394
|
+
The method inspects every signal net, determines the smallest trace width, and
|
|
395
|
+
seeds a :class:`LengthMeshOperation` whose maximum element length is
|
|
396
|
+
``smallest_width * trace_ratio_seeding``. Signal vias (padstack instances) are
|
|
397
|
+
configured with the requested number of polygon sides, while power/ground vias
|
|
398
|
+
are updated through the global ``num_via_sides`` advanced setting.
|
|
399
|
+
|
|
400
|
+
Parameters
|
|
401
|
+
----------
|
|
402
|
+
trace_ratio_seeding : float, optional
|
|
403
|
+
Ratio used to compute the maximum allowed element length from the
|
|
404
|
+
smallest trace width found in the design. The resulting length is
|
|
405
|
+
``min_width * trace_ratio_seeding``. Defaults to ``3``.
|
|
406
|
+
signal_via_side_number : int, optional
|
|
407
|
+
Number of sides (i.e. faceting resolution) assigned to **signal**
|
|
408
|
+
padstack instances that belong to the nets being meshed.
|
|
409
|
+
Defaults to ``12``.
|
|
410
|
+
power_ground_via_side_number : int, optional
|
|
411
|
+
Number of sides assigned to **power/ground** vias via the global
|
|
412
|
+
``advanced.num_via_sides`` setting. Defaults to ``6``.
|
|
413
|
+
|
|
414
|
+
Returns
|
|
415
|
+
-------
|
|
416
|
+
bool
|
|
417
|
+
|
|
418
|
+
Raises
|
|
419
|
+
------
|
|
420
|
+
ValueError
|
|
421
|
+
If the design contains no terminals, making mesh seeding impossible.
|
|
422
|
+
|
|
423
|
+
Notes
|
|
424
|
+
-----
|
|
425
|
+
* Only primitives of type ``"path"`` are considered when determining the
|
|
426
|
+
smallest trace width.
|
|
427
|
+
* Every ``(net, layer, sheet)`` tuple required by the mesher is
|
|
428
|
+
automatically populated; sheet are explicitly marked as ``False``.
|
|
429
|
+
* Existing contents of :attr:`mesh_operations` are **replaced** by the
|
|
430
|
+
single new operation.
|
|
431
|
+
|
|
432
|
+
Examples
|
|
433
|
+
--------
|
|
434
|
+
>>> setup = edbapp.setups["my_setup"]
|
|
435
|
+
>>> setup.auto_mesh_operation(trace_ratio_seeding=4, signal_vias_side_number=16)
|
|
436
|
+
>>> setup.mesh_operations[0].max_length
|
|
437
|
+
'2.5um'
|
|
438
|
+
"""
|
|
439
|
+
net_for_mesh_seeding = list(set([term.net.name for term in list(self._pedb.terminals.values())]))
|
|
440
|
+
if not net_for_mesh_seeding:
|
|
441
|
+
raise ValueError("No terminals found to seed the mesh operation.")
|
|
442
|
+
net_layer_dict = {}
|
|
443
|
+
smallest_width = 1e3
|
|
444
|
+
for net in net_for_mesh_seeding:
|
|
445
|
+
net_layer_dict[net] = []
|
|
446
|
+
traces = [prim for prim in self._pedb.modeler.primitives_by_net[net] if prim.type.lower() == "path"]
|
|
447
|
+
_width = min([trace.width for trace in traces], default=1e3)
|
|
448
|
+
if _width < smallest_width:
|
|
449
|
+
smallest_width = _width
|
|
450
|
+
layers = list(set([trace.layer.name for trace in traces]))
|
|
451
|
+
for layer in layers:
|
|
452
|
+
net_layer_dict[net].append(layer)
|
|
453
|
+
for inst in [
|
|
454
|
+
inst for inst in list(self._pedb.padstacks.padstack_instances.values()) if inst.net_name == net
|
|
455
|
+
]:
|
|
456
|
+
inst.side_number = signal_via_side_number
|
|
457
|
+
self.add_length_mesh_operation(
|
|
458
|
+
net_layer_list=net_layer_dict,
|
|
459
|
+
name=f"{self.name}_AutoMeshOp",
|
|
460
|
+
max_length=f"{round(float((smallest_width * trace_ratio_seeding)), 9) * 1e6}um",
|
|
461
|
+
)
|
|
462
|
+
if f"{self.name}_AutoMeshOp" in self.mesh_operations:
|
|
463
|
+
return True
|
|
464
|
+
return False
|
|
465
|
+
|
|
385
466
|
|
|
386
467
|
class HFSSPISimulationSetup(SimulationSetup):
|
|
387
468
|
"""Manages EDB methods for HFSSPI simulation setup."""
|
|
@@ -371,11 +371,13 @@ class SimulationSetup(object):
|
|
|
371
371
|
Examples
|
|
372
372
|
--------
|
|
373
373
|
>>> setup1 = edbapp.create_siwave_syz_setup("setup1")
|
|
374
|
-
>>> setup1.add_frequency_sweep(
|
|
375
|
-
... [
|
|
376
|
-
...
|
|
377
|
-
...
|
|
378
|
-
...
|
|
374
|
+
>>> setup1.add_frequency_sweep(
|
|
375
|
+
... frequency_sweep=[
|
|
376
|
+
... ["linear count", "0", "1kHz", 1],
|
|
377
|
+
... ["log scale", "1kHz", "0.1GHz", 10],
|
|
378
|
+
... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"],
|
|
379
|
+
... ]
|
|
380
|
+
... )
|
|
379
381
|
"""
|
|
380
382
|
warnings.warn("`add_frequency_sweep` is deprecated. Use `add_sweep` method instead.", DeprecationWarning)
|
|
381
383
|
return self.add_sweep(name, frequency_sweep)
|
|
@@ -691,6 +691,7 @@ class SIWaveCPASimulationSetup:
|
|
|
691
691
|
self._pedb = pedb
|
|
692
692
|
self._channel_setup = ChannelSetup(pedb)
|
|
693
693
|
self._solver_options = SolverOptions(pedb)
|
|
694
|
+
self.type = "cpa"
|
|
694
695
|
if isinstance(siwave_cpa_setup_class, SIwaveCpaSetup):
|
|
695
696
|
self._apply_cfg_object(siwave_cpa_setup_class)
|
|
696
697
|
else:
|