pyedb 0.52.0__py3-none-any.whl → 0.54.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_common.py +12 -15
- pyedb/configuration/cfg_data.py +2 -2
- pyedb/configuration/cfg_modeler.py +163 -234
- pyedb/configuration/cfg_ports_sources.py +6 -8
- pyedb/configuration/cfg_stackup.py +62 -249
- pyedb/configuration/configuration.py +272 -170
- pyedb/dotnet/database/cell/hierarchy/model.py +1 -1
- pyedb/dotnet/database/cell/layout.py +1 -1
- pyedb/dotnet/database/cell/layout_obj.py +3 -3
- pyedb/dotnet/database/cell/primitive/path.py +1 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +8 -8
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +24 -26
- pyedb/dotnet/database/components.py +33 -27
- pyedb/dotnet/database/definition/component_def.py +3 -3
- pyedb/dotnet/database/definition/component_model.py +1 -1
- pyedb/dotnet/database/definition/package_def.py +1 -1
- pyedb/dotnet/database/dotnet/database.py +47 -38
- pyedb/dotnet/database/dotnet/primitive.py +16 -16
- pyedb/dotnet/database/edb_data/hfss_extent_info.py +6 -6
- pyedb/dotnet/database/edb_data/layer_data.py +17 -15
- pyedb/dotnet/database/edb_data/padstacks_data.py +12 -12
- pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
- pyedb/dotnet/database/edb_data/sources.py +6 -6
- pyedb/dotnet/database/edb_data/variables.py +7 -3
- pyedb/dotnet/database/geometry/point_data.py +1 -1
- pyedb/dotnet/database/geometry/polygon_data.py +2 -4
- pyedb/dotnet/database/hfss.py +7 -7
- pyedb/dotnet/database/materials.py +2 -2
- pyedb/dotnet/database/modeler.py +8 -11
- pyedb/dotnet/database/nets.py +1 -1
- pyedb/dotnet/database/padstack.py +72 -1
- pyedb/dotnet/database/sim_setup_data/data/settings.py +24 -0
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +26 -1
- pyedb/dotnet/database/siwave.py +19 -5
- pyedb/dotnet/database/stackup.py +80 -137
- pyedb/dotnet/database/utilities/heatsink.py +4 -4
- pyedb/dotnet/database/utilities/obj_base.py +1 -1
- pyedb/dotnet/database/utilities/simulation_setup.py +1 -1
- pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +894 -0
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +15 -0
- pyedb/dotnet/database/utilities/value.py +116 -0
- pyedb/dotnet/edb.py +58 -45
- pyedb/generic/design_types.py +39 -1
- pyedb/generic/grpc_warnings.py +5 -0
- pyedb/grpc/__init__.py +0 -0
- pyedb/grpc/database/components.py +155 -98
- pyedb/grpc/database/control_file.py +240 -193
- pyedb/grpc/database/definition/materials.py +23 -30
- pyedb/grpc/database/definition/package_def.py +15 -15
- pyedb/grpc/database/definition/padstack_def.py +51 -51
- pyedb/grpc/database/definitions.py +7 -5
- pyedb/grpc/database/geometry/arc_data.py +7 -5
- pyedb/grpc/database/geometry/point_3d_data.py +8 -7
- pyedb/grpc/database/geometry/polygon_data.py +3 -2
- pyedb/grpc/database/hierarchy/component.py +43 -38
- pyedb/grpc/database/hierarchy/pin_pair_model.py +15 -14
- pyedb/grpc/database/hierarchy/pingroup.py +9 -9
- pyedb/grpc/database/layers/stackup_layer.py +45 -44
- pyedb/grpc/database/layout/layout.py +9 -8
- pyedb/grpc/database/layout/voltage_regulator.py +7 -7
- pyedb/grpc/database/layout_validation.py +13 -12
- pyedb/grpc/database/modeler.py +156 -131
- pyedb/grpc/database/nets.py +42 -31
- pyedb/grpc/database/padstacks.py +270 -175
- pyedb/grpc/database/ports/ports.py +5 -6
- pyedb/grpc/database/primitive/bondwire.py +8 -7
- pyedb/grpc/database/primitive/circle.py +4 -4
- pyedb/grpc/database/primitive/padstack_instance.py +18 -18
- pyedb/grpc/database/primitive/path.py +7 -7
- pyedb/grpc/database/primitive/polygon.py +3 -3
- pyedb/grpc/database/primitive/primitive.py +13 -17
- pyedb/grpc/database/primitive/rectangle.py +13 -13
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +10 -0
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +961 -0
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +17 -1
- pyedb/grpc/database/siwave.py +44 -24
- pyedb/grpc/database/source_excitations.py +333 -229
- pyedb/grpc/database/stackup.py +164 -147
- pyedb/grpc/database/terminal/bundle_terminal.py +17 -7
- pyedb/grpc/database/terminal/edge_terminal.py +10 -0
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +15 -4
- pyedb/grpc/database/terminal/pingroup_terminal.py +11 -10
- pyedb/grpc/database/terminal/point_terminal.py +4 -3
- pyedb/grpc/database/terminal/terminal.py +9 -9
- pyedb/grpc/database/utility/value.py +109 -0
- pyedb/grpc/edb.py +129 -45
- pyedb/grpc/edb_init.py +0 -7
- pyedb/siwave_core/cpa/simulation_setup_data_model.py +132 -0
- pyedb/siwave_core/product_properties.py +198 -0
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/METADATA +15 -13
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/RECORD +97 -89
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/WHEEL +1 -1
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info/licenses}/LICENSE +0 -0
pyedb/grpc/edb.py
CHANGED
|
@@ -70,6 +70,9 @@ import warnings
|
|
|
70
70
|
from zipfile import ZipFile as zpf
|
|
71
71
|
|
|
72
72
|
from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
|
|
73
|
+
from ansys.edb.core.hierarchy.layout_component import (
|
|
74
|
+
LayoutComponent as GrpcLayoutComponent,
|
|
75
|
+
)
|
|
73
76
|
import ansys.edb.core.layout.cell
|
|
74
77
|
from ansys.edb.core.simulation_setup.siwave_dcir_simulation_setup import (
|
|
75
78
|
SIWaveDCIRSimulationSetup as GrpcSIWaveDCIRSimulationSetup,
|
|
@@ -111,6 +114,9 @@ from pyedb.grpc.database.simulation_setup.hfss_simulation_setup import (
|
|
|
111
114
|
from pyedb.grpc.database.simulation_setup.raptor_x_simulation_setup import (
|
|
112
115
|
RaptorXSimulationSetup,
|
|
113
116
|
)
|
|
117
|
+
from pyedb.grpc.database.simulation_setup.siwave_cpa_simulation_setup import (
|
|
118
|
+
SIWaveCPASimulationSetup,
|
|
119
|
+
)
|
|
114
120
|
from pyedb.grpc.database.simulation_setup.siwave_dcir_simulation_setup import (
|
|
115
121
|
SIWaveDCIRSimulationSetup,
|
|
116
122
|
)
|
|
@@ -125,6 +131,7 @@ from pyedb.grpc.database.terminal.padstack_instance_terminal import (
|
|
|
125
131
|
)
|
|
126
132
|
from pyedb.grpc.database.terminal.terminal import Terminal
|
|
127
133
|
from pyedb.grpc.database.utility.constants import get_terminal_supported_boundary_types
|
|
134
|
+
from pyedb.grpc.database.utility.value import Value
|
|
128
135
|
from pyedb.grpc.edb_init import EdbInit
|
|
129
136
|
from pyedb.ipc2581.ipc2581 import Ipc2581
|
|
130
137
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
@@ -196,14 +203,13 @@ class Edb(EdbInit):
|
|
|
196
203
|
edbversion: str = None,
|
|
197
204
|
isaedtowned: bool = False,
|
|
198
205
|
oproject=None,
|
|
199
|
-
student_version: bool = False,
|
|
200
206
|
use_ppe: bool = False,
|
|
201
207
|
control_file: str = None,
|
|
202
208
|
map_file: str = None,
|
|
203
209
|
technology_file: str = None,
|
|
204
210
|
layer_filter: str = None,
|
|
205
|
-
remove_existing_aedt: bool = False,
|
|
206
211
|
restart_rpc_server=False,
|
|
212
|
+
**kwargs,
|
|
207
213
|
):
|
|
208
214
|
edbversion = get_string_version(edbversion)
|
|
209
215
|
self._clean_variables()
|
|
@@ -285,13 +291,13 @@ class Edb(EdbInit):
|
|
|
285
291
|
return False
|
|
286
292
|
elif edbpath.endswith("edb.def"):
|
|
287
293
|
self.edbpath = os.path.dirname(edbpath)
|
|
288
|
-
self.
|
|
294
|
+
self.open(restart_rpc_server=restart_rpc_server)
|
|
289
295
|
elif not os.path.exists(os.path.join(self.edbpath, "edb.def")):
|
|
290
|
-
self.
|
|
296
|
+
self.create(restart_rpc_server=restart_rpc_server)
|
|
291
297
|
self.logger.info("EDB %s created correctly.", self.edbpath)
|
|
292
298
|
elif ".aedb" in edbpath:
|
|
293
299
|
self.edbpath = edbpath
|
|
294
|
-
self.
|
|
300
|
+
self.open(restart_rpc_server=restart_rpc_server)
|
|
295
301
|
if self.active_cell:
|
|
296
302
|
self.logger.info("EDB initialized.")
|
|
297
303
|
else:
|
|
@@ -360,6 +366,11 @@ class Edb(EdbInit):
|
|
|
360
366
|
if description: # Add the variable description if a two-item list is passed for variable_value.
|
|
361
367
|
self.__getitem__(variable_name).description = description
|
|
362
368
|
|
|
369
|
+
@property
|
|
370
|
+
def core(self) -> ansys.edb.core:
|
|
371
|
+
"""Ansys Edb Core module."""
|
|
372
|
+
return ansys.edb.core
|
|
373
|
+
|
|
363
374
|
def _check_remove_project_files(self, edbpath: str, remove_existing_aedt: bool) -> None:
|
|
364
375
|
aedt_file = os.path.splitext(edbpath)[0] + ".aedt"
|
|
365
376
|
files = [aedt_file, aedt_file + ".lock"]
|
|
@@ -391,6 +402,14 @@ class Edb(EdbInit):
|
|
|
391
402
|
self._differential_pairs = DifferentialPairs(self)
|
|
392
403
|
self._extended_nets = ExtendedNets(self)
|
|
393
404
|
|
|
405
|
+
def value(self, val):
|
|
406
|
+
"""Convert a value into a pyedb value."""
|
|
407
|
+
if isinstance(val, GrpcValue):
|
|
408
|
+
return Value(val)
|
|
409
|
+
else:
|
|
410
|
+
context = self.active_cell if not str(val).startswith("$") else self.active_db
|
|
411
|
+
return Value(GrpcValue(val, context), context)
|
|
412
|
+
|
|
394
413
|
@property
|
|
395
414
|
def cell_names(self) -> [str]:
|
|
396
415
|
"""List of all cell names in the database.
|
|
@@ -411,7 +430,7 @@ class Edb(EdbInit):
|
|
|
411
430
|
dict[str, float]
|
|
412
431
|
Variable names and values.
|
|
413
432
|
"""
|
|
414
|
-
return {i: self.active_cell.get_variable_value(i)
|
|
433
|
+
return {i: Value(self.active_cell.get_variable_value(i)) for i in self.active_cell.get_all_variable_names()}
|
|
415
434
|
|
|
416
435
|
@property
|
|
417
436
|
def project_variables(self) -> dict[str, float]:
|
|
@@ -422,7 +441,7 @@ class Edb(EdbInit):
|
|
|
422
441
|
dict[str, float]
|
|
423
442
|
Variable names and values.
|
|
424
443
|
"""
|
|
425
|
-
return {i: self.active_db.get_variable_value(i)
|
|
444
|
+
return {i: Value(self.active_db.get_variable_value(i)) for i in self.active_db.get_all_variable_names()}
|
|
426
445
|
|
|
427
446
|
@property
|
|
428
447
|
def layout_validation(self) -> LayoutValidation:
|
|
@@ -533,7 +552,11 @@ class Edb(EdbInit):
|
|
|
533
552
|
dict[str, :class:`Terminal <pyedb.grpc.database.terminal.terminal.Terminal>`]
|
|
534
553
|
Source names and objects.
|
|
535
554
|
"""
|
|
536
|
-
return
|
|
555
|
+
return {
|
|
556
|
+
k: i
|
|
557
|
+
for k, i in self.terminals.items()
|
|
558
|
+
if "source" in i.boundary_type or "terminal" in i.boundary_type or i.is_reference_terminal
|
|
559
|
+
}
|
|
537
560
|
|
|
538
561
|
@property
|
|
539
562
|
def voltage_regulator_modules(self):
|
|
@@ -559,7 +582,7 @@ class Edb(EdbInit):
|
|
|
559
582
|
dict[str, :class:`Terminal <pyedb.grpc.database.terminal.terminal.Terminal>`]
|
|
560
583
|
Probe names and objects.
|
|
561
584
|
"""
|
|
562
|
-
terms = [term for term in self.layout.terminals if term.boundary_type
|
|
585
|
+
terms = [term for term in self.layout.terminals if term.boundary_type == "voltage_probe"]
|
|
563
586
|
return {ter.name: ter for ter in terms}
|
|
564
587
|
|
|
565
588
|
def open(self, restart_rpc_server=False) -> bool:
|
|
@@ -1279,7 +1302,7 @@ class Edb(EdbInit):
|
|
|
1279
1302
|
func : str
|
|
1280
1303
|
Command to execute.
|
|
1281
1304
|
"""
|
|
1282
|
-
# return self.
|
|
1305
|
+
# return self.core.utility.utility.Command.Execute(func)
|
|
1283
1306
|
pass
|
|
1284
1307
|
|
|
1285
1308
|
def import_cadence_file(self, inputBrd, WorkDir=None, anstranslator_full_path="", use_ppe=False) -> bool:
|
|
@@ -1553,7 +1576,7 @@ class Edb(EdbInit):
|
|
|
1553
1576
|
for term in terms:
|
|
1554
1577
|
if term.type == "PointTerminal" and term.net.name in reference_list:
|
|
1555
1578
|
pd = term.get_parameters()[1]
|
|
1556
|
-
locations.append([pd.x
|
|
1579
|
+
locations.append([Value(pd.x), Value(pd.y)])
|
|
1557
1580
|
for point in locations:
|
|
1558
1581
|
pointA = GrpcPointData([point[0] - expansion_size, point[1] - expansion_size])
|
|
1559
1582
|
pointB = GrpcPointData([point[0] + expansion_size, point[1] + expansion_size])
|
|
@@ -1821,7 +1844,7 @@ class Edb(EdbInit):
|
|
|
1821
1844
|
include_pingroups=True,
|
|
1822
1845
|
inlcude_voids_in_extents=False,
|
|
1823
1846
|
):
|
|
1824
|
-
expansion_size =
|
|
1847
|
+
expansion_size = Value(expansion_size)
|
|
1825
1848
|
|
|
1826
1849
|
# validate nets in layout
|
|
1827
1850
|
net_signals = [net for net in self.layout.nets if net.name in signal_list]
|
|
@@ -1904,7 +1927,7 @@ class Edb(EdbInit):
|
|
|
1904
1927
|
self.components.delete_single_pin_rlc()
|
|
1905
1928
|
self.logger.info_timer("Single Pins components deleted")
|
|
1906
1929
|
self.components.refresh_components()
|
|
1907
|
-
return [[pt.x
|
|
1930
|
+
return [[Value(pt.x), Value(pt.y)] for pt in _poly.without_arcs().points]
|
|
1908
1931
|
|
|
1909
1932
|
def _create_cutout_multithread(
|
|
1910
1933
|
self,
|
|
@@ -1933,7 +1956,7 @@ class Edb(EdbInit):
|
|
|
1933
1956
|
if output_aedb_path:
|
|
1934
1957
|
self.save_edb_as(output_aedb_path)
|
|
1935
1958
|
self.logger.info("Cutout Multithread started.")
|
|
1936
|
-
expansion_size =
|
|
1959
|
+
expansion_size = Value(expansion_size)
|
|
1937
1960
|
|
|
1938
1961
|
timer_start = self.logger.reset_timer()
|
|
1939
1962
|
if custom_extent:
|
|
@@ -1977,17 +2000,20 @@ class Edb(EdbInit):
|
|
|
1977
2000
|
reference_pinsts = []
|
|
1978
2001
|
reference_prims = []
|
|
1979
2002
|
reference_paths = []
|
|
2003
|
+
delete_list = []
|
|
1980
2004
|
for i in self.padstacks.instances.values():
|
|
1981
2005
|
net_name = i.net_name
|
|
1982
2006
|
id = i.id
|
|
1983
2007
|
if net_name not in all_list and id not in pins_to_preserve:
|
|
1984
|
-
|
|
2008
|
+
delete_list.append(i)
|
|
2009
|
+
# i.delete()
|
|
1985
2010
|
elif net_name in reference_list and id not in pins_to_preserve:
|
|
1986
2011
|
reference_pinsts.append(i)
|
|
1987
2012
|
for i in self.modeler.primitives:
|
|
1988
2013
|
if not i.is_null and not i.net.is_null:
|
|
1989
2014
|
if i.net.name not in all_list:
|
|
1990
|
-
i.delete()
|
|
2015
|
+
# i.delete()
|
|
2016
|
+
delete_list.append(i)
|
|
1991
2017
|
elif i.net.name in reference_list and not i.is_void:
|
|
1992
2018
|
if keep_lines_as_path and isinstance(i, Path):
|
|
1993
2019
|
reference_paths.append(i)
|
|
@@ -1995,7 +2021,8 @@ class Edb(EdbInit):
|
|
|
1995
2021
|
reference_prims.append(i)
|
|
1996
2022
|
self.logger.info_timer("Net clean up")
|
|
1997
2023
|
self.logger.reset_timer()
|
|
1998
|
-
|
|
2024
|
+
for i in delete_list:
|
|
2025
|
+
i.delete()
|
|
1999
2026
|
if custom_extent and isinstance(custom_extent, list):
|
|
2000
2027
|
if custom_extent[0] != custom_extent[-1]:
|
|
2001
2028
|
custom_extent.append(custom_extent[0])
|
|
@@ -2027,7 +2054,7 @@ class Edb(EdbInit):
|
|
|
2027
2054
|
ExtentType as GrpcExtentType,
|
|
2028
2055
|
)
|
|
2029
2056
|
|
|
2030
|
-
if extent_type in ["Conforming", GrpcExtentType.CONFORMING, 1]:
|
|
2057
|
+
if extent_type in ["Conformal", "Conforming", GrpcExtentType.CONFORMING, 1]:
|
|
2031
2058
|
if extent_defeature > 0:
|
|
2032
2059
|
_poly = _poly.defeature(extent_defeature)
|
|
2033
2060
|
_poly1 = GrpcPolygonData(arcs=_poly.arc_data, closed=True)
|
|
@@ -2150,7 +2177,7 @@ class Edb(EdbInit):
|
|
|
2150
2177
|
self.save_edb()
|
|
2151
2178
|
self.logger.info_timer("Cutout completed.", timer_start)
|
|
2152
2179
|
self.logger.reset_timer()
|
|
2153
|
-
return [[pt.x
|
|
2180
|
+
return [[Value(pt.x), Value(pt.y)] for pt in _poly.without_arcs().points]
|
|
2154
2181
|
|
|
2155
2182
|
def get_conformal_polygon_from_netlist(self, netlist=None) -> Union[bool, Polygon]:
|
|
2156
2183
|
"""Returns conformal polygon data based on a netlist.
|
|
@@ -2276,7 +2303,7 @@ class Edb(EdbInit):
|
|
|
2276
2303
|
for p in p_missing:
|
|
2277
2304
|
position = GrpcPointData(p.position)
|
|
2278
2305
|
net = self.nets.find_or_create_net(p.net_name)
|
|
2279
|
-
rotation =
|
|
2306
|
+
rotation = Value(p.rotation)
|
|
2280
2307
|
sign_layers = list(self.stackup.signal_layers.keys())
|
|
2281
2308
|
if not p.start_layer: # pragma: no cover
|
|
2282
2309
|
fromlayer = self.stackup.signal_layers[sign_layers[0]]
|
|
@@ -2368,7 +2395,7 @@ class Edb(EdbInit):
|
|
|
2368
2395
|
self.logger.warning("aedb def file manually created.")
|
|
2369
2396
|
except:
|
|
2370
2397
|
pass
|
|
2371
|
-
return [[pt.x
|
|
2398
|
+
return [[Value(pt.x), Value(pt.y)] for pt in polygon_data.without_arcs().points]
|
|
2372
2399
|
|
|
2373
2400
|
@staticmethod
|
|
2374
2401
|
def write_export3d_option_config_file(path_to_output, config_dictionaries=None):
|
|
@@ -2651,12 +2678,12 @@ class Edb(EdbInit):
|
|
|
2651
2678
|
Variable value if exists, else False.
|
|
2652
2679
|
"""
|
|
2653
2680
|
if self.variable_exists(variable_name):
|
|
2654
|
-
if "$"
|
|
2655
|
-
|
|
2656
|
-
variable = next(var for var in self.active_db.get_all_variable_names())
|
|
2657
|
-
else:
|
|
2658
|
-
variable = next(var for var in self.active_cell.get_all_variable_names())
|
|
2681
|
+
if variable_name.startswith("$"):
|
|
2682
|
+
variable = next(var for var in self.active_db.get_all_variable_names())
|
|
2659
2683
|
return self.db.get_variable_value(variable)
|
|
2684
|
+
else:
|
|
2685
|
+
variable = next(var for var in self.active_cell.get_all_variable_names())
|
|
2686
|
+
return self.active_cell.get_variable_value(variable)
|
|
2660
2687
|
self.logger.info(f"Variable {variable_name} doesn't exists.")
|
|
2661
2688
|
return False
|
|
2662
2689
|
|
|
@@ -2730,11 +2757,11 @@ class Edb(EdbInit):
|
|
|
2730
2757
|
"""
|
|
2731
2758
|
if self.variable_exists(variable_name):
|
|
2732
2759
|
if variable_name in self.db.get_all_variable_names():
|
|
2733
|
-
self.db.set_variable_value(variable_name,
|
|
2760
|
+
self.db.set_variable_value(variable_name, Value(variable_value))
|
|
2734
2761
|
elif variable_name in self.active_cell.get_all_variable_names():
|
|
2735
|
-
self.active_cell.set_variable_value(variable_name,
|
|
2762
|
+
self.active_cell.set_variable_value(variable_name, Value(variable_value))
|
|
2736
2763
|
|
|
2737
|
-
def get_bounding_box(self) ->
|
|
2764
|
+
def get_bounding_box(self) -> tuple[tuple[float, float], tuple[float, float]]:
|
|
2738
2765
|
"""Get layout bounding box.
|
|
2739
2766
|
|
|
2740
2767
|
Returns
|
|
@@ -2744,7 +2771,7 @@ class Edb(EdbInit):
|
|
|
2744
2771
|
"""
|
|
2745
2772
|
lay_inst_polygon_data = [obj_inst.get_bbox() for obj_inst in self.layout_instance.query_layout_obj_instances()]
|
|
2746
2773
|
layout_bbox = GrpcPolygonData.bbox_of_polygons(lay_inst_polygon_data)
|
|
2747
|
-
return
|
|
2774
|
+
return ((Value(layout_bbox[0].x), Value(layout_bbox[0].y)), (Value(layout_bbox[1].x), Value(layout_bbox[1].y)))
|
|
2748
2775
|
|
|
2749
2776
|
def get_statistics(self, compute_area=False):
|
|
2750
2777
|
"""Get layout statistics.
|
|
@@ -2838,7 +2865,16 @@ class Edb(EdbInit):
|
|
|
2838
2865
|
@property
|
|
2839
2866
|
def setups(
|
|
2840
2867
|
self,
|
|
2841
|
-
) ->
|
|
2868
|
+
) -> dict[
|
|
2869
|
+
str,
|
|
2870
|
+
Union[
|
|
2871
|
+
HfssSimulationSetup,
|
|
2872
|
+
SiwaveSimulationSetup,
|
|
2873
|
+
SIWaveDCIRSimulationSetup,
|
|
2874
|
+
RaptorXSimulationSetup,
|
|
2875
|
+
SIWaveCPASimulationSetup,
|
|
2876
|
+
],
|
|
2877
|
+
]:
|
|
2842
2878
|
"""Get the dictionary of all EDB HFSS and SIwave setups.
|
|
2843
2879
|
|
|
2844
2880
|
Returns
|
|
@@ -2847,21 +2883,34 @@ class Edb(EdbInit):
|
|
|
2847
2883
|
Dict[str,:class:`SiwaveSimulationSetup`] or
|
|
2848
2884
|
Dict[str,:class:`SIWaveDCIRSimulationSetup`] or
|
|
2849
2885
|
Dict[str,:class:`RaptorXSimulationSetup`]
|
|
2886
|
+
Dict[str,:class:`SIWaveCPASimulationSetup`]
|
|
2850
2887
|
|
|
2851
2888
|
"""
|
|
2852
|
-
|
|
2889
|
+
from ansys.edb.core.database import ProductIdType as GrpcProductIdType
|
|
2890
|
+
|
|
2891
|
+
from pyedb.siwave_core.product_properties import SIwaveProperties
|
|
2892
|
+
|
|
2893
|
+
setups = {}
|
|
2853
2894
|
for setup in self.active_cell.simulation_setups:
|
|
2854
2895
|
setup = setup.cast()
|
|
2855
2896
|
setup_type = setup.type.name
|
|
2856
2897
|
if setup_type == "HFSS":
|
|
2857
|
-
|
|
2898
|
+
setups[setup.name] = HfssSimulationSetup(self, setup)
|
|
2858
2899
|
elif setup_type == "SI_WAVE":
|
|
2859
|
-
|
|
2900
|
+
setups[setup.name] = SiwaveSimulationSetup(self, setup)
|
|
2860
2901
|
elif setup_type == "SI_WAVE_DCIR":
|
|
2861
|
-
|
|
2902
|
+
setups[setup.name] = SIWaveDCIRSimulationSetup(self, setup)
|
|
2862
2903
|
elif setup_type == "RAPTOR_X":
|
|
2863
|
-
|
|
2864
|
-
|
|
2904
|
+
setups[setup.name] = RaptorXSimulationSetup(self, setup)
|
|
2905
|
+
try:
|
|
2906
|
+
cpa_setup_name = self.active_cell.get_product_property(
|
|
2907
|
+
GrpcProductIdType.SIWAVE, SIwaveProperties.CPA_SIM_NAME
|
|
2908
|
+
).value
|
|
2909
|
+
except:
|
|
2910
|
+
cpa_setup_name = ""
|
|
2911
|
+
if cpa_setup_name:
|
|
2912
|
+
setups[cpa_setup_name] = SIWaveCPASimulationSetup(self, cpa_setup_name)
|
|
2913
|
+
return setups
|
|
2865
2914
|
|
|
2866
2915
|
@property
|
|
2867
2916
|
def hfss_setups(self) -> dict[str, HfssSimulationSetup]:
|
|
@@ -3409,7 +3458,7 @@ class Edb(EdbInit):
|
|
|
3409
3458
|
_layers = {k: v for k, v in self.stackup.layers.items() if k in layer_filter}
|
|
3410
3459
|
for layer_name, layer in _layers.items():
|
|
3411
3460
|
var, val = _apply_variable(f"${layer_name}", layer.thickness)
|
|
3412
|
-
layer.thickness =
|
|
3461
|
+
layer.thickness = Value(var, self.active_db)
|
|
3413
3462
|
parameters.append(val)
|
|
3414
3463
|
if materials:
|
|
3415
3464
|
if not material_filter:
|
|
@@ -3419,14 +3468,14 @@ class Edb(EdbInit):
|
|
|
3419
3468
|
for mat_name, material in _materials.items():
|
|
3420
3469
|
if not material.conductivity or material.conductivity < 1e4:
|
|
3421
3470
|
var, val = _apply_variable(f"$epsr_{mat_name}", material.permittivity)
|
|
3422
|
-
material.permittivity =
|
|
3471
|
+
material.permittivity = Value(var, self.active_db)
|
|
3423
3472
|
parameters.append(val)
|
|
3424
3473
|
var, val = _apply_variable(f"$loss_tangent_{mat_name}", material.dielectric_loss_tangent)
|
|
3425
|
-
material.dielectric_loss_tangent =
|
|
3474
|
+
material.dielectric_loss_tangent = Value(var, self.active_db)
|
|
3426
3475
|
parameters.append(val)
|
|
3427
3476
|
else:
|
|
3428
3477
|
var, val = _apply_variable(f"$sigma_{mat_name}", material.conductivity)
|
|
3429
|
-
material.conductivity =
|
|
3478
|
+
material.conductivity = Value(var, self.active_db)
|
|
3430
3479
|
parameters.append(val)
|
|
3431
3480
|
if traces:
|
|
3432
3481
|
if not trace_net_filter:
|
|
@@ -3442,7 +3491,7 @@ class Edb(EdbInit):
|
|
|
3442
3491
|
else:
|
|
3443
3492
|
trace_width_variable = f"{path.aedt_name}"
|
|
3444
3493
|
var, val = _apply_variable(trace_width_variable, path.width)
|
|
3445
|
-
path.width =
|
|
3494
|
+
path.width = Value(var, self.active_cell)
|
|
3446
3495
|
parameters.append(val)
|
|
3447
3496
|
if not padstack_definition_filter:
|
|
3448
3497
|
if trace_net_filter:
|
|
@@ -3469,7 +3518,7 @@ class Edb(EdbInit):
|
|
|
3469
3518
|
hole_variable = f"${def_name}_hole_diameter"
|
|
3470
3519
|
if padstack_def.hole_diameter:
|
|
3471
3520
|
var, val = _apply_variable(hole_variable, padstack_def.hole_diameter)
|
|
3472
|
-
padstack_def.hole_properties =
|
|
3521
|
+
padstack_def.hole_properties = Value(var, self.active_db)
|
|
3473
3522
|
parameters.append(val)
|
|
3474
3523
|
if pads:
|
|
3475
3524
|
for layer, pad in padstack_def.pad_by_layer.items():
|
|
@@ -3684,7 +3733,7 @@ class Edb(EdbInit):
|
|
|
3684
3733
|
material="pec",
|
|
3685
3734
|
)
|
|
3686
3735
|
if launching_box_thickness:
|
|
3687
|
-
launching_box_thickness = str(
|
|
3736
|
+
launching_box_thickness = str(Value(launching_box_thickness))
|
|
3688
3737
|
cloned_edb.stackup.add_layer(
|
|
3689
3738
|
layer_name="ref",
|
|
3690
3739
|
layer_type="signal",
|
|
@@ -3719,7 +3768,7 @@ class Edb(EdbInit):
|
|
|
3719
3768
|
.parameters_values
|
|
3720
3769
|
)
|
|
3721
3770
|
else:
|
|
3722
|
-
pad_diameter =
|
|
3771
|
+
pad_diameter = Value(terminal_diameter)
|
|
3723
3772
|
_temp_circle = cloned_edb.modeler.create_circle(
|
|
3724
3773
|
layer_name="ports",
|
|
3725
3774
|
x=inst.position[0],
|
|
@@ -3834,3 +3883,38 @@ class Edb(EdbInit):
|
|
|
3834
3883
|
else:
|
|
3835
3884
|
self.logger.info("Comparison correctly completed")
|
|
3836
3885
|
return True
|
|
3886
|
+
|
|
3887
|
+
def import_layout_component(self, component_path) -> GrpcLayoutComponent:
|
|
3888
|
+
"""Import a layout component inside the current layout and place it at the origin.
|
|
3889
|
+
This feature is only supported with PyEDB gRPC. Encryption is not yet supported.
|
|
3890
|
+
|
|
3891
|
+
Parameters
|
|
3892
|
+
----------
|
|
3893
|
+
component_path : str
|
|
3894
|
+
Layout component path (.aedbcomp file).
|
|
3895
|
+
|
|
3896
|
+
Returns
|
|
3897
|
+
-------
|
|
3898
|
+
class:`LayoutComponent <ansys.edb.core.hierarchy.layout_component.LayoutComponent>`.
|
|
3899
|
+
"""
|
|
3900
|
+
|
|
3901
|
+
return GrpcLayoutComponent.import_layout_component(layout=self.active_layout, aedb_comp_path=component_path)
|
|
3902
|
+
|
|
3903
|
+
def export_layout_component(self, component_path) -> bool:
|
|
3904
|
+
"""Export a layout component from the current layout.
|
|
3905
|
+
This feature is only supported with PyEDB gRPC. Encryption is not yet supported.
|
|
3906
|
+
|
|
3907
|
+
Parameters
|
|
3908
|
+
----------
|
|
3909
|
+
component_path : str
|
|
3910
|
+
Layout component path (.aedbcomp file).
|
|
3911
|
+
|
|
3912
|
+
Returns
|
|
3913
|
+
-------
|
|
3914
|
+
bool
|
|
3915
|
+
`True` if layout component is successfully exported, `False` otherwise.
|
|
3916
|
+
"""
|
|
3917
|
+
|
|
3918
|
+
return GrpcLayoutComponent.export_layout_component(
|
|
3919
|
+
layout=self.active_layout, output_aedb_comp_path=component_path
|
|
3920
|
+
)
|
pyedb/grpc/edb_init.py
CHANGED
|
@@ -34,7 +34,6 @@ from pyedb import __version__
|
|
|
34
34
|
from pyedb.edb_logger import pyedb_logger
|
|
35
35
|
from pyedb.generic.general_methods import env_path, env_value, is_linux
|
|
36
36
|
from pyedb.grpc.rpc_session import RpcSession
|
|
37
|
-
from pyedb.misc.misc import list_installed_ansysem
|
|
38
37
|
|
|
39
38
|
|
|
40
39
|
class EdbInit(object):
|
|
@@ -43,12 +42,6 @@ class EdbInit(object):
|
|
|
43
42
|
def __init__(self, edbversion):
|
|
44
43
|
self.logger = pyedb_logger
|
|
45
44
|
self._db = None
|
|
46
|
-
if not edbversion: # pragma: no cover
|
|
47
|
-
try:
|
|
48
|
-
edbversion = "20{}.{}".format(list_installed_ansysem()[0][-3:-1], list_installed_ansysem()[0][-1:])
|
|
49
|
-
self.logger.info("Edb version " + edbversion)
|
|
50
|
-
except IndexError:
|
|
51
|
-
raise Exception("No ANSYSEM_ROOTxxx is found.")
|
|
52
45
|
self.edbversion = edbversion
|
|
53
46
|
self.logger.info("Logger is initialized in EDB.")
|
|
54
47
|
self.logger.info("legacy v%s", __version__)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
from typing import Dict, List
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SolverOptions(BaseModel):
|
|
7
|
+
"""Configuration options for the SI-Wave solver.
|
|
8
|
+
|
|
9
|
+
Attributes:
|
|
10
|
+
extraction_mode (str): Mode of extraction, defaults to "si"
|
|
11
|
+
custom_refinement (bool): Enable custom refinement settings, defaults to False
|
|
12
|
+
extraction_frequency (str): Frequency for extraction, defaults to "10Ghz"
|
|
13
|
+
compute_capacitance (bool): Enable capacitance computation, defaults to True
|
|
14
|
+
compute_dc_parameters (bool): Enable DC parameters computation, defaults to True
|
|
15
|
+
compute_ac_rl (bool): Enable AC RL computation, defaults to True
|
|
16
|
+
ground_power_ground_nets_for_si (bool): Ground power/ground nets for SI analysis, defaults to False
|
|
17
|
+
small_hole_diameter (str): Small hole diameter setting, defaults to "auto"
|
|
18
|
+
cg_max_passes (int): Maximum passes for CG computation, defaults to 10
|
|
19
|
+
cg_percent_error (float): Percentage error threshold for CG computation, defaults to 0.02
|
|
20
|
+
cg_percent_refinement_per_pass (float): Refinement percentage per pass for CG, defaults to 0.33
|
|
21
|
+
rl_max_passes (int): Maximum passes for RL computation, defaults to 10
|
|
22
|
+
rl_percent_error (float): Percentage error threshold for RL computation, defaults to 0.02
|
|
23
|
+
rl_percent_refinement_per_pass (float): Refinement percentage per pass for RL, defaults to 0.33
|
|
24
|
+
compute_dc_rl (bool): Enable DC RL computation, defaults to True
|
|
25
|
+
compute_dc_cg (bool): Enable DC CG computation, defaults to True
|
|
26
|
+
return_path_net_for_loop_parameters (bool): Include return path net for loop parameters, defaults to True
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
extraction_mode: str = "si"
|
|
30
|
+
custom_refinement: bool = False
|
|
31
|
+
extraction_frequency: str = "10Ghz"
|
|
32
|
+
compute_capacitance: bool = True
|
|
33
|
+
compute_dc_parameters: bool = True
|
|
34
|
+
compute_ac_rl: bool = True
|
|
35
|
+
ground_power_ground_nets_for_si: bool = False
|
|
36
|
+
small_hole_diameter: str = "auto"
|
|
37
|
+
cg_max_passes: int = 10
|
|
38
|
+
cg_percent_error: float = 0.02
|
|
39
|
+
cg_percent_refinement_per_pass: float = 0.33
|
|
40
|
+
rl_max_passes: int = 10
|
|
41
|
+
rl_percent_error: float = 0.02
|
|
42
|
+
rl_percent_refinement_per_pass: float = 0.33
|
|
43
|
+
compute_dc_rl: bool = True
|
|
44
|
+
compute_dc_cg: bool = True
|
|
45
|
+
return_path_net_for_loop_parameters: bool = True
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Vrm(BaseModel):
|
|
49
|
+
"""Voltage Regulator Module configuration.
|
|
50
|
+
|
|
51
|
+
Attributes:
|
|
52
|
+
name (str): Name of the VRM, defaults to empty string
|
|
53
|
+
voltage (float): Voltage value, defaults to 0.0
|
|
54
|
+
power_net (str): Power net identifier, defaults to empty string
|
|
55
|
+
reference_net (str): Reference net identifier, defaults to empty string
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
name: str = ""
|
|
59
|
+
voltage: float = 0.0
|
|
60
|
+
power_net: str = ""
|
|
61
|
+
reference_net: str = ""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class ChannelSetup(BaseModel):
|
|
65
|
+
"""Channel configuration setup.
|
|
66
|
+
|
|
67
|
+
Attributes:
|
|
68
|
+
die_name (str): Name of the die, defaults to empty string
|
|
69
|
+
pin_grouping_mode (str): Mode for pin grouping, defaults to "perpin"
|
|
70
|
+
channel_component_exposure (Dict[str, bool]): Component exposure settings
|
|
71
|
+
vrm_setup (List[Vrm]): List of VRM configurations
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
die_name: str = ""
|
|
75
|
+
pin_grouping_mode: str = "perpin"
|
|
76
|
+
channel_component_exposure: Dict[str, bool] = Field(default_factory=dict)
|
|
77
|
+
vrm_setup: List[Vrm] = Field(default_factory=list)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class SIwaveCpaSetup(BaseModel):
|
|
81
|
+
"""Main configuration class for SI-Wave CPA (Channel Parameter Analyzer) setup.
|
|
82
|
+
|
|
83
|
+
Attributes:
|
|
84
|
+
name (str): Name of the setup, defaults to empty string
|
|
85
|
+
mode (str): Operation mode, defaults to "channel"
|
|
86
|
+
model_type (str): Type of model, defaults to "rlcg"
|
|
87
|
+
use_q3d_solver (bool): Use Q3D solver flag, defaults to True
|
|
88
|
+
net_processing_mode (str): Net processing mode, defaults to "userspecified"
|
|
89
|
+
return_path_net_for_loop_parameters (bool): Include return path net for loop parameters, defaults to True
|
|
90
|
+
channel_setup (ChannelSetup): Channel configuration settings
|
|
91
|
+
solver_options (SolverOptions): Solver configuration options
|
|
92
|
+
nets_to_process (List[str]): List of nets to process
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
name: str = ""
|
|
96
|
+
mode: str = "channel"
|
|
97
|
+
model_type: str = "rlcg"
|
|
98
|
+
use_q3d_solver: bool = True
|
|
99
|
+
net_processing_mode: str = "userspecified"
|
|
100
|
+
return_path_net_for_loop_parameters: bool = True
|
|
101
|
+
channel_setup: ChannelSetup = Field(default_factory=ChannelSetup)
|
|
102
|
+
solver_options: SolverOptions = Field(default_factory=SolverOptions)
|
|
103
|
+
nets_to_process: List[str] = Field(default_factory=list)
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def from_dict(cls, data: Dict) -> "SIwaveCpaSetup":
|
|
107
|
+
"""Convert dictionary to SIwaveCpaSetup object.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
data (Dict): Dictionary containing SIwaveCpaSetup configuration
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
SIwaveCpaSetup: New instance created from the dictionary
|
|
114
|
+
"""
|
|
115
|
+
if "channel_setup" in data:
|
|
116
|
+
data["channel_setup"] = ChannelSetup(**data["channel_setup"])
|
|
117
|
+
if "solver_options" in data:
|
|
118
|
+
data["solver_options"] = SolverOptions(**data["solver_options"])
|
|
119
|
+
return cls(**data)
|
|
120
|
+
|
|
121
|
+
def to_dict(self) -> Dict:
|
|
122
|
+
"""Convert SIwaveCpaSetup object to dictionary.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Dict: Dictionary representation of the SIwaveCpaSetup instance
|
|
126
|
+
"""
|
|
127
|
+
data = self.model_dump()
|
|
128
|
+
if self.channel_setup:
|
|
129
|
+
data["channel_setup"] = self.channel_setup.model_dump()
|
|
130
|
+
if self.solver_options:
|
|
131
|
+
data["solver_options"] = self.solver_options.model_dump()
|
|
132
|
+
return data
|