pyedb 0.50.1__py3-none-any.whl → 0.51.2__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 +27 -0
- 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/layout_validation.py +17 -13
- pyedb/dotnet/database/modeler.py +0 -1
- pyedb/dotnet/edb.py +7 -1
- pyedb/generic/design_types.py +183 -62
- pyedb/grpc/database/components.py +110 -0
- pyedb/grpc/database/control_file.py +150 -17
- 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/layout_validation.py +58 -7
- 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 +307 -40
- 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 +134 -81
- pyedb/grpc/edb_init.py +50 -3
- {pyedb-0.50.1.dist-info → pyedb-0.51.2.dist-info}/METADATA +1 -1
- {pyedb-0.50.1.dist-info → pyedb-0.51.2.dist-info}/RECORD +31 -31
- {pyedb-0.50.1.dist-info → pyedb-0.51.2.dist-info}/LICENSE +0 -0
- {pyedb-0.50.1.dist-info → pyedb-0.51.2.dist-info}/WHEEL +0 -0
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
|
|
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
|
|
|
@@ -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)
|
|
@@ -35,23 +35,156 @@ from pyedb.misc.misc import list_installed_ansysem
|
|
|
35
35
|
def convert_technology_file(tech_file, edbversion=None, control_file=None):
|
|
36
36
|
"""Convert a technology file to EDB control file (XML).
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
Parameters
|
|
39
|
+
----------
|
|
40
|
+
tech_file : str
|
|
41
|
+
Full path to technology file.
|
|
42
|
+
edbversion : str, optional
|
|
43
|
+
EDB version to use. If ``None``, uses latest available version.
|
|
44
|
+
control_file : str, optional
|
|
45
|
+
Output control file path. If ``None``, uses same path and name as ``tech_file``.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
str or bool
|
|
50
|
+
Full path to created control file if successful, ``False`` otherwise.
|
|
51
|
+
|
|
52
|
+
Notes
|
|
53
|
+
-----
|
|
54
|
+
This function is only supported on Linux systems.
|
|
55
|
+
|
|
56
|
+
Example
|
|
57
|
+
-------
|
|
58
|
+
# Example 1: Converting a technology file to control file
|
|
59
|
+
>>> converted_file = convert_technology_file(
|
|
60
|
+
>>> tech_file="/path/to/tech.t",
|
|
61
|
+
>>> edbversion="2025.2",
|
|
62
|
+
>>> control_file="/path/to/output.xml"
|
|
63
|
+
>>> )
|
|
64
|
+
>>> if converted_file:
|
|
65
|
+
>>> print(f"Converted to: {converted_file}")
|
|
66
|
+
|
|
67
|
+
# Example 2: Creating a material
|
|
68
|
+
>>> from pyedb import ControlFileMaterial
|
|
69
|
+
>>> material = ControlFileMaterial(
|
|
70
|
+
>>> "Copper",
|
|
71
|
+
>>> {"Permittivity": 1.0, "Conductivity": 5.8e7}
|
|
72
|
+
>>> )
|
|
73
|
+
|
|
74
|
+
# Example 3: Creating a dielectric layer
|
|
75
|
+
>>> from pyedb import ControlFileDielectric
|
|
76
|
+
>>> dielectric = ControlFileDielectric(
|
|
77
|
+
>>> "Core",
|
|
78
|
+
>>> {"Thickness": "0.2mm", "Material": "FR4"}
|
|
79
|
+
>>> )
|
|
80
|
+
|
|
81
|
+
# Example 4: Creating a signal layer
|
|
82
|
+
>>> from pyedb import ControlFileLayer
|
|
83
|
+
>>> signal_layer = ControlFileLayer(
|
|
84
|
+
>>> "TopLayer",
|
|
85
|
+
>>> {"Type": "signal", "Material": "Copper", "Thickness": "0.035mm"}
|
|
86
|
+
>>> )
|
|
87
|
+
|
|
88
|
+
# Example 5: Creating a via layer
|
|
89
|
+
>>> from pyedb import ControlFileVia
|
|
90
|
+
>>> via_layer = ControlFileVia(
|
|
91
|
+
>>> "Via1",
|
|
92
|
+
>>> {"StartLayer": "TopLayer", "StopLayer": "BottomLayer"}
|
|
93
|
+
>>> )
|
|
94
|
+
>>> via_layer.create_via_group = True
|
|
95
|
+
>>> via_layer.tolerance = "0.1mm"
|
|
96
|
+
|
|
97
|
+
# Example 6: Managing stackup
|
|
98
|
+
>>> from pyedb import ControlFileStackup
|
|
99
|
+
>>> stackup = ControlFileStackup(units="mm")
|
|
100
|
+
>>> stackup.add_material("FR4", permittivity=4.4, dielectric_loss_tg=0.02)
|
|
101
|
+
>>> stackup.add_layer("L1", elevation=0, material="Copper", thickness=0.035)
|
|
102
|
+
>>> stackup.add_dielectric("Diel1", material="FR4", thickness=0.2)
|
|
103
|
+
>>> stackup.add_via("Via1", start_layer="L1", stop_layer="L2")
|
|
104
|
+
|
|
105
|
+
# Example 7: Configuring import options
|
|
106
|
+
>>> from pyedb import ControlFileImportOptions
|
|
107
|
+
>>> import_ops = ControlFileImportOptions()
|
|
108
|
+
>>> import_ops.auto_close = True
|
|
109
|
+
>>> import_ops.defeature_tolerance = 0.001
|
|
110
|
+
|
|
111
|
+
# Example 8: Setting up simulation extents
|
|
112
|
+
>>> from pyedb import ControlExtent
|
|
113
|
+
>>> extent = ControlExtent(
|
|
114
|
+
>>> type="Conforming",
|
|
115
|
+
>>> diel_hactor=0.3,
|
|
116
|
+
>>> airbox_hfactor=0.5
|
|
117
|
+
>>> )
|
|
118
|
+
|
|
119
|
+
# Example 9: Creating circuit ports
|
|
120
|
+
>>> from pyedb import ControlCircuitPt
|
|
121
|
+
>>> port = ControlCircuitPt("Port1", 0, 0, "TopLayer", 1, 0, "TopLayer", 50)
|
|
122
|
+
|
|
123
|
+
# Example 10: Managing components
|
|
124
|
+
>>> from pyedb import ControlFileComponent
|
|
125
|
+
>>> comp = ControlFileComponent()
|
|
126
|
+
>>> comp.refdes = "U1"
|
|
127
|
+
>>> comp.add_pin("Pin1", 0.5, 0.5, "TopLayer")
|
|
128
|
+
>>> comp.add_port("Port1", 50, "Pin1", refpin="GND")
|
|
129
|
+
|
|
130
|
+
# Example 11: Component management
|
|
131
|
+
>>> from pyedb import ControlFileComponents
|
|
132
|
+
>>> components = ControlFileComponents()
|
|
133
|
+
>>> ic = components.add_component("U1", "BGA", "IC", die_type="Flip chip")
|
|
134
|
+
>>> ic.add_pin("A1", 1.0, 1.0, "TopLayer")
|
|
135
|
+
|
|
136
|
+
# Example 12: Boundary setup
|
|
137
|
+
>>> from pyedb import ControlFileBoundaries
|
|
138
|
+
>>> boundaries = ControlFileBoundaries()
|
|
139
|
+
>>> boundaries.add_port("Port1", 0, 0, "L1", 1, 0, "L1", 50)
|
|
140
|
+
>>> boundaries.add_extent(diel_hactor=0.3)
|
|
141
|
+
|
|
142
|
+
# Example 13: Frequency sweep configuration
|
|
143
|
+
>>> from pyedb import ControlFileSweep
|
|
144
|
+
>>> sweep = ControlFileSweep(
|
|
145
|
+
>>> "Sweep1", "1GHz", "10GHz", "0.1GHz",
|
|
146
|
+
>>> "Interpolating", "LinearStep", True
|
|
147
|
+
>>> )
|
|
148
|
+
|
|
149
|
+
# Example 14: Mesh operation setup
|
|
150
|
+
>>> from pyedb import ControlFileMeshOp
|
|
151
|
+
>>> mesh_op = ControlFileMeshOp(
|
|
152
|
+
>>> "FineMesh", "Region1", "MeshOperationSkinDepth",
|
|
153
|
+
>>> {"Net1": "TopLayer"}
|
|
154
|
+
>>> )
|
|
155
|
+
>>> mesh_op.skin_depth = "1um"
|
|
156
|
+
|
|
157
|
+
# Example 15: Simulation setup configuration
|
|
158
|
+
>>> from pyedb import ControlFileSetup
|
|
159
|
+
>>> setup = ControlFileSetup("SimSetup1")
|
|
160
|
+
>>> setup.frequency = "5GHz"
|
|
161
|
+
>>> setup.add_sweep("Sweep1", "1GHz", "10GHz", "0.5GHz")
|
|
162
|
+
>>> setup.add_mesh_operation("Mesh1", "Chip", "MeshOperationLength", {"PWR": "Top"})
|
|
163
|
+
|
|
164
|
+
# Example 16: Setup management
|
|
165
|
+
>>> from pyedb import ControlFileSetups
|
|
166
|
+
>>> setups = ControlFileSetups()
|
|
167
|
+
>>> sim_setup = setups.add_setup("MySetup", "10GHz")
|
|
168
|
+
>>> sim_setup.add_sweep("Swp1", "1GHz", "20GHz", 100, step_type="LinearCount")
|
|
169
|
+
|
|
170
|
+
# Example 17: Main control file creation
|
|
171
|
+
>>> from pyedb import ControlFile
|
|
172
|
+
|
|
173
|
+
# Create from scratch
|
|
174
|
+
>>> ctrl = ControlFile()
|
|
175
|
+
>>> ctrl.stackup.add_material("Copper", conductivity=5.8e7)
|
|
176
|
+
>>> ctrl.stackup.add_layer("Signal", thickness=0.035, material="Copper")
|
|
177
|
+
>>> ctrl.boundaries.add_port("Input", 0, 0, "Signal", 1, 0, "Signal", 50)
|
|
178
|
+
>>> ctrl.write_xml("/path/to/control.xml")
|
|
179
|
+
|
|
180
|
+
# Parse existing file
|
|
181
|
+
>>> ctrl = ControlFile(xml_input="/path/to/existing.xml")
|
|
182
|
+
|
|
183
|
+
# Convert technology file
|
|
184
|
+
>>> ctrl = ControlFile(tecnhology="/path/to/tech.t")
|
|
185
|
+
|
|
186
|
+
# Apply layer mapping
|
|
187
|
+
>>> ctrl.parse_layer_map("/path/to/layer_map.txt")
|
|
55
188
|
"""
|
|
56
189
|
if is_linux: # pragma: no cover
|
|
57
190
|
if not edbversion:
|
|
@@ -34,12 +34,30 @@ class Definitions:
|
|
|
34
34
|
|
|
35
35
|
@property
|
|
36
36
|
def component(self) -> dict[str, ComponentDef]:
|
|
37
|
-
"""Component definitions
|
|
37
|
+
"""Component definitions
|
|
38
|
+
|
|
39
|
+
Examples
|
|
40
|
+
--------
|
|
41
|
+
>>> from pyedb import Edb
|
|
42
|
+
>>> edb = Edb()
|
|
43
|
+
>>> component_defs = edb.definitions.component
|
|
44
|
+
>>> for name, comp_def in component_defs.items():
|
|
45
|
+
... print(f"Component: {name}, Part: {comp_def.part}")
|
|
46
|
+
"""
|
|
38
47
|
return {l.name: ComponentDef(self._pedb, l) for l in self._pedb.active_db.component_defs}
|
|
39
48
|
|
|
40
49
|
@property
|
|
41
50
|
def package(self) -> dict[str, PackageDef]:
|
|
42
|
-
"""Package definitions.
|
|
51
|
+
"""Package definitions.
|
|
52
|
+
|
|
53
|
+
Examples
|
|
54
|
+
--------
|
|
55
|
+
>>> from pyedb import Edb
|
|
56
|
+
>>> edb = Edb()
|
|
57
|
+
>>> package_defs = edb.definitions.package
|
|
58
|
+
>>> for name, pkg_def in package_defs.items():
|
|
59
|
+
... print(f"Package: {name}, Boundary: {pkg_def.exterior_boundary}")
|
|
60
|
+
"""
|
|
43
61
|
return {l.name: PackageDef(self._pedb, l) for l in self._pedb.active_db.package_defs}
|
|
44
62
|
|
|
45
63
|
def add_package_def(self, name, component_part_name=None, boundary_points=None) -> Union[PackageDef, bool]:
|
|
@@ -57,6 +75,22 @@ class Definitions:
|
|
|
57
75
|
Returns
|
|
58
76
|
-------
|
|
59
77
|
PackageDef object.
|
|
78
|
+
|
|
79
|
+
Examples
|
|
80
|
+
--------
|
|
81
|
+
>>> from pyedb import Edb
|
|
82
|
+
>>> edb = Edb()
|
|
83
|
+
|
|
84
|
+
Example 1: Create package using component's bounding box
|
|
85
|
+
>>> comp_def = edb.definitions.add_package_def("QFP64", "QFP64_COMPONENT")
|
|
86
|
+
>>> if comp_def: # Check if created successfully
|
|
87
|
+
... print(f"Created package: {comp_def.name}")
|
|
88
|
+
|
|
89
|
+
Example 2: Create package with custom boundary
|
|
90
|
+
>>> boundary = [[0, 0], [10e-3, 0], [10e-3, 10e-3], [0, 10e-3]]
|
|
91
|
+
>>> custom_pkg = edb.definitions.add_package_def("CustomIC", boundary_points=boundary)
|
|
92
|
+
>>> if custom_pkg:
|
|
93
|
+
... print(f"Custom package boundary: {custom_pkg.exterior_boundary}")
|
|
60
94
|
"""
|
|
61
95
|
if not name in self.package:
|
|
62
96
|
package_def = PackageDef.create(self._pedb.active_db, name=name)
|
pyedb/grpc/database/hfss.py
CHANGED
|
@@ -200,6 +200,12 @@ class Hfss(object):
|
|
|
200
200
|
-------
|
|
201
201
|
dict
|
|
202
202
|
Dictionary mapping net names to smallest trace widths.
|
|
203
|
+
|
|
204
|
+
Examples
|
|
205
|
+
--------
|
|
206
|
+
>>> widths = edb.hfss.get_trace_width_for_traces_with_ports()
|
|
207
|
+
>>> for net_name, width in widths.items():
|
|
208
|
+
... print(f"Net '{net_name}': Smallest width = {width}")
|
|
203
209
|
"""
|
|
204
210
|
nets = {}
|
|
205
211
|
for net in self._pedb.excitations_nets:
|
|
@@ -925,6 +931,15 @@ class Hfss(object):
|
|
|
925
931
|
-------
|
|
926
932
|
list
|
|
927
933
|
[min_x, min_y, max_x, max_y] coordinates.
|
|
934
|
+
|
|
935
|
+
Examples
|
|
936
|
+
--------
|
|
937
|
+
>>> bbox = edb.hfss.get_layout_bounding_box()
|
|
938
|
+
>>> print(f"Layout Bounding Box: {bbox}")
|
|
939
|
+
>>>
|
|
940
|
+
>>> # With custom parameters
|
|
941
|
+
>>> custom_layout = edb.layouts["MyLayout"]
|
|
942
|
+
>>> bbox = edb.hfss.get_layout_bounding_box(custom_layout, 5)
|
|
928
943
|
"""
|
|
929
944
|
if not layout:
|
|
930
945
|
layout = self._active_layout
|