pyedb 0.18.0__py3-none-any.whl → 0.20.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyedb might be problematic. Click here for more details.

Files changed (54) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_data.py +8 -11
  3. pyedb/configuration/cfg_nets.py +14 -0
  4. pyedb/configuration/cfg_pin_groups.py +57 -20
  5. pyedb/configuration/cfg_ports_sources.py +248 -60
  6. pyedb/configuration/configuration.py +51 -17
  7. pyedb/dotnet/edb.py +156 -236
  8. pyedb/dotnet/edb_core/cell/connectable.py +64 -0
  9. pyedb/dotnet/edb_core/cell/hierarchy/component.py +12 -10
  10. pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py +1 -1
  11. pyedb/dotnet/edb_core/cell/layout.py +271 -76
  12. pyedb/dotnet/edb_core/cell/layout_obj.py +4 -49
  13. pyedb/dotnet/edb_core/cell/primitive.py +14 -2
  14. pyedb/dotnet/edb_core/cell/terminal/padstack_instance_terminal.py +10 -0
  15. pyedb/dotnet/edb_core/cell/terminal/pingroup_terminal.py +5 -0
  16. pyedb/dotnet/edb_core/cell/terminal/point_terminal.py +1 -12
  17. pyedb/dotnet/edb_core/cell/terminal/terminal.py +36 -20
  18. pyedb/dotnet/edb_core/cell/voltage_regulator.py +2 -16
  19. pyedb/dotnet/edb_core/components.py +88 -31
  20. pyedb/dotnet/edb_core/dotnet/database.py +5 -10
  21. pyedb/dotnet/edb_core/dotnet/primitive.py +20 -7
  22. pyedb/dotnet/edb_core/edb_data/control_file.py +2 -12
  23. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +28 -37
  24. pyedb/dotnet/edb_core/edb_data/ports.py +0 -18
  25. pyedb/dotnet/edb_core/edb_data/primitives_data.py +1 -1
  26. pyedb/dotnet/edb_core/general.py +6 -9
  27. pyedb/dotnet/edb_core/hfss.py +4 -8
  28. pyedb/dotnet/edb_core/layout_obj_instance.py +30 -0
  29. pyedb/dotnet/edb_core/materials.py +4 -11
  30. pyedb/dotnet/edb_core/{layout.py → modeler.py} +153 -7
  31. pyedb/dotnet/edb_core/net_class.py +7 -8
  32. pyedb/dotnet/edb_core/nets.py +3 -9
  33. pyedb/dotnet/edb_core/padstack.py +23 -10
  34. pyedb/dotnet/edb_core/sim_setup_data/data/sim_setup_info.py +42 -3
  35. pyedb/dotnet/edb_core/sim_setup_data/data/simulation_settings.py +92 -158
  36. pyedb/dotnet/edb_core/sim_setup_data/data/siw_dc_ir_settings.py +22 -22
  37. pyedb/dotnet/edb_core/sim_setup_data/data/sweep_data.py +5 -2
  38. pyedb/dotnet/edb_core/sim_setup_data/io/siwave.py +76 -76
  39. pyedb/dotnet/edb_core/siwave.py +5 -6
  40. pyedb/dotnet/edb_core/stackup.py +18 -23
  41. pyedb/dotnet/edb_core/utilities/hfss_simulation_setup.py +23 -94
  42. pyedb/dotnet/edb_core/utilities/simulation_setup.py +40 -41
  43. pyedb/dotnet/edb_core/utilities/siwave_simulation_setup.py +26 -17
  44. pyedb/generic/filesystem.py +2 -8
  45. pyedb/generic/general_methods.py +4 -10
  46. pyedb/generic/plot.py +26 -29
  47. pyedb/generic/process.py +2 -6
  48. pyedb/misc/downloads.py +3 -40
  49. pyedb/siwave.py +2 -5
  50. {pyedb-0.18.0.dist-info → pyedb-0.20.0.dist-info}/METADATA +8 -8
  51. {pyedb-0.18.0.dist-info → pyedb-0.20.0.dist-info}/RECORD +53 -52
  52. pyedb/dotnet/edb_core/dotnet/layout.py +0 -260
  53. {pyedb-0.18.0.dist-info → pyedb-0.20.0.dist-info}/LICENSE +0 -0
  54. {pyedb-0.18.0.dist-info → pyedb-0.20.0.dist-info}/WHEEL +0 -0
