pyedb 0.50.1__py3-none-any.whl → 0.52.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 +79 -239
- pyedb/configuration/configuration.py +213 -340
- pyedb/dotnet/clr_module.py +9 -3
- pyedb/dotnet/database/cell/layout.py +10 -1
- pyedb/dotnet/database/dotnet/database.py +0 -2
- pyedb/dotnet/database/edb_data/padstacks_data.py +8 -2
- pyedb/dotnet/database/layout_validation.py +20 -26
- pyedb/dotnet/database/modeler.py +0 -1
- pyedb/dotnet/database/stackup.py +4 -3
- pyedb/dotnet/edb.py +42 -2
- pyedb/generic/design_types.py +183 -62
- pyedb/grpc/database/__init__.py +0 -1
- pyedb/grpc/database/components.py +110 -0
- pyedb/grpc/database/control_file.py +150 -17
- pyedb/grpc/database/definition/materials.py +7 -7
- pyedb/grpc/database/definitions.py +36 -2
- pyedb/grpc/database/hfss.py +15 -0
- pyedb/grpc/database/hierarchy/component.py +10 -2
- pyedb/grpc/database/hierarchy/pin_pair_model.py +1 -1
- pyedb/grpc/database/layout_validation.py +58 -7
- pyedb/grpc/database/net/differential_pair.py +2 -1
- pyedb/grpc/database/nets.py +233 -4
- pyedb/grpc/database/padstacks.py +97 -0
- pyedb/grpc/database/primitive/padstack_instance.py +1 -1
- pyedb/grpc/database/primitive/polygon.py +1 -1
- pyedb/grpc/database/siwave.py +63 -3
- pyedb/grpc/database/source_excitations.py +317 -50
- pyedb/grpc/database/stackup.py +107 -2
- pyedb/grpc/database/terminal/point_terminal.py +2 -2
- pyedb/grpc/database/terminal/terminal.py +1 -1
- pyedb/grpc/edb.py +190 -224
- pyedb/grpc/edb_init.py +54 -5
- {pyedb-0.50.1.dist-info → pyedb-0.52.0.dist-info}/METADATA +4 -4
- {pyedb-0.50.1.dist-info → pyedb-0.52.0.dist-info}/RECORD +37 -37
- {pyedb-0.50.1.dist-info → pyedb-0.52.0.dist-info}/LICENSE +0 -0
- {pyedb-0.50.1.dist-info → pyedb-0.52.0.dist-info}/WHEEL +0 -0
|
@@ -80,6 +80,7 @@ def primitive_cast(pedb, edb_object):
|
|
|
80
80
|
class Layout(ObjBase):
|
|
81
81
|
def __init__(self, pedb, edb_object):
|
|
82
82
|
super().__init__(pedb, edb_object)
|
|
83
|
+
self._primitives = []
|
|
83
84
|
|
|
84
85
|
@property
|
|
85
86
|
def cell(self):
|
|
@@ -230,7 +231,15 @@ class Layout(ObjBase):
|
|
|
230
231
|
-------
|
|
231
232
|
list of :class:`dotnet.database.dotnet.primitive.PrimitiveDotNet` cast objects.
|
|
232
233
|
"""
|
|
233
|
-
|
|
234
|
+
primitives = list(self._edb_object.Primitives)
|
|
235
|
+
if len(primitives) != len(self._primitives):
|
|
236
|
+
self._primitives = [primitive_cast(self._pedb, p) for p in primitives]
|
|
237
|
+
return self._primitives
|
|
238
|
+
|
|
239
|
+
@property
|
|
240
|
+
def primitives_by_aedt_name(self) -> dict:
|
|
241
|
+
"""Primitives."""
|
|
242
|
+
return {i.aedt_name: i for i in self.primitives}
|
|
234
243
|
|
|
235
244
|
@property
|
|
236
245
|
def bondwires(self):
|
|
@@ -27,7 +27,6 @@ import sys
|
|
|
27
27
|
|
|
28
28
|
from pyedb import __version__
|
|
29
29
|
from pyedb.dotnet.database.general import convert_py_list_to_net_list
|
|
30
|
-
from pyedb.edb_logger import pyedb_logger
|
|
31
30
|
from pyedb.generic.general_methods import (
|
|
32
31
|
env_path,
|
|
33
32
|
env_path_student,
|
|
@@ -704,7 +703,6 @@ class EdbDotNet(object):
|
|
|
704
703
|
"""Edb Dot Net Class."""
|
|
705
704
|
|
|
706
705
|
def __init__(self, edbversion, student_version=False):
|
|
707
|
-
self._logger = pyedb_logger
|
|
708
706
|
if not edbversion: # pragma: no cover
|
|
709
707
|
try:
|
|
710
708
|
edbversion = "20{}.{}".format(list_installed_ansysem()[0][-3:-1], list_installed_ansysem()[0][-1:])
|
|
@@ -1807,8 +1807,14 @@ class EDBPadstackInstance(Primitive):
|
|
|
1807
1807
|
|
|
1808
1808
|
val = String("")
|
|
1809
1809
|
_, name = self._edb_padstackinstance.GetProductProperty(self._pedb.edb_api.ProductId.Designer, 11, val)
|
|
1810
|
-
|
|
1811
|
-
|
|
1810
|
+
aedt_name = str(name).strip("'")
|
|
1811
|
+
if aedt_name == "":
|
|
1812
|
+
if self.is_pin and self.component:
|
|
1813
|
+
aedt_name = f"{self.component.name}-{self.component_pin}"
|
|
1814
|
+
elif self.component_pin:
|
|
1815
|
+
aedt_name = self.component_pin
|
|
1816
|
+
self.aedt_name = aedt_name
|
|
1817
|
+
return aedt_name
|
|
1812
1818
|
|
|
1813
1819
|
@aedt_name.setter
|
|
1814
1820
|
def aedt_name(self, value):
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
|
|
23
23
|
import re
|
|
24
24
|
|
|
25
|
-
from pyedb.dotnet.clr_module import String
|
|
26
25
|
from pyedb.dotnet.database.edb_data.padstacks_data import EDBPadstackInstance
|
|
27
26
|
from pyedb.dotnet.database.edb_data.primitives_data import Primitive
|
|
28
27
|
from pyedb.generic.general_methods import generate_unique_name
|
|
@@ -304,38 +303,33 @@ class LayoutValidation:
|
|
|
304
303
|
|
|
305
304
|
def illegal_rlc_values(self, fix=False):
|
|
306
305
|
"""Find and fix RLC illegal values."""
|
|
307
|
-
inductors = self._pedb.components.inductors
|
|
308
306
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
307
|
+
for name, objs in {
|
|
308
|
+
"inductors": self._pedb.components.inductors,
|
|
309
|
+
"resistors": self._pedb.components.resistors,
|
|
310
|
+
"capacitors": self._pedb.components.capacitors,
|
|
311
|
+
}.items():
|
|
312
|
+
temp = []
|
|
313
|
+
for k, v in objs.items():
|
|
314
|
+
componentProperty = v.edbcomponent.GetComponentProperty()
|
|
315
|
+
model = componentProperty.GetModel().Clone()
|
|
316
|
+
pinpairs = model.PinPairs
|
|
317
|
+
|
|
318
|
+
if not len(list(pinpairs)): # pragma: no cover
|
|
319
|
+
temp.append(k)
|
|
320
|
+
if fix:
|
|
321
|
+
v.rlc_values = [0, 1, 0]
|
|
322
|
+
|
|
323
|
+
self._pedb._logger.info(f"Found {len(temp)} {name} have no value.")
|
|
321
324
|
return
|
|
322
325
|
|
|
323
326
|
def padstacks_no_name(self, fix=False):
|
|
327
|
+
"""Find and fix padstacks without aedt_name."""
|
|
324
328
|
pds = self._pedb.layout.padstack_instances
|
|
325
329
|
counts = 0
|
|
326
|
-
via_count = 1
|
|
327
330
|
for obj in pds:
|
|
328
|
-
|
|
329
|
-
_, name = obj._edb_object.GetProductProperty(self._pedb.edb_api.ProductId.Designer, 11, val)
|
|
330
|
-
name = str(name).strip("'")
|
|
331
|
-
if name == "":
|
|
331
|
+
if obj.aedt_name == "":
|
|
332
332
|
counts += 1
|
|
333
333
|
if fix:
|
|
334
|
-
|
|
335
|
-
obj._edb_object.SetProductProperty(self._pedb.edb_api.ProductId.Designer, 11, f"Via{via_count}")
|
|
336
|
-
via_count = via_count + 1
|
|
337
|
-
else:
|
|
338
|
-
obj._edb_object.SetProductProperty(
|
|
339
|
-
self._pedb.edb_api.ProductId.Designer, 11, f"{obj.component.name}-{obj.component_pin}"
|
|
340
|
-
)
|
|
334
|
+
obj.aedt_name = f"via_{obj.id}"
|
|
341
335
|
self._pedb._logger.info(f"Found {counts}/{len(pds)} padstacks have no name.")
|
pyedb/dotnet/database/modeler.py
CHANGED
pyedb/dotnet/database/stackup.py
CHANGED
|
@@ -2234,7 +2234,7 @@ class Stackup(LayerCollection):
|
|
|
2234
2234
|
material.loss_tanget = material_properties["DielectricLossTangent"]
|
|
2235
2235
|
return True
|
|
2236
2236
|
|
|
2237
|
-
def _import_xml(self, file_path
|
|
2237
|
+
def _import_xml(self, file_path):
|
|
2238
2238
|
"""Read external xml file and convert into json file.
|
|
2239
2239
|
You can use xml file to import layer stackup but using json file is recommended.
|
|
2240
2240
|
see :class:`pyedb.dotnet.database.edb_data.simulation_configuration.SimulationConfiguration´ class to
|
|
@@ -2304,7 +2304,8 @@ class Stackup(LayerCollection):
|
|
|
2304
2304
|
layers.append(layer)
|
|
2305
2305
|
stackup_dict["layers"] = layers
|
|
2306
2306
|
cfg = {"stackup": stackup_dict}
|
|
2307
|
-
|
|
2307
|
+
self._pedb.configuration.load(cfg)
|
|
2308
|
+
return self._pedb.configuration.run()
|
|
2308
2309
|
|
|
2309
2310
|
def _export_xml(self, file_path):
|
|
2310
2311
|
"""Export stackup information to an external XMLfile.
|
|
@@ -2391,7 +2392,7 @@ class Stackup(LayerCollection):
|
|
|
2391
2392
|
elif file_path.endswith(".json"):
|
|
2392
2393
|
return self._import_json(file_path, rename=rename)
|
|
2393
2394
|
elif file_path.endswith(".xml"):
|
|
2394
|
-
return self._import_xml(file_path
|
|
2395
|
+
return self._import_xml(file_path)
|
|
2395
2396
|
else:
|
|
2396
2397
|
return False
|
|
2397
2398
|
|
pyedb/dotnet/edb.py
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
This module is implicitly loaded in HFSS 3D Layout when launched.
|
|
26
26
|
|
|
27
27
|
"""
|
|
28
|
+
from datetime import datetime
|
|
28
29
|
from itertools import combinations
|
|
29
30
|
import os
|
|
30
31
|
from pathlib import Path
|
|
@@ -91,6 +92,7 @@ from pyedb.dotnet.database.utilities.siwave_simulation_setup import (
|
|
|
91
92
|
SiwaveDCSimulationSetup,
|
|
92
93
|
SiwaveSimulationSetup,
|
|
93
94
|
)
|
|
95
|
+
from pyedb.edb_logger import pyedb_logger
|
|
94
96
|
from pyedb.generic.constants import AEDT_UNITS, SolverType, unit_converter
|
|
95
97
|
from pyedb.generic.general_methods import (
|
|
96
98
|
generate_unique_name,
|
|
@@ -195,6 +197,10 @@ class Edb(Database):
|
|
|
195
197
|
layer_filter: str = None,
|
|
196
198
|
remove_existing_aedt: bool = False,
|
|
197
199
|
):
|
|
200
|
+
self._logger = pyedb_logger
|
|
201
|
+
now = datetime.now()
|
|
202
|
+
self.logger.info(f"Star initializing Edb {now.time()}")
|
|
203
|
+
|
|
198
204
|
if isinstance(edbpath, Path):
|
|
199
205
|
edbpath = str(edbpath)
|
|
200
206
|
|
|
@@ -290,7 +296,7 @@ class Edb(Database):
|
|
|
290
296
|
self._logger.add_file_logger(self.log_name, "Edb")
|
|
291
297
|
self.open_edb()
|
|
292
298
|
if self.active_cell:
|
|
293
|
-
self.logger.info("EDB initialized.")
|
|
299
|
+
self.logger.info(f"EDB initialized.Time lapse {datetime.now() - now}")
|
|
294
300
|
else:
|
|
295
301
|
raise AttributeError("Failed to initialize DLLs.")
|
|
296
302
|
|
|
@@ -1232,7 +1238,7 @@ class Edb(Database):
|
|
|
1232
1238
|
return self._core_primitives
|
|
1233
1239
|
|
|
1234
1240
|
@property
|
|
1235
|
-
def layout(self):
|
|
1241
|
+
def layout(self) -> Layout:
|
|
1236
1242
|
"""Layout object.
|
|
1237
1243
|
|
|
1238
1244
|
Returns
|
|
@@ -4729,3 +4735,37 @@ class Edb(Database):
|
|
|
4729
4735
|
return self.variables[variable_name]
|
|
4730
4736
|
else:
|
|
4731
4737
|
return False
|
|
4738
|
+
|
|
4739
|
+
def compare(self, input_file, results=""):
|
|
4740
|
+
"""Compares current open database with another one.
|
|
4741
|
+
|
|
4742
|
+
Parameters
|
|
4743
|
+
----------
|
|
4744
|
+
input_file : str
|
|
4745
|
+
Path to the edb file.
|
|
4746
|
+
results: str, optional
|
|
4747
|
+
Path to directory in which results will be saved. If no path is given, a new "_compare_results"
|
|
4748
|
+
directory will be created with the same naming and path as the .aedb folder.
|
|
4749
|
+
Returns
|
|
4750
|
+
-------
|
|
4751
|
+
bool
|
|
4752
|
+
``True`` when successful, ``False`` when failed.
|
|
4753
|
+
"""
|
|
4754
|
+
self.save()
|
|
4755
|
+
if not results:
|
|
4756
|
+
results = self.edbpath[:-5] + "_compare_results"
|
|
4757
|
+
os.mkdir(results)
|
|
4758
|
+
command = os.path.join(self.base_path, "EDBDiff.exe")
|
|
4759
|
+
if is_linux:
|
|
4760
|
+
mono_path = os.path.join(self.base_path, "common/mono/Linux64/bin/mono")
|
|
4761
|
+
cmd_input = [mono_path, command, input_file, self.edbpath, results]
|
|
4762
|
+
else:
|
|
4763
|
+
cmd_input = [command, input_file, self.edbpath, results]
|
|
4764
|
+
subprocess.run(cmd_input)
|
|
4765
|
+
|
|
4766
|
+
if not os.path.exists(os.path.join(results, "EDBDiff.csv")):
|
|
4767
|
+
self.logger.error("Comparison execution failed")
|
|
4768
|
+
return False
|
|
4769
|
+
else:
|
|
4770
|
+
self.logger.info("Comparison correctly completed")
|
|
4771
|
+
return True
|
pyedb/generic/design_types.py
CHANGED
|
@@ -37,79 +37,200 @@ def Edb(
|
|
|
37
37
|
):
|
|
38
38
|
"""Provides the EDB application interface.
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
40
|
+
This module inherits all objects that belong to EDB.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
edbpath : str, optional
|
|
45
|
+
Full path to the ``aedb`` folder. The variable can also contain
|
|
46
|
+
the path to a layout to import. Allowed formats are BRD,
|
|
47
|
+
XML (IPC2581), GDS, and DXF. The default is ``None``.
|
|
48
|
+
For GDS import, the Ansys control file (also XML) should have the same
|
|
49
|
+
name as the GDS file. Only the file extension differs.
|
|
50
|
+
cellname : str, optional
|
|
51
|
+
Name of the cell to select. The default is ``None``.
|
|
52
|
+
isreadonly : bool, optional
|
|
53
|
+
Whether to open EBD in read-only mode when it is
|
|
54
|
+
owned by HFSS 3D Layout. The default is ``False``.
|
|
55
|
+
edbversion : str, optional
|
|
56
|
+
Version of EDB to use. The default is ``"2021.2"``.
|
|
57
|
+
isaedtowned : bool, optional
|
|
58
|
+
Whether to launch EDB from HFSS 3D Layout. The
|
|
59
|
+
default is ``False``.
|
|
60
|
+
oproject : optional
|
|
61
|
+
Reference to the AEDT project object.
|
|
62
|
+
student_version : bool, optional
|
|
63
|
+
Whether to open the AEDT student version. The default is ``False.``
|
|
64
|
+
technology_file : str, optional
|
|
65
|
+
Full path to technology file to be converted to xml before importing or xml. Supported by GDS format only.
|
|
66
|
+
grpc : bool, optional
|
|
67
|
+
Whether to enable gRPC. Default value is ``False``.
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
:class:`Edb <pyedb.dotnet.edb.Edb>` or :class:`Edb <pyedb.grpc.edb.Edb>`
|
|
72
|
+
|
|
73
|
+
Note
|
|
74
|
+
----
|
|
75
|
+
PyEDB gRPC will be released starting ANSYS release 2025R2. For legacy purpose, the gRPC will not be activated by
|
|
76
|
+
default. However, PyEDB gRPC will be the lon term supported version. The legacy PyEDB .NET will be deprecated
|
|
77
|
+
and at some point all new features will only be implemented in PyEDB gRPC. We highly encourage users moving to
|
|
78
|
+
gRPC starting release 2025R2, we tried keeping gRPC version backward compatible with legace .NET as much as
|
|
79
|
+
possible and only minor adjustments are required to be compatible.
|
|
80
|
+
|
|
81
|
+
Examples
|
|
82
|
+
--------
|
|
83
|
+
1. Creating and Opening an EDB Database
|
|
84
84
|
|
|
85
85
|
>>> from pyedb import Edb
|
|
86
|
-
>>> app = Edb()
|
|
87
86
|
|
|
88
|
-
|
|
87
|
+
# Create a new EDB instance
|
|
88
|
+
>>> edb = Edb()
|
|
89
|
+
|
|
90
|
+
# Open an existing AEDB database
|
|
91
|
+
>>> edb = Edb(edbpath="my_project.aedb")
|
|
92
|
+
|
|
93
|
+
# Import a board file (BRD, XML, GDS, etc.)
|
|
94
|
+
>>> edb = Edb(edbpath="my_board.brd")
|
|
95
|
+
|
|
96
|
+
2. Cutout Operation
|
|
97
|
+
|
|
98
|
+
# Simple cutout with signal and reference nets
|
|
99
|
+
>>> edb.cutout(
|
|
100
|
+
>>> signal_list=["PCIe", "USB"],
|
|
101
|
+
>>> reference_list=["GND"]
|
|
102
|
+
>>> )
|
|
103
|
+
|
|
104
|
+
# Advanced cutout with custom parameters
|
|
105
|
+
>>> edb.cutout(
|
|
106
|
+
>>> signal_list=["DDR"],
|
|
107
|
+
>>> reference_list=["GND"],
|
|
108
|
+
>>> extent_type="ConvexHull",
|
|
109
|
+
>>> expansion_size=0.002,
|
|
110
|
+
>>> use_round_corner=True,
|
|
111
|
+
>>> output_aedb_path="cutout.aedb",
|
|
112
|
+
>>> remove_single_pin_components=True
|
|
113
|
+
>>> )
|
|
114
|
+
|
|
115
|
+
3. Exporting Designs
|
|
116
|
+
|
|
117
|
+
# Export to IPC2581 format
|
|
118
|
+
>>> edb.export_to_ipc2581("output.xml", units="millimeter")
|
|
119
|
+
|
|
120
|
+
# Export to HFSS project
|
|
121
|
+
>>> edb.export_hfss("hfss_output")
|
|
122
|
+
|
|
123
|
+
# Export to Q3D project
|
|
124
|
+
>>> edb.export_q3d("q3d_output", net_list=["PowerNet"])
|
|
125
|
+
|
|
126
|
+
# Export to Maxwell project
|
|
127
|
+
>>> edb.export_maxwell("maxwell_output")
|
|
128
|
+
|
|
129
|
+
4. Simulation Setup
|
|
130
|
+
|
|
131
|
+
# Create SIwave SYZ setup
|
|
132
|
+
>>> syz_setup = edb.create_siwave_syz_setup(
|
|
133
|
+
>>> name="GHz_Setup",
|
|
134
|
+
>>> start_freq="1GHz",
|
|
135
|
+
>>> stop_freq="10GHz"
|
|
136
|
+
>>> )
|
|
137
|
+
|
|
138
|
+
# Create SIwave DC setup
|
|
139
|
+
>>> dc_setup = edb.create_siwave_dc_setup(
|
|
140
|
+
>>> name="DC_Analysis",
|
|
141
|
+
>>> use_dc_point=True
|
|
142
|
+
>>> )
|
|
143
|
+
|
|
144
|
+
# Solve with SIwave
|
|
145
|
+
>>> edb.solve_siwave()
|
|
146
|
+
|
|
147
|
+
5. Database Management
|
|
148
|
+
|
|
149
|
+
# Save database
|
|
150
|
+
>>> edb.save()
|
|
151
|
+
|
|
152
|
+
# Save as new database
|
|
153
|
+
>>> edb.save_as("new_project.aedb")
|
|
154
|
+
|
|
155
|
+
# Close database
|
|
156
|
+
>>> edb.close()
|
|
157
|
+
|
|
158
|
+
6. Stackup and Material Operations
|
|
159
|
+
|
|
160
|
+
# Access stackup layers
|
|
161
|
+
>>> for layer_name, layer in edb.stackup.layers.items():
|
|
162
|
+
>>> print(f"Layer: {layer_name}, Thickness: {layer.thickness}")
|
|
163
|
+
|
|
164
|
+
# Add new material
|
|
165
|
+
>>> edb.materials.add_material("MyMaterial", permittivity=4.3, loss_tangent=0.02)
|
|
166
|
+
|
|
167
|
+
# Change layer thickness
|
|
168
|
+
>>> edb.stackup["TopLayer"].thickness = "0.035mm"
|
|
169
|
+
|
|
170
|
+
7. Port Creation
|
|
171
|
+
|
|
172
|
+
# Create wave port between two pins
|
|
173
|
+
>>> wave_port = edb.source_excitation.create_port(
|
|
174
|
+
>>> positive_terminal=pin1,
|
|
175
|
+
>>> negative_terminal=pin2,
|
|
176
|
+
>>> port_type="Wave"
|
|
177
|
+
>>> )
|
|
178
|
+
|
|
179
|
+
# Create lumped port
|
|
180
|
+
>>> lumped_port = edb.source_excitation.create_port(
|
|
181
|
+
>>> positive_terminal=via_terminal,
|
|
182
|
+
>>> port_type="Lumped"
|
|
183
|
+
>>> )
|
|
184
|
+
|
|
185
|
+
8. Component Management
|
|
186
|
+
|
|
187
|
+
# Delete components by type
|
|
188
|
+
>>> edb.components.delete_component(["R1", "C2"])
|
|
189
|
+
|
|
190
|
+
# Set component properties
|
|
191
|
+
>>> edb.components["U1"].set_property("Value", "10nH")
|
|
192
|
+
|
|
193
|
+
9. Parametrization
|
|
194
|
+
|
|
195
|
+
# Auto-parametrize design elements
|
|
196
|
+
>>> params = edb.auto_parametrize_design(
|
|
197
|
+
>>> traces=True,
|
|
198
|
+
>>> pads=True,
|
|
199
|
+
>>> antipads=True,
|
|
200
|
+
>>> use_relative_variables=True
|
|
201
|
+
>>> )
|
|
202
|
+
>>> print("Created parameters:", params)
|
|
89
203
|
|
|
90
|
-
|
|
91
|
-
>>> app['s1'].tofloat
|
|
92
|
-
>>> 0.00025
|
|
93
|
-
>>> app['s1'].tostring
|
|
94
|
-
>>> "0.25mm"
|
|
204
|
+
10. Design Statistics
|
|
95
205
|
|
|
96
|
-
|
|
206
|
+
# Get layout statistics with area calculation
|
|
207
|
+
>>> stats = edb.get_statistics(compute_area=True)
|
|
208
|
+
>>> print(f"Total nets: {stats.net_count}")
|
|
209
|
+
>>> print(f"Total components: {stats.component_count}")
|
|
97
210
|
|
|
98
|
-
|
|
99
|
-
>>> app['s2'].value
|
|
100
|
-
>>> 1.9999999999999998e-05
|
|
101
|
-
>>> app['s2'].description
|
|
102
|
-
>>> 'Spacing between traces'
|
|
211
|
+
11. Layout Validation
|
|
103
212
|
|
|
213
|
+
# Run DRC check
|
|
214
|
+
>>> drc_errors = edb.layout_validation.run_drc()
|
|
215
|
+
>>> print(f"Found {len(drc_errors)} DRC violations")
|
|
104
216
|
|
|
105
|
-
|
|
217
|
+
12. Differential Pairs
|
|
106
218
|
|
|
107
|
-
|
|
219
|
+
# Create differential pair
|
|
220
|
+
>>> edb.differential_pairs.create(
|
|
221
|
+
>>> positive_net="USB_P",
|
|
222
|
+
>>> negative_net="USB_N",
|
|
223
|
+
>>> name="USB_DP"
|
|
224
|
+
>>> )
|
|
108
225
|
|
|
109
|
-
|
|
110
|
-
The XML control file resides in the same directory as the GDS file: (myfile.xml).
|
|
226
|
+
13. Workflow Automation
|
|
111
227
|
|
|
112
|
-
|
|
228
|
+
# Define and run workflow
|
|
229
|
+
>>> workflow = edb.workflow
|
|
230
|
+
>>> workflow.add_task("Import", file_path="input.brd")
|
|
231
|
+
>>> workflow.add_task("Cutout", signal_nets=["PCIe"])
|
|
232
|
+
>>> workflow.add_task("Export", format="IPC2581")
|
|
233
|
+
>>> workflow.run()
|
|
113
234
|
|
|
114
235
|
"""
|
|
115
236
|
|
pyedb/grpc/database/__init__.py
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from __future__ import absolute_import # noreorder
|
|
@@ -2159,3 +2159,113 @@ class Components(object):
|
|
|
2159
2159
|
pin.name for pin in list(self.instances[reference_designator].pins.values()) if pin.net_name == net_name
|
|
2160
2160
|
]
|
|
2161
2161
|
return self.create_pin_group(reference_designator, pins, group_name)
|
|
2162
|
+
|
|
2163
|
+
def deactivate_rlc_component(self, component=None, create_circuit_port=False, pec_boundary=False):
|
|
2164
|
+
"""Deactivate RLC component with a possibility to convert it to a circuit port.
|
|
2165
|
+
|
|
2166
|
+
Parameters
|
|
2167
|
+
----------
|
|
2168
|
+
component : str
|
|
2169
|
+
Reference designator of the RLC component.
|
|
2170
|
+
|
|
2171
|
+
create_circuit_port : bool, optional
|
|
2172
|
+
Whether to replace the deactivated RLC component with a circuit port. The default
|
|
2173
|
+
is ``False``.
|
|
2174
|
+
pec_boundary : bool, optional
|
|
2175
|
+
Whether to define the PEC boundary, The default is ``False``. If set to ``True``,
|
|
2176
|
+
a perfect short is created between the pin and impedance is ignored. This
|
|
2177
|
+
parameter is only supported on a port created between two pins, such as
|
|
2178
|
+
when there is no pin group.
|
|
2179
|
+
|
|
2180
|
+
Returns
|
|
2181
|
+
-------
|
|
2182
|
+
bool
|
|
2183
|
+
``True`` when successful, ``False`` when failed.
|
|
2184
|
+
|
|
2185
|
+
Examples
|
|
2186
|
+
--------
|
|
2187
|
+
>>> from pyedb import Edb
|
|
2188
|
+
>>> edb_file = r'C:\my_edb_file.aedb'
|
|
2189
|
+
>>> edb = Edb(edb_file)
|
|
2190
|
+
>>> for cmp in list(edb.components.instances.keys()):
|
|
2191
|
+
>>> edb.components.deactivate_rlc_component(component=cmp, create_circuit_port=False)
|
|
2192
|
+
>>> edb.save_edb()
|
|
2193
|
+
>>> edb.close_edb()
|
|
2194
|
+
"""
|
|
2195
|
+
if not component:
|
|
2196
|
+
return False
|
|
2197
|
+
if isinstance(component, str):
|
|
2198
|
+
component = self.instances[component]
|
|
2199
|
+
if not component:
|
|
2200
|
+
self._logger.error("component %s not found.", component)
|
|
2201
|
+
return False
|
|
2202
|
+
if component.type in ["other", "ic", "io"]:
|
|
2203
|
+
self._logger.info(f"Component {component.refdes} passed to deactivate is not an RLC.")
|
|
2204
|
+
return False
|
|
2205
|
+
component.is_enabled = False
|
|
2206
|
+
return self._pedb.source_excitation.add_port_on_rlc_component(
|
|
2207
|
+
component=component.refdes, circuit_ports=create_circuit_port, pec_boundary=pec_boundary
|
|
2208
|
+
)
|
|
2209
|
+
|
|
2210
|
+
def replace_rlc_by_gap_boundaries(self, component=None):
|
|
2211
|
+
"""Replace RLC component by RLC gap boundaries. These boundary types are compatible with 3D modeler export.
|
|
2212
|
+
Only 2 pins RLC components are supported in this command.
|
|
2213
|
+
|
|
2214
|
+
Parameters
|
|
2215
|
+
----------
|
|
2216
|
+
component : str
|
|
2217
|
+
Reference designator of the RLC component.
|
|
2218
|
+
|
|
2219
|
+
Returns
|
|
2220
|
+
-------
|
|
2221
|
+
bool
|
|
2222
|
+
``True`` when succeed, ``False`` if it failed.
|
|
2223
|
+
|
|
2224
|
+
Examples
|
|
2225
|
+
--------
|
|
2226
|
+
>>> from pyedb import Edb
|
|
2227
|
+
>>> edb = Edb(edb_file)
|
|
2228
|
+
>>> for refdes, cmp in edb.components.capacitors.items():
|
|
2229
|
+
>>> edb.components.replace_rlc_by_gap_boundaries(refdes)
|
|
2230
|
+
>>> edb.save_edb()
|
|
2231
|
+
>>> edb.close_edb()
|
|
2232
|
+
"""
|
|
2233
|
+
if not component:
|
|
2234
|
+
return False
|
|
2235
|
+
if isinstance(component, str):
|
|
2236
|
+
component = self.instances[component]
|
|
2237
|
+
if not component:
|
|
2238
|
+
self._logger.error("component %s not found.", component)
|
|
2239
|
+
return False
|
|
2240
|
+
if component.type in ["other", "ic", "io"]:
|
|
2241
|
+
self._logger.info(f"Component {component.refdes} skipped to deactivate is not an RLC.")
|
|
2242
|
+
return False
|
|
2243
|
+
component.enabled = False
|
|
2244
|
+
return self._pedb.source_excitation.add_rlc_boundary(component.refdes, False)
|
|
2245
|
+
|
|
2246
|
+
def add_rlc_boundary(self, component=None, circuit_type=True):
|
|
2247
|
+
"""Add RLC gap boundary on component and replace it with a circuit port.
|
|
2248
|
+
The circuit port supports only 2-pin components.
|
|
2249
|
+
|
|
2250
|
+
. deprecated:: pyedb 0.28.0
|
|
2251
|
+
Use :func:`pyedb.grpc.core.excitations.add_rlc_boundary` instead.
|
|
2252
|
+
|
|
2253
|
+
Parameters
|
|
2254
|
+
----------
|
|
2255
|
+
component : str
|
|
2256
|
+
Reference designator of the RLC component.
|
|
2257
|
+
circuit_type : bool
|
|
2258
|
+
When ``True`` circuit type are defined, if ``False`` gap type will be used instead (compatible with HFSS 3D
|
|
2259
|
+
modeler). Default value is ``True``.
|
|
2260
|
+
|
|
2261
|
+
Returns
|
|
2262
|
+
-------
|
|
2263
|
+
bool
|
|
2264
|
+
``True`` when successful, ``False`` when failed.
|
|
2265
|
+
"""
|
|
2266
|
+
warnings.warn(
|
|
2267
|
+
"`add_rlc_boundary` is deprecated and is now located here "
|
|
2268
|
+
"`pyedb.grpc.core.excitations.add_rlc_boundary` instead.",
|
|
2269
|
+
DeprecationWarning,
|
|
2270
|
+
)
|
|
2271
|
+
return self._pedb.source_excitation.add_rlc_boundary(self, component=component, circuit_type=circuit_type)
|