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.

Files changed (97) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_common.py +12 -15
  3. pyedb/configuration/cfg_data.py +2 -2
  4. pyedb/configuration/cfg_modeler.py +163 -234
  5. pyedb/configuration/cfg_ports_sources.py +6 -8
  6. pyedb/configuration/cfg_stackup.py +62 -249
  7. pyedb/configuration/configuration.py +272 -170
  8. pyedb/dotnet/database/cell/hierarchy/model.py +1 -1
  9. pyedb/dotnet/database/cell/layout.py +1 -1
  10. pyedb/dotnet/database/cell/layout_obj.py +3 -3
  11. pyedb/dotnet/database/cell/primitive/path.py +1 -1
  12. pyedb/dotnet/database/cell/primitive/primitive.py +8 -8
  13. pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
  14. pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
  15. pyedb/dotnet/database/cell/terminal/terminal.py +24 -26
  16. pyedb/dotnet/database/components.py +33 -27
  17. pyedb/dotnet/database/definition/component_def.py +3 -3
  18. pyedb/dotnet/database/definition/component_model.py +1 -1
  19. pyedb/dotnet/database/definition/package_def.py +1 -1
  20. pyedb/dotnet/database/dotnet/database.py +47 -38
  21. pyedb/dotnet/database/dotnet/primitive.py +16 -16
  22. pyedb/dotnet/database/edb_data/hfss_extent_info.py +6 -6
  23. pyedb/dotnet/database/edb_data/layer_data.py +17 -15
  24. pyedb/dotnet/database/edb_data/padstacks_data.py +12 -12
  25. pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
  26. pyedb/dotnet/database/edb_data/sources.py +6 -6
  27. pyedb/dotnet/database/edb_data/variables.py +7 -3
  28. pyedb/dotnet/database/geometry/point_data.py +1 -1
  29. pyedb/dotnet/database/geometry/polygon_data.py +2 -4
  30. pyedb/dotnet/database/hfss.py +7 -7
  31. pyedb/dotnet/database/materials.py +2 -2
  32. pyedb/dotnet/database/modeler.py +8 -11
  33. pyedb/dotnet/database/nets.py +1 -1
  34. pyedb/dotnet/database/padstack.py +72 -1
  35. pyedb/dotnet/database/sim_setup_data/data/settings.py +24 -0
  36. pyedb/dotnet/database/sim_setup_data/io/siwave.py +26 -1
  37. pyedb/dotnet/database/siwave.py +19 -5
  38. pyedb/dotnet/database/stackup.py +80 -137
  39. pyedb/dotnet/database/utilities/heatsink.py +4 -4
  40. pyedb/dotnet/database/utilities/obj_base.py +1 -1
  41. pyedb/dotnet/database/utilities/simulation_setup.py +1 -1
  42. pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +894 -0
  43. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +15 -0
  44. pyedb/dotnet/database/utilities/value.py +116 -0
  45. pyedb/dotnet/edb.py +58 -45
  46. pyedb/generic/design_types.py +39 -1
  47. pyedb/generic/grpc_warnings.py +5 -0
  48. pyedb/grpc/__init__.py +0 -0
  49. pyedb/grpc/database/components.py +155 -98
  50. pyedb/grpc/database/control_file.py +240 -193
  51. pyedb/grpc/database/definition/materials.py +23 -30
  52. pyedb/grpc/database/definition/package_def.py +15 -15
  53. pyedb/grpc/database/definition/padstack_def.py +51 -51
  54. pyedb/grpc/database/definitions.py +7 -5
  55. pyedb/grpc/database/geometry/arc_data.py +7 -5
  56. pyedb/grpc/database/geometry/point_3d_data.py +8 -7
  57. pyedb/grpc/database/geometry/polygon_data.py +3 -2
  58. pyedb/grpc/database/hierarchy/component.py +43 -38
  59. pyedb/grpc/database/hierarchy/pin_pair_model.py +15 -14
  60. pyedb/grpc/database/hierarchy/pingroup.py +9 -9
  61. pyedb/grpc/database/layers/stackup_layer.py +45 -44
  62. pyedb/grpc/database/layout/layout.py +9 -8
  63. pyedb/grpc/database/layout/voltage_regulator.py +7 -7
  64. pyedb/grpc/database/layout_validation.py +13 -12
  65. pyedb/grpc/database/modeler.py +156 -131
  66. pyedb/grpc/database/nets.py +42 -31
  67. pyedb/grpc/database/padstacks.py +270 -175
  68. pyedb/grpc/database/ports/ports.py +5 -6
  69. pyedb/grpc/database/primitive/bondwire.py +8 -7
  70. pyedb/grpc/database/primitive/circle.py +4 -4
  71. pyedb/grpc/database/primitive/padstack_instance.py +18 -18
  72. pyedb/grpc/database/primitive/path.py +7 -7
  73. pyedb/grpc/database/primitive/polygon.py +3 -3
  74. pyedb/grpc/database/primitive/primitive.py +13 -17
  75. pyedb/grpc/database/primitive/rectangle.py +13 -13
  76. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
  77. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +10 -0
  78. pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +961 -0
  79. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +17 -1
  80. pyedb/grpc/database/siwave.py +44 -24
  81. pyedb/grpc/database/source_excitations.py +333 -229
  82. pyedb/grpc/database/stackup.py +164 -147
  83. pyedb/grpc/database/terminal/bundle_terminal.py +17 -7
  84. pyedb/grpc/database/terminal/edge_terminal.py +10 -0
  85. pyedb/grpc/database/terminal/padstack_instance_terminal.py +15 -4
  86. pyedb/grpc/database/terminal/pingroup_terminal.py +11 -10
  87. pyedb/grpc/database/terminal/point_terminal.py +4 -3
  88. pyedb/grpc/database/terminal/terminal.py +9 -9
  89. pyedb/grpc/database/utility/value.py +109 -0
  90. pyedb/grpc/edb.py +129 -45
  91. pyedb/grpc/edb_init.py +0 -7
  92. pyedb/siwave_core/cpa/simulation_setup_data_model.py +132 -0
  93. pyedb/siwave_core/product_properties.py +198 -0
  94. {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/METADATA +15 -13
  95. {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/RECORD +97 -89
  96. {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/WHEEL +1 -1
  97. {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.open_edb(restart_rpc_server=restart_rpc_server)
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.create_edb(restart_rpc_server=restart_rpc_server)
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.open_edb(restart_rpc_server=restart_rpc_server)
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).value for i in self.active_cell.get_all_variable_names()}
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).value for i in self.active_db.get_all_variable_names()}
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 self.terminals
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.value == 8]
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.edb_api.utility.utility.Command.Execute(func)
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.value, pd.y.value])
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 = GrpcValue(expansion_size).value
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.value, pt.y.value] for pt in _poly.without_arcs().points]
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 = GrpcValue(expansion_size).value
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
- i.delete()
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.value, pt.y.value] for pt in _poly.without_arcs().points]
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 = GrpcValue(p.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.value, pt.y.value] for pt in polygon_data.without_arcs().points]
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 "$" in variable_name:
2655
- if variable_name.index("$") == 0:
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, GrpcValue(variable_value))
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, GrpcValue(variable_value))
2762
+ self.active_cell.set_variable_value(variable_name, Value(variable_value))
2736
2763
 