@@ -65,14 +65,16 @@ class Configuration:
65
65
  """
66
66
  if isinstance(config_file, dict):
67
67
  data = config_file
68
- elif os.path.isfile(config_file):
69
- with open(config_file, "r") as f:
70
- if config_file.endswith(".json"):
71
- data = json.load(f)
72
- elif config_file.endswith(".toml"):
73
- data = toml.load(f)
74
- else: # pragma: no cover
75
- return False
68
+ else:
69
+ config_file = str(config_file)
70
+ if os.path.isfile(config_file):
71
+ with open(config_file, "r") as f:
72
+ if config_file.endswith(".json"):
73
+ data = json.load(f)
74
+ elif config_file.endswith(".toml"):
75
+ data = toml.load(f)
76
+ else: # pragma: no cover
77
+ return False
76
78
 
77
79
  if not append: # pragma: no cover
78
80
  self.data = {}
@@ -120,16 +122,13 @@ class Configuration:
120
122
  self.cfg_data.padstacks.apply()
121
123
 
122
124
  # Configure pin groups
123
- for pin_group in self.cfg_data.pin_groups:
124
- pin_group.apply()
125
+ self.cfg_data.pin_groups.apply()
125
126
 
126
127
  # Configure ports
127
- for port in self.cfg_data.ports:
128
- port.create()
128
+ self.cfg_data.ports.apply()
129
129
 
130
130
  # Configure sources
131
- for source in self.cfg_data.sources:
132
- source.create()
131
+ self.cfg_data.sources.apply()
133
132
 
134
133
  # Configure setup
135
134
  self.cfg_data.setups.apply()
@@ -271,12 +270,30 @@ class Configuration:
271
270
  data["package_definitions"] = self.cfg_data.package_definitions.get_data_from_db()
272
271
  if kwargs.get("setups", False):
273
272
  data["setups"] = self.cfg_data.setups.get_data_from_db()
273
+ if kwargs.get("sources", False):
274
+ data["sources"] = self.cfg_data.sources.get_data_from_db()
275
+ if kwargs.get("ports", False):
276
+ data["ports"] = self.cfg_data.ports.get_data_from_db()
274
277
  if kwargs.get("components", False):
275
278
  data["components"] = self.cfg_data.components.get_data_from_db()
279
+ if kwargs.get("nets", False):
280
+ data["nets"] = self.cfg_data.nets.get_data_from_db()
281
+ if kwargs.get("pin_groups", False):
282
+ data["pin_groups"] = self.cfg_data.pin_groups.get_data_from_db()
276
283
 
277
284
  return data
278
285
 
279
- def export(self, file_path, stackup=True, package_definitions=True, setups=True):
286
+ def export(
287
+ self,
288
+ file_path,
289
+ stackup=True,
290
+ package_definitions=True,
291
+ setups=True,
292
+ sources=True,
293
+ ports=True,
294
+ nets=True,
295
+ pin_groups=True,
296
+ ):
280
297
  """Export the configuration data from layout to a file.
281
298
 
282
299
  Parameters
@@ -285,14 +302,31 @@ class Configuration:
285
302
  File path to export the configuration data.
286
303
  stackup : bool
287
304
  Whether to export stackup or not.
288
-
305
+ package_definitions : bool
306
+ Whether to export package definitions or not.
307
+ setups : bool
308
+ Whether to export setups or not.
309
+ sources : bool
310
+ Whether to export sources or not.
311
+ ports : bool
312
+ Whether to export ports or not.
313
+ nets : bool
314
+ Whether to export nets.
289
315
  Returns
290
316
  -------
291
317
  bool
