pyedb 0.52.0__py3-none-any.whl → 0.54.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_common.py +12 -15
- pyedb/configuration/cfg_data.py +2 -2
- pyedb/configuration/cfg_modeler.py +163 -234
- pyedb/configuration/cfg_ports_sources.py +6 -8
- pyedb/configuration/cfg_stackup.py +62 -249
- pyedb/configuration/configuration.py +272 -170
- pyedb/dotnet/database/cell/hierarchy/model.py +1 -1
- pyedb/dotnet/database/cell/layout.py +1 -1
- pyedb/dotnet/database/cell/layout_obj.py +3 -3
- pyedb/dotnet/database/cell/primitive/path.py +1 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +8 -8
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +24 -26
- pyedb/dotnet/database/components.py +33 -27
- pyedb/dotnet/database/definition/component_def.py +3 -3
- pyedb/dotnet/database/definition/component_model.py +1 -1
- pyedb/dotnet/database/definition/package_def.py +1 -1
- pyedb/dotnet/database/dotnet/database.py +47 -38
- pyedb/dotnet/database/dotnet/primitive.py +16 -16
- pyedb/dotnet/database/edb_data/hfss_extent_info.py +6 -6
- pyedb/dotnet/database/edb_data/layer_data.py +17 -15
- pyedb/dotnet/database/edb_data/padstacks_data.py +12 -12
- pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
- pyedb/dotnet/database/edb_data/sources.py +6 -6
- pyedb/dotnet/database/edb_data/variables.py +7 -3
- pyedb/dotnet/database/geometry/point_data.py +1 -1
- pyedb/dotnet/database/geometry/polygon_data.py +2 -4
- pyedb/dotnet/database/hfss.py +7 -7
- pyedb/dotnet/database/materials.py +2 -2
- pyedb/dotnet/database/modeler.py +8 -11
- pyedb/dotnet/database/nets.py +1 -1
- pyedb/dotnet/database/padstack.py +72 -1
- pyedb/dotnet/database/sim_setup_data/data/settings.py +24 -0
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +26 -1
- pyedb/dotnet/database/siwave.py +19 -5
- pyedb/dotnet/database/stackup.py +80 -137
- pyedb/dotnet/database/utilities/heatsink.py +4 -4
- pyedb/dotnet/database/utilities/obj_base.py +1 -1
- pyedb/dotnet/database/utilities/simulation_setup.py +1 -1
- pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +894 -0
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +15 -0
- pyedb/dotnet/database/utilities/value.py +116 -0
- pyedb/dotnet/edb.py +58 -45
- pyedb/generic/design_types.py +39 -1
- pyedb/generic/grpc_warnings.py +5 -0
- pyedb/grpc/__init__.py +0 -0
- pyedb/grpc/database/components.py +155 -98
- pyedb/grpc/database/control_file.py +240 -193
- pyedb/grpc/database/definition/materials.py +23 -30
- pyedb/grpc/database/definition/package_def.py +15 -15
- pyedb/grpc/database/definition/padstack_def.py +51 -51
- pyedb/grpc/database/definitions.py +7 -5
- pyedb/grpc/database/geometry/arc_data.py +7 -5
- pyedb/grpc/database/geometry/point_3d_data.py +8 -7
- pyedb/grpc/database/geometry/polygon_data.py +3 -2
- pyedb/grpc/database/hierarchy/component.py +43 -38
- pyedb/grpc/database/hierarchy/pin_pair_model.py +15 -14
- pyedb/grpc/database/hierarchy/pingroup.py +9 -9
- pyedb/grpc/database/layers/stackup_layer.py +45 -44
- pyedb/grpc/database/layout/layout.py +9 -8
- pyedb/grpc/database/layout/voltage_regulator.py +7 -7
- pyedb/grpc/database/layout_validation.py +13 -12
- pyedb/grpc/database/modeler.py +156 -131
- pyedb/grpc/database/nets.py +42 -31
- pyedb/grpc/database/padstacks.py +270 -175
- pyedb/grpc/database/ports/ports.py +5 -6
- pyedb/grpc/database/primitive/bondwire.py +8 -7
- pyedb/grpc/database/primitive/circle.py +4 -4
- pyedb/grpc/database/primitive/padstack_instance.py +18 -18
- pyedb/grpc/database/primitive/path.py +7 -7
- pyedb/grpc/database/primitive/polygon.py +3 -3
- pyedb/grpc/database/primitive/primitive.py +13 -17
- pyedb/grpc/database/primitive/rectangle.py +13 -13
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +10 -0
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +961 -0
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +17 -1
- pyedb/grpc/database/siwave.py +44 -24
- pyedb/grpc/database/source_excitations.py +333 -229
- pyedb/grpc/database/stackup.py +164 -147
- pyedb/grpc/database/terminal/bundle_terminal.py +17 -7
- pyedb/grpc/database/terminal/edge_terminal.py +10 -0
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +15 -4
- pyedb/grpc/database/terminal/pingroup_terminal.py +11 -10
- pyedb/grpc/database/terminal/point_terminal.py +4 -3
- pyedb/grpc/database/terminal/terminal.py +9 -9
- pyedb/grpc/database/utility/value.py +109 -0
- pyedb/grpc/edb.py +129 -45
- pyedb/grpc/edb_init.py +0 -7
- pyedb/siwave_core/cpa/simulation_setup_data_model.py +132 -0
- pyedb/siwave_core/product_properties.py +198 -0
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/METADATA +15 -13
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/RECORD +97 -89
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/WHEEL +1 -1
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info/licenses}/LICENSE +0 -0
|
@@ -20,7 +20,7 @@
|
|
|
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 typing import List, Set, Union
|
|
23
|
+
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
|
24
24
|
|
|
25
25
|
from ansys.edb.core.database import ProductIdType as GrpcProductIdType
|
|
26
26
|
from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
|
|
@@ -29,7 +29,6 @@ from ansys.edb.core.terminal.edge_terminal import EdgeTerminal as GrpcEdgeTermin
|
|
|
29
29
|
from ansys.edb.core.terminal.edge_terminal import PrimitiveEdge as GrpcPrimitiveEdge
|
|
30
30
|
from ansys.edb.core.terminal.terminal import BoundaryType as GrpcBoundaryType
|
|
31
31
|
from ansys.edb.core.utility.rlc import Rlc as GrpcRlc
|
|
32
|
-
from ansys.edb.core.utility.value import Value as GrpcValue
|
|
33
32
|
|
|
34
33
|
from pyedb.generic.general_methods import generate_unique_name
|
|
35
34
|
from pyedb.grpc.database.components import Component
|
|
@@ -39,12 +38,15 @@ from pyedb.grpc.database.ports.ports import BundleWavePort, WavePort
|
|
|
39
38
|
from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
|
|
40
39
|
from pyedb.grpc.database.primitive.primitive import Primitive
|
|
41
40
|
from pyedb.grpc.database.terminal.bundle_terminal import BundleTerminal
|
|
41
|
+
from pyedb.grpc.database.terminal.edge_terminal import EdgeTerminal
|
|
42
42
|
from pyedb.grpc.database.terminal.padstack_instance_terminal import (
|
|
43
43
|
PadstackInstanceTerminal,
|
|
44
44
|
)
|
|
45
45
|
from pyedb.grpc.database.terminal.pingroup_terminal import PinGroupTerminal
|
|
46
46
|
from pyedb.grpc.database.terminal.point_terminal import PointTerminal
|
|
47
|
+
from pyedb.grpc.database.terminal.terminal import Terminal
|
|
47
48
|
from pyedb.grpc.database.utility.sources import Source, SourceType
|
|
49
|
+
from pyedb.grpc.database.utility.value import Value
|
|
48
50
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
49
51
|
|
|
50
52
|
|
|
@@ -206,25 +208,25 @@ class SourceExcitation:
|
|
|
206
208
|
self._pedb = pedb
|
|
207
209
|
|
|
208
210
|
@property
|
|
209
|
-
def _logger(self):
|
|
211
|
+
def _logger(self) -> Any:
|
|
210
212
|
return self._pedb.logger
|
|
211
213
|
|
|
212
214
|
@property
|
|
213
|
-
def excitations(self):
|
|
215
|
+
def excitations(self) -> Dict[str, Any]:
|
|
214
216
|
"""Get all excitations."""
|
|
215
217
|
return self._pedb.excitations
|
|
216
218
|
|
|
217
219
|
@property
|
|
218
|
-
def sources(self):
|
|
220
|
+
def sources(self) -> Dict[str, Any]:
|
|
219
221
|
"""Get all sources."""
|
|
220
222
|
return self._pedb.sources
|
|
221
223
|
|
|
222
224
|
@property
|
|
223
|
-
def probes(self):
|
|
225
|
+
def probes(self) -> Dict[str, Any]:
|
|
224
226
|
"""Get all probes."""
|
|
225
227
|
return self._pedb.probes
|
|
226
228
|
|
|
227
|
-
def create_source_on_component(self, sources=None):
|
|
229
|
+
def create_source_on_component(self, sources: Optional[Union[Source, List[Source]]] = None) -> bool:
|
|
228
230
|
"""Create voltage, current source, or resistor on component.
|
|
229
231
|
|
|
230
232
|
Parameters
|
|
@@ -278,12 +280,12 @@ class SourceExcitation:
|
|
|
278
280
|
term_name = source.name
|
|
279
281
|
positive_pin_group_term.SetName(term_name)
|
|
280
282
|
negative_pin_group_term.SetName("{}_ref".format(term_name))
|
|
281
|
-
positive_pin_group_term.source_amplitude =
|
|
282
|
-
negative_pin_group_term.source_amplitude =
|
|
283
|
-
positive_pin_group_term.source_phase =
|
|
284
|
-
negative_pin_group_term.source_phase =
|
|
285
|
-
positive_pin_group_term.impedance =
|
|
286
|
-
negative_pin_group_term.impedance =
|
|
283
|
+
positive_pin_group_term.source_amplitude = Value(source.amplitude)
|
|
284
|
+
negative_pin_group_term.source_amplitude = Value(source.amplitude)
|
|
285
|
+
positive_pin_group_term.source_phase = Value(source.phase)
|
|
286
|
+
negative_pin_group_term.source_phase = Value(source.phase)
|
|
287
|
+
positive_pin_group_term.impedance = Value(source.impedance)
|
|
288
|
+
negative_pin_group_term.impedance = Value(source.impedance)
|
|
287
289
|
positive_pin_group_term.reference_terminal = negative_pin_group_term
|
|
288
290
|
elif source.source_type == SourceType.Isource: # pragma: no cover
|
|
289
291
|
positive_pin_group_term = self._pedb.components._create_pin_group_terminal(
|
|
@@ -296,12 +298,12 @@ class SourceExcitation:
|
|
|
296
298
|
negative_pin_group_term.boundary_type = GrpcBoundaryType.CURRENT_SOURCE
|
|
297
299
|
positive_pin_group_term.name = source.name
|
|
298
300
|
negative_pin_group_term.name = "{}_ref".format(source.name)
|
|
299
|
-
positive_pin_group_term.source_amplitude =
|
|
300
|
-
negative_pin_group_term.source_amplitude =
|
|
301
|
-
positive_pin_group_term.source_phase =
|
|
302
|
-
negative_pin_group_term.source_phase =
|
|
303
|
-
positive_pin_group_term.impedance =
|
|
304
|
-
negative_pin_group_term.impedance =
|
|
301
|
+
positive_pin_group_term.source_amplitude = Value(source.amplitude)
|
|
302
|
+
negative_pin_group_term.source_amplitude = Value(source.amplitude)
|
|
303
|
+
positive_pin_group_term.source_phase = Value(source.phase)
|
|
304
|
+
negative_pin_group_term.source_phase = Value(source.phase)
|
|
305
|
+
positive_pin_group_term.impedance = Value(source.impedance)
|
|
306
|
+
negative_pin_group_term.impedance = Value(source.impedance)
|
|
305
307
|
positive_pin_group_term.reference_terminal = negative_pin_group_term
|
|
306
308
|
elif source.source_type == SourceType.Rlc: # pragma: no cover
|
|
307
309
|
self._pedb.components.create(
|
|
@@ -314,7 +316,13 @@ class SourceExcitation:
|
|
|
314
316
|
)
|
|
315
317
|
return True
|
|
316
318
|
|
|
317
|
-
def create_port(
|
|
319
|
+
def create_port(
|
|
320
|
+
self,
|
|
321
|
+
terminal: Terminal,
|
|
322
|
+
ref_terminal: Optional[Terminal] = None,
|
|
323
|
+
is_circuit_port: bool = False,
|
|
324
|
+
name: Optional[str] = None,
|
|
325
|
+
) -> Any:
|
|
318
326
|
"""Create a port.
|
|
319
327
|
|
|
320
328
|
Parameters
|
|
@@ -363,14 +371,14 @@ class SourceExcitation:
|
|
|
363
371
|
|
|
364
372
|
def create_port_on_pins(
|
|
365
373
|
self,
|
|
366
|
-
refdes,
|
|
367
|
-
pins,
|
|
368
|
-
reference_pins,
|
|
369
|
-
impedance=
|
|
370
|
-
port_name=None,
|
|
371
|
-
pec_boundary=False,
|
|
372
|
-
pingroup_on_single_pin=False,
|
|
373
|
-
):
|
|
374
|
+
refdes: Union[str, Component],
|
|
375
|
+
pins: Union[int, str, PadstackInstance, List[Union[int, str, PadstackInstance]]],
|
|
376
|
+
reference_pins: Union[int, str, PadstackInstance, List[Union[int, str, PadstackInstance]]] = None,
|
|
377
|
+
impedance: Union[str, float] = "50ohm",
|
|
378
|
+
port_name: Optional[str] = None,
|
|
379
|
+
pec_boundary: bool = False,
|
|
380
|
+
pingroup_on_single_pin: bool = False,
|
|
381
|
+
) -> PadstackInstanceTerminal:
|
|
374
382
|
"""Create circuit port between pins and reference ones.
|
|
375
383
|
|
|
376
384
|
Parameters
|
|
@@ -461,7 +469,7 @@ class SourceExcitation:
|
|
|
461
469
|
ref_term = self._create_terminal(reference_pins[0], term_name=port_name + "_ref")
|
|
462
470
|
ref_term.is_circuit_port = True
|
|
463
471
|
|
|
464
|
-
term.impedance =
|
|
472
|
+
term.impedance = Value(impedance)
|
|
465
473
|
term.reference_terminal = ref_term
|
|
466
474
|
if pec_boundary:
|
|
467
475
|
term.is_circuit_port = False
|
|
@@ -499,17 +507,17 @@ class SourceExcitation:
|
|
|
499
507
|
|
|
500
508
|
def create_port_on_component(
|
|
501
509
|
self,
|
|
502
|
-
component,
|
|
503
|
-
net_list,
|
|
504
|
-
port_type
|
|
505
|
-
do_pingroup=True,
|
|
506
|
-
reference_net=
|
|
507
|
-
port_name=None,
|
|
508
|
-
solder_balls_height=None,
|
|
509
|
-
solder_balls_size=None,
|
|
510
|
-
solder_balls_mid_size=None,
|
|
511
|
-
extend_reference_pins_outside_component=False,
|
|
512
|
-
):
|
|
510
|
+
component: Union[str, List[str]],
|
|
511
|
+
net_list: Union[str, List[str]],
|
|
512
|
+
port_type: SourceType,
|
|
513
|
+
do_pingroup: Optional[bool] = True,
|
|
514
|
+
reference_net: Optional[str] = None,
|
|
515
|
+
port_name: Optional[List[str]] = None,
|
|
516
|
+
solder_balls_height: Optional[float] = None,
|
|
517
|
+
solder_balls_size: Optional[float] = None,
|
|
518
|
+
solder_balls_mid_size: Optional[float] = None,
|
|
519
|
+
extend_reference_pins_outside_component: Optional[bool] = False,
|
|
520
|
+
) -> List[str]:
|
|
513
521
|
"""Create ports on a component.
|
|
514
522
|
|
|
515
523
|
Parameters
|
|
@@ -525,7 +533,7 @@ class SourceExcitation:
|
|
|
525
533
|
do_pingroup : bool
|
|
526
534
|
True activate pingroup during port creation (only used with combination of CircPort),
|
|
527
535
|
False will take the closest reference pin and generate one port per signal pin.
|
|
528
|
-
|
|
536
|
+
reference_net : string or list of string.
|
|
529
537
|
list of the reference net.
|
|
530
538
|
port_name : str
|
|
531
539
|
Port name for overwriting the default port-naming convention,
|
|
@@ -556,7 +564,7 @@ class SourceExcitation:
|
|
|
556
564
|
>>> from pyedb import Edb
|
|
557
565
|
>>> edbapp = Edb("myaedbfolder")
|
|
558
566
|
>>> net_list = ["M_DQ<1>", "M_DQ<2>", "M_DQ<3>", "M_DQ<4>", "M_DQ<5>"]
|
|
559
|
-
>>> edbapp.
|
|
567
|
+
>>> edbapp.excitations.create_port_on_component(cmp="U2A5", net_list=net_list,
|
|
560
568
|
>>> port_type=SourceType.CoaxPort, do_pingroup=False, refnet="GND")
|
|
561
569
|
|
|
562
570
|
"""
|
|
@@ -613,7 +621,7 @@ class SourceExcitation:
|
|
|
613
621
|
pad_params = self._pedb.padstacks.get_pad_parameters(pin=cmp_pins[0], layername=pin_layers[0], pad_type=0)
|
|
614
622
|
if not pad_params[0] == 7:
|
|
615
623
|
if not solder_balls_size: # pragma no cover
|
|
616
|
-
sball_diam = min([
|
|
624
|
+
sball_diam = min([Value(val) for val in pad_params[1]])
|
|
617
625
|
sball_mid_diam = sball_diam
|
|
618
626
|
else: # pragma no cover
|
|
619
627
|
sball_diam = solder_balls_size
|
|
@@ -721,7 +729,7 @@ class SourceExcitation:
|
|
|
721
729
|
return True
|
|
722
730
|
|
|
723
731
|
@staticmethod
|
|
724
|
-
def _normalize_net_list(net_list) -> Set[str]:
|
|
732
|
+
def _normalize_net_list(net_list: Union[str, List[str]]) -> Set[str]:
|
|
725
733
|
if not isinstance(net_list, list):
|
|
726
734
|
net_list = [net_list]
|
|
727
735
|
nets = set()
|
|
@@ -734,7 +742,9 @@ class SourceExcitation:
|
|
|
734
742
|
nets.add(net)
|
|
735
743
|
return nets
|
|
736
744
|
|
|
737
|
-
def _create_terminal(
|
|
745
|
+
def _create_terminal(
|
|
746
|
+
self, pin: PadstackInstance, term_name: Optional[str] = None
|
|
747
|
+
) -> Optional[PadstackInstanceTerminal]:
|
|
738
748
|
"""Create terminal on component pin.
|
|
739
749
|
|
|
740
750
|
Parameters
|
|
@@ -759,7 +769,9 @@ class SourceExcitation:
|
|
|
759
769
|
layout=self._pedb.layout, name=term_name, padstack_instance=pin, layer=from_layer, net=pin.net, is_ref=False
|
|
760
770
|
)
|
|
761
771
|
|
|
762
|
-
def add_port_on_rlc_component(
|
|
772
|
+
def add_port_on_rlc_component(
|
|
773
|
+
self, component: Optional[Union[str, Component]] = None, circuit_ports: bool = True, pec_boundary: bool = False
|
|
774
|
+
) -> bool:
|
|
763
775
|
"""Deactivate RLC component and replace it with a circuit port.
|
|
764
776
|
The circuit port supports only two-pin components.
|
|
765
777
|
|
|
@@ -840,7 +852,7 @@ class SourceExcitation:
|
|
|
840
852
|
return True
|
|
841
853
|
return False
|
|
842
854
|
|
|
843
|
-
def add_rlc_boundary(self, component=None, circuit_type=True):
|
|
855
|
+
def add_rlc_boundary(self, component: Optional[Union[str, Component]] = None, circuit_type: bool = True) -> bool:
|
|
844
856
|
"""Add RLC gap boundary on component and replace it with a circuit port.
|
|
845
857
|
The circuit port supports only 2-pin components.
|
|
846
858
|
|
|
@@ -903,19 +915,25 @@ class SourceExcitation:
|
|
|
903
915
|
rlc = GrpcRlc()
|
|
904
916
|
if rlc_values[0]:
|
|
905
917
|
rlc.r_enabled = True
|
|
906
|
-
rlc.r =
|
|
918
|
+
rlc.r = Value(rlc_values[0])
|
|
907
919
|
if rlc_values[1]:
|
|
908
920
|
rlc.l_enabled = True
|
|
909
|
-
rlc.l =
|
|
921
|
+
rlc.l = Value(rlc_values[1])
|
|
910
922
|
if rlc_values[2]:
|
|
911
923
|
rlc.c_enabled = True
|
|
912
|
-
rlc.c =
|
|
924
|
+
rlc.c = Value(rlc_values[2])
|
|
913
925
|
rlc.is_parallel = component.is_parallel_rlc
|
|
914
926
|
pos_pin_term.rlc_boundary = rlc
|
|
915
927
|
self._logger.info("Component {} has been replaced by port".format(component.refdes))
|
|
916
928
|
return True
|
|
917
929
|
|
|
918
|
-
def _create_pin_group_terminal(
|
|
930
|
+
def _create_pin_group_terminal(
|
|
931
|
+
self,
|
|
932
|
+
pingroup: Union[str, "PinGroup"],
|
|
933
|
+
isref: bool = False,
|
|
934
|
+
term_name: Optional[str] = None,
|
|
935
|
+
term_type: str = "circuit",
|
|
936
|
+
) -> Optional["PinGroupTerminal"]:
|
|
919
937
|
"""Creates an EDB pin group terminal from a given EDB pin group.
|
|
920
938
|
|
|
921
939
|
Parameters
|
|
@@ -963,7 +981,13 @@ class SourceExcitation:
|
|
|
963
981
|
pingroup_term.is_circuit_port = True
|
|
964
982
|
return pingroup_term
|
|
965
983
|
|
|
966
|
-
def create_coax_port(
|
|
984
|
+
def create_coax_port(
|
|
985
|
+
self,
|
|
986
|
+
padstackinstance: Union[PadstackInstance, int],
|
|
987
|
+
use_dot_separator: bool = True,
|
|
988
|
+
name: Optional[str] = None,
|
|
989
|
+
create_on_top: bool = True,
|
|
990
|
+
) -> Optional[str]:
|
|
967
991
|
"""Create HFSS 3Dlayout coaxial lumped port on a pastack
|
|
968
992
|
Requires to have solder ball defined before calling this method.
|
|
969
993
|
|
|
@@ -1030,10 +1054,16 @@ class SourceExcitation:
|
|
|
1030
1054
|
)
|
|
1031
1055
|
return port_name
|
|
1032
1056
|
|
|
1033
|
-
def _port_exist(self, port_name):
|
|
1057
|
+
def _port_exist(self, port_name: str) -> bool:
|
|
1034
1058
|
return any(port for port in list(self._pedb.excitations.keys()) if port == port_name)
|
|
1035
1059
|
|
|
1036
|
-
def _create_edge_terminal(
|
|
1060
|
+
def _create_edge_terminal(
|
|
1061
|
+
self,
|
|
1062
|
+
prim_id: Union[int, Primitive],
|
|
1063
|
+
point_on_edge: List[float],
|
|
1064
|
+
terminal_name: Optional[str] = None,
|
|
1065
|
+
is_ref: bool = False,
|
|
1066
|
+
) -> Optional[GrpcEdgeTerminal]:
|
|
1037
1067
|
"""Create an edge terminal.
|
|
1038
1068
|
|
|
1039
1069
|
Parameters
|
|
@@ -1068,7 +1098,13 @@ class SourceExcitation:
|
|
|
1068
1098
|
layout=prim.layout, name=terminal_name, edges=pos_edge, net=prim.net, is_ref=is_ref
|
|
1069
1099
|
)
|
|
1070
1100
|
|
|
1071
|
-
def create_circuit_port_on_pin(
|
|
1101
|
+
def create_circuit_port_on_pin(
|
|
1102
|
+
self,
|
|
1103
|
+
pos_pin: Union[str, PadstackInstance],
|
|
1104
|
+
neg_pin: Union[str, PadstackInstance],
|
|
1105
|
+
impedance: Union[int, float] = 50,
|
|
1106
|
+
port_name: Optional[str] = None,
|
|
1107
|
+
) -> Optional[str]:
|
|
1072
1108
|
"""Create a circuit port on a pin.
|
|
1073
1109
|
|
|
1074
1110
|
Parameters
|
|
@@ -1103,18 +1139,18 @@ class SourceExcitation:
|
|
|
1103
1139
|
|
|
1104
1140
|
def _create_terminal_on_pins(
|
|
1105
1141
|
self,
|
|
1106
|
-
positive_pin,
|
|
1107
|
-
negative_pin,
|
|
1108
|
-
name=None,
|
|
1109
|
-
use_pin_top_layer=True,
|
|
1110
|
-
source_type="circuit_port",
|
|
1111
|
-
impedance=50,
|
|
1112
|
-
magnitude=0,
|
|
1113
|
-
phase=0,
|
|
1114
|
-
r=0,
|
|
1115
|
-
l=0,
|
|
1116
|
-
c=0,
|
|
1117
|
-
):
|
|
1142
|
+
positive_pin: PadstackInstance,
|
|
1143
|
+
negative_pin: PadstackInstance,
|
|
1144
|
+
name: Optional[str] = None,
|
|
1145
|
+
use_pin_top_layer: bool = True,
|
|
1146
|
+
source_type: str = "circuit_port",
|
|
1147
|
+
impedance: Union[int, float, str] = 50,
|
|
1148
|
+
magnitude: Union[int, float, str] = 0,
|
|
1149
|
+
phase: Union[int, float, str] = 0,
|
|
1150
|
+
r: Union[int, float] = 0,
|
|
1151
|
+
l: Union[int, float] = 0,
|
|
1152
|
+
c: Union[int, float] = 0,
|
|
1153
|
+
) -> Optional[str]:
|
|
1118
1154
|
"""Create a terminal on pins.
|
|
1119
1155
|
|
|
1120
1156
|
Parameters
|
|
@@ -1173,7 +1209,7 @@ class SourceExcitation:
|
|
|
1173
1209
|
if source_type in ["circuit_port", "lumped_port"]:
|
|
1174
1210
|
pos_terminal.boundary_type = GrpcBoundaryType.PORT
|
|
1175
1211
|
neg_terminal.boundary_type = GrpcBoundaryType.PORT
|
|
1176
|
-
pos_terminal.impedance =
|
|
1212
|
+
pos_terminal.impedance = Value(impedance)
|
|
1177
1213
|
if source_type == "lumped_port":
|
|
1178
1214
|
pos_terminal.is_circuit_port = False
|
|
1179
1215
|
neg_terminal.is_circuit_port = False
|
|
@@ -1186,18 +1222,18 @@ class SourceExcitation:
|
|
|
1186
1222
|
elif source_type == "current_source":
|
|
1187
1223
|
pos_terminal.boundary_type = GrpcBoundaryType.CURRENT_SOURCE
|
|
1188
1224
|
neg_terminal.boundary_type = GrpcBoundaryType.CURRENT_SOURCE
|
|
1189
|
-
pos_terminal.source_amplitude =
|
|
1190
|
-
pos_terminal.source_phase =
|
|
1191
|
-
pos_terminal.impedance =
|
|
1225
|
+
pos_terminal.source_amplitude = Value(magnitude)
|
|
1226
|
+
pos_terminal.source_phase = Value(phase)
|
|
1227
|
+
pos_terminal.impedance = Value(impedance)
|
|
1192
1228
|
pos_terminal.reference_terminal = neg_terminal
|
|
1193
1229
|
pos_terminal.name = name
|
|
1194
1230
|
|
|
1195
1231
|
elif source_type == "voltage_source":
|
|
1196
1232
|
pos_terminal.boundary_type = GrpcBoundaryType.VOLTAGE_SOURCE
|
|
1197
1233
|
neg_terminal.boundary_type = GrpcBoundaryType.VOLTAGE_SOURCE
|
|
1198
|
-
pos_terminal.source_amplitude =
|
|
1199
|
-
pos_terminal.impedance =
|
|
1200
|
-
pos_terminal.source_phase =
|
|
1234
|
+
pos_terminal.source_amplitude = Value(magnitude)
|
|
1235
|
+
pos_terminal.impedance = Value(impedance)
|
|
1236
|
+
pos_terminal.source_phase = Value(phase)
|
|
1201
1237
|
pos_terminal.reference_terminal = neg_terminal
|
|
1202
1238
|
pos_terminal.name = name
|
|
1203
1239
|
|
|
@@ -1209,9 +1245,9 @@ class SourceExcitation:
|
|
|
1209
1245
|
rlc.r_enabled = bool(r)
|
|
1210
1246
|
rlc.l_enabled = bool(l)
|
|
1211
1247
|
rlc.c_enabled = bool(c)
|
|
1212
|
-
rlc.r =
|
|
1213
|
-
rlc.l =
|
|
1214
|
-
rlc.c =
|
|
1248
|
+
rlc.r = Value(r)
|
|
1249
|
+
rlc.l = Value(l)
|
|
1250
|
+
rlc.c = Value(c)
|
|
1215
1251
|
pos_terminal.rlc_boundary_parameters = rlc
|
|
1216
1252
|
pos_terminal.name = name
|
|
1217
1253
|
|
|
@@ -1220,7 +1256,14 @@ class SourceExcitation:
|
|
|
1220
1256
|
return False
|
|
1221
1257
|
return pos_terminal.name
|
|
1222
1258
|
|
|
1223
|
-
def create_voltage_source_on_pin(
|
|
1259
|
+
def create_voltage_source_on_pin(
|
|
1260
|
+
self,
|
|
1261
|
+
pos_pin: Union[str, PadstackInstance],
|
|
1262
|
+
neg_pin: Union[str, PadstackInstance],
|
|
1263
|
+
voltage_value: Union[int, float] = 0,
|
|
1264
|
+
phase_value: Union[int, float] = 0,
|
|
1265
|
+
source_name: Optional[str] = None,
|
|
1266
|
+
) -> Optional[str]:
|
|
1224
1267
|
"""Create a voltage source.
|
|
1225
1268
|
|
|
1226
1269
|
Parameters
|
|
@@ -1263,7 +1306,14 @@ class SourceExcitation:
|
|
|
1263
1306
|
source_type="voltage_source",
|
|
1264
1307
|
)
|
|
1265
1308
|
|
|
1266
|
-
def create_current_source_on_pin(
|
|
1309
|
+
def create_current_source_on_pin(
|
|
1310
|
+
self,
|
|
1311
|
+
pos_pin: Union[str, PadstackInstance],
|
|
1312
|
+
neg_pin: Union[str, PadstackInstance],
|
|
1313
|
+
current_value: Union[int, float] = 0,
|
|
1314
|
+
phase_value: Union[int, float] = 0,
|
|
1315
|
+
source_name: Optional[str] = None,
|
|
1316
|
+
) -> Optional[str]:
|
|
1267
1317
|
"""Create a voltage source.
|
|
1268
1318
|
|
|
1269
1319
|
Parameters
|
|
@@ -1306,7 +1356,13 @@ class SourceExcitation:
|
|
|
1306
1356
|
source_type="current_source",
|
|
1307
1357
|
)
|
|
1308
1358
|
|
|
1309
|
-
def create_resistor_on_pin(
|
|
1359
|
+
def create_resistor_on_pin(
|
|
1360
|
+
self,
|
|
1361
|
+
pos_pin: Union[str, PadstackInstance],
|
|
1362
|
+
neg_pin: Union[str, PadstackInstance],
|
|
1363
|
+
rvalue: Union[int, float] = 1,
|
|
1364
|
+
resistor_name: Optional[str] = "",
|
|
1365
|
+
) -> Optional[str]:
|
|
1310
1366
|
"""Create a Resistor boundary between two given pins..
|
|
1311
1367
|
|
|
1312
1368
|
Parameters
|
|
@@ -1343,13 +1399,13 @@ class SourceExcitation:
|
|
|
1343
1399
|
|
|
1344
1400
|
def create_circuit_port_on_net(
|
|
1345
1401
|
self,
|
|
1346
|
-
positive_component_name,
|
|
1347
|
-
positive_net_name,
|
|
1348
|
-
negative_component_name
|
|
1349
|
-
negative_net_name=None,
|
|
1350
|
-
|
|
1351
|
-
port_name=
|
|
1352
|
-
):
|
|
1402
|
+
positive_component_name: str,
|
|
1403
|
+
positive_net_name: str,
|
|
1404
|
+
negative_component_name: str,
|
|
1405
|
+
negative_net_name: Optional[str] = None,
|
|
1406
|
+
impedance_value: Union[int, float] = 50,
|
|
1407
|
+
port_name: Optional[str] = None,
|
|
1408
|
+
) -> Optional[str]:
|
|
1353
1409
|
"""Create a circuit port on a NET.
|
|
1354
1410
|
|
|
1355
1411
|
It groups all pins belonging to the specified net and then applies the port on PinGroups.
|
|
@@ -1414,23 +1470,23 @@ class SourceExcitation:
|
|
|
1414
1470
|
positive_pins=positive_pins,
|
|
1415
1471
|
negatives_pins=negative_pins,
|
|
1416
1472
|
name=port_name,
|
|
1417
|
-
impedance=
|
|
1473
|
+
impedance=impedance_value,
|
|
1418
1474
|
source_type="circuit_port",
|
|
1419
1475
|
)
|
|
1420
1476
|
|
|
1421
1477
|
def create_pin_group_terminal(
|
|
1422
1478
|
self,
|
|
1423
|
-
positive_pins,
|
|
1424
|
-
negatives_pins,
|
|
1425
|
-
name=None,
|
|
1426
|
-
impedance=50,
|
|
1427
|
-
source_type="circuit_port",
|
|
1428
|
-
magnitude=1.0,
|
|
1429
|
-
phase=0,
|
|
1430
|
-
r=0.0,
|
|
1431
|
-
l=0.0,
|
|
1432
|
-
c=0.0,
|
|
1433
|
-
):
|
|
1479
|
+
positive_pins: Union[PadstackInstance, List[PadstackInstance]],
|
|
1480
|
+
negatives_pins: Optional[Union[PadstackInstance, List[PadstackInstance]]] = None,
|
|
1481
|
+
name: Optional[str] = None,
|
|
1482
|
+
impedance: Union[int, float, str] = 50,
|
|
1483
|
+
source_type: str = "circuit_port",
|
|
1484
|
+
magnitude: Union[float, str] = 1.0,
|
|
1485
|
+
phase: Union[float, str] = 0,
|
|
1486
|
+
r: float = 0.0,
|
|
1487
|
+
l: float = 0.0,
|
|
1488
|
+
c: float = 0.0,
|
|
1489
|
+
) -> Optional[str]:
|
|
1434
1490
|
"""Create a pin group terminal.
|
|
1435
1491
|
|
|
1436
1492
|
Parameters
|
|
@@ -1490,7 +1546,7 @@ class SourceExcitation:
|
|
|
1490
1546
|
)
|
|
1491
1547
|
if source_type in ["circuit_port", "lumped_port"]:
|
|
1492
1548
|
pos_pingroup_terminal.boundary_type = GrpcBoundaryType.PORT
|
|
1493
|
-
pos_pingroup_terminal.impedance =
|
|
1549
|
+
pos_pingroup_terminal.impedance = Value(impedance)
|
|
1494
1550
|
if len(positive_pins) > 1 and len(negatives_pins) > 1:
|
|
1495
1551
|
if source_type == "lumped_port":
|
|
1496
1552
|
source_type = "circuit_port"
|
|
@@ -1506,16 +1562,16 @@ class SourceExcitation:
|
|
|
1506
1562
|
elif source_type == "current_source":
|
|
1507
1563
|
pos_pingroup_terminal.boundary_type = GrpcBoundaryType.CURRENT_SOURCE
|
|
1508
1564
|
neg_pingroup_terminal.boundary_type = GrpcBoundaryType.CURRENT_SOURCE
|
|
1509
|
-
pos_pingroup_terminal.source_amplitude =
|
|
1510
|
-
pos_pingroup_terminal.source_phase =
|
|
1565
|
+
pos_pingroup_terminal.source_amplitude = Value(magnitude)
|
|
1566
|
+
pos_pingroup_terminal.source_phase = Value(phase)
|
|
1511
1567
|
pos_pingroup_terminal.reference_terminal = neg_pingroup_terminal
|
|
1512
1568
|
pos_pingroup_terminal.name = name
|
|
1513
1569
|
|
|
1514
1570
|
elif source_type == "voltage_source":
|
|
1515
1571
|
pos_pingroup_terminal.boundary_type = GrpcBoundaryType.VOLTAGE_SOURCE
|
|
1516
1572
|
neg_pingroup_terminal.boundary_type = GrpcBoundaryType.VOLTAGE_SOURCE
|
|
1517
|
-
pos_pingroup_terminal.source_amplitude =
|
|
1518
|
-
pos_pingroup_terminal.source_phase =
|
|
1573
|
+
pos_pingroup_terminal.source_amplitude = Value(magnitude)
|
|
1574
|
+
pos_pingroup_terminal.source_phase = Value(phase)
|
|
1519
1575
|
pos_pingroup_terminal.reference_terminal = neg_pingroup_terminal
|
|
1520
1576
|
pos_pingroup_terminal.name = name
|
|
1521
1577
|
|
|
@@ -1527,9 +1583,9 @@ class SourceExcitation:
|
|
|
1527
1583
|
Rlc.r_enabled = bool(r)
|
|
1528
1584
|
Rlc.l_enabled = bool(l)
|
|
1529
1585
|
Rlc.c_enabled = bool(c)
|
|
1530
|
-
Rlc.r =
|
|
1531
|
-
Rlc.l =
|
|
1532
|
-
Rlc.c =
|
|
1586
|
+
Rlc.r = Value(r)
|
|
1587
|
+
Rlc.l = Value(l)
|
|
1588
|
+
Rlc.c = Value(c)
|
|
1533
1589
|
pos_pingroup_terminal.rlc_boundary_parameters = Rlc
|
|
1534
1590
|
|
|
1535
1591
|
elif source_type == "dc_terminal":
|
|
@@ -1538,7 +1594,7 @@ class SourceExcitation:
|
|
|
1538
1594
|
pass
|
|
1539
1595
|
return pos_pingroup_terminal.name
|
|
1540
1596
|
|
|
1541
|
-
def _check_gnd(self, component_name):
|
|
1597
|
+
def _check_gnd(self, component_name: str) -> Optional[str]:
|
|
1542
1598
|
negative_net_name = None
|
|
1543
1599
|
if self._pedb.nets.is_net_in_component(component_name, "GND"):
|
|
1544
1600
|
negative_net_name = "GND"
|
|
@@ -1554,14 +1610,14 @@ class SourceExcitation:
|
|
|
1554
1610
|
|
|
1555
1611
|
def create_voltage_source_on_net(
|
|
1556
1612
|
self,
|
|
1557
|
-
positive_component_name,
|
|
1558
|
-
positive_net_name,
|
|
1559
|
-
negative_component_name=None,
|
|
1560
|
-
negative_net_name=None,
|
|
1561
|
-
voltage_value=
|
|
1562
|
-
phase_value=0,
|
|
1563
|
-
source_name=None,
|
|
1564
|
-
):
|
|
1613
|
+
positive_component_name: str,
|
|
1614
|
+
positive_net_name: str,
|
|
1615
|
+
negative_component_name: Optional[str] = None,
|
|
1616
|
+
negative_net_name: Optional[str] = None,
|
|
1617
|
+
voltage_value: Union[int, float] = 0,
|
|
1618
|
+
phase_value: Union[int, float] = 0,
|
|
1619
|
+
source_name: Optional[str] = None,
|
|
1620
|
+
) -> Optional[str]:
|
|
1565
1621
|
"""Create a voltage source.
|
|
1566
1622
|
|
|
1567
1623
|
Parameters
|
|
@@ -1617,14 +1673,14 @@ class SourceExcitation:
|
|
|
1617
1673
|
|
|
1618
1674
|
def create_current_source_on_net(
|
|
1619
1675
|
self,
|
|
1620
|
-
positive_component_name,
|
|
1621
|
-
positive_net_name,
|
|
1622
|
-
negative_component_name=None,
|
|
1623
|
-
negative_net_name=None,
|
|
1624
|
-
current_value=
|
|
1625
|
-
phase_value=0,
|
|
1626
|
-
source_name=None,
|
|
1627
|
-
):
|
|
1676
|
+
positive_component_name: str,
|
|
1677
|
+
positive_net_name: str,
|
|
1678
|
+
negative_component_name: Optional[str] = None,
|
|
1679
|
+
negative_net_name: Optional[str] = None,
|
|
1680
|
+
current_value: Union[int, float] = 0,
|
|
1681
|
+
phase_value: Union[int, float] = 0,
|
|
1682
|
+
source_name: Optional[str] = None,
|
|
1683
|
+
) -> Optional[str]:
|
|
1628
1684
|
"""Create a voltage source.
|
|
1629
1685
|
|
|
1630
1686
|
Parameters
|
|
@@ -1679,7 +1735,12 @@ class SourceExcitation:
|
|
|
1679
1735
|
source_type="current_source",
|
|
1680
1736
|
)
|
|
1681
1737
|
|
|
1682
|
-
def create_coax_port_on_component(
|
|
1738
|
+
def create_coax_port_on_component(
|
|
1739
|
+
self,
|
|
1740
|
+
ref_des_list: Union[str, List[str]],
|
|
1741
|
+
net_list: Union[str, List[str]],
|
|
1742
|
+
delete_existing_terminal: bool = False,
|
|
1743
|
+
) -> List[str]:
|
|
1683
1744
|
"""Create a coaxial port on a component or component list on a net or net list.
|
|
1684
1745
|
The name of the new coaxial port is automatically assigned.
|
|
1685
1746
|
|
|
@@ -1741,7 +1802,7 @@ class SourceExcitation:
|
|
|
1741
1802
|
self._logger.error(error)
|
|
1742
1803
|
return coax
|
|
1743
1804
|
|
|
1744
|
-
def check_before_terminal_assignement(self, connectable, delete_existing_terminal=False):
|
|
1805
|
+
def check_before_terminal_assignement(self, connectable: Any, delete_existing_terminal: bool = False) -> bool:
|
|
1745
1806
|
if not connectable:
|
|
1746
1807
|
return False
|
|
1747
1808
|
existing_terminals = [term for term in self._pedb.active_layout.terminals if term.id == connectable.id]
|
|
@@ -1763,15 +1824,15 @@ class SourceExcitation:
|
|
|
1763
1824
|
|
|
1764
1825
|
def create_differential_wave_port(
|
|
1765
1826
|
self,
|
|
1766
|
-
positive_primitive_id,
|
|
1767
|
-
positive_points_on_edge,
|
|
1768
|
-
negative_primitive_id,
|
|
1769
|
-
negative_points_on_edge,
|
|
1770
|
-
port_name=None,
|
|
1771
|
-
horizontal_extent_factor=5,
|
|
1772
|
-
vertical_extent_factor=3,
|
|
1773
|
-
pec_launch_width="0.01mm",
|
|
1774
|
-
):
|
|
1827
|
+
positive_primitive_id: Union[int, Primitive],
|
|
1828
|
+
positive_points_on_edge: List[float],
|
|
1829
|
+
negative_primitive_id: Union[int, Primitive],
|
|
1830
|
+
negative_points_on_edge: List[float],
|
|
1831
|
+
port_name: Optional[str] = None,
|
|
1832
|
+
horizontal_extent_factor: Union[int, float] = 5,
|
|
1833
|
+
vertical_extent_factor: Union[int, float] = 3,
|
|
1834
|
+
pec_launch_width: str = "0.01mm",
|
|
1835
|
+
) -> Tuple[str, BundleTerminal]:
|
|
1775
1836
|
"""Create a differential wave port.
|
|
1776
1837
|
|
|
1777
1838
|
Parameters
|
|
@@ -1842,14 +1903,14 @@ class SourceExcitation:
|
|
|
1842
1903
|
|
|
1843
1904
|
def create_wave_port(
|
|
1844
1905
|
self,
|
|
1845
|
-
prim_id,
|
|
1846
|
-
point_on_edge,
|
|
1847
|
-
port_name=None,
|
|
1848
|
-
impedance=50,
|
|
1849
|
-
horizontal_extent_factor=5,
|
|
1850
|
-
vertical_extent_factor=3,
|
|
1851
|
-
pec_launch_width="0.01mm",
|
|
1852
|
-
):
|
|
1906
|
+
prim_id: Union[int, Primitive],
|
|
1907
|
+
point_on_edge: List[float],
|
|
1908
|
+
port_name: Optional[str] = None,
|
|
1909
|
+
impedance: Union[int, float] = 50,
|
|
1910
|
+
horizontal_extent_factor: Union[int, float] = 5,
|
|
1911
|
+
vertical_extent_factor: Union[int, float] = 3,
|
|
1912
|
+
pec_launch_width: str = "0.01mm",
|
|
1913
|
+
) -> Tuple[str, WavePort]:
|
|
1853
1914
|
"""Create a wave port.
|
|
1854
1915
|
|
|
1855
1916
|
Parameters
|
|
@@ -1888,7 +1949,7 @@ class SourceExcitation:
|
|
|
1888
1949
|
if isinstance(prim_id, Primitive):
|
|
1889
1950
|
prim_id = prim_id.edb_uid
|
|
1890
1951
|
pos_edge_term = self._create_edge_terminal(prim_id, point_on_edge, port_name)
|
|
1891
|
-
pos_edge_term.impedance =
|
|
1952
|
+
pos_edge_term.impedance = Value(impedance)
|
|
1892
1953
|
wave_port = WavePort(self._pedb, pos_edge_term)
|
|
1893
1954
|
wave_port.horizontal_extent_factor = horizontal_extent_factor
|
|
1894
1955
|
wave_port.vertical_extent_factor = vertical_extent_factor
|
|
@@ -1902,16 +1963,16 @@ class SourceExcitation:
|
|
|
1902
1963
|
|
|
1903
1964
|
def create_edge_port_vertical(
|
|
1904
1965
|
self,
|
|
1905
|
-
prim_id,
|
|
1906
|
-
point_on_edge,
|
|
1907
|
-
port_name=None,
|
|
1908
|
-
impedance=50,
|
|
1909
|
-
reference_layer=None,
|
|
1910
|
-
hfss_type="Gap",
|
|
1911
|
-
horizontal_extent_factor=5,
|
|
1912
|
-
vertical_extent_factor=3,
|
|
1913
|
-
pec_launch_width="0.01mm",
|
|
1914
|
-
):
|
|
1966
|
+
prim_id: int,
|
|
1967
|
+
point_on_edge: List[float],
|
|
1968
|
+
port_name: Optional[str] = None,
|
|
1969
|
+
impedance: Union[int, float] = 50,
|
|
1970
|
+
reference_layer: Optional[str] = None,
|
|
1971
|
+
hfss_type: str = "Gap",
|
|
1972
|
+
horizontal_extent_factor: Union[int, float] = 5,
|
|
1973
|
+
vertical_extent_factor: Union[int, float] = 3,
|
|
1974
|
+
pec_launch_width: str = "0.01mm",
|
|
1975
|
+
) -> str:
|
|
1915
1976
|
"""Create a vertical edge port.
|
|
1916
1977
|
|
|
1917
1978
|
Parameters
|
|
@@ -1953,7 +2014,7 @@ class SourceExcitation:
|
|
|
1953
2014
|
if not port_name:
|
|
1954
2015
|
port_name = generate_unique_name("Terminal_")
|
|
1955
2016
|
pos_edge_term = self._create_edge_terminal(prim_id, point_on_edge, port_name)
|
|
1956
|
-
pos_edge_term.impedance =
|
|
2017
|
+
pos_edge_term.impedance = Value(impedance)
|
|
1957
2018
|
if reference_layer:
|
|
1958
2019
|
reference_layer = self._pedb.stackup.signal_layers[reference_layer]
|
|
1959
2020
|
pos_edge_term.reference_layer = reference_layer
|
|
@@ -1980,14 +2041,14 @@ class SourceExcitation:
|
|
|
1980
2041
|
|
|
1981
2042
|
def create_edge_port_horizontal(
|
|
1982
2043
|
self,
|
|
1983
|
-
prim_id,
|
|
1984
|
-
point_on_edge,
|
|
1985
|
-
ref_prim_id=None,
|
|
1986
|
-
point_on_ref_edge=None,
|
|
1987
|
-
port_name=None,
|
|
1988
|
-
impedance=50,
|
|
1989
|
-
layer_alignment="Upper",
|
|
1990
|
-
):
|
|
2044
|
+
prim_id: Union[int, Primitive],
|
|
2045
|
+
point_on_edge: List[float],
|
|
2046
|
+
ref_prim_id: Optional[Union[int, Primitive]] = None,
|
|
2047
|
+
point_on_ref_edge: Optional[List[float]] = None,
|
|
2048
|
+
port_name: Optional[str] = None,
|
|
2049
|
+
impedance: Union[int, float] = 50,
|
|
2050
|
+
layer_alignment: str = "Upper",
|
|
2051
|
+
) -> Optional[EdgeTerminal]:
|
|
1991
2052
|
"""Create a horizontal edge port.
|
|
1992
2053
|
|
|
1993
2054
|
Parameters
|
|
@@ -2025,7 +2086,7 @@ class SourceExcitation:
|
|
|
2025
2086
|
pos_edge_term = self._create_edge_terminal(prim_id, point_on_edge, port_name)
|
|
2026
2087
|
neg_edge_term = self._create_edge_terminal(ref_prim_id, point_on_ref_edge, port_name + "_ref", is_ref=True)
|
|
2027
2088
|
|
|
2028
|
-
pos_edge_term.impedance =
|
|
2089
|
+
pos_edge_term.impedance = Value(impedance)
|
|
2029
2090
|
pos_edge_term.reference_terminal = neg_edge_term
|
|
2030
2091
|
if not layer_alignment == "Upper":
|
|
2031
2092
|
layer_alignment = "Lower"
|
|
@@ -2040,7 +2101,12 @@ class SourceExcitation:
|
|
|
2040
2101
|
return False
|
|
2041
2102
|
|
|
2042
2103
|
def create_lumped_port_on_net(
|
|
2043
|
-
self,
|
|
2104
|
+
self,
|
|
2105
|
+
nets: Optional[Union[str, List[str]]] = None,
|
|
2106
|
+
reference_layer: Optional[Union[str, StackupLayer]] = None,
|
|
2107
|
+
return_points_only: bool = False,
|
|
2108
|
+
digit_resolution: int = 6,
|
|
2109
|
+
at_bounding_box: bool = True,
|
|
2044
2110
|
) -> bool:
|
|
2045
2111
|
"""Create an edge port on nets. This command looks for traces and polygons on the
|
|
2046
2112
|
nets and tries to assign vertical lumped port.
|
|
@@ -2095,11 +2161,11 @@ class SourceExcitation:
|
|
|
2095
2161
|
layout_extent_segments = [pt for pt in list(layout_bbox.arc_data) if pt.is_segment]
|
|
2096
2162
|
first_pt = layout_extent_segments[0]
|
|
2097
2163
|
layout_extent_points = [
|
|
2098
|
-
[first_pt.start.x
|
|
2099
|
-
[first_pt.Start.y
|
|
2164
|
+
[Value(first_pt.start.x), Value(first_pt.end.x)],
|
|
2165
|
+
[Value(first_pt.Start.y), Value(first_pt.end.y)],
|
|
2100
2166
|
]
|
|
2101
2167
|
for segment in layout_extent_segments[1:]:
|
|
2102
|
-
end_point = (segment.end.x
|
|
2168
|
+
end_point = (Value(segment.end.x), Value(segment.end.y))
|
|
2103
2169
|
layout_extent_points[0].append(end_point[0])
|
|
2104
2170
|
layout_extent_points[1].append(end_point[1])
|
|
2105
2171
|
for net in nets:
|
|
@@ -2110,8 +2176,8 @@ class SourceExcitation:
|
|
|
2110
2176
|
port_name = f"{net.name}_{path.id}"
|
|
2111
2177
|
for pt in trace_path_pts:
|
|
2112
2178
|
_pt = [
|
|
2113
|
-
round(pt.x
|
|
2114
|
-
round(pt.y
|
|
2179
|
+
round(Value(pt.x), digit_resolution),
|
|
2180
|
+
round(Value(pt.y), digit_resolution),
|
|
2115
2181
|
]
|
|
2116
2182
|
if at_bounding_box:
|
|
2117
2183
|
if GeometryOperators.point_in_polygon(_pt, layout_extent_points) == 0:
|
|
@@ -2134,7 +2200,7 @@ class SourceExcitation:
|
|
|
2134
2200
|
for segment in poly_segment:
|
|
2135
2201
|
if (
|
|
2136
2202
|
GeometryOperators.point_in_polygon(
|
|
2137
|
-
[segment.mid_point.x
|
|
2203
|
+
[Value(segment.mid_point.x), Value(segment.mid_point.y)], layout_extent_points
|
|
2138
2204
|
)
|
|
2139
2205
|
== 0
|
|
2140
2206
|
):
|
|
@@ -2152,8 +2218,11 @@ class SourceExcitation:
|
|
|
2152
2218
|
return port_created
|
|
2153
2219
|
|
|
2154
2220
|
def create_vertical_circuit_port_on_clipped_traces(
|
|
2155
|
-
self,
|
|
2156
|
-
|
|
2221
|
+
self,
|
|
2222
|
+
nets: Optional[Union[str, List[str], Net, List[Net]]] = None,
|
|
2223
|
+
reference_net: Optional[Union[str, Net]] = None,
|
|
2224
|
+
user_defined_extent: Optional[Union[List[float], GrpcPolygonData]] = None,
|
|
2225
|
+
) -> Union[List[List[str]], bool]:
|
|
2157
2226
|
"""Create an edge port on clipped signal traces.
|
|
2158
2227
|
|
|
2159
2228
|
Parameters
|
|
@@ -2196,15 +2265,15 @@ class SourceExcitation:
|
|
|
2196
2265
|
_x = []
|
|
2197
2266
|
_y = []
|
|
2198
2267
|
for pt in _points:
|
|
2199
|
-
if pt.x
|
|
2200
|
-
_x.append(pt.x
|
|
2201
|
-
_y.append(pt.y
|
|
2268
|
+
if Value(pt.x) < 1e100 and Value(pt.y) < 1e100:
|
|
2269
|
+
_x.append(Value(pt.x))
|
|
2270
|
+
_y.append(Value(pt.y))
|
|
2202
2271
|
user_defined_extent = [_x, _y]
|
|
2203
2272
|
terminal_info = []
|
|
2204
2273
|
for net in nets:
|
|
2205
2274
|
net_polygons = [prim for prim in self._pedb.modeler.primitives if prim.type in ["polygon", "rectangle"]]
|
|
2206
2275
|
for poly in net_polygons:
|
|
2207
|
-
mid_points = [[arc.midpoint.x
|
|
2276
|
+
mid_points = [[Value(arc.midpoint.x), Value(arc.midpoint.y)] for arc in poly.arcs]
|
|
2208
2277
|
for mid_point in mid_points:
|
|
2209
2278
|
if GeometryOperators.point_in_polygon(mid_point, user_defined_extent) == 0:
|
|
2210
2279
|
port_name = generate_unique_name(f"{poly.net_name}_{poly.id}")
|
|
@@ -2248,13 +2317,13 @@ class SourceExcitation:
|
|
|
2248
2317
|
|
|
2249
2318
|
def create_bundle_wave_port(
|
|
2250
2319
|
self,
|
|
2251
|
-
primitives_id,
|
|
2252
|
-
points_on_edge,
|
|
2253
|
-
port_name=None,
|
|
2254
|
-
horizontal_extent_factor=5,
|
|
2255
|
-
vertical_extent_factor=3,
|
|
2256
|
-
pec_launch_width="0.01mm",
|
|
2257
|
-
):
|
|
2320
|
+
primitives_id: List[Union[int, Primitive]],
|
|
2321
|
+
points_on_edge: List[List[float]],
|
|
2322
|
+
port_name: Optional[str] = None,
|
|
2323
|
+
horizontal_extent_factor: Union[int, float] = 5,
|
|
2324
|
+
vertical_extent_factor: Union[int, float] = 3,
|
|
2325
|
+
pec_launch_width: str = "0.01mm",
|
|
2326
|
+
) -> Tuple[str, BundleWavePort]:
|
|
2258
2327
|
"""Create a bundle wave port.
|
|
2259
2328
|
|
|
2260
2329
|
Parameters
|
|
@@ -2308,7 +2377,7 @@ class SourceExcitation:
|
|
|
2308
2377
|
_edb_bundle_terminal = BundleTerminal.create(terminals)
|
|
2309
2378
|
return port_name, BundleWavePort(self._pedb, _edb_bundle_terminal)
|
|
2310
2379
|
|
|
2311
|
-
def create_hfss_ports_on_padstack(self, pinpos, portname=None):
|
|
2380
|
+
def create_hfss_ports_on_padstack(self, pinpos: PadstackInstance, portname: Optional[str] = None) -> bool:
|
|
2312
2381
|
"""Create an HFSS port on a padstack.
|
|
2313
2382
|
|
|
2314
2383
|
Parameters
|
|
@@ -2343,7 +2412,7 @@ class SourceExcitation:
|
|
|
2343
2412
|
else:
|
|
2344
2413
|
return False
|
|
2345
2414
|
|
|
2346
|
-
def get_ports_number(self):
|
|
2415
|
+
def get_ports_number(self) -> int:
|
|
2347
2416
|
"""Return the total number of excitation ports in a layout.
|
|
2348
2417
|
|
|
2349
2418
|
Parameters
|
|
@@ -2364,7 +2433,7 @@ class SourceExcitation:
|
|
|
2364
2433
|
terms = [term for term in self._pedb.layout.terminals]
|
|
2365
2434
|
return len([i for i in terms if not i.is_reference_terminal])
|
|
2366
2435
|
|
|
2367
|
-
def get_point_terminal(self, name, net_name, location, layer) -> PointTerminal:
|
|
2436
|
+
def get_point_terminal(self, name: str, net_name: str, location: List[float], layer: str) -> PointTerminal:
|
|
2368
2437
|
"""Place terminal between two points.
|
|
2369
2438
|
|
|
2370
2439
|
Parameters
|
|
@@ -2394,7 +2463,14 @@ class SourceExcitation:
|
|
|
2394
2463
|
layout=self._pedb.active_layout, name=name, net=net_name, layer=layer, point=location
|
|
2395
2464
|
)
|
|
2396
2465
|
|
|
2397
|
-
def create_rlc_boundary_on_pins(
|
|
2466
|
+
def create_rlc_boundary_on_pins(
|
|
2467
|
+
self,
|
|
2468
|
+
positive_pin: Optional[PadstackInstance] = None,
|
|
2469
|
+
negative_pin: Optional[PadstackInstance] = None,
|
|
2470
|
+
rvalue: float = 0.0,
|
|
2471
|
+
lvalue: float = 0.0,
|
|
2472
|
+
cvalue: float = 0.0,
|
|
2473
|
+
) -> Union[Terminal, bool]:
|
|
2398
2474
|
"""Create hfss rlc boundary on pins.
|
|
2399
2475
|
|
|
2400
2476
|
Parameters
|
|
@@ -2435,9 +2511,9 @@ class SourceExcitation:
|
|
|
2435
2511
|
rlc.r_enabled = True
|
|
2436
2512
|
rlc.l_enabled = True
|
|
2437
2513
|
rlc.c_enabled = True
|
|
2438
|
-
rlc.r =
|
|
2439
|
-
rlc.l =
|
|
2440
|
-
rlc.c =
|
|
2514
|
+
rlc.r = Value(rvalue)
|
|
2515
|
+
rlc.l = Value(lvalue)
|
|
2516
|
+
rlc.c = Value(cvalue)
|
|
2441
2517
|
positive_pin_term.rlc_boundary_parameters = rlc
|
|
2442
2518
|
term_name = f"{positive_pin.component.name}_{positive_pin.net.name}_{positive_pin.name}"
|
|
2443
2519
|
positive_pin_term.name = term_name
|
|
@@ -2448,15 +2524,15 @@ class SourceExcitation:
|
|
|
2448
2524
|
|
|
2449
2525
|
def create_edge_port_on_polygon(
|
|
2450
2526
|
self,
|
|
2451
|
-
polygon=None,
|
|
2452
|
-
reference_polygon=None,
|
|
2453
|
-
terminal_point=None,
|
|
2454
|
-
reference_point=None,
|
|
2455
|
-
reference_layer=None,
|
|
2456
|
-
port_name=None,
|
|
2457
|
-
port_impedance=50.0,
|
|
2458
|
-
force_circuit_port=False,
|
|
2459
|
-
):
|
|
2527
|
+
polygon: Optional[Primitive] = None,
|
|
2528
|
+
reference_polygon: Optional[Primitive] = None,
|
|
2529
|
+
terminal_point: Optional[List[float]] = None,
|
|
2530
|
+
reference_point: Optional[List[float]] = None,
|
|
2531
|
+
reference_layer: Optional[Union[str, StackupLayer]] = None,
|
|
2532
|
+
port_name: Optional[str] = None,
|
|
2533
|
+
port_impedance: Union[int, float] = 50.0,
|
|
2534
|
+
force_circuit_port: bool = False,
|
|
2535
|
+
) -> Optional[str]:
|
|
2460
2536
|
"""Create lumped port between two edges from two different polygons. Can also create a vertical port when
|
|
2461
2537
|
the reference layer name is only provided. When a port is created between two edge from two polygons which don't
|
|
2462
2538
|
belong to the same layer, a circuit port will be automatically created instead of lumped. To enforce the circuit
|
|
@@ -2525,7 +2601,7 @@ class SourceExcitation:
|
|
|
2525
2601
|
edge_term.is_circuit_port = False
|
|
2526
2602
|
|
|
2527
2603
|
if port_impedance:
|
|
2528
|
-
edge_term.impedance =
|
|
2604
|
+
edge_term.impedance = Value(port_impedance)
|
|
2529
2605
|
edge_term.name = port_name
|
|
2530
2606
|
if reference_polygon and reference_point:
|
|
2531
2607
|
ref_edge = GrpcPrimitiveEdge.create(reference_polygon, reference_point)
|
|
@@ -2545,13 +2621,18 @@ class SourceExcitation:
|
|
|
2545
2621
|
ref_edge_term.is_circuit_port = False
|
|
2546
2622
|
|
|
2547
2623
|
if port_impedance:
|
|
2548
|
-
ref_edge_term.impedance =
|
|
2624
|
+
ref_edge_term.impedance = Value(port_impedance)
|
|
2549
2625
|
edge_term.reference_terminal = ref_edge_term
|
|
2550
2626
|
return True
|
|
2551
2627
|
|
|
2552
2628
|
def create_port_between_pin_and_layer(
|
|
2553
|
-
self,
|
|
2554
|
-
|
|
2629
|
+
self,
|
|
2630
|
+
component_name: Optional[str] = None,
|
|
2631
|
+
pins_name: Optional[Union[str, List[str]]] = None,
|
|
2632
|
+
layer_name: Optional[str] = None,
|
|
2633
|
+
reference_net: Optional[str] = None,
|
|
2634
|
+
impedance: Union[int, float] = 50.0,
|
|
2635
|
+
) -> bool:
|
|
2555
2636
|
"""Create circuit port between pin and a reference layer.
|
|
2556
2637
|
|
|
2557
2638
|
Parameters
|
|
@@ -2607,7 +2688,7 @@ class SourceExcitation:
|
|
|
2607
2688
|
layout=pin.layout, net=pin.net, padstack_instance=pin, name=term_name, layer=start_layer
|
|
2608
2689
|
)
|
|
2609
2690
|
positive_terminal.boundary_type = GrpcBoundaryType.PORT
|
|
2610
|
-
positive_terminal.impedance =
|
|
2691
|
+
positive_terminal.impedance = Value(impedance)
|
|
2611
2692
|
positive_terminal.Is_circuit_port = True
|
|
2612
2693
|
position = GrpcPointData(self._pedb.components.get_pin_position(pin))
|
|
2613
2694
|
negative_terminal = PointTerminal.create(
|
|
@@ -2618,7 +2699,7 @@ class SourceExcitation:
|
|
|
2618
2699
|
point=position,
|
|
2619
2700
|
)
|
|
2620
2701
|
negative_terminal.boundary_type = GrpcBoundaryType.PORT
|
|
2621
|
-
negative_terminal.impedance =
|
|
2702
|
+
negative_terminal.impedance = Value(impedance)
|
|
2622
2703
|
negative_terminal.is_circuit_port = True
|
|
2623
2704
|
positive_terminal.reference_terminal = negative_terminal
|
|
2624
2705
|
self._logger.info("Port {} successfully created".format(term_name))
|
|
@@ -2630,7 +2711,11 @@ class SourceExcitation:
|
|
|
2630
2711
|
return terms
|
|
2631
2712
|
return False
|
|
2632
2713
|
|
|
2633
|
-
def create_current_source(
|
|
2714
|
+
def create_current_source(
|
|
2715
|
+
self,
|
|
2716
|
+
terminal: Union[PadstackInstanceTerminal, EdgeTerminal],
|
|
2717
|
+
ref_terminal: Union[PadstackInstanceTerminal, EdgeTerminal],
|
|
2718
|
+
) -> bool:
|
|
2634
2719
|
"""Create a current source.
|
|
2635
2720
|
|
|
2636
2721
|
Parameters
|
|
@@ -2668,8 +2753,13 @@ class SourceExcitation:
|
|
|
2668
2753
|
return term
|
|
2669
2754
|
|
|
2670
2755
|
def create_current_source_on_pin_group(
|
|
2671
|
-
self,
|
|
2672
|
-
|
|
2756
|
+
self,
|
|
2757
|
+
pos_pin_group_name: str,
|
|
2758
|
+
neg_pin_group_name: str,
|
|
2759
|
+
magnitude: Union[int, float] = 1,
|
|
2760
|
+
phase: Union[int, float] = 0,
|
|
2761
|
+
name: Optional[str] = None,
|
|
2762
|
+
) -> bool:
|
|
2673
2763
|
"""Create current source between two pin groups.
|
|
2674
2764
|
|
|
2675
2765
|
Parameters
|
|
@@ -2707,7 +2797,11 @@ class SourceExcitation:
|
|
|
2707
2797
|
pos_terminal.reference_terminal = neg_terminal
|
|
2708
2798
|
return True
|
|
2709
2799
|
|
|
2710
|
-
def create_voltage_source(
|
|
2800
|
+
def create_voltage_source(
|
|
2801
|
+
self,
|
|
2802
|
+
terminal: Union[PadstackInstanceTerminal, EdgeTerminal],
|
|
2803
|
+
ref_terminal: Union[PadstackInstanceTerminal, EdgeTerminal],
|
|
2804
|
+
) -> bool:
|
|
2711
2805
|
"""Create a voltage source.
|
|
2712
2806
|
|
|
2713
2807
|
Parameters
|
|
@@ -2745,8 +2839,14 @@ class SourceExcitation:
|
|
|
2745
2839
|
return term
|
|
2746
2840
|
|
|
2747
2841
|
def create_voltage_source_on_pin_group(
|
|
2748
|
-
self,
|
|
2749
|
-
|
|
2842
|
+
self,
|
|
2843
|
+
pos_pin_group_name: str,
|
|
2844
|
+
neg_pin_group_name: str,
|
|
2845
|
+
magnitude: Union[int, float] = 1,
|
|
2846
|
+
phase: Union[int, float] = 0,
|
|
2847
|
+
name: Optional[str] = None,
|
|
2848
|
+
impedance: Union[int, float] = 0.001,
|
|
2849
|
+
) -> bool:
|
|
2750
2850
|
"""Create voltage source between two pin groups.
|
|
2751
2851
|
|
|
2752
2852
|
Parameters
|
|
@@ -2789,7 +2889,7 @@ class SourceExcitation:
|
|
|
2789
2889
|
pos_terminal.reference_terminal = neg_terminal
|
|
2790
2890
|
return True
|
|
2791
2891
|
|
|
2792
|
-
def create_voltage_probe(self, terminal, ref_terminal):
|
|
2892
|
+
def create_voltage_probe(self, terminal: Terminal, ref_terminal: Terminal) -> Terminal:
|
|
2793
2893
|
"""Create a voltage probe.
|
|
2794
2894
|
|
|
2795
2895
|
Parameters
|
|
@@ -2820,7 +2920,9 @@ class SourceExcitation:
|
|
|
2820
2920
|
term.ref_terminal = ref_terminal
|
|
2821
2921
|
return term
|
|
2822
2922
|
|
|
2823
|
-
def create_voltage_probe_on_pin_group(
|
|
2923
|
+
def create_voltage_probe_on_pin_group(
|
|
2924
|
+
self, probe_name: str, pos_pin_group_name: str, neg_pin_group_name: str, impedance: Union[int, float] = 1000000
|
|
2925
|
+
) -> bool:
|
|
2824
2926
|
"""Create voltage probe between two pin groups.
|
|
2825
2927
|
|
|
2826
2928
|
Parameters
|
|
@@ -2859,11 +2961,8 @@ class SourceExcitation:
|
|
|
2859
2961
|
return not pos_terminal.is_null
|
|
2860
2962
|
|
|
2861
2963
|
def create_dc_terminal(
|
|
2862
|
-
self,
|
|
2863
|
-
|
|
2864
|
-
net_name,
|
|
2865
|
-
source_name=None,
|
|
2866
|
-
):
|
|
2964
|
+
self, component_name: str, net_name: str, source_name: Optional[str] = None
|
|
2965
|
+
) -> Optional[str]:
|
|
2867
2966
|
"""Create a dc terminal.
|
|
2868
2967
|
|
|
2869
2968
|
Parameters
|
|
@@ -2872,7 +2971,6 @@ class SourceExcitation:
|
|
|
2872
2971
|
Name of the positive component.
|
|
2873
2972
|
net_name : str
|
|
2874
2973
|
Name of the positive net.
|
|
2875
|
-
|
|
2876
2974
|
source_name : str, optional
|
|
2877
2975
|
Name of the source. The default is ``""``.
|
|
2878
2976
|
|
|
@@ -2897,7 +2995,13 @@ class SourceExcitation:
|
|
|
2897
2995
|
positive_pins=node_pin, name=source_name, source_type="dc_terminal", negatives_pins=None
|
|
2898
2996
|
)
|
|
2899
2997
|
|
|
2900
|
-
def create_circuit_port_on_pin_group(
|
|
2998
|
+
def create_circuit_port_on_pin_group(
|
|
2999
|
+
self,
|
|
3000
|
+
pos_pin_group_name: str,
|
|
3001
|
+
neg_pin_group_name: str,
|
|
3002
|
+
impedance: Union[int, float] = 50,
|
|
3003
|
+
name: Optional[str] = None,
|
|
3004
|
+
) -> bool:
|
|
2901
3005
|
"""Create a port between two pin groups.
|
|
2902
3006
|
|
|
2903
3007
|
Parameters
|
|
@@ -2939,14 +3043,14 @@ class SourceExcitation:
|
|
|
2939
3043
|
|
|
2940
3044
|
def place_voltage_probe(
|
|
2941
3045
|
self,
|
|
2942
|
-
name,
|
|
2943
|
-
positive_net_name,
|
|
2944
|
-
positive_location,
|
|
2945
|
-
positive_layer,
|
|
2946
|
-
negative_net_name,
|
|
2947
|
-
negative_location,
|
|
2948
|
-
negative_layer,
|
|
2949
|
-
):
|
|
3046
|
+
name: str,
|
|
3047
|
+
positive_net_name: str,
|
|
3048
|
+
positive_location: List[float],
|
|
3049
|
+
positive_layer: str,
|
|
3050
|
+
negative_net_name: str,
|
|
3051
|
+
negative_location: List[float],
|
|
3052
|
+
negative_layer: str,
|
|
3053
|
+
) -> Terminal:
|
|
2950
3054
|
"""Place a voltage probe between two points.
|
|
2951
3055
|
|
|
2952
3056
|
Parameters
|