pyedb 0.18.0__py3-none-any.whl → 0.19.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_data.py +8 -11
- pyedb/configuration/cfg_nets.py +14 -0
- pyedb/configuration/cfg_pin_groups.py +57 -20
- pyedb/configuration/cfg_ports_sources.py +248 -60
- pyedb/configuration/configuration.py +51 -17
- pyedb/dotnet/edb.py +2 -1
- pyedb/dotnet/edb_core/cell/layout.py +48 -1
- pyedb/dotnet/edb_core/cell/terminal/padstack_instance_terminal.py +10 -0
- pyedb/dotnet/edb_core/cell/terminal/pingroup_terminal.py +5 -0
- pyedb/dotnet/edb_core/cell/terminal/point_terminal.py +0 -11
- pyedb/dotnet/edb_core/cell/terminal/terminal.py +35 -1
- pyedb/dotnet/edb_core/components.py +74 -18
- pyedb/dotnet/edb_core/dotnet/primitive.py +9 -6
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +8 -4
- pyedb/dotnet/edb_core/edb_data/ports.py +0 -18
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +1 -1
- pyedb/dotnet/edb_core/padstack.py +10 -1
- pyedb/dotnet/edb_core/sim_setup_data/data/sim_setup_info.py +42 -3
- pyedb/dotnet/edb_core/sim_setup_data/data/simulation_settings.py +92 -158
- pyedb/dotnet/edb_core/sim_setup_data/data/siw_dc_ir_settings.py +22 -22
- pyedb/dotnet/edb_core/sim_setup_data/io/siwave.py +76 -76
- pyedb/dotnet/edb_core/utilities/hfss_simulation_setup.py +23 -94
- pyedb/dotnet/edb_core/utilities/simulation_setup.py +40 -38
- pyedb/dotnet/edb_core/utilities/siwave_simulation_setup.py +26 -17
- {pyedb-0.18.0.dist-info → pyedb-0.19.0.dist-info}/METADATA +8 -8
- {pyedb-0.18.0.dist-info → pyedb-0.19.0.dist-info}/RECORD +29 -29
- {pyedb-0.18.0.dist-info → pyedb-0.19.0.dist-info}/LICENSE +0 -0
- {pyedb-0.18.0.dist-info → pyedb-0.19.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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
124
|
-
pin_group.apply()
|
|
125
|
+
self.cfg_data.pin_groups.apply()
|
|
125
126
|
|
|
126
127
|
# Configure ports
|
|
127
|
-
|
|
128
|
-
port.create()
|
|
128
|
+
self.cfg_data.ports.apply()
|
|
129
129
|
|
|
130
130
|
# Configure sources
|
|
131
|
-
|
|
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(
|
|
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(
|
|
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
|
@@ -510,6 +510,7 @@ class Edb(Database):
|
|
|
510
510
|
def sources(self):
|
|
511
511
|
"""Get all layout sources."""
|
|
512
512
|
terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [3, 4, 7]]
|
|
513
|
+
terms = [term for term in terms if not term.IsReferenceTerminal()]
|
|
513
514
|
return {ter.GetName(): ExcitationSources(self, ter) for ter in terms}
|
|
514
515
|
|
|
515
516
|
@property
|
|
@@ -3743,7 +3744,7 @@ class Edb(Database):
|
|
|
3743
3744
|
if float(self.edbversion) < 2024.2:
|
|
3744
3745
|
self.logger.error("HFSSPI simulation only supported with Ansys release 2024R2 and higher")
|
|
3745
3746
|
return False
|
|
3746
|
-
return HFSSPISimulationSetup(self
|
|
3747
|
+
return HFSSPISimulationSetup(self, name=name)
|
|
3747
3748
|
|
|
3748
3749
|
def create_siwave_syz_setup(self, name=None, **kwargs):
|
|
3749
3750
|
"""Create a setup from a template.
|
|
@@ -23,9 +23,11 @@
|
|
|
23
23
|
"""
|
|
24
24
|
This module contains these classes: `EdbLayout` and `Shape`.
|
|
25
25
|
"""
|
|
26
|
-
|
|
27
26
|
from pyedb.dotnet.edb_core.cell.primitive import Bondwire
|
|
28
27
|
from pyedb.dotnet.edb_core.edb_data.nets_data import EDBNetsData
|
|
28
|
+
from pyedb.dotnet.edb_core.edb_data.padstacks_data import EDBPadstackInstance
|
|
29
|
+
from pyedb.dotnet.edb_core.edb_data.sources import PinGroup
|
|
30
|
+
from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
|
|
29
31
|
from pyedb.dotnet.edb_core.layout import EdbLayout
|
|
30
32
|
|
|
31
33
|
|
|
@@ -65,6 +67,11 @@ class Layout(EdbLayout):
|
|
|
65
67
|
if i.GetPrimitiveType().ToString() == "Bondwire"
|
|
66
68
|
]
|
|
67
69
|
|
|
70
|
+
@property
|
|
71
|
+
def padstack_instances(self):
|
|
72
|
+
"""Get all padstack instances in a list."""
|
|
73
|
+
return [EDBPadstackInstance(i, self._pedb) for i in self._edb_object.PadstackInstances]
|
|
74
|
+
|
|
68
75
|
def create_bondwire(
|
|
69
76
|
self,
|
|
70
77
|
definition_name,
|
|
@@ -129,3 +136,43 @@ class Layout(EdbLayout):
|
|
|
129
136
|
end_y=self._pedb.edb_value(end_y),
|
|
130
137
|
net=self.nets[net]._edb_object,
|
|
131
138
|
)
|
|
139
|
+
|
|
140
|
+
def find_object_by_id(self, value: int):
|
|
141
|
+
"""Find a Connectable object by Database ID.
|
|
142
|
+
|
|
143
|
+
Parameters
|
|
144
|
+
----------
|
|
145
|
+
value : int
|
|
146
|
+
"""
|
|
147
|
+
obj = self._pedb._edb.Cell.Connectable.FindById(self._edb_object, value)
|
|
148
|
+
if obj.GetObjType().ToString() == "PadstackInstance":
|
|
149
|
+
return EDBPadstackInstance(obj, self._pedb)
|
|
150
|
+
|
|
151
|
+
def create_pin_group(self, name: str, pins_by_id: list[int] = None, pins_by_aedt_name: list[str] = None):
|
|
152
|
+
"""Create a PinGroup.
|
|
153
|
+
|
|
154
|
+
Parameters
|
|
155
|
+
name : str,
|
|
156
|
+
Name of the PinGroup.
|
|
157
|
+
pins_by_id : list[int] or None
|
|
158
|
+
List of pins by ID.
|
|
159
|
+
pins_by_aedt_name : list[str] or None
|
|
160
|
+
List of pins by AEDT name.
|
|
161
|
+
"""
|
|
162
|
+
pins = []
|
|
163
|
+
|
|
164
|
+
if pins_by_id is not None:
|
|
165
|
+
for p in pins_by_id:
|
|
166
|
+
pins.append(self.find_object_by_id(p._edb_object))
|
|
167
|
+
else:
|
|
168
|
+
p_inst = self.padstack_instances
|
|
169
|
+
while True:
|
|
170
|
+
p = p_inst.pop(0)
|
|
171
|
+
if p.aedt_name in pins_by_aedt_name:
|
|
172
|
+
pins.append(p._edb_object)
|
|
173
|
+
pins_by_aedt_name.remove(p.aedt_name)
|
|
174
|
+
if len(pins_by_aedt_name) == 0:
|
|
175
|
+
break
|
|
176
|
+
|
|
177
|
+
obj = self._edb.cell.hierarchy.pin_group.Create(self._edb_object, name, convert_py_list_to_net_list(pins))
|
|
178
|
+
return PinGroup(name, obj, self._pedb)
|
|
@@ -86,3 +86,13 @@ class PadstackInstanceTerminal(Terminal):
|
|
|
86
86
|
terminal = PadstackInstanceTerminal(self._pedb, terminal)
|
|
87
87
|
|
|
88
88
|
return terminal if not terminal.is_null else False
|
|
89
|
+
|
|
90
|
+
def _get_parameters(self):
|
|
91
|
+
"""Gets the parameters of the padstack instance terminal."""
|
|
92
|
+
_, padstack_inst, layer_obj = self._edb_object.GetParameters()
|
|
93
|
+
return padstack_inst, layer_obj
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def padstack_instance(self):
|
|
97
|
+
p_inst, _ = self._get_parameters()
|
|
98
|
+
return self._pedb.modeler.find_object_by_id(p_inst.GetId())
|
|
@@ -57,3 +57,8 @@ class PinGroupTerminal(Terminal):
|
|
|
57
57
|
)
|
|
58
58
|
term = PinGroupTerminal(self._pedb, term)
|
|
59
59
|
return term if not term.is_null else False
|
|
60
|
+
|
|
61
|
+
def pin_group(self):
|
|
62
|
+
"""Gets the pin group the terminal refers to."""
|
|
63
|
+
name = self._edb_object.GetPinGroup().GetName()
|
|
64
|
+
return self._pedb.siwave.pin_groups[name]
|
|
@@ -60,14 +60,3 @@ class PointTerminal(Terminal):
|
|
|
60
60
|
)
|
|
61
61
|
terminal = PointTerminal(self._pedb, terminal)
|
|
62
62
|
return terminal if not terminal.is_null else False
|
|
63
|
-
|
|
64
|
-
@property
|
|
65
|
-
def ref_terminal(self):
|
|
66
|
-
"""Get reference terminal."""
|
|
67
|
-
|
|
68
|
-
terminal = Terminal(self._pedb, self._edb_object.GetReferenceTerminal())
|
|
69
|
-
return terminal if not terminal.is_null else False
|
|
70
|
-
|
|
71
|
-
@ref_terminal.setter
|
|
72
|
-
def ref_terminal(self, value):
|
|
73
|
-
self._edb_object.SetReferenceTerminal(value._edb_object)
|
|
@@ -217,6 +217,21 @@ class Terminal(Connectable):
|
|
|
217
217
|
def boundary_type(self, value):
|
|
218
218
|
self._edb_object.SetBoundaryType(self._boundary_type_mapping[value])
|
|
219
219
|
|
|
220
|
+
@property
|
|
221
|
+
def is_port(self):
|
|
222
|
+
"""Whether it is a port."""
|
|
223
|
+
return True if self.boundary_type == "PortBoundary" else False
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def is_current_source(self):
|
|
227
|
+
"""Whether it is a current source."""
|
|
228
|
+
return True if self.boundary_type == "kCurrentSource" else False
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def is_voltage_source(self):
|
|
232
|
+
"""Whether it is a voltage source."""
|
|
233
|
+
return True if self.boundary_type == "kVoltageSource" else False
|
|
234
|
+
|
|
220
235
|
@property
|
|
221
236
|
def impedance(self):
|
|
222
237
|
"""Impedance of the port."""
|
|
@@ -235,7 +250,8 @@ class Terminal(Connectable):
|
|
|
235
250
|
def ref_terminal(self):
|
|
236
251
|
"""Get reference terminal."""
|
|
237
252
|
|
|
238
|
-
|
|
253
|
+
edb_terminal = self._edb_object.GetReferenceTerminal()
|
|
254
|
+
terminal = self._pedb.terminals[edb_terminal.GetName()]
|
|
239
255
|
if not terminal.is_null:
|
|
240
256
|
return terminal
|
|
241
257
|
|
|
@@ -444,3 +460,21 @@ class Terminal(Connectable):
|
|
|
444
460
|
pin_obj = pin
|
|
445
461
|
if pin_obj:
|
|
446
462
|
return EDBPadstackInstance(pin_obj, self._pedb)
|
|
463
|
+
|
|
464
|
+
@property
|
|
465
|
+
def magnitude(self):
|
|
466
|
+
"""Get the magnitude of the source."""
|
|
467
|
+
return self._edb_object.GetSourceAmplitude().ToDouble()
|
|
468
|
+
|
|
469
|
+
@magnitude.setter
|
|
470
|
+
def magnitude(self, value):
|
|
471
|
+
self._edb_object.SetSourceAmplitude(self._edb.utility.value(value))
|
|
472
|
+
|
|
473
|
+
@property
|
|
474
|
+
def phase(self):
|
|
475
|
+
"""Get the phase of the source."""
|
|
476
|
+
return self._edb_object.GetSourcePhase().ToDouble()
|
|
477
|
+
|
|
478
|
+
@phase.setter
|
|
479
|
+
def phase(self, value):
|
|
480
|
+
self._edb_object.SetSourcePhase(self._edb.utility.value(value))
|
|
@@ -766,20 +766,44 @@ class Components(object):
|
|
|
766
766
|
>>> edb.close_edb()
|
|
767
767
|
"""
|
|
768
768
|
|
|
769
|
-
if isinstance(pins, str)
|
|
769
|
+
if isinstance(pins, str):
|
|
770
770
|
pins = [pins]
|
|
771
|
+
elif isinstance(pins, EDBPadstackInstance):
|
|
772
|
+
pins = [pins.name]
|
|
771
773
|
if isinstance(reference_pins, str):
|
|
772
774
|
reference_pins = [reference_pins]
|
|
773
|
-
if isinstance(
|
|
775
|
+
if isinstance(reference_pins, list):
|
|
776
|
+
_temp = []
|
|
777
|
+
for ref_pin in reference_pins:
|
|
778
|
+
if isinstance(ref_pin, int):
|
|
779
|
+
if ref_pin in self._padstack.instances:
|
|
780
|
+
_temp.append(self._padstack.instances[ref_pin])
|
|
781
|
+
elif isinstance(ref_pin, str):
|
|
782
|
+
if ref_pin in self.instances[refdes].pins:
|
|
783
|
+
_temp.append(self.instances[refdes].pins[ref_pin])
|
|
784
|
+
else:
|
|
785
|
+
p = [pp for pp in list(self._padstack.instances.values()) if pp.name == ref_pin]
|
|
786
|
+
if p:
|
|
787
|
+
_temp.append(p)
|
|
788
|
+
elif isinstance(ref_pin, EDBPadstackInstance):
|
|
789
|
+
_temp.append(ref_pin.name)
|
|
790
|
+
reference_pins = _temp
|
|
791
|
+
elif isinstance(reference_pins, int):
|
|
792
|
+
if reference_pins in self._padstack.instances:
|
|
793
|
+
reference_pins = self._padstack.instances[reference_pins]
|
|
794
|
+
if isinstance(refdes, str):
|
|
774
795
|
refdes = self.instances[refdes]
|
|
796
|
+
elif isinstance(refdes, self._pedb._edb.Cell.Hierarchy.Component):
|
|
797
|
+
refdes = EDBComponent(self._pedb, refdes)
|
|
798
|
+
refdes_pins = refdes.pins
|
|
775
799
|
if any(refdes.rlc_values):
|
|
776
800
|
return self.deactivate_rlc_component(component=refdes, create_circuit_port=True)
|
|
777
801
|
if len([pin for pin in pins if isinstance(pin, str)]) == len(pins):
|
|
778
802
|
cmp_pins = []
|
|
779
803
|
for pin_name in pins:
|
|
780
|
-
cmp_pin = [pin for pin in list(
|
|
804
|
+
cmp_pin = [pin for pin in list(refdes_pins.values()) if pin_name == pin.name]
|
|
781
805
|
if not cmp_pin:
|
|
782
|
-
cmp_pin = [pin for pin in list(
|
|
806
|
+
cmp_pin = [pin for pin in list(refdes_pins.values()) if pin_name == pin.name.split("-")[1]]
|
|
783
807
|
if cmp_pin:
|
|
784
808
|
cmp_pins.append(cmp_pin[0])
|
|
785
809
|
if not cmp_pins:
|
|
@@ -793,15 +817,15 @@ class Components(object):
|
|
|
793
817
|
if len([pin for pin in reference_pins if isinstance(pin, str)]) == len(reference_pins):
|
|
794
818
|
ref_cmp_pins = []
|
|
795
819
|
for ref_pin_name in reference_pins:
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
ref_cmp_pins.append(cmp_ref_pin[0])
|
|
820
|
+
if ref_pin_name in refdes_pins:
|
|
821
|
+
ref_cmp_pins.append(refdes_pins[ref_pin_name])
|
|
822
|
+
elif "-" in ref_pin_name and ref_pin_name.split("-")[1] in refdes_pins:
|
|
823
|
+
ref_cmp_pins.append(refdes_pins[ref_pin_name.split("-")[1]])
|
|
801
824
|
if not ref_cmp_pins:
|
|
802
825
|
return
|
|
803
826
|
reference_pins = ref_cmp_pins
|
|
804
|
-
if not
|
|
827
|
+
if not reference_pins:
|
|
828
|
+
self._logger.error("No reference pins found.")
|
|
805
829
|
return
|
|
806
830
|
if len(pins) > 1:
|
|
807
831
|
pec_boundary = False
|
|
@@ -883,7 +907,7 @@ class Components(object):
|
|
|
883
907
|
solder_balls_size : float, optional
|
|
884
908
|
Solder balls diameter. When provided auto evaluation based on padstack size will be disabled.
|
|
885
909
|
solder_balls_mid_size : float, optional
|
|
886
|
-
Solder balls mid
|
|
910
|
+
Solder balls mid-diameter. When provided if value is different than solder balls size, spheroid shape will
|
|
887
911
|
be switched.
|
|
888
912
|
|
|
889
913
|
Returns
|
|
@@ -904,11 +928,11 @@ class Components(object):
|
|
|
904
928
|
if isinstance(component, str):
|
|
905
929
|
component = self.instances[component].edbcomponent
|
|
906
930
|
if not solder_balls_height:
|
|
907
|
-
solder_balls_height = self.
|
|
931
|
+
solder_balls_height = self.instances[component.GetName()].solder_ball_height
|
|
908
932
|
if not solder_balls_size:
|
|
909
|
-
solder_balls_size = self.
|
|
933
|
+
solder_balls_size = self.instances[component.GetName()].solder_ball_diameter[0]
|
|
910
934
|
if not solder_balls_mid_size:
|
|
911
|
-
solder_balls_mid_size = self.
|
|
935
|
+
solder_balls_mid_size = self.instances[component.GetName()].solder_ball_diameter[1]
|
|
912
936
|
if not isinstance(net_list, list):
|
|
913
937
|
net_list = [net_list]
|
|
914
938
|
for net in net_list:
|
|
@@ -934,6 +958,18 @@ class Components(object):
|
|
|
934
958
|
return False
|
|
935
959
|
pin_layers = cmp_pins[0].GetPadstackDef().GetData().GetLayerNames()
|
|
936
960
|
if port_type == SourceType.CoaxPort:
|
|
961
|
+
ref_pins = [
|
|
962
|
+
p
|
|
963
|
+
for p in list(component.LayoutObjs)
|
|
964
|
+
if int(p.GetObjType()) == 1 and p.GetNet().GetName() in reference_net
|
|
965
|
+
]
|
|
966
|
+
if not ref_pins:
|
|
967
|
+
self._logger.error(
|
|
968
|
+
"No reference pins found on component. You might consider"
|
|
969
|
+
"using Circuit port instead since reference pins can be extended"
|
|
970
|
+
"outside the component automatically when not found."
|
|
971
|
+
)
|
|
972
|
+
return False
|
|
937
973
|
pad_params = self._padstack.get_pad_parameters(pin=cmp_pins[0], layername=pin_layers[0], pad_type=0)
|
|
938
974
|
if not pad_params[0] == 7:
|
|
939
975
|
if not solder_balls_size: # pragma no cover
|
|
@@ -981,17 +1017,25 @@ class Components(object):
|
|
|
981
1017
|
for p in ref_pins:
|
|
982
1018
|
if not p.IsLayoutPin():
|
|
983
1019
|
p.SetIsLayoutPin(True)
|
|
984
|
-
if
|
|
985
|
-
self._logger.
|
|
1020
|
+
if not ref_pins:
|
|
1021
|
+
self._logger.warning("No reference pins found on component, the closest pin will be selected.")
|
|
1022
|
+
do_pingroup = False
|
|
986
1023
|
if do_pingroup:
|
|
987
1024
|
if len(ref_pins) == 1:
|
|
1025
|
+
ref_pins.is_pin = True
|
|
988
1026
|
ref_pin_group_term = self._create_terminal(ref_pins[0])
|
|
989
1027
|
else:
|
|
1028
|
+
for pin in ref_pins:
|
|
1029
|
+
pin.is_pin = True
|
|
990
1030
|
ref_pin_group = self.create_pingroup_from_pins(ref_pins)
|
|
991
1031
|
if not ref_pin_group:
|
|
1032
|
+
self._logger.error(f"Failed to create reference pin group on component {component.GetName()}.")
|
|
992
1033
|
return False
|
|
993
|
-
ref_pin_group_term = self._create_pin_group_terminal(ref_pin_group, isref=
|
|
1034
|
+
ref_pin_group_term = self._create_pin_group_terminal(ref_pin_group, isref=False)
|
|
994
1035
|
if not ref_pin_group_term:
|
|
1036
|
+
self._logger.error(
|
|
1037
|
+
f"Failed to create reference pin group terminal on component {component.GetName()}"
|
|
1038
|
+
)
|
|
995
1039
|
return False
|
|
996
1040
|
for net in net_list:
|
|
997
1041
|
pins = [pin for pin in cmp_pins if pin.GetNet().GetName() == net]
|
|
@@ -1013,7 +1057,19 @@ class Components(object):
|
|
|
1013
1057
|
for net in net_list:
|
|
1014
1058
|
pins = [pin for pin in cmp_pins if pin.GetNet().GetName() == net]
|
|
1015
1059
|
for pin in pins:
|
|
1016
|
-
|
|
1060
|
+
if ref_pins:
|
|
1061
|
+
self.create_port_on_pins(component, pin, ref_pins)
|
|
1062
|
+
else:
|
|
1063
|
+
_pin = EDBPadstackInstance(pin, self._pedb)
|
|
1064
|
+
ref_pin = _pin.get_reference_pins(
|
|
1065
|
+
reference_net=reference_net[0], max_limit=1, component_only=False, search_radius=3e-3
|
|
1066
|
+
)
|
|
1067
|
+
if ref_pin:
|
|
1068
|
+
self.create_port_on_pins(
|
|
1069
|
+
component,
|
|
1070
|
+
[EDBPadstackInstance(pin, self._pedb).name],
|
|
1071
|
+
[EDBPadstackInstance(ref_pin[0], self._pedb).id],
|
|
1072
|
+
)
|
|
1017
1073
|
return True
|
|
1018
1074
|
|
|
1019
1075
|
def _create_terminal(self, pin, term_name=None):
|
|
@@ -837,9 +837,8 @@ class PathDotNet(PrimitiveDotNet):
|
|
|
837
837
|
net = net.api_object
|
|
838
838
|
width = self._app.edb_api.utility.value(width)
|
|
839
839
|
if isinstance(points, list):
|
|
840
|
-
points = self._app.
|
|
841
|
-
|
|
842
|
-
)
|
|
840
|
+
points = convert_py_list_to_net_list([self._app.point_data(i[0], i[1]) for i in points])
|
|
841
|
+
points = self._app.edb_api.geometry.polygon_data.dotnetobj(points)
|
|
843
842
|
return PathDotNet(
|
|
844
843
|
self._app, self.api.Path.Create(layout, layer, net, width, end_cap1, end_cap2, corner_style, points)
|
|
845
844
|
)
|
|
@@ -847,11 +846,15 @@ class PathDotNet(PrimitiveDotNet):
|
|
|
847
846
|
@property
|
|
848
847
|
def center_line(self):
|
|
849
848
|
""":class:`PolygonData <ansys.edb.geometry.PolygonData>`: Center line for this Path."""
|
|
850
|
-
|
|
849
|
+
edb_center_line = self.prim_obj.GetCenterLine()
|
|
850
|
+
return [[pt.X.ToDouble(), pt.Y.ToDouble()] for pt in list(edb_center_line.Points)]
|
|
851
851
|
|
|
852
852
|
@center_line.setter
|
|
853
|
-
def center_line(self,
|
|
854
|
-
|
|
853
|
+
def center_line(self, value):
|
|
854
|
+
if isinstance(value, list):
|
|
855
|
+
points = [self._pedb.point_data(i[0], i[1]) for i in value]
|
|
856
|
+
polygon_data = self._edb.geometry.polygon_data.dotnetobj(convert_py_list_to_net_list(points), False)
|
|
857
|
+
self.prim_obj.SetCenterLine(polygon_data)
|
|
855
858
|
|
|
856
859
|
@property
|
|
857
860
|
def end_cap_style(self):
|
|
@@ -1678,11 +1678,9 @@ class EDBPadstackInstance(Primitive):
|
|
|
1678
1678
|
def name(self):
|
|
1679
1679
|
"""Padstack Instance Name. If it is a pin, the syntax will be like in AEDT ComponentName-PinName."""
|
|
1680
1680
|
if self.is_pin:
|
|
1681
|
-
|
|
1682
|
-
pin_name = self._edb_padstackinstance.GetName()
|
|
1683
|
-
return "-".join([comp_name, pin_name])
|
|
1681
|
+
return self.aedt_name
|
|
1684
1682
|
else:
|
|
1685
|
-
return self.
|
|
1683
|
+
return self.component_pin
|
|
1686
1684
|
|
|
1687
1685
|
@name.setter
|
|
1688
1686
|
def name(self, value):
|
|
@@ -1725,6 +1723,12 @@ class EDBPadstackInstance(Primitive):
|
|
|
1725
1723
|
@property
|
|
1726
1724
|
def pin_number(self):
|
|
1727
1725
|
"""Get pin number."""
|
|
1726
|
+
warnings.warn("`pin_number` is deprecated. Use `component_pin` method instead.", DeprecationWarning)
|
|
1727
|
+
return self.component_pin
|
|
1728
|
+
|
|
1729
|
+
@property
|
|
1730
|
+
def component_pin(self):
|
|
1731
|
+
"""Get component pin."""
|
|
1728
1732
|
return self._edb_padstackinstance.GetName()
|
|
1729
1733
|
|
|
1730
1734
|
@property
|
|
@@ -198,24 +198,6 @@ class ExcitationSources(Terminal):
|
|
|
198
198
|
def __init__(self, pedb, edb_terminal):
|
|
199
199
|
Terminal.__init__(self, pedb, edb_terminal)
|
|
200
200
|
|
|
201
|
-
@property
|
|
202
|
-
def magnitude(self):
|
|
203
|
-
"""Get the magnitude of the source."""
|
|
204
|
-
return self._edb_object.GetSourceAmplitude().ToDouble()
|
|
205
|
-
|
|
206
|
-
@magnitude.setter
|
|
207
|
-
def magnitude(self, value):
|
|
208
|
-
self._edb_object.SetSourceAmplitude(self._edb.utility.value(value))
|
|
209
|
-
|
|
210
|
-
@property
|
|
211
|
-
def phase(self):
|
|
212
|
-
"""Get the phase of the source."""
|
|
213
|
-
return self._edb_object.GetSourcePhase().ToDouble()
|
|
214
|
-
|
|
215
|
-
@phase.setter
|
|
216
|
-
def phase(self, value):
|
|
217
|
-
self._edb_object.SetSourcePhase(self._edb.utility.value(value))
|
|
218
|
-
|
|
219
201
|
|
|
220
202
|
class BundleWavePort(BundleTerminal):
|
|
221
203
|
"""Manages bundle wave port properties.
|
|
@@ -631,7 +631,7 @@ class EdbPath(EDBPrimitives, PathDotNet):
|
|
|
631
631
|
float
|
|
632
632
|
Path length in meters.
|
|
633
633
|
"""
|
|
634
|
-
center_line_arcs = list(self.
|
|
634
|
+
center_line_arcs = list(self.api_object.GetCenterLine().GetArcData())
|
|
635
635
|
path_length = 0.0
|
|
636
636
|
for arc in center_line_arcs:
|
|
637
637
|
path_length += arc.GetLength()
|
|
@@ -241,6 +241,15 @@ class EdbPadstacks(object):
|
|
|
241
241
|
)
|
|
242
242
|
return padstack_instances
|
|
243
243
|
|
|
244
|
+
def find_instance_by_id(self, value: int):
|
|
245
|
+
"""Find a padstack instance by database id.
|
|
246
|
+
|
|
247
|
+
Parameters
|
|
248
|
+
----------
|
|
249
|
+
value : int
|
|
250
|
+
"""
|
|
251
|
+
return self._pedb.modeler.find_object_by_id(value)
|
|
252
|
+
|
|
244
253
|
@property
|
|
245
254
|
def pins(self):
|
|
246
255
|
"""Dictionary of all pins instances (belonging to component).
|
|
@@ -1441,7 +1450,7 @@ class EdbPadstacks(object):
|
|
|
1441
1450
|
instances = [inst for inst in instances if inst.component.refdes in refdes]
|
|
1442
1451
|
if component_pin:
|
|
1443
1452
|
component_pin = component_pin if isinstance(component_pin, list) else [component_pin]
|
|
1444
|
-
instances = [inst for inst in instances if inst.
|
|
1453
|
+
instances = [inst for inst in instances if inst.component_pin in component_pin]
|
|
1445
1454
|
return instances
|
|
1446
1455
|
|
|
1447
1456
|
def get_padstack_instance_by_net_name(self, net_name):
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
+
from pyedb.dotnet.edb_core.sim_setup_data.data.simulation_settings import ( # HFSSSimulationSettings
|
|
24
|
+
HFSSPISimulationSettings,
|
|
25
|
+
)
|
|
23
26
|
from pyedb.dotnet.edb_core.sim_setup_data.data.sweep_data import SweepData
|
|
24
27
|
|
|
25
28
|
|
|
@@ -58,17 +61,53 @@ class SimSetupInfo:
|
|
|
58
61
|
else:
|
|
59
62
|
self._edb_object = edb_object
|
|
60
63
|
|
|
64
|
+
@property
|
|
65
|
+
def name(self):
|
|
66
|
+
return self._edb_object.Name
|
|
67
|
+
|
|
68
|
+
@name.setter
|
|
69
|
+
def name(self, name):
|
|
70
|
+
self._edb_object.Name = name
|
|
71
|
+
|
|
61
72
|
@property
|
|
62
73
|
def position(self):
|
|
63
74
|
return self._edb_object.Position
|
|
64
75
|
|
|
65
76
|
@property
|
|
66
77
|
def sim_setup_type(self):
|
|
67
|
-
|
|
78
|
+
"""
|
|
79
|
+
"kHFSS": self._pedb.simsetupdata.HFSSSimulationSettings,
|
|
80
|
+
"kPEM": None,
|
|
81
|
+
"kSIwave": self._pedb.simsetupdata.SIwave.SIWSimulationSettings,
|
|
82
|
+
"kLNA": None,
|
|
83
|
+
"kTransient": None,
|
|
84
|
+
"kQEye": None,
|
|
85
|
+
"kVEye": None,
|
|
86
|
+
"kAMI": None,
|
|
87
|
+
"kAnalysisOption": None,
|
|
88
|
+
"kSIwaveDCIR": self._pedb.simsetupdata.SIwave.SIWDCIRSimulationSettings,
|
|
89
|
+
"kSIwaveEMI": None,
|
|
90
|
+
"kHFSSPI": self._pedb.simsetupdata.HFSSPISimulationSettings,
|
|
91
|
+
"kDDRwizard": None,
|
|
92
|
+
"kQ3D": None,
|
|
93
|
+
"kNumSetupTypes": None,
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
return self._edb_object.SimSetupType.ToString()
|
|
68
97
|
|
|
69
98
|
@property
|
|
70
99
|
def simulation_settings(self):
|
|
71
|
-
|
|
100
|
+
if self.sim_setup_type == "kHFSS":
|
|
101
|
+
return self._edb_object.SimulationSettings
|
|
102
|
+
# todo refactor HFSS
|
|
103
|
+
# return HFSSSimulationSettings(self._pedb, self.sim_setup, self._edb_object.SimulationSettings)
|
|
104
|
+
elif self.sim_setup_type == "kHFSSPI":
|
|
105
|
+
return HFSSPISimulationSettings(self._pedb, self.sim_setup, self._edb_object.SimulationSettings)
|
|
106
|
+
elif self.sim_setup_type == "kSIwave": # todo refactor
|
|
107
|
+
return self._edb_object.SimulationSettings
|
|
108
|
+
|
|
109
|
+
elif self.sim_setup_type == "kSIwaveDCIR": # todo refactor
|
|
110
|
+
return self._edb_object.SimulationSettings
|
|
72
111
|
|
|
73
112
|
@property
|
|
74
113
|
def sweep_data_list(self):
|
|
@@ -77,5 +116,5 @@ class SimSetupInfo:
|
|
|
77
116
|
]
|
|
78
117
|
|
|
79
118
|
def add_sweep_data(self, sweep_data):
|
|
80
|
-
sweep_data.
|
|
119
|
+
sweep_data._sim_setup = self.sim_setup
|
|
81
120
|
self._edb_object.SweepDataList.Add(sweep_data._edb_object)
|