292
318
  """
293
319
  file_path = file_path if isinstance(file_path, Path) else Path(file_path)
294
320
  file_path = file_path if file_path.suffix == ".json" else file_path.with_suffix(".json")
295
- data = self.get_data_from_db(stackup=stackup, package_definitions=package_definitions, setups=setups)
321
+ data = self.get_data_from_db(
322
+ stackup=stackup,
323
+ package_definitions=package_definitions,
324
+ setups=setups,
325
+ sources=sources,
326
+ ports=ports,
327
+ nets=nets,
328
+ pin_groups=pin_groups,
329
+ )
296
330
  with open(file_path, "w") as f:
297
331
  json.dump(data, f, ensure_ascii=False, indent=4)
298
332
  return True if os.path.isfile(file_path) else False
pyedb/dotnet/edb.py CHANGED
@@ -30,6 +30,7 @@ import os
30
30
  from pathlib import Path
31
31
  import re
32
32
  import shutil
33
+ import subprocess
33
34
  import sys
34
35
  import tempfile
35
36
  import time
@@ -37,21 +38,14 @@ import traceback
37
38
  from typing import Union
38
39
  import warnings
39
40
 
41
+ import rtree
42
+
40
43
  from pyedb.configuration.configuration import Configuration
41
44
  from pyedb.dotnet.application.Variables import decompose_variable_value
42
45
  from pyedb.dotnet.edb_core.cell.layout import Layout
43
- from pyedb.dotnet.edb_core.cell.terminal.bundle_terminal import BundleTerminal
44
- from pyedb.dotnet.edb_core.cell.terminal.edge_terminal import EdgeTerminal
45
- from pyedb.dotnet.edb_core.cell.terminal.padstack_instance_terminal import (
46
- PadstackInstanceTerminal,
47
- )
48
- from pyedb.dotnet.edb_core.cell.terminal.pingroup_terminal import PinGroupTerminal
49
- from pyedb.dotnet.edb_core.cell.terminal.point_terminal import PointTerminal
50
46
  from pyedb.dotnet.edb_core.cell.terminal.terminal import Terminal
51
- from pyedb.dotnet.edb_core.cell.voltage_regulator import VoltageRegulator
52
47
  from pyedb.dotnet.edb_core.components import Components
53
48
  from pyedb.dotnet.edb_core.dotnet.database import Database
54
- from pyedb.dotnet.edb_core.dotnet.layout import LayoutDotNet
55
49
  from pyedb.dotnet.edb_core.edb_data.control_file import (
56
50
  ControlFile,
57
51
  convert_technology_file,
@@ -82,6 +76,7 @@ from pyedb.dotnet.edb_core.general import (
82
76
  from pyedb.dotnet.edb_core.hfss import EdbHfss
83
77
  from pyedb.dotnet.edb_core.layout_validation import LayoutValidation
84
78
  from pyedb.dotnet.edb_core.materials import Materials
79
+ from pyedb.dotnet.edb_core.modeler import Modeler
85
80
  from pyedb.dotnet.edb_core.net_class import (
86
81
  EdbDifferentialPairs,
87
82
  EdbExtendedNets,
@@ -103,8 +98,6 @@ from pyedb.generic.constants import AEDT_UNITS, SolverType
103
98
  from pyedb.generic.general_methods import (
104
99
  generate_unique_name,
105
100
  get_string_version,
106
- inside_desktop,
107
- is_ironpython,
108
101
  is_linux,
109
102
  is_windows,
110
103
  )
@@ -114,13 +107,6 @@ from pyedb.ipc2581.ipc2581 import Ipc2581
114
107
  from pyedb.modeler.geometry_operators import GeometryOperators
115
108
  from pyedb.workflow import Workflow
116
109
 
117
- if is_linux and is_ironpython:
118
- import subprocessdotnet as subprocess
119
- else:
120
- import subprocess
121
-
122
- import rtree
123
-
124
110
 
125
111
  class Edb(Database):
126
112
  """Provides the EDB application interface.
@@ -235,9 +221,7 @@ class Edb(Database):
235
221
  if not isreadonly:
236
222
  self._check_remove_project_files(edbpath, remove_existing_aedt)
237
223
 
238
- if isaedtowned and (inside_desktop or settings.remote_rpc_session):
239
- self.open_edb_inside_aedt()
240
- elif edbpath[-3:] in ["brd", "mcm", "sip", "gds", "xml", "dxf", "tgz", "anf"]:
224
+ if edbpath[-3:] in ["brd", "mcm", "sip", "gds", "xml", "dxf", "tgz", "anf"]:
241
225
  self.edbpath = edbpath[:-4] + ".aedb"
242
226
  working_dir = os.path.dirname(edbpath)
243
227
  control_file = None
@@ -361,7 +345,7 @@ class Edb(Database):
361
345
  self._siwave = EdbSiwave(self)
362
346
  self._hfss = EdbHfss(self)
363
347
  self._nets = EdbNets(self)
364
- self._core_primitives = Layout(self, self._active_cell.GetLayout())
348
+ self._core_primitives = Modeler(self)
365
349
  self._stackup2 = self._stackup
366
350
  self._materials = Materials(self)
367
351
 
@@ -437,23 +421,10 @@ class Edb(Database):
437
421
 
438
422
  Returns
439
423
  -------