2737
- def get_bounding_box(self) -> list[list[float, float], list[float, float]]:
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 [[layout_bbox[0].x.value, layout_bbox[0].y.value], [layout_bbox[1].x.value, layout_bbox[1].y.value]]
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
- ) -> Union[HfssSimulationSetup, SiwaveSimulationSetup, SIWaveDCIRSimulationSetup, RaptorXSimulationSetup]:
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
- self._setups = {}
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
- self._setups[setup.name] = HfssSimulationSetup(self, setup)
2898
+ setups[setup.name] = HfssSimulationSetup(self, setup)
2858
2899
  elif setup_type == "SI_WAVE":
2859
- self._setups[setup.name] = SiwaveSimulationSetup(self, setup)
2900
+ setups[setup.name] = SiwaveSimulationSetup(self, setup)
2860
2901
  elif setup_type == "SI_WAVE_DCIR":
2861
- self._setups[setup.name] = SIWaveDCIRSimulationSetup(self, setup)
2902
+ setups[setup.name] = SIWaveDCIRSimulationSetup(self, setup)
2862
2903
  elif setup_type == "RAPTOR_X":
2863
- self._setups[setup.name] = RaptorXSimulationSetup(self, setup)
2864
- return self._setups
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 = GrpcValue(var, self.active_db)
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 = GrpcValue(var, self.active_db)
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 = GrpcValue(var, self.active_db)
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 = GrpcValue(var, self.active_db)
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 = GrpcValue(var, self.active_cell)
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 = GrpcValue(var, self.active_db)
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(GrpcValue(launching_box_thickness))
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 = GrpcValue(terminal_diameter).value
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