pyedb 0.19.0__py3-none-any.whl → 0.20.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/dotnet/edb.py +154 -235
- pyedb/dotnet/edb_core/cell/connectable.py +64 -0
- pyedb/dotnet/edb_core/cell/hierarchy/component.py +12 -10
- pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py +1 -1
- pyedb/dotnet/edb_core/cell/layout.py +253 -105
- pyedb/dotnet/edb_core/cell/layout_obj.py +4 -49
- pyedb/dotnet/edb_core/cell/primitive.py +14 -2
- pyedb/dotnet/edb_core/cell/terminal/padstack_instance_terminal.py +1 -1
- pyedb/dotnet/edb_core/cell/terminal/point_terminal.py +1 -1
- pyedb/dotnet/edb_core/cell/terminal/terminal.py +1 -19
- pyedb/dotnet/edb_core/cell/voltage_regulator.py +2 -16
- pyedb/dotnet/edb_core/components.py +14 -13
- pyedb/dotnet/edb_core/dotnet/database.py +5 -10
- pyedb/dotnet/edb_core/dotnet/primitive.py +11 -1
- pyedb/dotnet/edb_core/edb_data/control_file.py +2 -12
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +20 -33
- pyedb/dotnet/edb_core/general.py +6 -9
- pyedb/dotnet/edb_core/hfss.py +4 -8
- pyedb/dotnet/edb_core/layout_obj_instance.py +30 -0
- pyedb/dotnet/edb_core/materials.py +4 -11
- pyedb/dotnet/edb_core/{layout.py → modeler.py} +153 -7
- pyedb/dotnet/edb_core/net_class.py +7 -8
- pyedb/dotnet/edb_core/nets.py +3 -9
- pyedb/dotnet/edb_core/padstack.py +13 -9
- pyedb/dotnet/edb_core/sim_setup_data/data/sweep_data.py +5 -2
- pyedb/dotnet/edb_core/siwave.py +5 -6
- pyedb/dotnet/edb_core/stackup.py +18 -23
- pyedb/dotnet/edb_core/utilities/simulation_setup.py +1 -4
- pyedb/generic/filesystem.py +2 -8
- pyedb/generic/general_methods.py +4 -10
- pyedb/generic/plot.py +26 -29
- pyedb/generic/process.py +2 -6
- pyedb/misc/downloads.py +3 -40
- pyedb/siwave.py +2 -5
- {pyedb-0.19.0.dist-info → pyedb-0.20.0.dist-info}/METADATA +2 -2
- {pyedb-0.19.0.dist-info → pyedb-0.20.0.dist-info}/RECORD +39 -38
- pyedb/dotnet/edb_core/dotnet/layout.py +0 -260
- {pyedb-0.19.0.dist-info → pyedb-0.20.0.dist-info}/LICENSE +0 -0
- {pyedb-0.19.0.dist-info → pyedb-0.20.0.dist-info}/WHEEL +0 -0
pyedb/__init__.py
CHANGED
pyedb/dotnet/edb.py
CHANGED
|
@@ -30,6 +30,7 @@ import os
|
|
|
30
30
|
from pathlib import Path
|
|
31
31
|
import re
|
|
32
32
|
import shutil
|
|
33
|
+
import subprocess
|
|
33
34
|
import sys
|
|
34
35
|
import tempfile
|
|
35
36
|
import time
|
|
@@ -37,21 +38,14 @@ import traceback
|
|
|
37
38
|
from typing import Union
|
|
38
39
|
import warnings
|
|
39
40
|
|
|
41
|
+
import rtree
|
|
42
|
+
|
|
40
43
|
from pyedb.configuration.configuration import Configuration
|
|
41
44
|
from pyedb.dotnet.application.Variables import decompose_variable_value
|
|
42
45
|
from pyedb.dotnet.edb_core.cell.layout import Layout
|
|
43
|
-
from pyedb.dotnet.edb_core.cell.terminal.bundle_terminal import BundleTerminal
|
|
44
|
-
from pyedb.dotnet.edb_core.cell.terminal.edge_terminal import EdgeTerminal
|
|
45
|
-
from pyedb.dotnet.edb_core.cell.terminal.padstack_instance_terminal import (
|
|
46
|
-
PadstackInstanceTerminal,
|
|
47
|
-
)
|
|
48
|
-
from pyedb.dotnet.edb_core.cell.terminal.pingroup_terminal import PinGroupTerminal
|
|
49
|
-
from pyedb.dotnet.edb_core.cell.terminal.point_terminal import PointTerminal
|
|
50
46
|
from pyedb.dotnet.edb_core.cell.terminal.terminal import Terminal
|
|
51
|
-
from pyedb.dotnet.edb_core.cell.voltage_regulator import VoltageRegulator
|
|
52
47
|
from pyedb.dotnet.edb_core.components import Components
|
|
53
48
|
from pyedb.dotnet.edb_core.dotnet.database import Database
|
|
54
|
-
from pyedb.dotnet.edb_core.dotnet.layout import LayoutDotNet
|
|
55
49
|
from pyedb.dotnet.edb_core.edb_data.control_file import (
|
|
56
50
|
ControlFile,
|
|
57
51
|
convert_technology_file,
|
|
@@ -82,6 +76,7 @@ from pyedb.dotnet.edb_core.general import (
|
|
|
82
76
|
from pyedb.dotnet.edb_core.hfss import EdbHfss
|
|
83
77
|
from pyedb.dotnet.edb_core.layout_validation import LayoutValidation
|
|
84
78
|
from pyedb.dotnet.edb_core.materials import Materials
|
|
79
|
+
from pyedb.dotnet.edb_core.modeler import Modeler
|
|
85
80
|
from pyedb.dotnet.edb_core.net_class import (
|
|
86
81
|
EdbDifferentialPairs,
|
|
87
82
|
EdbExtendedNets,
|
|
@@ -103,8 +98,6 @@ from pyedb.generic.constants import AEDT_UNITS, SolverType
|
|
|
103
98
|
from pyedb.generic.general_methods import (
|
|
104
99
|
generate_unique_name,
|
|
105
100
|
get_string_version,
|
|
106
|
-
inside_desktop,
|
|
107
|
-
is_ironpython,
|
|
108
101
|
is_linux,
|
|
109
102
|
is_windows,
|
|
110
103
|
)
|
|
@@ -114,13 +107,6 @@ from pyedb.ipc2581.ipc2581 import Ipc2581
|
|
|
114
107
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
115
108
|
from pyedb.workflow import Workflow
|
|
116
109
|
|
|
117
|
-
if is_linux and is_ironpython:
|
|
118
|
-
import subprocessdotnet as subprocess
|
|
119
|
-
else:
|
|
120
|
-
import subprocess
|
|
121
|
-
|
|
122
|
-
import rtree
|
|
123
|
-
|
|
124
110
|
|
|
125
111
|
class Edb(Database):
|
|
126
112
|
"""Provides the EDB application interface.
|
|
@@ -235,9 +221,7 @@ class Edb(Database):
|
|
|
235
221
|
if not isreadonly:
|
|
236
222
|
self._check_remove_project_files(edbpath, remove_existing_aedt)
|
|
237
223
|
|
|
238
|
-
if
|
|
239
|
-
self.open_edb_inside_aedt()
|
|
240
|
-
elif edbpath[-3:] in ["brd", "mcm", "sip", "gds", "xml", "dxf", "tgz", "anf"]:
|
|
224
|
+
if edbpath[-3:] in ["brd", "mcm", "sip", "gds", "xml", "dxf", "tgz", "anf"]:
|
|
241
225
|
self.edbpath = edbpath[:-4] + ".aedb"
|
|
242
226
|
working_dir = os.path.dirname(edbpath)
|
|
243
227
|
control_file = None
|
|
@@ -361,7 +345,7 @@ class Edb(Database):
|
|
|
361
345
|
self._siwave = EdbSiwave(self)
|
|
362
346
|
self._hfss = EdbHfss(self)
|
|
363
347
|
self._nets = EdbNets(self)
|
|
364
|
-
self._core_primitives =
|
|
348
|
+
self._core_primitives = Modeler(self)
|
|
365
349
|
self._stackup2 = self._stackup
|
|
366
350
|
self._materials = Materials(self)
|
|
367
351
|
|
|
@@ -437,23 +421,10 @@ class Edb(Database):
|
|
|
437
421
|
|
|
438
422
|
Returns
|
|
439
423
|
-------
|
|
440
|
-
|
|
424
|
+
Dict
|
|
441
425
|
"""
|
|
442
426
|
|
|
443
|
-
|
|
444
|
-
for i in self.layout.terminals:
|
|
445
|
-
terminal_type = i.ToString().split(".")[-1]
|
|
446
|
-
if terminal_type == "PinGroupTerminal":
|
|
447
|
-
temp[i.GetName()] = PinGroupTerminal(self, i)
|
|
448
|
-
elif terminal_type == "PadstackInstanceTerminal":
|
|
449
|
-
temp[i.GetName()] = PadstackInstanceTerminal(self, i)
|
|
450
|
-
elif terminal_type == "EdgeTerminal":
|
|
451
|
-
temp[i.GetName()] = EdgeTerminal(self, i)
|
|
452
|
-
elif terminal_type == "BundleTerminal":
|
|
453
|
-
temp[i.GetName()] = BundleTerminal(self, i)
|
|
454
|
-
elif terminal_type == "PointTerminal":
|
|
455
|
-
temp[i.GetName()] = PointTerminal(self, i)
|
|
456
|
-
return temp
|
|
427
|
+
return {i.name: i for i in self.layout.terminals}
|
|
457
428
|
|
|
458
429
|
@property
|
|
459
430
|
def excitations(self):
|
|
@@ -516,7 +487,7 @@ class Edb(Database):
|
|
|
516
487
|
@property
|
|
517
488
|
def voltage_regulator_modules(self):
|
|
518
489
|
"""Get all voltage regulator modules"""
|
|
519
|
-
vrms =
|
|
490
|
+
vrms = self.layout.voltage_regulators
|
|
520
491
|
_vrms = {}
|
|
521
492
|
for vrm in vrms:
|
|
522
493
|
_vrms[vrm.name] = vrm
|
|
@@ -574,40 +545,6 @@ class Edb(Database):
|
|
|
574
545
|
|
|
575
546
|
return True
|
|
576
547
|
|
|
577
|
-
def open_edb_inside_aedt(self):
|
|
578
|
-
"""Open EDB inside AEDT.
|
|
579
|
-
|
|
580
|
-
Returns
|
|
581
|
-
-------
|
|
582
|
-
``True`` when succeed ``False`` if failed : bool
|
|
583
|
-
|
|
584
|
-
"""
|
|
585
|
-
self.logger.info("Opening EDB from HDL")
|
|
586
|
-
self.run_as_standalone(False)
|
|
587
|
-
if self.oproject.GetEDBHandle():
|
|
588
|
-
self.attach(self.oproject.GetEDBHandle())
|
|
589
|
-
if not self.active_db:
|
|
590
|
-
self.logger.warning("Error getting the database.")
|
|
591
|
-
self._active_cell = None
|
|
592
|
-
return None
|
|
593
|
-
self._active_cell = self.edb_api.cell.cell.FindByName(
|
|
594
|
-
self.active_db,
|
|
595
|
-
self.edb_api.cell._cell.CellType.CircuitCell,
|
|
596
|
-
self.cellname,
|
|
597
|
-
)
|
|
598
|
-
if self._active_cell is None:
|
|
599
|
-
self._active_cell = list(self.top_circuit_cells)[0]
|
|
600
|
-
if self._active_cell:
|
|
601
|
-
if not os.path.exists(self.edbpath):
|
|
602
|
-
os.makedirs(self.edbpath)
|
|
603
|
-
self._init_objects()
|
|
604
|
-
return True
|
|
605
|
-
else:
|
|
606
|
-
return None
|
|
607
|
-
else:
|
|
608
|
-
self._active_cell = None
|
|
609
|
-
return None
|
|
610
|
-
|
|
611
548
|
def create_edb(self):
|
|
612
549
|
"""Create EDB.
|
|
613
550
|
|
|
@@ -1153,7 +1090,7 @@ class Edb(Database):
|
|
|
1153
1090
|
>>> top_prims = edbapp.modeler.primitives_by_layer["TOP"]
|
|
1154
1091
|
"""
|
|
1155
1092
|
if not self._core_primitives and self.active_db:
|
|
1156
|
-
self._core_primitives =
|
|
1093
|
+
self._core_primitives = Modeler(self)
|
|
1157
1094
|
return self._core_primitives
|
|
1158
1095
|
|
|
1159
1096
|
@property
|
|
@@ -1164,7 +1101,7 @@ class Edb(Database):
|
|
|
1164
1101
|
-------
|
|
1165
1102
|
:class:`legacy.edb_core.dotnet.layout.Layout`
|
|
1166
1103
|
"""
|
|
1167
|
-
return
|
|
1104
|
+
return Layout(self, self._active_cell.GetLayout())
|
|
1168
1105
|
|
|
1169
1106
|
@property
|
|
1170
1107
|
def active_layout(self):
|
|
@@ -1174,12 +1111,12 @@ class Edb(Database):
|
|
|
1174
1111
|
-------
|
|
1175
1112
|
Instance of EDB API Layout Class.
|
|
1176
1113
|
"""
|
|
1177
|
-
return self.layout.
|
|
1114
|
+
return self.layout._edb_object
|
|
1178
1115
|
|
|
1179
1116
|
@property
|
|
1180
1117
|
def layout_instance(self):
|
|
1181
1118
|
"""Edb Layout Instance."""
|
|
1182
|
-
return self.layout.
|
|
1119
|
+
return self.layout._edb_object.GetLayoutInstance()
|
|
1183
1120
|
|
|
1184
1121
|
def get_connected_objects(self, layout_object_instance):
|
|
1185
1122
|
"""Get connected objects.
|
|
@@ -2218,9 +2155,6 @@ class Edb(Database):
|
|
|
2218
2155
|
keep_lines_as_path=False,
|
|
2219
2156
|
inlcude_voids_in_extents=False,
|
|
2220
2157
|
):
|
|
2221
|
-
if is_ironpython: # pragma: no cover
|
|
2222
|
-
self.logger.error("Method working only in Cpython")
|
|
2223
|
-
return False
|
|
2224
2158
|
from concurrent.futures import ThreadPoolExecutor
|
|
2225
2159
|
|
|
2226
2160
|
if output_aedb_path:
|
|
@@ -2750,20 +2684,12 @@ class Edb(Database):
|
|
|
2750
2684
|
|
|
2751
2685
|
for void_circle in voids_to_add:
|
|
2752
2686
|
if void_circle.type == "Circle":
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
) = void_circle.primitive_object.GetParameters()
|
|
2760
|
-
else:
|
|
2761
|
-
(
|
|
2762
|
-
res,
|
|
2763
|
-
center_x,
|
|
2764
|
-
center_y,
|
|
2765
|
-
radius,
|
|
2766
|
-
) = void_circle.primitive_object.GetParameters(0.0, 0.0, 0.0)
|
|
2687
|
+
(
|
|
2688
|
+
res,
|
|
2689
|
+
center_x,
|
|
2690
|
+
center_y,
|
|
2691
|
+
radius,
|
|
2692
|
+
) = void_circle.primitive_object.GetParameters(0.0, 0.0, 0.0)
|
|
2767
2693
|
cloned_circle = self.edb_api.cell.primitive.circle.create(
|
|
2768
2694
|
layout,
|
|
2769
2695
|
void_circle.layer_name,
|
|
@@ -3344,163 +3270,156 @@ class Edb(Database):
|
|
|
3344
3270
|
legacy_name = self.edbpath
|
|
3345
3271
|
if simulation_setup.output_aedb:
|
|
3346
3272
|
self.save_edb_as(simulation_setup.output_aedb)
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
for
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
):
|
|
3382
|
-
self.logger.info("Cutout processed.")
|
|
3383
|
-
old_cell = self.active_cell.FindByName(
|
|
3384
|
-
self.db,
|
|
3385
|
-
self.edb_api.cell.CellType.CircuitCell,
|
|
3386
|
-
old_cell_name,
|
|
3387
|
-
)
|
|
3388
|
-
if old_cell:
|
|
3389
|
-
old_cell.Delete()
|
|
3390
|
-
else: # pragma: no cover
|
|
3391
|
-
self.logger.error("Cutout failed.")
|
|
3392
|
-
else:
|
|
3393
|
-
self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type))
|
|
3394
|
-
self.cutout(
|
|
3395
|
-
signal_list=simulation_setup.signal_nets,
|
|
3396
|
-
reference_list=simulation_setup.power_nets,
|
|
3397
|
-
expansion_size=simulation_setup.cutout_subdesign_expansion,
|
|
3398
|
-
use_round_corner=simulation_setup.cutout_subdesign_round_corner,
|
|
3399
|
-
extent_type=simulation_setup.cutout_subdesign_type,
|
|
3400
|
-
use_pyaedt_cutout=True,
|
|
3401
|
-
use_pyaedt_extent_computing=True,
|
|
3402
|
-
remove_single_pin_components=True,
|
|
3403
|
-
)
|
|
3273
|
+
if simulation_setup.signal_layer_etching_instances:
|
|
3274
|
+
for layer in simulation_setup.signal_layer_etching_instances:
|
|
3275
|
+
if layer in self.stackup.layers:
|
|
3276
|
+
idx = simulation_setup.signal_layer_etching_instances.index(layer)
|
|
3277
|
+
if len(simulation_setup.etching_factor_instances) > idx:
|
|
3278
|
+
self.stackup[layer].etch_factor = float(simulation_setup.etching_factor_instances[idx])
|
|
3279
|
+
|
|
3280
|
+
if not simulation_setup.signal_nets and simulation_setup.components:
|
|
3281
|
+
nets_to_include = []
|
|
3282
|
+
pnets = list(self.nets.power.keys())[:]
|
|
3283
|
+
for el in simulation_setup.components:
|
|
3284
|
+
nets_to_include.append([i for i in self.components[el].nets if i not in pnets])
|
|
3285
|
+
simulation_setup.signal_nets = [
|
|
3286
|
+
i
|
|
3287
|
+
for i in list(set.intersection(*map(set, nets_to_include)))
|
|
3288
|
+
if i not in simulation_setup.power_nets and i != ""
|
|
3289
|
+
]
|
|
3290
|
+
self.nets.classify_nets(simulation_setup.power_nets, simulation_setup.signal_nets)
|
|
3291
|
+
if not simulation_setup.power_nets or not simulation_setup.signal_nets:
|
|
3292
|
+
self.logger.info("Disabling cutout as no signals or power nets have been defined.")
|
|
3293
|
+
simulation_setup.do_cutout_subdesign = False
|
|
3294
|
+
if simulation_setup.do_cutout_subdesign:
|
|
3295
|
+
self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type))
|
|
3296
|
+
if simulation_setup.use_default_cutout:
|
|
3297
|
+
old_cell_name = self.active_cell.GetName()
|
|
3298
|
+
if self.cutout(
|
|
3299
|
+
signal_list=simulation_setup.signal_nets,
|
|
3300
|
+
reference_list=simulation_setup.power_nets,
|
|
3301
|
+
expansion_size=simulation_setup.cutout_subdesign_expansion,
|
|
3302
|
+
use_round_corner=simulation_setup.cutout_subdesign_round_corner,
|
|
3303
|
+
extent_type=simulation_setup.cutout_subdesign_type,
|
|
3304
|
+
use_pyaedt_cutout=False,
|
|
3305
|
+
use_pyaedt_extent_computing=False,
|
|
3306
|
+
):
|
|
3404
3307
|
self.logger.info("Cutout processed.")
|
|
3308
|
+
old_cell = self.active_cell.FindByName(
|
|
3309
|
+
self.db,
|
|
3310
|
+
self.edb_api.cell.CellType.CircuitCell,
|
|
3311
|
+
old_cell_name,
|
|
3312
|
+
)
|
|
3313
|
+
if old_cell:
|
|
3314
|
+
old_cell.Delete()
|
|
3315
|
+
else: # pragma: no cover
|
|
3316
|
+
self.logger.error("Cutout failed.")
|
|
3405
3317
|
else:
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3318
|
+
self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type))
|
|
3319
|
+
self.cutout(
|
|
3320
|
+
signal_list=simulation_setup.signal_nets,
|
|
3321
|
+
reference_list=simulation_setup.power_nets,
|
|
3322
|
+
expansion_size=simulation_setup.cutout_subdesign_expansion,
|
|
3323
|
+
use_round_corner=simulation_setup.cutout_subdesign_round_corner,
|
|
3324
|
+
extent_type=simulation_setup.cutout_subdesign_type,
|
|
3325
|
+
use_pyaedt_cutout=True,
|
|
3326
|
+
use_pyaedt_extent_computing=True,
|
|
3327
|
+
remove_single_pin_components=True,
|
|
3328
|
+
)
|
|
3329
|
+
self.logger.info("Cutout processed.")
|
|
3330
|
+
else:
|
|
3331
|
+
if simulation_setup.include_only_selected_nets:
|
|
3332
|
+
included_nets = simulation_setup.signal_nets + simulation_setup.power_nets
|
|
3333
|
+
nets_to_remove = [net.name for net in list(self.nets.nets.values()) if not net.name in included_nets]
|
|
3334
|
+
self.nets.delete(nets_to_remove)
|
|
3335
|
+
self.logger.info("Deleting existing ports.")
|
|
3336
|
+
map(lambda port: port.Delete(), self.layout.terminals)
|
|
3337
|
+
map(lambda pg: pg.Delete(), self.layout.pin_groups)
|
|
3338
|
+
if simulation_setup.solver_type == SolverType.Hfss3dLayout:
|
|
3339
|
+
if simulation_setup.generate_excitations:
|
|
3340
|
+
self.logger.info("Creating HFSS ports for signal nets.")
|
|
3341
|
+
source_type = SourceType.CoaxPort
|
|
3342
|
+
if not simulation_setup.generate_solder_balls:
|
|
3343
|
+
source_type = SourceType.CircPort
|
|
3344
|
+
for cmp in simulation_setup.components:
|
|
3345
|
+
if isinstance(cmp, str): # keep legacy component
|
|
3346
|
+
self.components.create_port_on_component(
|
|
3347
|
+
cmp,
|
|
3348
|
+
net_list=simulation_setup.signal_nets,
|
|
3349
|
+
do_pingroup=False,
|
|
3350
|
+
reference_net=simulation_setup.power_nets,
|
|
3351
|
+
port_type=source_type,
|
|
3352
|
+
)
|
|
3353
|
+
elif isinstance(cmp, dict):
|
|
3354
|
+
if "refdes" in cmp:
|
|
3355
|
+
if not "solder_balls_height" in cmp: # pragma no cover
|
|
3356
|
+
cmp["solder_balls_height"] = None
|
|
3357
|
+
if not "solder_balls_size" in cmp: # pragma no cover
|
|
3358
|
+
cmp["solder_balls_size"] = None
|
|
3359
|
+
cmp["solder_balls_mid_size"] = None
|
|
3360
|
+
if not "solder_balls_mid_size" in cmp: # pragma no cover
|
|
3361
|
+
cmp["solder_balls_mid_size"] = None
|
|
3423
3362
|
self.components.create_port_on_component(
|
|
3424
|
-
cmp,
|
|
3363
|
+
cmp["refdes"],
|
|
3425
3364
|
net_list=simulation_setup.signal_nets,
|
|
3426
3365
|
do_pingroup=False,
|
|
3427
3366
|
reference_net=simulation_setup.power_nets,
|
|
3428
3367
|
port_type=source_type,
|
|
3368
|
+
solder_balls_height=cmp["solder_balls_height"],
|
|
3369
|
+
solder_balls_size=cmp["solder_balls_size"],
|
|
3370
|
+
solder_balls_mid_size=cmp["solder_balls_mid_size"],
|
|
3429
3371
|
)
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
if
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
simulation_setup.generate_solder_balls and simulation_setup.trim_reference_size
|
|
3457
|
-
): # pragma: no cover
|
|
3458
|
-
self.logger.info(
|
|
3459
|
-
"Trimming the reference plane for coaxial ports: {0}".format(
|
|
3460
|
-
bool(simulation_setup.trim_reference_size)
|
|
3461
|
-
)
|
|
3372
|
+
if simulation_setup.generate_solder_balls and not self.hfss.set_coax_port_attributes(
|
|
3373
|
+
simulation_setup
|
|
3374
|
+
): # pragma: no cover
|
|
3375
|
+
self.logger.error("Failed to configure coaxial port attributes.")
|
|
3376
|
+
self.logger.info("Number of ports: {}".format(self.hfss.get_ports_number()))
|
|
3377
|
+
self.logger.info("Configure HFSS extents.")
|
|
3378
|
+
if simulation_setup.generate_solder_balls and simulation_setup.trim_reference_size: # pragma: no cover
|
|
3379
|
+
self.logger.info(
|
|
3380
|
+
"Trimming the reference plane for coaxial ports: {0}".format(
|
|
3381
|
+
bool(simulation_setup.trim_reference_size)
|
|
3382
|
+
)
|
|
3383
|
+
)
|
|
3384
|
+
self.hfss.trim_component_reference_size(simulation_setup) # pragma: no cover
|
|
3385
|
+
self.hfss.configure_hfss_extents(simulation_setup)
|
|
3386
|
+
if not self.hfss.configure_hfss_analysis_setup(simulation_setup):
|
|
3387
|
+
self.logger.error("Failed to configure HFSS simulation setup.")
|
|
3388
|
+
if simulation_setup.solver_type == SolverType.SiwaveSYZ:
|
|
3389
|
+
if simulation_setup.generate_excitations:
|
|
3390
|
+
for cmp in simulation_setup.components:
|
|
3391
|
+
if isinstance(cmp, str): # keep legacy
|
|
3392
|
+
self.components.create_port_on_component(
|
|
3393
|
+
cmp,
|
|
3394
|
+
net_list=simulation_setup.signal_nets,
|
|
3395
|
+
do_pingroup=simulation_setup.do_pingroup,
|
|
3396
|
+
reference_net=simulation_setup.power_nets,
|
|
3397
|
+
port_type=SourceType.CircPort,
|
|
3462
3398
|
)
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
if not self.hfss.configure_hfss_analysis_setup(simulation_setup):
|
|
3466
|
-
self.logger.error("Failed to configure HFSS simulation setup.")
|
|
3467
|
-
if simulation_setup.solver_type == SolverType.SiwaveSYZ:
|
|
3468
|
-
if simulation_setup.generate_excitations:
|
|
3469
|
-
for cmp in simulation_setup.components:
|
|
3470
|
-
if isinstance(cmp, str): # keep legacy
|
|
3399
|
+
elif isinstance(cmp, dict):
|
|
3400
|
+
if "refdes" in cmp: # pragma no cover
|
|
3471
3401
|
self.components.create_port_on_component(
|
|
3472
|
-
cmp,
|
|
3402
|
+
cmp["refdes"],
|
|
3473
3403
|
net_list=simulation_setup.signal_nets,
|
|
3474
3404
|
do_pingroup=simulation_setup.do_pingroup,
|
|
3475
3405
|
reference_net=simulation_setup.power_nets,
|
|
3476
3406
|
port_type=SourceType.CircPort,
|
|
3477
3407
|
)
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover
|
|
3494
|
-
self.logger.error("Failed to configure Siwave simulation setup.")
|
|
3495
|
-
self.padstacks.check_and_fix_via_plating()
|
|
3496
|
-
self.save_edb()
|
|
3497
|
-
if not simulation_setup.open_edb_after_build and simulation_setup.output_aedb:
|
|
3498
|
-
self.close_edb()
|
|
3499
|
-
self.edbpath = legacy_name
|
|
3500
|
-
self.open_edb()
|
|
3501
|
-
return True
|
|
3502
|
-
except:
|
|
3503
|
-
return False
|
|
3408
|
+
self.logger.info("Configuring analysis setup.")
|
|
3409
|
+
if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover
|
|
3410
|
+
self.logger.error("Failed to configure Siwave simulation setup.")
|
|
3411
|
+
if simulation_setup.solver_type == SolverType.SiwaveDC:
|
|
3412
|
+
if simulation_setup.generate_excitations:
|
|
3413
|
+
self.components.create_source_on_component(simulation_setup.sources)
|
|
3414
|
+
if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover
|
|
3415
|
+
self.logger.error("Failed to configure Siwave simulation setup.")
|
|
3416
|
+
self.padstacks.check_and_fix_via_plating()
|
|
3417
|
+
self.save_edb()
|
|
3418
|
+
if not simulation_setup.open_edb_after_build and simulation_setup.output_aedb:
|
|
3419
|
+
self.close_edb()
|
|
3420
|
+
self.edbpath = legacy_name
|
|
3421
|
+
self.open_edb()
|
|
3422
|
+
return True
|
|
3504
3423
|
|
|
3505
3424
|
def get_statistics(self, compute_area=False):
|
|
3506
3425
|
"""Get the EDBStatistics object.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
#
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
from pyedb.dotnet.edb_core.cell.layout_obj import LayoutObj
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Connectable(LayoutObj):
|
|
27
|
+
"""Manages EDB functionalities for a connectable object."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, pedb, edb_object):
|
|
30
|
+
super().__init__(pedb, edb_object)
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def net(self):
|
|
34
|
+
"""Net Object.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
:class:`pyedb.dotnet.edb_core.edb_data.nets_data.EDBNetsData`
|
|
39
|
+
"""
|
|
40
|
+
from pyedb.dotnet.edb_core.edb_data.nets_data import EDBNetsData
|
|
41
|
+
|
|
42
|
+
return EDBNetsData(self._edb_object.GetNet(), self._pedb)
|
|
43
|
+
|
|
44
|
+
@net.setter
|
|
45
|
+
def net(self, value):
|
|
46
|
+
"""Set net."""
|
|
47
|
+
net = self._pedb.nets[value]
|
|
48
|
+
self._edb_object.SetNet(net.net_object)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def component(self):
|
|
52
|
+
"""Component connected to this object.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
:class:`dotnet.edb_core.edb_data.nets_data.EDBComponent`
|
|
57
|
+
"""
|
|
58
|
+
from pyedb.dotnet.edb_core.cell.hierarchy.component import EDBComponent
|
|
59
|
+
|
|
60
|
+
edb_comp = self._edb_object.GetComponent()
|
|
61
|
+
if edb_comp.IsNull():
|
|
62
|
+
return None
|
|
63
|
+
else:
|
|
64
|
+
return EDBComponent(self._pedb, edb_comp)
|
|
@@ -32,16 +32,14 @@ from pyedb.dotnet.edb_core.cell.hierarchy.s_parameter_model import SparamModel
|
|
|
32
32
|
from pyedb.dotnet.edb_core.cell.hierarchy.spice_model import SpiceModel
|
|
33
33
|
from pyedb.dotnet.edb_core.definition.package_def import PackageDef
|
|
34
34
|
from pyedb.dotnet.edb_core.edb_data.padstacks_data import EDBPadstackInstance
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"Install with \n\npip install numpy\n\nRequires CPython."
|
|
44
|
-
)
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
import numpy as np
|
|
38
|
+
except ImportError:
|
|
39
|
+
warnings.warn(
|
|
40
|
+
"The NumPy module is required to run some functionalities of EDB.\n"
|
|
41
|
+
"Install with \n\npip install numpy\n\nRequires CPython."
|
|
42
|
+
)
|
|
45
43
|
from pyedb.generic.general_methods import get_filename_without_extension
|
|
46
44
|
|
|
47
45
|
|
|
@@ -63,6 +61,10 @@ class EDBComponent(Group):
|
|
|
63
61
|
self._layout_instance = None
|
|
64
62
|
self._comp_instance = None
|
|
65
63
|
|
|
64
|
+
@property
|
|
65
|
+
def group_type(self):
|
|
66
|
+
return self._edb_object.ToString().split(".")[-1].lower()
|
|
67
|
+
|
|
66
68
|
@property
|
|
67
69
|
def layout_instance(self):
|
|
68
70
|
"""EDB layout instance object."""
|