440
- Terminal dictionary : Dict[str, pyedb.dotnet.edb_core.edb_data.terminals.Terminal]
424
+ Dict
441
425
  """
442
426
 
443
- temp = {}
444
- for i in self.layout.terminals:
445
- terminal_type = i.ToString().split(".")[-1]
446
- if terminal_type == "PinGroupTerminal":
447
- temp[i.GetName()] = PinGroupTerminal(self, i)
448
- elif terminal_type == "PadstackInstanceTerminal":
449
- temp[i.GetName()] = PadstackInstanceTerminal(self, i)
450
- elif terminal_type == "EdgeTerminal":
451
- temp[i.GetName()] = EdgeTerminal(self, i)
452
- elif terminal_type == "BundleTerminal":
453
- temp[i.GetName()] = BundleTerminal(self, i)
454
- elif terminal_type == "PointTerminal":
455
- temp[i.GetName()] = PointTerminal(self, i)
456
- return temp
427
+ return {i.name: i for i in self.layout.terminals}
457
428
 
458
429
  @property
459
430
  def excitations(self):
@@ -510,12 +481,13 @@ class Edb(Database):
510
481
  def sources(self):
511
482
  """Get all layout sources."""
512
483
  terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [3, 4, 7]]
484
+ terms = [term for term in terms if not term.IsReferenceTerminal()]
513
485
  return {ter.GetName(): ExcitationSources(self, ter) for ter in terms}
514
486
 
515
487
  @property
516
488
  def voltage_regulator_modules(self):
517
489
  """Get all voltage regulator modules"""
518
- vrms = [VoltageRegulator(self, edb_object) for edb_object in list(self.active_layout.VoltageRegulators)]
490
+ vrms = self.layout.voltage_regulators
519
491
  _vrms = {}
520
492
  for vrm in vrms:
521
493
  _vrms[vrm.name] = vrm
@@ -573,40 +545,6 @@ class Edb(Database):
573
545
 
574
546
  return True
575
547
 
576
- def open_edb_inside_aedt(self):
577
- """Open EDB inside AEDT.
578
-
579
- Returns
580
- -------
581
- ``True`` when succeed ``False`` if failed : bool
582
-
583
- """
584
- self.logger.info("Opening EDB from HDL")
585
- self.run_as_standalone(False)
586
- if self.oproject.GetEDBHandle():
587
- self.attach(self.oproject.GetEDBHandle())
588
- if not self.active_db:
589
- self.logger.warning("Error getting the database.")
590
- self._active_cell = None
591
- return None
592
- self._active_cell = self.edb_api.cell.cell.FindByName(
593
- self.active_db,
594
- self.edb_api.cell._cell.CellType.CircuitCell,
595
- self.cellname,
596
- )
597
- if self._active_cell is None:
598
- self._active_cell = list(self.top_circuit_cells)[0]
599
- if self._active_cell:
600
- if not os.path.exists(self.edbpath):
601
- os.makedirs(self.edbpath)
602
- self._init_objects()
603
- return True
604
- else:
605
- return None
606
- else:
607
- self._active_cell = None
608
- return None
609
-
610
548
  def create_edb(self):
611
549
  """Create EDB.
612
550
 
@@ -1152,7 +1090,7 @@ class Edb(Database):
1152
1090
  >>> top_prims = edbapp.modeler.primitives_by_layer["TOP"]
1153
1091
  """
1154
1092
  if not self._core_primitives and self.active_db:
1155
- self._core_primitives = Layout(self, self._active_cell.GetLayout())
1093
+ self._core_primitives = Modeler(self)
1156
1094
  return self._core_primitives
1157
1095
 
1158
1096
  @property
@@ -1163,7 +1101,7 @@ class Edb(Database):
1163
1101
  -------
1164
1102
  :class:`legacy.edb_core.dotnet.layout.Layout`
1165
1103
  """
1166
- return LayoutDotNet(self)
1104
+ return Layout(self, self._active_cell.GetLayout())
1167
1105
 
1168
1106
  @property
1169
1107
  def active_layout(self):
@@ -1173,12 +1111,12 @@ class Edb(Database):
1173
1111
  -------
1174
1112
  Instance of EDB API Layout Class.
1175
1113
  """
1176
- return self.layout._layout
1114
+ return self.layout._edb_object
1177
1115
 
1178
1116
  @property
1179
1117
  def layout_instance(self):
1180
1118
  """Edb Layout Instance."""
1181
- return self.layout.layout_instance
1119
+ return self.layout._edb_object.GetLayoutInstance()
1182
1120
 
1183
1121
  def get_connected_objects(self, layout_object_instance):
1184
1122
  """Get connected objects.
@@ -2217,9 +2155,6 @@ class Edb(Database):
2217
2155
  keep_lines_as_path=False,
