pyedb 0.18.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/configuration/cfg_data.py +8 -11
- pyedb/configuration/cfg_nets.py +14 -0
- pyedb/configuration/cfg_pin_groups.py +57 -20
- pyedb/configuration/cfg_ports_sources.py +248 -60
- pyedb/configuration/configuration.py +51 -17
- pyedb/dotnet/edb.py +156 -236
- 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 +271 -76
- 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 +10 -0
- pyedb/dotnet/edb_core/cell/terminal/pingroup_terminal.py +5 -0
- pyedb/dotnet/edb_core/cell/terminal/point_terminal.py +1 -12
- pyedb/dotnet/edb_core/cell/terminal/terminal.py +36 -20
- pyedb/dotnet/edb_core/cell/voltage_regulator.py +2 -16
- pyedb/dotnet/edb_core/components.py +88 -31
- pyedb/dotnet/edb_core/dotnet/database.py +5 -10
- pyedb/dotnet/edb_core/dotnet/primitive.py +20 -7
- pyedb/dotnet/edb_core/edb_data/control_file.py +2 -12
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +28 -37
- pyedb/dotnet/edb_core/edb_data/ports.py +0 -18
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +1 -1
- 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 +23 -10
- pyedb/dotnet/edb_core/sim_setup_data/data/sim_setup_info.py +42 -3
- pyedb/dotnet/edb_core/sim_setup_data/data/simulation_settings.py +92 -158
- pyedb/dotnet/edb_core/sim_setup_data/data/siw_dc_ir_settings.py +22 -22
- pyedb/dotnet/edb_core/sim_setup_data/data/sweep_data.py +5 -2
- pyedb/dotnet/edb_core/sim_setup_data/io/siwave.py +76 -76
- pyedb/dotnet/edb_core/siwave.py +5 -6
- pyedb/dotnet/edb_core/stackup.py +18 -23
- pyedb/dotnet/edb_core/utilities/hfss_simulation_setup.py +23 -94
- pyedb/dotnet/edb_core/utilities/simulation_setup.py +40 -41
- pyedb/dotnet/edb_core/utilities/siwave_simulation_setup.py +26 -17
- 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.18.0.dist-info → pyedb-0.20.0.dist-info}/METADATA +8 -8
- {pyedb-0.18.0.dist-info → pyedb-0.20.0.dist-info}/RECORD +53 -52
- pyedb/dotnet/edb_core/dotnet/layout.py +0 -260
- {pyedb-0.18.0.dist-info → pyedb-0.20.0.dist-info}/LICENSE +0 -0
- {pyedb-0.18.0.dist-info → pyedb-0.20.0.dist-info}/WHEEL +0 -0
|
@@ -65,14 +65,16 @@ class Configuration:
|
|
|
65
65
|
"""
|
|
66
66
|
if isinstance(config_file, dict):
|
|
67
67
|
data = config_file
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
else:
|
|
69
|
+
config_file = str(config_file)
|
|
70
|
+
if os.path.isfile(config_file):
|
|
71
|
+
with open(config_file, "r") as f:
|
|
72
|
+
if config_file.endswith(".json"):
|
|
73
|
+
data = json.load(f)
|
|
74
|
+
elif config_file.endswith(".toml"):
|
|
75
|
+
data = toml.load(f)
|
|
76
|
+
else: # pragma: no cover
|
|
77
|
+
return False
|
|
76
78
|
|
|
77
79
|
if not append: # pragma: no cover
|
|
78
80
|
self.data = {}
|
|
@@ -120,16 +122,13 @@ class Configuration:
|
|
|
120
122
|
self.cfg_data.padstacks.apply()
|
|
121
123
|
|
|
122
124
|
# Configure pin groups
|
|
123
|
-
|
|
124
|
-
pin_group.apply()
|
|
125
|
+
self.cfg_data.pin_groups.apply()
|
|
125
126
|
|
|
126
127
|
# Configure ports
|
|
127
|
-
|
|
128
|
-
port.create()
|
|
128
|
+
self.cfg_data.ports.apply()
|
|
129
129
|
|
|
130
130
|
# Configure sources
|
|
131
|
-
|
|
132
|
-
source.create()
|
|
131
|
+
self.cfg_data.sources.apply()
|
|
133
132
|
|
|
134
133
|
# Configure setup
|
|
135
134
|
self.cfg_data.setups.apply()
|
|
@@ -271,12 +270,30 @@ class Configuration:
|
|
|
271
270
|
data["package_definitions"] = self.cfg_data.package_definitions.get_data_from_db()
|
|
272
271
|
if kwargs.get("setups", False):
|
|
273
272
|
data["setups"] = self.cfg_data.setups.get_data_from_db()
|
|
273
|
+
if kwargs.get("sources", False):
|
|
274
|
+
data["sources"] = self.cfg_data.sources.get_data_from_db()
|
|
275
|
+
if kwargs.get("ports", False):
|
|
276
|
+
data["ports"] = self.cfg_data.ports.get_data_from_db()
|
|
274
277
|
if kwargs.get("components", False):
|
|
275
278
|
data["components"] = self.cfg_data.components.get_data_from_db()
|
|
279
|
+
if kwargs.get("nets", False):
|
|
280
|
+
data["nets"] = self.cfg_data.nets.get_data_from_db()
|
|
281
|
+
if kwargs.get("pin_groups", False):
|
|
282
|
+
data["pin_groups"] = self.cfg_data.pin_groups.get_data_from_db()
|
|
276
283
|
|
|
277
284
|
return data
|
|
278
285
|
|
|
279
|
-
def export(
|
|
286
|
+
def export(
|
|
287
|
+
self,
|
|
288
|
+
file_path,
|
|
289
|
+
stackup=True,
|
|
290
|
+
package_definitions=True,
|
|
291
|
+
setups=True,
|
|
292
|
+
sources=True,
|
|
293
|
+
ports=True,
|
|
294
|
+
nets=True,
|
|
295
|
+
pin_groups=True,
|
|
296
|
+
):
|
|
280
297
|
"""Export the configuration data from layout to a file.
|
|
281
298
|
|
|
282
299
|
Parameters
|
|
@@ -285,14 +302,31 @@ class Configuration:
|
|
|
285
302
|
File path to export the configuration data.
|
|
286
303
|
stackup : bool
|
|
287
304
|
Whether to export stackup or not.
|
|
288
|
-
|
|
305
|
+
package_definitions : bool
|
|
306
|
+
Whether to export package definitions or not.
|
|
307
|
+
setups : bool
|
|
308
|
+
Whether to export setups or not.
|
|
309
|
+
sources : bool
|
|
310
|
+
Whether to export sources or not.
|
|
311
|
+
ports : bool
|
|
312
|
+
Whether to export ports or not.
|
|
313
|
+
nets : bool
|
|
314
|
+
Whether to export nets.
|
|
289
315
|
Returns
|
|
290
316
|
-------
|
|
291
317
|
bool
|
|
292
318
|
"""
|
|
293
319
|
file_path = file_path if isinstance(file_path, Path) else Path(file_path)
|
|
294
320
|
file_path = file_path if file_path.suffix == ".json" else file_path.with_suffix(".json")
|
|
295
|
-
data = self.get_data_from_db(
|
|
321
|
+
data = self.get_data_from_db(
|
|
322
|
+
stackup=stackup,
|
|
323
|
+
package_definitions=package_definitions,
|
|
324
|
+
setups=setups,
|
|
325
|
+
sources=sources,
|
|
326
|
+
ports=ports,
|
|
327
|
+
nets=nets,
|
|
328
|
+
pin_groups=pin_groups,
|
|
329
|
+
)
|
|
296
330
|
with open(file_path, "w") as f:
|
|
297
331
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
|
298
332
|
return True if os.path.isfile(file_path) else False
|
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):
|
|
@@ -510,12 +481,13 @@ class Edb(Database):
|
|
|
510
481
|
def sources(self):
|
|
511
482
|
"""Get all layout sources."""
|
|
512
483
|
terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [3, 4, 7]]
|
|
484
|
+
terms = [term for term in terms if not term.IsReferenceTerminal()]
|
|
513
485
|
return {ter.GetName(): ExcitationSources(self, ter) for ter in terms}
|
|
514
486
|
|
|
515
487
|
@property
|
|
516
488
|
def voltage_regulator_modules(self):
|
|
517
489
|
"""Get all voltage regulator modules"""
|
|
518
|
-
vrms =
|
|
490
|
+
vrms = self.layout.voltage_regulators
|
|
519
491
|
_vrms = {}
|
|
520
492
|
for vrm in vrms:
|
|
521
493
|
_vrms[vrm.name] = vrm
|
|
@@ -573,40 +545,6 @@ class Edb(Database):
|
|
|
573
545
|
|
|
574
546
|
return True
|
|
575
547
|
|
|
576
|
-
def open_edb_inside_aedt(self):
|
|
577
|
-
"""Open EDB inside AEDT.
|
|
578
|
-
|
|
579
|
-
Returns
|
|
580
|
-
-------
|
|
581
|
-
``True`` when succeed ``False`` if failed : bool
|
|
582
|
-
|
|
583
|
-
"""
|
|
584
|
-
self.logger.info("Opening EDB from HDL")
|
|
585
|
-
self.run_as_standalone(False)
|
|
586
|
-
if self.oproject.GetEDBHandle():
|
|
587
|
-
self.attach(self.oproject.GetEDBHandle())
|
|
588
|
-
if not self.active_db:
|
|
589
|
-
self.logger.warning("Error getting the database.")
|
|
590
|
-
self._active_cell = None
|
|
591
|
-
return None
|
|
592
|
-
self._active_cell = self.edb_api.cell.cell.FindByName(
|
|
593
|
-
self.active_db,
|
|
594
|
-
self.edb_api.cell._cell.CellType.CircuitCell,
|
|
595
|
-
self.cellname,
|
|
596
|
-
)
|
|
597
|
-
if self._active_cell is None:
|
|
598
|
-
self._active_cell = list(self.top_circuit_cells)[0]
|
|
599
|
-
if self._active_cell:
|
|
600
|
-
if not os.path.exists(self.edbpath):
|
|
601
|
-
os.makedirs(self.edbpath)
|
|
602
|
-
self._init_objects()
|
|
603
|
-
return True
|
|
604
|
-
else:
|
|
605
|
-
return None
|
|
606
|
-
else:
|
|
607
|
-
self._active_cell = None
|
|
608
|
-
return None
|
|
609
|
-
|
|
610
548
|
def create_edb(self):
|
|
611
549
|
"""Create EDB.
|
|
612
550
|
|
|
@@ -1152,7 +1090,7 @@ class Edb(Database):
|
|
|
1152
1090
|
>>> top_prims = edbapp.modeler.primitives_by_layer["TOP"]
|
|
1153
1091
|
"""
|
|
1154
1092
|
if not self._core_primitives and self.active_db:
|
|
1155
|
-
self._core_primitives =
|
|
1093
|
+
self._core_primitives = Modeler(self)
|
|
1156
1094
|
return self._core_primitives
|
|
1157
1095
|
|
|
1158
1096
|
@property
|
|
@@ -1163,7 +1101,7 @@ class Edb(Database):
|
|
|
1163
1101
|
-------
|
|
1164
1102
|
:class:`legacy.edb_core.dotnet.layout.Layout`
|
|
1165
1103
|
"""
|
|
1166
|
-
return
|
|
1104
|
+
return Layout(self, self._active_cell.GetLayout())
|
|
1167
1105
|
|
|
1168
1106
|
@property
|
|
1169
1107
|
def active_layout(self):
|
|
@@ -1173,12 +1111,12 @@ class Edb(Database):
|
|
|
1173
1111
|
-------
|
|
1174
1112
|
Instance of EDB API Layout Class.
|
|
1175
1113
|
"""
|
|
1176
|
-
return self.layout.
|
|
1114
|
+
return self.layout._edb_object
|
|
1177
1115
|
|
|
1178
1116
|
@property
|
|
1179
1117
|
def layout_instance(self):
|
|
1180
1118
|
"""Edb Layout Instance."""
|
|
1181
|
-
return self.layout.
|
|
1119
|
+
return self.layout._edb_object.GetLayoutInstance()
|
|
1182
1120
|
|
|
1183
1121
|
def get_connected_objects(self, layout_object_instance):
|
|
1184
1122
|
"""Get connected objects.
|
|
@@ -2217,9 +2155,6 @@ class Edb(Database):
|
|
|
2217
2155
|
keep_lines_as_path=False,
|
|
2218
2156
|
inlcude_voids_in_extents=False,
|
|
2219
2157
|
):
|
|
2220
|
-
if is_ironpython: # pragma: no cover
|
|
2221
|
-
self.logger.error("Method working only in Cpython")
|
|
2222
|
-
return False
|
|
2223
2158
|
from concurrent.futures import ThreadPoolExecutor
|
|
2224
2159
|
|
|
2225
2160
|
if output_aedb_path:
|
|
@@ -2749,20 +2684,12 @@ class Edb(Database):
|
|
|
2749
2684
|
|
|
2750
2685
|
for void_circle in voids_to_add:
|
|
2751
2686
|
if void_circle.type == "Circle":
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
) = void_circle.primitive_object.GetParameters()
|
|
2759
|
-
else:
|
|
2760
|
-
(
|
|
2761
|
-
res,
|
|
2762
|
-
center_x,
|
|
2763
|
-
center_y,
|
|
2764
|
-
radius,
|
|
2765
|
-
) = 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)
|
|
2766
2693
|
cloned_circle = self.edb_api.cell.primitive.circle.create(
|
|
2767
2694
|
layout,
|
|
2768
2695
|
void_circle.layer_name,
|
|
@@ -3343,163 +3270,156 @@ class Edb(Database):
|
|
|
3343
3270
|
legacy_name = self.edbpath
|
|
3344
3271
|
if simulation_setup.output_aedb:
|
|
3345
3272
|
self.save_edb_as(simulation_setup.output_aedb)
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
for
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
):
|
|
3381
|
-
self.logger.info("Cutout processed.")
|
|
3382
|
-
old_cell = self.active_cell.FindByName(
|
|
3383
|
-
self.db,
|
|
3384
|
-
self.edb_api.cell.CellType.CircuitCell,
|
|
3385
|
-
old_cell_name,
|
|
3386
|
-
)
|
|
3387
|
-
if old_cell:
|
|
3388
|
-
old_cell.Delete()
|
|
3389
|
-
else: # pragma: no cover
|
|
3390
|
-
self.logger.error("Cutout failed.")
|
|
3391
|
-
else:
|
|
3392
|
-
self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type))
|
|
3393
|
-
self.cutout(
|
|
3394
|
-
signal_list=simulation_setup.signal_nets,
|
|
3395
|
-
reference_list=simulation_setup.power_nets,
|
|
3396
|
-
expansion_size=simulation_setup.cutout_subdesign_expansion,
|
|
3397
|
-
use_round_corner=simulation_setup.cutout_subdesign_round_corner,
|
|
3398
|
-
extent_type=simulation_setup.cutout_subdesign_type,
|
|
3399
|
-
use_pyaedt_cutout=True,
|
|
3400
|
-
use_pyaedt_extent_computing=True,
|
|
3401
|
-
remove_single_pin_components=True,
|
|
3402
|
-
)
|
|
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
|
+
):
|
|
3403
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.")
|
|
3404
3317
|
else:
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
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
|
|
3422
3362
|
self.components.create_port_on_component(
|
|
3423
|
-
cmp,
|
|
3363
|
+
cmp["refdes"],
|
|
3424
3364
|
net_list=simulation_setup.signal_nets,
|
|
3425
3365
|
do_pingroup=False,
|
|
3426
3366
|
reference_net=simulation_setup.power_nets,
|
|
3427
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"],
|
|
3428
3371
|
)
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
if
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
simulation_setup.generate_solder_balls and simulation_setup.trim_reference_size
|
|
3456
|
-
): # pragma: no cover
|
|
3457
|
-
self.logger.info(
|
|
3458
|
-
"Trimming the reference plane for coaxial ports: {0}".format(
|
|
3459
|
-
bool(simulation_setup.trim_reference_size)
|
|
3460
|
-
)
|
|
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,
|
|
3461
3398
|
)
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
if not self.hfss.configure_hfss_analysis_setup(simulation_setup):
|
|
3465
|
-
self.logger.error("Failed to configure HFSS simulation setup.")
|
|
3466
|
-
if simulation_setup.solver_type == SolverType.SiwaveSYZ:
|
|
3467
|
-
if simulation_setup.generate_excitations:
|
|
3468
|
-
for cmp in simulation_setup.components:
|
|
3469
|
-
if isinstance(cmp, str): # keep legacy
|
|
3399
|
+
elif isinstance(cmp, dict):
|
|
3400
|
+
if "refdes" in cmp: # pragma no cover
|
|
3470
3401
|
self.components.create_port_on_component(
|
|
3471
|
-
cmp,
|
|
3402
|
+
cmp["refdes"],
|
|
3472
3403
|
net_list=simulation_setup.signal_nets,
|
|
3473
3404
|
do_pingroup=simulation_setup.do_pingroup,
|
|
3474
3405
|
reference_net=simulation_setup.power_nets,
|
|
3475
3406
|
port_type=SourceType.CircPort,
|
|
3476
3407
|
)
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover
|
|
3493
|
-
self.logger.error("Failed to configure Siwave simulation setup.")
|
|
3494
|
-
self.padstacks.check_and_fix_via_plating()
|
|
3495
|
-
self.save_edb()
|
|
3496
|
-
if not simulation_setup.open_edb_after_build and simulation_setup.output_aedb:
|
|
3497
|
-
self.close_edb()
|
|
3498
|
-
self.edbpath = legacy_name
|
|
3499
|
-
self.open_edb()
|
|
3500
|
-
return True
|
|
3501
|
-
except:
|
|
3502
|
-
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
|
|
3503
3423
|
|
|
3504
3424
|
def get_statistics(self, compute_area=False):
|
|
3505
3425
|
"""Get the EDBStatistics object.
|
|
@@ -3743,7 +3663,7 @@ class Edb(Database):
|
|
|
3743
3663
|
if float(self.edbversion) < 2024.2:
|
|
3744
3664
|
self.logger.error("HFSSPI simulation only supported with Ansys release 2024R2 and higher")
|
|
3745
3665
|
return False
|
|
3746
|
-
return HFSSPISimulationSetup(self
|
|
3666
|
+
return HFSSPISimulationSetup(self, name=name)
|
|
3747
3667
|
|
|
3748
3668
|
def create_siwave_syz_setup(self, name=None, **kwargs):
|
|
3749
3669
|
"""Create a setup from a template.
|