2218
2156
  inlcude_voids_in_extents=False,
2219
2157
  ):
2220
- if is_ironpython: # pragma: no cover
2221
- self.logger.error("Method working only in Cpython")
2222
- return False
2223
2158
  from concurrent.futures import ThreadPoolExecutor
2224
2159
 
2225
2160
  if output_aedb_path:
@@ -2749,20 +2684,12 @@ class Edb(Database):
2749
2684
 
2750
2685
  for void_circle in voids_to_add:
2751
2686
  if void_circle.type == "Circle":
2752
- if is_ironpython: # pragma: no cover
2753
- (
2754
- res,
2755
- center_x,
2756
- center_y,
2757
- radius,
2758
- ) = void_circle.primitive_object.GetParameters()
2759
- else:
2760
- (
2761
- res,
2762
- center_x,
2763
- center_y,
2764
- radius,
2765
- ) = void_circle.primitive_object.GetParameters(0.0, 0.0, 0.0)
2687
+ (
2688
+ res,
2689
+ center_x,
2690
+ center_y,
2691
+ radius,
2692
+ ) = void_circle.primitive_object.GetParameters(0.0, 0.0, 0.0)
2766
2693
  cloned_circle = self.edb_api.cell.primitive.circle.create(
2767
2694
  layout,
2768
2695
  void_circle.layer_name,
@@ -3343,163 +3270,156 @@ class Edb(Database):
3343
3270
  legacy_name = self.edbpath
3344
3271
  if simulation_setup.output_aedb:
3345
3272
  self.save_edb_as(simulation_setup.output_aedb)
3346
- try:
3347
- if simulation_setup.signal_layer_etching_instances:
3348
- for layer in simulation_setup.signal_layer_etching_instances:
3349
- if layer in self.stackup.layers:
3350
- idx = simulation_setup.signal_layer_etching_instances.index(layer)
3351
- if len(simulation_setup.etching_factor_instances) > idx:
3352
- self.stackup[layer].etch_factor = float(simulation_setup.etching_factor_instances[idx])
3353
-
3354
- if not simulation_setup.signal_nets and simulation_setup.components:
3355
- nets_to_include = []
3356
- pnets = list(self.nets.power.keys())[:]
3357
- for el in simulation_setup.components:
3358
- nets_to_include.append([i for i in self.components[el].nets if i not in pnets])
3359
- simulation_setup.signal_nets = [
3360
- i
3361
- for i in list(set.intersection(*map(set, nets_to_include)))
3362
- if i not in simulation_setup.power_nets and i != ""
3363
- ]
3364
- self.nets.classify_nets(simulation_setup.power_nets, simulation_setup.signal_nets)
3365
- if not simulation_setup.power_nets or not simulation_setup.signal_nets:
3366
- self.logger.info("Disabling cutout as no signals or power nets have been defined.")
3367
- simulation_setup.do_cutout_subdesign = False
3368
- if simulation_setup.do_cutout_subdesign:
3369
- self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type))
3370
- if simulation_setup.use_default_cutout:
3371
- old_cell_name = self.active_cell.GetName()
3372
- if self.cutout(
3373
- signal_list=simulation_setup.signal_nets,
3374
- reference_list=simulation_setup.power_nets,
3375
- expansion_size=simulation_setup.cutout_subdesign_expansion,
3376
- use_round_corner=simulation_setup.cutout_subdesign_round_corner,
3377
- extent_type=simulation_setup.cutout_subdesign_type,
3378
- use_pyaedt_cutout=False,
3379
- use_pyaedt_extent_computing=False,
3380
- ):
3381
- self.logger.info("Cutout processed.")
3382
- old_cell = self.active_cell.FindByName(
3383
- self.db,
3384
- self.edb_api.cell.CellType.CircuitCell,
3385
- old_cell_name,
3386
- )
3387
- if old_cell:
3388
- old_cell.Delete()
3389
- else: # pragma: no cover
3390
- self.logger.error("Cutout failed.")
3391
- else:
3392
- self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type))
3393
- self.cutout(
3394
- signal_list=simulation_setup.signal_nets,
3395
- reference_list=simulation_setup.power_nets,
3396
- expansion_size=simulation_setup.cutout_subdesign_expansion,
3397
- use_round_corner=simulation_setup.cutout_subdesign_round_corner,
3398
- extent_type=simulation_setup.cutout_subdesign_type,
3399
- use_pyaedt_cutout=True,
3400
- use_pyaedt_extent_computing=True,
3401
- remove_single_pin_components=True,
3402
- )
3273
+ if simulation_setup.signal_layer_etching_instances:
3274
+ for layer in simulation_setup.signal_layer_etching_instances:
3275
+ if layer in self.stackup.layers:
3276
+ idx = simulation_setup.signal_layer_etching_instances.index(layer)
3277
+ if len(simulation_setup.etching_factor_instances) > idx:
3278
+ self.stackup[layer].etch_factor = float(simulation_setup.etching_factor_instances[idx])
3279
+
3280
+ if not simulation_setup.signal_nets and simulation_setup.components:
3281
+ nets_to_include = []
3282
+ pnets = list(self.nets.power.keys())[:]
3283
+ for el in simulation_setup.components:
3284
+ nets_to_include.append([i for i in self.components[el].nets if i not in pnets])
3285
+ simulation_setup.signal_nets = [
3286
+ i
3287
+ for i in list(set.intersection(*map(set, nets_to_include)))
3288
+ if i not in simulation_setup.power_nets and i != ""
3289
+ ]
3290
+ self.nets.classify_nets(simulation_setup.power_nets, simulation_setup.signal_nets)
3291
+ if not simulation_setup.power_nets or not simulation_setup.signal_nets:
3292
+ self.logger.info("Disabling cutout as no signals or power nets have been defined.")
3293
+ simulation_setup.do_cutout_subdesign = False
3294
+ if simulation_setup.do_cutout_subdesign:
3295
+ self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type))
3296
+ if simulation_setup.use_default_cutout:
3297
+ old_cell_name = self.active_cell.GetName()
3298
+ if self.cutout(
3299
+ signal_list=simulation_setup.signal_nets,
3300
+ reference_list=simulation_setup.power_nets,
3301
+ expansion_size=simulation_setup.cutout_subdesign_expansion,
3302
+ use_round_corner=simulation_setup.cutout_subdesign_round_corner,
3303
+ extent_type=simulation_setup.cutout_subdesign_type,
3304
+ use_pyaedt_cutout=False,
3305
+ use_pyaedt_extent_computing=False,
3306
+ ):
3403
3307
  self.logger.info("Cutout processed.")
3308
+ old_cell = self.active_cell.FindByName(
3309
+ self.db,
3310
+ self.edb_api.cell.CellType.CircuitCell,
3311
+ old_cell_name,
3312
+ )
3313
+ if old_cell:
3314
+ old_cell.Delete()
3315
+ else: # pragma: no cover
3316
+ self.logger.error("Cutout failed.")
3404
3317
  else:
3405
- if simulation_setup.include_only_selected_nets:
3406
- included_nets = simulation_setup.signal_nets + simulation_setup.power_nets
3407
- nets_to_remove = [
3408
- net.name for net in list(self.nets.nets.values()) if not net.name in included_nets
3409
- ]
3410
- self.nets.delete(nets_to_remove)
3411
- self.logger.info("Deleting existing ports.")
3412
- map(lambda port: port.Delete(), self.layout.terminals)
3413
- map(lambda pg: pg.Delete(), self.layout.pin_groups)
3414
- if simulation_setup.solver_type == SolverType.Hfss3dLayout:
3415
- if simulation_setup.generate_excitations:
3416
- self.logger.info("Creating HFSS ports for signal nets.")
3417
- source_type = SourceType.CoaxPort
3418
- if not simulation_setup.generate_solder_balls:
3419
- source_type = SourceType.CircPort
3420
- for cmp in simulation_setup.components:
3421
- if isinstance(cmp, str): # keep legacy component
3318
+ self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type))
3319
+ self.cutout(
3320
+ signal_list=simulation_setup.signal_nets,
3321
+ reference_list=simulation_setup.power_nets,
3322
+ expansion_size=simulation_setup.cutout_subdesign_expansion,
3323
+ use_round_corner=simulation_setup.cutout_subdesign_round_corner,
3324
+ extent_type=simulation_setup.cutout_subdesign_type,
3325
+ use_pyaedt_cutout=True,
3326
+ use_pyaedt_extent_computing=True,
3327
+ remove_single_pin_components=True,
3328
+ )
3329
+ self.logger.info("Cutout processed.")
3330
+ else:
3331
+ if simulation_setup.include_only_selected_nets:
3332
+ included_nets = simulation_setup.signal_nets + simulation_setup.power_nets
3333
+ nets_to_remove = [net.name for net in list(self.nets.nets.values()) if not net.name in included_nets]
3334
+ self.nets.delete(nets_to_remove)
3335
+ self.logger.info("Deleting existing ports.")
3336
+ map(lambda port: port.Delete(), self.layout.terminals)
3337
+ map(lambda pg: pg.Delete(), self.layout.pin_groups)
3338
+ if simulation_setup.solver_type == SolverType.Hfss3dLayout:
3339
+ if simulation_setup.generate_excitations:
3340
+ self.logger.info("Creating HFSS ports for signal nets.")
3341
+ source_type = SourceType.CoaxPort
3342
+ if not simulation_setup.generate_solder_balls:
3343
+ source_type = SourceType.CircPort
3344
+ for cmp in simulation_setup.components:
3345
+ if isinstance(cmp, str): # keep legacy component
3346
+ self.components.create_port_on_component(
3347
+ cmp,
3348
+ net_list=simulation_setup.signal_nets,
3349
+ do_pingroup=False,
3350
+ reference_net=simulation_setup.power_nets,
3351
+ port_type=source_type,
3352
+ )
3353
+ elif isinstance(cmp, dict):
3354
+ if "refdes" in cmp:
3355
+ if not "solder_balls_height" in cmp: # pragma no cover
3356
+ cmp["solder_balls_height"] = None
3357
+ if not "solder_balls_size" in cmp: # pragma no cover
3358
+ cmp["solder_balls_size"] = None
3359
+ cmp["solder_balls_mid_size"] = None
3360
+ if not "solder_balls_mid_size" in cmp: # pragma no cover
3361
+ cmp["solder_balls_mid_size"] = None
3422
3362
  self.components.create_port_on_component(
3423
- cmp,
3363
+ cmp["refdes"],
3424
3364
  net_list=simulation_setup.signal_nets,
3425
3365
  do_pingroup=False,
3426
3366
  reference_net=simulation_setup.power_nets,
3427
3367
  port_type=source_type,
3368
+ solder_balls_height=cmp["solder_balls_height"],
3369
+ solder_balls_size=cmp["solder_balls_size"],
3370
+ solder_balls_mid_size=cmp["solder_balls_mid_size"],
3428
3371
  )
3429
- elif isinstance(cmp, dict):
3430
- if "refdes" in cmp:
3431
- if not "solder_balls_height" in cmp: # pragma no cover
3432
- cmp["solder_balls_height"] = None
3433
- if not "solder_balls_size" in cmp: # pragma no cover
3434
- cmp["solder_balls_size"] = None
3435
- cmp["solder_balls_mid_size"] = None
3436
- if not "solder_balls_mid_size" in cmp: # pragma no cover
3437
- cmp["solder_balls_mid_size"] = None
3438
- self.components.create_port_on_component(
3439
- cmp["refdes"],
3440
- net_list=simulation_setup.signal_nets,
3441
- do_pingroup=False,
3442
- reference_net=simulation_setup.power_nets,
3443
- port_type=source_type,
3444
- solder_balls_height=cmp["solder_balls_height"],
3445
- solder_balls_size=cmp["solder_balls_size"],
3446
- solder_balls_mid_size=cmp["solder_balls_mid_size"],
3447
- )
3448
- if simulation_setup.generate_solder_balls and not self.hfss.set_coax_port_attributes(
3449
- simulation_setup
3450
- ): # pragma: no cover
3451
- self.logger.error("Failed to configure coaxial port attributes.")
3452
- self.logger.info("Number of ports: {}".format(self.hfss.get_ports_number()))
3453
- self.logger.info("Configure HFSS extents.")
3454
- if (
3455
- simulation_setup.generate_solder_balls and simulation_setup.trim_reference_size
3456
- ): # pragma: no cover
3457
- self.logger.info(
3458
- "Trimming the reference plane for coaxial ports: {0}".format(
3459
- bool(simulation_setup.trim_reference_size)
3460
- )
3372
+ if simulation_setup.generate_solder_balls and not self.hfss.set_coax_port_attributes(
3373
+ simulation_setup
3374
+ ): # pragma: no cover
3375
+ self.logger.error("Failed to configure coaxial port attributes.")
3376
+ self.logger.info("Number of ports: {}".format(self.hfss.get_ports_number()))
3377
+ self.logger.info("Configure HFSS extents.")
3378
+ if simulation_setup.generate_solder_balls and simulation_setup.trim_reference_size: # pragma: no cover
3379
+ self.logger.info(
3380
+ "Trimming the reference plane for coaxial ports: {0}".format(
3381
+ bool(simulation_setup.trim_reference_size)
3382
+ )
3383
+ )
3384
+ self.hfss.trim_component_reference_size(simulation_setup) # pragma: no cover
3385
+ self.hfss.configure_hfss_extents(simulation_setup)
3386
+ if not self.hfss.configure_hfss_analysis_setup(simulation_setup):
3387
+ self.logger.error("Failed to configure HFSS simulation setup.")
3388
+ if simulation_setup.solver_type == SolverType.SiwaveSYZ:
3389
+ if simulation_setup.generate_excitations:
3390
+ for cmp in simulation_setup.components:
3391
+ if isinstance(cmp, str): # keep legacy
3392
+ self.components.create_port_on_component(
3393
+ cmp,
3394
+ net_list=simulation_setup.signal_nets,
3395
+ do_pingroup=simulation_setup.do_pingroup,
3396
+ reference_net=simulation_setup.power_nets,
3397
+ port_type=SourceType.CircPort,
3461
3398
  )
3462
- self.hfss.trim_component_reference_size(simulation_setup) # pragma: no cover
3463
- self.hfss.configure_hfss_extents(simulation_setup)
3464
- if not self.hfss.configure_hfss_analysis_setup(simulation_setup):
3465
- self.logger.error("Failed to configure HFSS simulation setup.")
3466
- if simulation_setup.solver_type == SolverType.SiwaveSYZ:
3467
- if simulation_setup.generate_excitations:
3468
- for cmp in simulation_setup.components:
3469
- if isinstance(cmp, str): # keep legacy
3399
+ elif isinstance(cmp, dict):
3400
+ if "refdes" in cmp: # pragma no cover
3470
3401
  self.components.create_port_on_component(
3471
- cmp,
3402
+ cmp["refdes"],
3472
3403
  net_list=simulation_setup.signal_nets,
3473
3404
  do_pingroup=simulation_setup.do_pingroup,
3474
3405
  reference_net=simulation_setup.power_nets,
3475
3406
  port_type=SourceType.CircPort,
3476
3407
  )
3477
- elif isinstance(cmp, dict):
3478
- if "refdes" in cmp: # pragma no cover
3479
- self.components.create_port_on_component(
3480
- cmp["refdes"],
3481
- net_list=simulation_setup.signal_nets,
3482
- do_pingroup=simulation_setup.do_pingroup,
3483
- reference_net=simulation_setup.power_nets,
3484
- port_type=SourceType.CircPort,
3485
- )
3486
- self.logger.info("Configuring analysis setup.")
3487
- if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover
3488
- self.logger.error("Failed to configure Siwave simulation setup.")
3489
- if simulation_setup.solver_type == SolverType.SiwaveDC:
3490
- if simulation_setup.generate_excitations:
3491
- self.components.create_source_on_component(simulation_setup.sources)
3492
- if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover
3493
- self.logger.error("Failed to configure Siwave simulation setup.")
3494
- self.padstacks.check_and_fix_via_plating()
3495
- self.save_edb()
3496
- if not simulation_setup.open_edb_after_build and simulation_setup.output_aedb:
3497
- self.close_edb()
3498
- self.edbpath = legacy_name
3499
- self.open_edb()
3500
- return True
3501
- except:
3502
- return False
3408
+ self.logger.info("Configuring analysis setup.")
3409
+ if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover
3410
+ self.logger.error("Failed to configure Siwave simulation setup.")
3411
+ if simulation_setup.solver_type == SolverType.SiwaveDC:
3412
+ if simulation_setup.generate_excitations:
3413
+ self.components.create_source_on_component(simulation_setup.sources)
3414
+ if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover
3415
+ self.logger.error("Failed to configure Siwave simulation setup.")
3416
+ self.padstacks.check_and_fix_via_plating()
3417
+ self.save_edb()
3418
+ if not simulation_setup.open_edb_after_build and simulation_setup.output_aedb:
3419
+ self.close_edb()
3420
+ self.edbpath = legacy_name
3421
+ self.open_edb()
3422
+ return True
3503
3423
 
3504
3424
  def get_statistics(self, compute_area=False):
3505
3425
  """Get the EDBStatistics object.
@@ -3743,7 +3663,7 @@ class Edb(Database):
3743
3663
  if float(self.edbversion) < 2024.2:
3744
3664
  self.logger.error("HFSSPI simulation only supported with Ansys release 2024R2 and higher")
3745
3665
  return False
3746
- return HFSSPISimulationSetup(self).create(name)
3666
+ return HFSSPISimulationSetup(self, name=name)
3747
3667
 
3748
3668
  def create_siwave_syz_setup(self, name=None, **kwargs):
3749
3669
  """Create a setup from a template.