pyedb 0.38.0__py3-none-any.whl → 0.39.1__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/common/nets.py +53 -139
- pyedb/configuration/cfg_components.py +1 -1
- pyedb/configuration/cfg_general.py +4 -2
- pyedb/configuration/cfg_modeler.py +1 -1
- pyedb/configuration/cfg_package_definition.py +1 -1
- pyedb/configuration/cfg_padstacks.py +1 -1
- pyedb/configuration/cfg_ports_sources.py +56 -23
- pyedb/configuration/configuration.py +18 -1
- pyedb/dotnet/{application → database}/Variables.py +21 -21
- pyedb/dotnet/{edb_core → database}/cell/connectable.py +5 -5
- pyedb/dotnet/{edb_core → database}/cell/hierarchy/component.py +11 -11
- pyedb/dotnet/{edb_core → database}/cell/hierarchy/hierarchy_obj.py +1 -1
- pyedb/dotnet/{edb_core → database}/cell/hierarchy/model.py +1 -1
- pyedb/dotnet/{edb_core → database}/cell/layout.py +17 -17
- pyedb/dotnet/{edb_core → database}/cell/layout_obj.py +3 -3
- pyedb/dotnet/{edb_core → database}/cell/primitive/bondwire.py +1 -1
- pyedb/dotnet/{edb_core → database}/cell/primitive/path.py +4 -4
- pyedb/dotnet/{edb_core → database}/cell/primitive/primitive.py +14 -14
- pyedb/dotnet/{edb_core → database}/cell/terminal/bundle_terminal.py +2 -2
- pyedb/dotnet/{edb_core → database}/cell/terminal/edge_terminal.py +4 -4
- pyedb/dotnet/{edb_core → database}/cell/terminal/padstack_instance_terminal.py +2 -2
- pyedb/dotnet/{edb_core → database}/cell/terminal/pingroup_terminal.py +2 -2
- pyedb/dotnet/{edb_core → database}/cell/terminal/point_terminal.py +2 -2
- pyedb/dotnet/{edb_core → database}/cell/terminal/terminal.py +11 -11
- pyedb/dotnet/{edb_core → database}/cell/voltage_regulator.py +2 -2
- pyedb/dotnet/{edb_core → database}/components.py +101 -124
- pyedb/dotnet/{edb_core → database}/definition/component_def.py +5 -5
- pyedb/dotnet/{edb_core → database}/definition/component_model.py +1 -1
- pyedb/dotnet/{edb_core → database}/definition/definition_obj.py +1 -1
- pyedb/dotnet/{edb_core → database}/definition/definitions.py +2 -2
- pyedb/dotnet/{edb_core → database}/definition/package_def.py +4 -4
- pyedb/dotnet/{edb_core → database}/dotnet/database.py +8 -8
- pyedb/dotnet/{edb_core → database}/dotnet/primitive.py +9 -9
- pyedb/dotnet/{edb_core → database}/edb_data/control_file.py +12 -12
- pyedb/dotnet/{edb_core → database}/edb_data/hfss_extent_info.py +7 -7
- pyedb/dotnet/{edb_core → database}/edb_data/nets_data.py +10 -13
- pyedb/dotnet/{edb_core → database}/edb_data/padstacks_data.py +16 -16
- pyedb/dotnet/{edb_core → database}/edb_data/ports.py +4 -4
- pyedb/dotnet/{edb_core → database}/edb_data/primitives_data.py +5 -5
- pyedb/dotnet/{edb_core → database}/edb_data/raptor_x_simulation_setup_data.py +4 -4
- pyedb/dotnet/{edb_core → database}/edb_data/simulation_configuration.py +10 -10
- pyedb/dotnet/{edb_core → database}/edb_data/sources.py +4 -4
- pyedb/dotnet/{edb_core → database}/edb_data/variables.py +1 -1
- pyedb/dotnet/{edb_core → database}/geometry/polygon_data.py +4 -4
- pyedb/dotnet/{edb_core → database}/hfss.py +8 -8
- pyedb/dotnet/{edb_core → database}/layout_obj_instance.py +1 -1
- pyedb/dotnet/{edb_core → database}/layout_validation.py +2 -2
- pyedb/dotnet/{edb_core → database}/materials.py +23 -8
- pyedb/dotnet/{edb_core → database}/modeler.py +27 -27
- pyedb/dotnet/{edb_core → database}/net_class.py +8 -8
- pyedb/dotnet/{edb_core → database}/nets.py +12 -12
- pyedb/dotnet/{edb_core → database}/padstack.py +15 -15
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/mesh_operation.py +1 -1
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/settings.py +3 -3
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sim_setup_info.py +2 -2
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/simulation_settings.py +1 -1
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/siw_dc_ir_settings.py +1 -1
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sweep_data.py +1 -1
- pyedb/dotnet/{edb_core → database}/siwave.py +10 -10
- pyedb/dotnet/{edb_core → database}/stackup.py +12 -12
- pyedb/dotnet/{edb_core → database}/utilities/hfss_simulation_setup.py +15 -15
- pyedb/dotnet/{edb_core → database}/utilities/obj_base.py +1 -1
- pyedb/dotnet/{edb_core → database}/utilities/simulation_setup.py +3 -3
- pyedb/dotnet/{edb_core → database}/utilities/siwave_simulation_setup.py +6 -6
- pyedb/dotnet/edb.py +117 -112
- pyedb/generic/design_types.py +26 -19
- pyedb/generic/general_methods.py +1 -1
- pyedb/generic/plot.py +0 -2
- pyedb/grpc/database/__init__.py +1 -0
- pyedb/grpc/database/components.py +2354 -0
- pyedb/grpc/database/control_file.py +1277 -0
- pyedb/grpc/database/definition/component_def.py +218 -0
- pyedb/grpc/database/definition/component_model.py +39 -0
- pyedb/grpc/database/definition/component_pin.py +32 -0
- pyedb/grpc/database/definition/materials.py +1207 -0
- pyedb/grpc/database/definition/n_port_component_model.py +34 -0
- pyedb/grpc/database/definition/package_def.py +227 -0
- pyedb/grpc/database/definition/padstack_def.py +842 -0
- pyedb/grpc/database/definitions.py +70 -0
- pyedb/grpc/database/general.py +43 -0
- pyedb/grpc/database/geometry/__init__.py +0 -0
- pyedb/grpc/database/geometry/arc_data.py +93 -0
- pyedb/grpc/database/geometry/point_3d_data.py +79 -0
- pyedb/grpc/database/geometry/point_data.py +30 -0
- pyedb/grpc/database/geometry/polygon_data.py +133 -0
- pyedb/grpc/database/hfss.py +1279 -0
- pyedb/grpc/database/hierarchy/__init__.py +0 -0
- pyedb/grpc/database/hierarchy/component.py +1301 -0
- pyedb/grpc/database/hierarchy/model.py +31 -0
- pyedb/grpc/database/hierarchy/netlist_model.py +30 -0
- pyedb/grpc/database/hierarchy/pin_pair_model.py +128 -0
- pyedb/grpc/database/hierarchy/pingroup.py +245 -0
- pyedb/grpc/database/hierarchy/s_parameter_model.py +33 -0
- pyedb/grpc/database/hierarchy/spice_model.py +48 -0
- pyedb/grpc/database/layers/__init__.py +0 -0
- pyedb/grpc/database/layers/layer.py +57 -0
- pyedb/grpc/database/layers/stackup_layer.py +410 -0
- pyedb/grpc/database/layout/__init__.py +0 -0
- pyedb/grpc/database/layout/cell.py +30 -0
- pyedb/grpc/database/layout/layout.py +196 -0
- pyedb/grpc/database/layout/voltage_regulator.py +149 -0
- pyedb/grpc/database/layout_validation.py +319 -0
- pyedb/grpc/database/modeler.py +1468 -0
- pyedb/grpc/database/net/__init__.py +0 -0
- pyedb/grpc/database/net/differential_pair.py +138 -0
- pyedb/grpc/database/net/extended_net.py +340 -0
- pyedb/grpc/database/net/net.py +198 -0
- pyedb/grpc/database/net/net_class.py +93 -0
- pyedb/grpc/database/nets.py +633 -0
- pyedb/grpc/database/padstacks.py +1500 -0
- pyedb/grpc/database/ports/__init__.py +0 -0
- pyedb/grpc/database/ports/ports.py +396 -0
- pyedb/grpc/database/primitive/__init__.py +3 -0
- pyedb/grpc/database/primitive/bondwire.py +181 -0
- pyedb/grpc/database/primitive/circle.py +75 -0
- pyedb/grpc/database/primitive/padstack_instance.py +1116 -0
- pyedb/grpc/database/primitive/path.py +346 -0
- pyedb/grpc/database/primitive/polygon.py +276 -0
- pyedb/grpc/database/primitive/primitive.py +739 -0
- pyedb/grpc/database/primitive/rectangle.py +146 -0
- pyedb/grpc/database/simulation_setup/__init__.py +0 -0
- pyedb/grpc/database/simulation_setup/adaptive_frequency.py +33 -0
- pyedb/grpc/database/simulation_setup/hfss_advanced_meshing_settings.py +32 -0
- pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +59 -0
- pyedb/grpc/database/simulation_setup/hfss_dcr_settings.py +35 -0
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +61 -0
- pyedb/grpc/database/simulation_setup/hfss_settings_options.py +78 -0
- pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +118 -0
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +355 -0
- pyedb/grpc/database/simulation_setup/hfss_solver_settings.py +34 -0
- pyedb/grpc/database/simulation_setup/mesh_operation.py +34 -0
- pyedb/grpc/database/simulation_setup/raptor_x_advanced_settings.py +34 -0
- pyedb/grpc/database/simulation_setup/raptor_x_general_settings.py +33 -0
- pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +64 -0
- pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +125 -0
- pyedb/grpc/database/simulation_setup/siwave_dcir_simulation_setup.py +34 -0
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +119 -0
- pyedb/grpc/database/simulation_setup/sweep_data.py +32 -0
- pyedb/grpc/database/siwave.py +1023 -0
- pyedb/grpc/database/source_excitations.py +2572 -0
- pyedb/grpc/database/stackup.py +2574 -0
- pyedb/grpc/database/terminal/__init__.py +0 -0
- pyedb/grpc/database/terminal/bundle_terminal.py +218 -0
- pyedb/grpc/database/terminal/edge_terminal.py +51 -0
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +171 -0
- pyedb/grpc/database/terminal/pingroup_terminal.py +162 -0
- pyedb/grpc/database/terminal/point_terminal.py +99 -0
- pyedb/grpc/database/terminal/terminal.py +470 -0
- pyedb/grpc/database/utility/__init__.py +3 -0
- pyedb/grpc/database/utility/constants.py +25 -0
- pyedb/grpc/database/utility/heat_sink.py +124 -0
- pyedb/grpc/database/utility/hfss_extent_info.py +448 -0
- pyedb/grpc/database/utility/layout_statistics.py +277 -0
- pyedb/grpc/database/utility/rlc.py +80 -0
- pyedb/grpc/database/utility/simulation_configuration.py +3305 -0
- pyedb/grpc/database/utility/sources.py +388 -0
- pyedb/grpc/database/utility/sweep_data_distribution.py +83 -0
- pyedb/grpc/database/utility/xml_control_file.py +1277 -0
- pyedb/grpc/edb.py +4152 -0
- pyedb/grpc/edb_init.py +481 -0
- pyedb/grpc/rpc_session.py +177 -0
- pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +3 -2
- pyedb/ipc2581/ecad/cad_data/feature.py +4 -3
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +32 -20
- pyedb/ipc2581/ecad/cad_data/outline.py +3 -2
- pyedb/ipc2581/ecad/cad_data/package.py +4 -3
- pyedb/ipc2581/ecad/cad_data/path.py +82 -31
- pyedb/ipc2581/ecad/cad_data/polygon.py +122 -60
- pyedb/ipc2581/ecad/cad_data/profile.py +13 -12
- pyedb/ipc2581/ecad/cad_data/step.py +53 -21
- pyedb/ipc2581/ipc2581.py +47 -49
- pyedb/modeler/geometry_operators.py +1 -1
- {pyedb-0.38.0.dist-info → pyedb-0.39.1.dist-info}/METADATA +5 -2
- pyedb-0.39.1.dist-info/RECORD +288 -0
- pyedb-0.38.0.dist-info/RECORD +0 -195
- /pyedb/dotnet/{edb_core → database}/__init__.py +0 -0
- /pyedb/dotnet/{application → database/cell}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/cell → database/cell/hierarchy}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/hierarchy/netlist_model.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/hierarchy/pin_pair_model.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/hierarchy/s_parameter_model.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/hierarchy/spice_model.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/primitive/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/cell/hierarchy → database/cell/terminal}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/cell/terminal → database/definition}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/definition → database/dotnet}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/dotnet → database/edb_data}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/edb_data/design_options.py +0 -0
- /pyedb/dotnet/{edb_core → database}/edb_data/edbvalue.py +0 -0
- /pyedb/dotnet/{edb_core → database}/edb_data/layer_data.py +0 -0
- /pyedb/dotnet/{edb_core → database}/edb_data/utilities.py +0 -0
- /pyedb/dotnet/{edb_core → database}/general.py +0 -0
- /pyedb/dotnet/{edb_core/edb_data → database/geometry}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/geometry/point_data.py +0 -0
- /pyedb/dotnet/{edb_core → database}/sim_setup_data/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/adaptive_frequency_data.py +0 -0
- /pyedb/dotnet/{edb_core/geometry → database/sim_setup_data/io}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/sim_setup_data/io/siwave.py +0 -0
- /pyedb/dotnet/{edb_core → database}/utilities/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/utilities/heatsink.py +0 -0
- /pyedb/{dotnet/edb_core/sim_setup_data/io → grpc/database/definition}/__init__.py +0 -0
- {pyedb-0.38.0.dist-info → pyedb-0.39.1.dist-info}/LICENSE +0 -0
- {pyedb-0.38.0.dist-info → pyedb-0.39.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,1301 @@
|
|
|
1
|
+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
#
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
import logging
|
|
24
|
+
import re
|
|
25
|
+
from typing import Optional
|
|
26
|
+
import warnings
|
|
27
|
+
|
|
28
|
+
from ansys.edb.core.definition.component_model import (
|
|
29
|
+
NPortComponentModel as GrpcNPortComponentModel,
|
|
30
|
+
)
|
|
31
|
+
from ansys.edb.core.definition.die_property import DieOrientation as GrpcDieOrientation
|
|
32
|
+
from ansys.edb.core.definition.die_property import DieType as GrpcDieType
|
|
33
|
+
from ansys.edb.core.definition.solder_ball_property import SolderballShape
|
|
34
|
+
from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
|
|
35
|
+
from ansys.edb.core.hierarchy.component_group import (
|
|
36
|
+
ComponentGroup as GrpcComponentGroup,
|
|
37
|
+
)
|
|
38
|
+
from ansys.edb.core.hierarchy.component_group import ComponentType as GrpcComponentType
|
|
39
|
+
from ansys.edb.core.hierarchy.netlist_model import NetlistModel as GrpcNetlistModel
|
|
40
|
+
from ansys.edb.core.hierarchy.pin_pair_model import PinPairModel as GrpcPinPairModel
|
|
41
|
+
from ansys.edb.core.hierarchy.sparameter_model import (
|
|
42
|
+
SParameterModel as GrpcSParameterModel,
|
|
43
|
+
)
|
|
44
|
+
from ansys.edb.core.primitive.primitive import PadstackInstance as GrpcPadstackInstance
|
|
45
|
+
from ansys.edb.core.terminal.terminals import (
|
|
46
|
+
PadstackInstanceTerminal as GrpcPadstackInstanceTerminal,
|
|
47
|
+
)
|
|
48
|
+
from ansys.edb.core.utility.rlc import Rlc as GrpcRlc
|
|
49
|
+
from ansys.edb.core.utility.value import Value as GrpcValue
|
|
50
|
+
|
|
51
|
+
from pyedb.grpc.database.hierarchy.pin_pair_model import PinPairModel
|
|
52
|
+
from pyedb.grpc.database.hierarchy.spice_model import SpiceModel
|
|
53
|
+
from pyedb.grpc.database.layers.stackup_layer import StackupLayer
|
|
54
|
+
from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
|
|
55
|
+
from pyedb.grpc.database.terminal.padstack_instance_terminal import (
|
|
56
|
+
PadstackInstanceTerminal,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
import numpy as np
|
|
61
|
+
except ImportError:
|
|
62
|
+
warnings.warn(
|
|
63
|
+
"The NumPy module is required to run some functionalities of EDB.\n"
|
|
64
|
+
"Install with \n\npip install numpy\n\nRequires CPython."
|
|
65
|
+
)
|
|
66
|
+
from pyedb.generic.general_methods import get_filename_without_extension
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class Component(GrpcComponentGroup):
|
|
70
|
+
"""Manages EDB functionalities for components.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
parent : :class:`pyedb.grpc.database.components.Components`
|
|
75
|
+
Components object.
|
|
76
|
+
component : object
|
|
77
|
+
Edb Component Object
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, pedb, edb_object):
|
|
82
|
+
super().__init__(edb_object.msg)
|
|
83
|
+
self._pedb = pedb
|
|
84
|
+
self._layout_instance = None
|
|
85
|
+
self._comp_instance = None
|
|
86
|
+
self._logger = pedb.logger
|
|
87
|
+
self._package_def = None
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def group_type(self):
|
|
91
|
+
return str(self.type).split(".")[-1].lower()
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def layout_instance(self):
|
|
95
|
+
"""Layout instance object.
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
:class:`LayoutInstance <ansys.edb.core.layout_instance.layout_instance.LayoutInstance>`
|
|
100
|
+
"""
|
|
101
|
+
return self._pedb.layout_instance
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def component_instance(self):
|
|
105
|
+
"""Component instance.
|
|
106
|
+
|
|
107
|
+
Returns
|
|
108
|
+
-------
|
|
109
|
+
:class:`LayoutObjInstance <ansys.edb.core.layout_instance.layout_obj_instance.LayoutObjInstance>`
|
|
110
|
+
"""
|
|
111
|
+
if self._comp_instance is None:
|
|
112
|
+
self._comp_instance = self.layout_instance.get_layout_obj_instance_in_context(self, None)
|
|
113
|
+
return self._comp_instance
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def is_enabled(self):
|
|
117
|
+
"""Component enable.
|
|
118
|
+
|
|
119
|
+
Returns
|
|
120
|
+
-------
|
|
121
|
+
bool
|
|
122
|
+
|
|
123
|
+
"""
|
|
124
|
+
return self.enabled
|
|
125
|
+
|
|
126
|
+
@is_enabled.setter
|
|
127
|
+
def is_enabled(self, value):
|
|
128
|
+
self.enabled = value
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def ic_die_properties(self):
|
|
132
|
+
"""IC Die property.
|
|
133
|
+
|
|
134
|
+
returns
|
|
135
|
+
-------
|
|
136
|
+
:class:`ICDieProperty <pyedb.grpc.database.hierarchy.component.ICDieProperty>`
|
|
137
|
+
"""
|
|
138
|
+
if self.type == "ic":
|
|
139
|
+
return ICDieProperty(self)
|
|
140
|
+
else:
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def _active_layout(self): # pragma: no cover
|
|
145
|
+
"""Active layout.
|
|
146
|
+
|
|
147
|
+
Returns
|
|
148
|
+
-------
|
|
149
|
+
:class:`Layout <ansys.edb.core.layout.layout.Layout>
|
|
150
|
+
"""
|
|
151
|
+
return self._pedb.active_layout
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def _edb_model(self): # pragma: no cover
|
|
155
|
+
"""Component model.
|
|
156
|
+
|
|
157
|
+
Returns
|
|
158
|
+
-------
|
|
159
|
+
:class:`Model <ansys.edb.core.hierarchy.model.Model>`
|
|
160
|
+
|
|
161
|
+
"""
|
|
162
|
+
comp_prop = self.component_property
|
|
163
|
+
return comp_prop.model
|
|
164
|
+
|
|
165
|
+
@property # pragma: no cover
|
|
166
|
+
def _pin_pairs(self):
|
|
167
|
+
"""Pins pairs.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
:class:`PinPairModel <ansys.edb.core.hierarchy.pin_pair_model.PinPairModel>`
|
|
172
|
+
"""
|
|
173
|
+
edb_model = self._edb_model
|
|
174
|
+
return edb_model.pin_pairs()
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def _rlc(self):
|
|
178
|
+
"""Rlc class.
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
:class:`Rlc <ansys.edb.core.utility.rlc.Rlc>`
|
|
183
|
+
|
|
184
|
+
"""
|
|
185
|
+
if self.model_type == "SPICEModel":
|
|
186
|
+
if len(self.pins) == 2:
|
|
187
|
+
self._pedb.logger.warning(f"Spice model defined on component {self.name}, replacing model by ")
|
|
188
|
+
rlc = GrpcRlc()
|
|
189
|
+
pins = list(self.pins.keys())
|
|
190
|
+
pin_pair = (pins[0], pins[1])
|
|
191
|
+
rlc_model = PinPairModel(self._pedb, GrpcPinPairModel.create())
|
|
192
|
+
rlc_model.set_rlc(pin_pair, rlc)
|
|
193
|
+
component_property = self.component_property
|
|
194
|
+
component_property.model = rlc_model
|
|
195
|
+
self.component_property = component_property
|
|
196
|
+
return [self._edb_model.rlc(pin_pair) for pin_pair in self._edb_model.pin_pairs()]
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def model(self):
|
|
200
|
+
"""Component model.
|
|
201
|
+
|
|
202
|
+
Returns
|
|
203
|
+
-------
|
|
204
|
+
:class:`Model <ansys.edb.core.hierarchy.model.Model>`
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
return self.component_property.model
|
|
208
|
+
|
|
209
|
+
@model.setter
|
|
210
|
+
def model(self, value):
|
|
211
|
+
if not isinstance(value, PinPairModel):
|
|
212
|
+
self._pedb.logger.error("Invalid input. Set model failed.")
|
|
213
|
+
|
|
214
|
+
comp_prop = self.component_property
|
|
215
|
+
comp_prop.model = value
|
|
216
|
+
self.component_property = comp_prop
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def package_def(self):
|
|
220
|
+
"""Package definition.
|
|
221
|
+
|
|
222
|
+
Returns
|
|
223
|
+
-------
|
|
224
|
+
:class:`PackageDef <ansys.edb.core.definition.package_def.PackageDef>`
|
|
225
|
+
"""
|
|
226
|
+
return self.component_property.package_def
|
|
227
|
+
|
|
228
|
+
@package_def.setter
|
|
229
|
+
def package_def(self, value):
|
|
230
|
+
from pyedb.grpc.database.definition.package_def import PackageDef
|
|
231
|
+
|
|
232
|
+
if value not in [package.name for package in self._pedb.package_defs]:
|
|
233
|
+
from ansys.edb.core.definition.package_def import (
|
|
234
|
+
PackageDef as GrpcPackageDef,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
self._package_def = GrpcPackageDef.create(self._pedb.db, name=value)
|
|
238
|
+
self._package_def.exterior_boundary = GrpcPolygonData(points=self.bounding_box)
|
|
239
|
+
comp_prop = self.component_property
|
|
240
|
+
comp_prop.package_def = self._package_def
|
|
241
|
+
self.component_property = comp_prop
|
|
242
|
+
elif isinstance(value, str):
|
|
243
|
+
package = next(package for package in self._pedb.package_defs if package.name == value)
|
|
244
|
+
comp_prop = self.component_property
|
|
245
|
+
comp_prop.package_def = package
|
|
246
|
+
self.component_property = comp_prop
|
|
247
|
+
|
|
248
|
+
elif isinstance(value, PackageDef):
|
|
249
|
+
comp_prop = self.component_property
|
|
250
|
+
comp_prop.package_def = value
|
|
251
|
+
self.component_property = comp_prop
|
|
252
|
+
|
|
253
|
+
@property
|
|
254
|
+
def is_mcad(self):
|
|
255
|
+
"""MCad component.
|
|
256
|
+
|
|
257
|
+
Returns
|
|
258
|
+
-------
|
|
259
|
+
bool
|
|
260
|
+
|
|
261
|
+
"""
|
|
262
|
+
return super().is_mcad.value
|
|
263
|
+
|
|
264
|
+
@is_mcad.setter
|
|
265
|
+
def is_mcad(self, value):
|
|
266
|
+
if isinstance(value, bool):
|
|
267
|
+
super(Component, self.__class__).is_mcad.__set__(self, GrpcValue(value))
|
|
268
|
+
|
|
269
|
+
@property
|
|
270
|
+
def is_mcad_3d_comp(self):
|
|
271
|
+
"""Mcad 3D component.
|
|
272
|
+
|
|
273
|
+
Returns
|
|
274
|
+
-------
|
|
275
|
+
bool
|
|
276
|
+
|
|
277
|
+
"""
|
|
278
|
+
return super().is_mcad_3d_comp.value
|
|
279
|
+
|
|
280
|
+
@is_mcad_3d_comp.setter
|
|
281
|
+
def is_mcad_3d_comp(self, value):
|
|
282
|
+
if isinstance(value, bool):
|
|
283
|
+
super(Component, self.__class__).is_mcad_3d_comp.__set__(self, GrpcValue(value))
|
|
284
|
+
|
|
285
|
+
@property
|
|
286
|
+
def is_mcad_hfss(self):
|
|
287
|
+
"""MCad HFSS.
|
|
288
|
+
|
|
289
|
+
Returns
|
|
290
|
+
-------
|
|
291
|
+
bool
|
|
292
|
+
|
|
293
|
+
"""
|
|
294
|
+
return super().is_mcad_hfss.value
|
|
295
|
+
|
|
296
|
+
@is_mcad_hfss.setter
|
|
297
|
+
def is_mcad_hfss(self, value):
|
|
298
|
+
if isinstance(value, bool):
|
|
299
|
+
super(Component, self.__class__).is_mcad_hfss.__set__(self, GrpcValue(value))
|
|
300
|
+
|
|
301
|
+
@property
|
|
302
|
+
def is_mcad_stride(self):
|
|
303
|
+
"""MCar stride.
|
|
304
|
+
|
|
305
|
+
Returns
|
|
306
|
+
-------
|
|
307
|
+
bool
|
|
308
|
+
|
|
309
|
+
"""
|
|
310
|
+
return super().is_mcad_stride.value
|
|
311
|
+
|
|
312
|
+
@is_mcad_stride.setter
|
|
313
|
+
def is_mcad_stride(self, value):
|
|
314
|
+
if isinstance(value, bool):
|
|
315
|
+
super(Component, self.__class__).is_mcad_stride.__set__(self, GrpcValue(value))
|
|
316
|
+
|
|
317
|
+
def create_package_def(self, name="", component_part_name=None):
|
|
318
|
+
"""Create a package definition and assign it to the component.
|
|
319
|
+
|
|
320
|
+
Parameters
|
|
321
|
+
----------
|
|
322
|
+
name: str, optional
|
|
323
|
+
Name of the package definition
|
|
324
|
+
component_part_name : str, optional
|
|
325
|
+
Part name of the component.
|
|
326
|
+
|
|
327
|
+
Returns
|
|
328
|
+
-------
|
|
329
|
+
bool
|
|
330
|
+
``True`` if succeeded, ``False`` otherwise.
|
|
331
|
+
"""
|
|
332
|
+
if not name:
|
|
333
|
+
name = f"{self.refdes}_{self.part_name}"
|
|
334
|
+
if name not in [package.name for package in self._pedb.package_defs]:
|
|
335
|
+
self.package_def = name
|
|
336
|
+
return True
|
|
337
|
+
else:
|
|
338
|
+
logging.error(f"Package definition {name} already exists")
|
|
339
|
+
return False
|
|
340
|
+
|
|
341
|
+
@property
|
|
342
|
+
def enabled(self):
|
|
343
|
+
"""Component active mode.
|
|
344
|
+
|
|
345
|
+
Returns
|
|
346
|
+
-------
|
|
347
|
+
bool
|
|
348
|
+
|
|
349
|
+
"""
|
|
350
|
+
if self.type.lower() in ["resistor", "capacitor", "inductor"]:
|
|
351
|
+
return self.component_property.enabled
|
|
352
|
+
else:
|
|
353
|
+
return
|
|
354
|
+
|
|
355
|
+
@enabled.setter
|
|
356
|
+
def enabled(self, value):
|
|
357
|
+
cmp_prop = self.component_property
|
|
358
|
+
cmp_prop.enabled = value
|
|
359
|
+
self.component_property = cmp_prop
|
|
360
|
+
|
|
361
|
+
@property
|
|
362
|
+
def spice_model(self):
|
|
363
|
+
"""Assigned Spice model.
|
|
364
|
+
|
|
365
|
+
Returns
|
|
366
|
+
-------
|
|
367
|
+
:class:`SpiceModel <pyedb.grpc.database.hierarchy.spice_model.SpiceModel>`
|
|
368
|
+
"""
|
|
369
|
+
if not self.model_type == "SPICEModel":
|
|
370
|
+
return None
|
|
371
|
+
else:
|
|
372
|
+
return SpiceModel(self._edb_model.msg)
|
|
373
|
+
|
|
374
|
+
@property
|
|
375
|
+
def s_param_model(self):
|
|
376
|
+
"""Assigned S-parameter model.
|
|
377
|
+
|
|
378
|
+
Returns
|
|
379
|
+
-------
|
|
380
|
+
:class:`SParameterModel <ansys.edb.core.hierarchy.sparameter_model.SParameterModel>`
|
|
381
|
+
"""
|
|
382
|
+
if not self.model_type == "SParameterModel":
|
|
383
|
+
return None
|
|
384
|
+
else:
|
|
385
|
+
return GrpcSParameterModel(self._edb_model.msg)
|
|
386
|
+
|
|
387
|
+
@property
|
|
388
|
+
def netlist_model(self):
|
|
389
|
+
"""Assigned netlist model.
|
|
390
|
+
|
|
391
|
+
Returns
|
|
392
|
+
-------
|
|
393
|
+
:class:`NetlistModel <ansys.edb.core.hierarchy.netlist_mode.NetlistModel>`
|
|
394
|
+
"""
|
|
395
|
+
if not self.model_type == "NetlistModel":
|
|
396
|
+
return None
|
|
397
|
+
else:
|
|
398
|
+
return GrpcNetlistModel(self._edb_model)
|
|
399
|
+
|
|
400
|
+
@property
|
|
401
|
+
def solder_ball_height(self):
|
|
402
|
+
"""Solder ball height if available.
|
|
403
|
+
|
|
404
|
+
Returns
|
|
405
|
+
-------
|
|
406
|
+
float
|
|
407
|
+
Balls height value.
|
|
408
|
+
"""
|
|
409
|
+
if not self.component_property.solder_ball_property.is_null:
|
|
410
|
+
return self.component_property.solder_ball_property.height.value
|
|
411
|
+
return None
|
|
412
|
+
|
|
413
|
+
@solder_ball_height.setter
|
|
414
|
+
def solder_ball_height(self, value):
|
|
415
|
+
if not self.component_property.solder_ball_property.is_null:
|
|
416
|
+
cmp_property = self.component_property
|
|
417
|
+
solder_ball_prop = cmp_property.solder_ball_property
|
|
418
|
+
solder_ball_prop.height = round(GrpcValue(value).value, 9)
|
|
419
|
+
cmp_property.solder_ball_property = solder_ball_prop
|
|
420
|
+
self.component_property = cmp_property
|
|
421
|
+
|
|
422
|
+
@property
|
|
423
|
+
def solder_ball_shape(self):
|
|
424
|
+
"""Solder ball shape.
|
|
425
|
+
|
|
426
|
+
Returns
|
|
427
|
+
-------
|
|
428
|
+
str
|
|
429
|
+
Solder balls shapes, ``none``, ``cylinder`` or ``spheroid``.
|
|
430
|
+
"""
|
|
431
|
+
if not self.component_property.solder_ball_property.is_null:
|
|
432
|
+
shape = self.component_property.solder_ball_property.shape
|
|
433
|
+
if shape == SolderballShape.NO_SOLDERBALL:
|
|
434
|
+
return "none"
|
|
435
|
+
elif shape == SolderballShape.SOLDERBALL_CYLINDER:
|
|
436
|
+
return "cylinder"
|
|
437
|
+
elif shape == SolderballShape.SOLDERBALL_SPHEROID:
|
|
438
|
+
return "spheroid"
|
|
439
|
+
|
|
440
|
+
@solder_ball_shape.setter
|
|
441
|
+
def solder_ball_shape(self, value):
|
|
442
|
+
if not self.component_property.solder_ball_property.is_null:
|
|
443
|
+
shape = None
|
|
444
|
+
if isinstance(value, str):
|
|
445
|
+
if value.lower() == "cylinder":
|
|
446
|
+
shape = SolderballShape.SOLDERBALL_CYLINDER
|
|
447
|
+
elif value.lower() == "none":
|
|
448
|
+
shape = SolderballShape.NO_SOLDERBALL
|
|
449
|
+
elif value.lower() == "spheroid":
|
|
450
|
+
shape = SolderballShape.SOLDERBALL_SPHEROID
|
|
451
|
+
if shape:
|
|
452
|
+
cmp_property = self.component_property
|
|
453
|
+
solder_ball_prop = cmp_property.solder_ball_property
|
|
454
|
+
solder_ball_prop.shape = shape
|
|
455
|
+
cmp_property.solder_ball_property = solder_ball_prop
|
|
456
|
+
self.component_property = cmp_property
|
|
457
|
+
|
|
458
|
+
@property
|
|
459
|
+
def solder_ball_diameter(self):
|
|
460
|
+
"""Solder ball diameter.
|
|
461
|
+
|
|
462
|
+
Returns
|
|
463
|
+
-------
|
|
464
|
+
float
|
|
465
|
+
diameter value.
|
|
466
|
+
"""
|
|
467
|
+
if not self.component_property.solder_ball_property.is_null:
|
|
468
|
+
diameter, mid_diameter = self.component_property.solder_ball_property.get_diameter()
|
|
469
|
+
return diameter.value, mid_diameter.value
|
|
470
|
+
|
|
471
|
+
@solder_ball_diameter.setter
|
|
472
|
+
def solder_ball_diameter(self, value):
|
|
473
|
+
if not self.component_property.solder_ball_property.is_null:
|
|
474
|
+
diameter = None
|
|
475
|
+
mid_diameter = diameter
|
|
476
|
+
if isinstance(value, tuple) or isinstance(value, list):
|
|
477
|
+
if len(value) == 2:
|
|
478
|
+
diameter = GrpcValue(value[0])
|
|
479
|
+
mid_diameter = GrpcValue(value[1])
|
|
480
|
+
elif len(value) == 1:
|
|
481
|
+
diameter = GrpcValue(value[0])
|
|
482
|
+
mid_diameter = GrpcValue(value[0])
|
|
483
|
+
if isinstance(value, str) or isinstance(value, float):
|
|
484
|
+
diameter = GrpcValue(value)
|
|
485
|
+
mid_diameter = GrpcValue(value)
|
|
486
|
+
cmp_property = self.component_property
|
|
487
|
+
solder_ball_prop = cmp_property.solder_ball_property
|
|
488
|
+
solder_ball_prop.set_diameter(diameter, mid_diameter)
|
|
489
|
+
cmp_property.solder_ball_property = solder_ball_prop
|
|
490
|
+
self.component_property = cmp_property
|
|
491
|
+
|
|
492
|
+
@property
|
|
493
|
+
def solder_ball_placement(self):
|
|
494
|
+
"""Solder ball placement if available.."""
|
|
495
|
+
if not self.component_property.solder_ball_property.is_null:
|
|
496
|
+
solder_placement = self.component_property.solder_ball_property.placement
|
|
497
|
+
return solder_placement.value
|
|
498
|
+
|
|
499
|
+
@property
|
|
500
|
+
def refdes(self):
|
|
501
|
+
"""Reference Designator Name.
|
|
502
|
+
|
|
503
|
+
Returns
|
|
504
|
+
-------
|
|
505
|
+
str
|
|
506
|
+
Reference Designator Name.
|
|
507
|
+
"""
|
|
508
|
+
return self.name
|
|
509
|
+
|
|
510
|
+
@refdes.setter
|
|
511
|
+
def refdes(self, name):
|
|
512
|
+
self.name = name
|
|
513
|
+
|
|
514
|
+
@property
|
|
515
|
+
def model_type(self):
|
|
516
|
+
"""Retrieve assigned model type.
|
|
517
|
+
|
|
518
|
+
Returns
|
|
519
|
+
-------
|
|
520
|
+
str
|
|
521
|
+
Model type, ``RLC``, `` SParameterModel`` or ``SPICEModel``.
|
|
522
|
+
"""
|
|
523
|
+
_model_type = str(self._edb_model).split(".")[-1]
|
|
524
|
+
if _model_type == "PinPairModel":
|
|
525
|
+
return "RLC"
|
|
526
|
+
elif "SParameterModel" in _model_type:
|
|
527
|
+
return "SParameterModel"
|
|
528
|
+
elif "SPICEModel" in _model_type:
|
|
529
|
+
return "SPICEModel"
|
|
530
|
+
else:
|
|
531
|
+
return _model_type
|
|
532
|
+
|
|
533
|
+
@property
|
|
534
|
+
def rlc_values(self):
|
|
535
|
+
"""Get component rlc values.
|
|
536
|
+
|
|
537
|
+
Returns
|
|
538
|
+
-------
|
|
539
|
+
List[Rvalue(float), Lvalue(float), Cvalue(float)].
|
|
540
|
+
"""
|
|
541
|
+
if not len(self._rlc):
|
|
542
|
+
return [None, None, None]
|
|
543
|
+
elif len(self._rlc) == 1:
|
|
544
|
+
return [self._rlc[0].r.value, self._rlc[0].l.value, self._rlc[0].c.value]
|
|
545
|
+
else:
|
|
546
|
+
return [[rlc.r.value, rlc.l.value, rlc.c.value] for rlc in self._rlc]
|
|
547
|
+
|
|
548
|
+
@rlc_values.setter
|
|
549
|
+
def rlc_values(self, value):
|
|
550
|
+
comp_property = self.component_property
|
|
551
|
+
if not isinstance(value, list) or isinstance(value, tuple):
|
|
552
|
+
self._logger.error("RLC values must be provided as `List` or `Tuple` in this order.")
|
|
553
|
+
return
|
|
554
|
+
if not len(value) == 3:
|
|
555
|
+
self._logger.error("RLC values must be provided as `List` or `Tuple` in this order.")
|
|
556
|
+
return
|
|
557
|
+
_rlc = []
|
|
558
|
+
for rlc in self._rlc:
|
|
559
|
+
if value[0]:
|
|
560
|
+
rlc.r = GrpcValue(value[0])
|
|
561
|
+
rlc.r_enabled = True
|
|
562
|
+
else:
|
|
563
|
+
rlc.r_enabled = False
|
|
564
|
+
if value[1]:
|
|
565
|
+
rlc.l = GrpcValue(value[1])
|
|
566
|
+
rlc.l_enabled = True
|
|
567
|
+
else:
|
|
568
|
+
rlc.l_enabled = False
|
|
569
|
+
if value[2]:
|
|
570
|
+
rlc.c = GrpcValue(value[2])
|
|
571
|
+
rlc.c_enabled = True
|
|
572
|
+
else:
|
|
573
|
+
rlc.c_enabled = False
|
|
574
|
+
_rlc.append(rlc)
|
|
575
|
+
for ind in range(len(self._rlc)):
|
|
576
|
+
self._edb_model.set_rlc(self._pin_pairs[ind], self._rlc[ind])
|
|
577
|
+
comp_property.model = self._edb_model
|
|
578
|
+
self.component_property = comp_property
|
|
579
|
+
|
|
580
|
+
@property
|
|
581
|
+
def value(self):
|
|
582
|
+
"""Retrieve discrete component value.
|
|
583
|
+
|
|
584
|
+
Returns
|
|
585
|
+
-------
|
|
586
|
+
float
|
|
587
|
+
Value. ``None`` if not an RLC Type.
|
|
588
|
+
"""
|
|
589
|
+
_values = {"resistor": self.rlc_values[0], "inductor": self.rlc_values[1], "capacitor": self.rlc_values[2]}
|
|
590
|
+
if self.type in _values:
|
|
591
|
+
return _values[self.type]
|
|
592
|
+
else:
|
|
593
|
+
return 0.0
|
|
594
|
+
|
|
595
|
+
@value.setter
|
|
596
|
+
def value(self, value):
|
|
597
|
+
if self.type == "resistor":
|
|
598
|
+
self.res_value = value
|
|
599
|
+
elif self.type == "inductor":
|
|
600
|
+
self.ind_value = value
|
|
601
|
+
elif self.type == "capacitor":
|
|
602
|
+
self.cap_value = value
|
|
603
|
+
|
|
604
|
+
@property
|
|
605
|
+
def res_value(self):
|
|
606
|
+
"""Resistance value.
|
|
607
|
+
|
|
608
|
+
Returns
|
|
609
|
+
-------
|
|
610
|
+
float
|
|
611
|
+
Resistance value or ``None`` if not an RLC type.
|
|
612
|
+
"""
|
|
613
|
+
cmp_type = self.component_type
|
|
614
|
+
if 0 < cmp_type.value < 4:
|
|
615
|
+
result = [rlc.r.value for rlc in self._rlc]
|
|
616
|
+
if len(result) == 1:
|
|
617
|
+
return result[0]
|
|
618
|
+
else:
|
|
619
|
+
return result
|
|
620
|
+
return None
|
|
621
|
+
|
|
622
|
+
@res_value.setter
|
|
623
|
+
def res_value(self, value): # pragma no cover
|
|
624
|
+
_rlc = []
|
|
625
|
+
model = PinPairModel(self._pedb, GrpcPinPairModel.create())
|
|
626
|
+
for rlc in self._rlc:
|
|
627
|
+
rlc.r_enabled = True
|
|
628
|
+
rlc.r = GrpcValue(value)
|
|
629
|
+
_rlc.append(rlc)
|
|
630
|
+
for ind in range(len(self._pin_pairs)):
|
|
631
|
+
model.set_rlc(self._pin_pairs[ind], _rlc[ind])
|
|
632
|
+
comp_prop = self.component_property
|
|
633
|
+
comp_prop.model = model
|
|
634
|
+
self.component_property = comp_prop
|
|
635
|
+
|
|
636
|
+
@property
|
|
637
|
+
def cap_value(self):
|
|
638
|
+
"""Capacitance Value.
|
|
639
|
+
|
|
640
|
+
Returns
|
|
641
|
+
-------
|
|
642
|
+
float
|
|
643
|
+
Capacitance Value. ``None`` if not an RLC Type.
|
|
644
|
+
"""
|
|
645
|
+
cmp_type = self.component_type
|
|
646
|
+
if 0 < cmp_type.value < 4:
|
|
647
|
+
result = [rlc.c.value for rlc in self._rlc]
|
|
648
|
+
if len(result) == 1:
|
|
649
|
+
return result[0]
|
|
650
|
+
else:
|
|
651
|
+
return result
|
|
652
|
+
return None
|
|
653
|
+
|
|
654
|
+
@cap_value.setter
|
|
655
|
+
def cap_value(self, value): # pragma no cover
|
|
656
|
+
if value:
|
|
657
|
+
_rlc = []
|
|
658
|
+
model = PinPairModel(self._pedb, GrpcPinPairModel.create())
|
|
659
|
+
for rlc in self._rlc:
|
|
660
|
+
rlc.c_enabled = True
|
|
661
|
+
rlc.c = GrpcValue(value)
|
|
662
|
+
_rlc.append(rlc)
|
|
663
|
+
for ind in range(len(self._pin_pairs)):
|
|
664
|
+
model.set_rlc(self._pin_pairs[ind], _rlc[ind])
|
|
665
|
+
comp_prop = self.component_property
|
|
666
|
+
comp_prop.model = model
|
|
667
|
+
self.component_property = comp_prop
|
|
668
|
+
|
|
669
|
+
@property
|
|
670
|
+
def ind_value(self):
|
|
671
|
+
"""Inductance Value.
|
|
672
|
+
|
|
673
|
+
Returns
|
|
674
|
+
-------
|
|
675
|
+
float
|
|
676
|
+
Inductance Value. ``None`` if not an RLC Type.
|
|
677
|
+
"""
|
|
678
|
+
cmp_type = self.component_type
|
|
679
|
+
if 0 < cmp_type.value < 4:
|
|
680
|
+
result = [rlc.l.value for rlc in self._rlc]
|
|
681
|
+
if len(result) == 1:
|
|
682
|
+
return result[0]
|
|
683
|
+
else:
|
|
684
|
+
return result
|
|
685
|
+
return None
|
|
686
|
+
|
|
687
|
+
@ind_value.setter
|
|
688
|
+
def ind_value(self, value): # pragma no cover
|
|
689
|
+
if value:
|
|
690
|
+
_rlc = []
|
|
691
|
+
model = PinPairModel(self._pedb, GrpcPinPairModel.create())
|
|
692
|
+
for rlc in self._rlc:
|
|
693
|
+
rlc.l_enabled = True
|
|
694
|
+
rlc.l = GrpcValue(value)
|
|
695
|
+
_rlc.append(rlc)
|
|
696
|
+
for ind in range(len(self._pin_pairs)):
|
|
697
|
+
model.set_rlc(self._pin_pairs[ind], _rlc[ind])
|
|
698
|
+
comp_prop = self.component_property
|
|
699
|
+
comp_prop.model = model
|
|
700
|
+
self.component_property = comp_prop
|
|
701
|
+
|
|
702
|
+
@property
|
|
703
|
+
def is_parallel_rlc(self):
|
|
704
|
+
"""Define if model is Parallel or Series.
|
|
705
|
+
|
|
706
|
+
Returns
|
|
707
|
+
-------
|
|
708
|
+
bool
|
|
709
|
+
`True´ if parallel rlc model.
|
|
710
|
+
`False` series RLC.
|
|
711
|
+
`None` if not RLC Type.
|
|
712
|
+
"""
|
|
713
|
+
cmp_type = self.component_type
|
|
714
|
+
if 0 < cmp_type.value < 4:
|
|
715
|
+
return self._rlc[0].is_parallel
|
|
716
|
+
return None
|
|
717
|
+
|
|
718
|
+
@is_parallel_rlc.setter
|
|
719
|
+
def is_parallel_rlc(self, value): # pragma no cover
|
|
720
|
+
if not len(self._pin_pairs):
|
|
721
|
+
logging.warning(self.refdes, " has no pin pair.")
|
|
722
|
+
else:
|
|
723
|
+
if isinstance(value, bool):
|
|
724
|
+
for rlc in self._rlc:
|
|
725
|
+
rlc.is_parallel = value
|
|
726
|
+
comp_property = self.component_property
|
|
727
|
+
comp_property.set_rcl(rlc)
|
|
728
|
+
self.component_property = comp_property
|
|
729
|
+
|
|
730
|
+
@property
|
|
731
|
+
def center(self):
|
|
732
|
+
"""Compute the component center.
|
|
733
|
+
|
|
734
|
+
Returns
|
|
735
|
+
-------
|
|
736
|
+
list
|
|
737
|
+
[x value, y value].
|
|
738
|
+
"""
|
|
739
|
+
return self.location
|
|
740
|
+
|
|
741
|
+
@property
|
|
742
|
+
def location(self):
|
|
743
|
+
"""Component center.
|
|
744
|
+
|
|
745
|
+
Returns
|
|
746
|
+
-------
|
|
747
|
+
List[float, float]
|
|
748
|
+
[x, y].
|
|
749
|
+
|
|
750
|
+
"""
|
|
751
|
+
return [pt.value for pt in super().location]
|
|
752
|
+
|
|
753
|
+
@location.setter
|
|
754
|
+
def location(self, value):
|
|
755
|
+
if isinstance(value, list):
|
|
756
|
+
_location = [GrpcValue(val) for val in value]
|
|
757
|
+
super(Component, self.__class__).location.__set__(self, _location)
|
|
758
|
+
|
|
759
|
+
@property
|
|
760
|
+
def bounding_box(self):
|
|
761
|
+
"""Component's bounding box.
|
|
762
|
+
|
|
763
|
+
Returns
|
|
764
|
+
-------
|
|
765
|
+
List[float]
|
|
766
|
+
List of coordinates for the component's bounding box, with the list of
|
|
767
|
+
coordinates in this order: [X lower left corner, Y lower left corner,
|
|
768
|
+
X upper right corner, Y upper right corner].
|
|
769
|
+
"""
|
|
770
|
+
bbox = self.component_instance.get_bbox().points
|
|
771
|
+
pt1 = bbox[0]
|
|
772
|
+
pt2 = bbox[2]
|
|
773
|
+
return [pt1.x.value, pt1.y.value, pt2.x.value, pt2.y.value]
|
|
774
|
+
|
|
775
|
+
@property
|
|
776
|
+
def rotation(self):
|
|
777
|
+
"""Compute the component rotation in radian.
|
|
778
|
+
|
|
779
|
+
Returns
|
|
780
|
+
-------
|
|
781
|
+
float
|
|
782
|
+
Rotation value.
|
|
783
|
+
"""
|
|
784
|
+
return self.transform.rotation.value
|
|
785
|
+
|
|
786
|
+
@property
|
|
787
|
+
def pinlist(self):
|
|
788
|
+
"""Pins of the component.
|
|
789
|
+
|
|
790
|
+
Returns
|
|
791
|
+
-------
|
|
792
|
+
list
|
|
793
|
+
List of Pins of Component.
|
|
794
|
+
"""
|
|
795
|
+
return self.pins
|
|
796
|
+
|
|
797
|
+
@property
|
|
798
|
+
def nets(self):
|
|
799
|
+
"""Nets of Component.
|
|
800
|
+
|
|
801
|
+
Returns
|
|
802
|
+
-------
|
|
803
|
+
list[str]
|
|
804
|
+
Component nets names.
|
|
805
|
+
"""
|
|
806
|
+
nets = []
|
|
807
|
+
for pin in list(self.pins.values()):
|
|
808
|
+
if not pin.net.is_null:
|
|
809
|
+
nets.append(pin.net.name)
|
|
810
|
+
return list(set(nets))
|
|
811
|
+
|
|
812
|
+
@property
|
|
813
|
+
def pins(self):
|
|
814
|
+
"""Component pins.
|
|
815
|
+
|
|
816
|
+
Returns
|
|
817
|
+
-------
|
|
818
|
+
Dic[str,:class:`PadstackInstance <pyedb.grpc.database.primitive.padstack_instance.PadstackInstance>`]
|
|
819
|
+
Component dictionary pins.
|
|
820
|
+
"""
|
|
821
|
+
_pins = {}
|
|
822
|
+
for connectable in self.members:
|
|
823
|
+
if isinstance(connectable, GrpcPadstackInstanceTerminal):
|
|
824
|
+
_pins[connectable.name] = PadstackInstanceTerminal(self._pedb, connectable)
|
|
825
|
+
if isinstance(connectable, GrpcPadstackInstance):
|
|
826
|
+
_pins[connectable.name] = PadstackInstance(self._pedb, connectable)
|
|
827
|
+
return _pins
|
|
828
|
+
|
|
829
|
+
@property
|
|
830
|
+
def type(self):
|
|
831
|
+
"""Component type.
|
|
832
|
+
|
|
833
|
+
Returns
|
|
834
|
+
-------
|
|
835
|
+
str
|
|
836
|
+
Type of the component. Options are ``"resistor"``, ``"inductor"``, ``"capacitor"``,
|
|
837
|
+
``"ic"``, ``"io"`` and ``"other"``.
|
|
838
|
+
"""
|
|
839
|
+
return self.component_type.name.lower()
|
|
840
|
+
|
|
841
|
+
@type.setter
|
|
842
|
+
def type(self, new_type):
|
|
843
|
+
"""Set component type
|
|
844
|
+
|
|
845
|
+
Parameters
|
|
846
|
+
----------
|
|
847
|
+
new_type : str
|
|
848
|
+
Type of the component. Options are ``"resistor"``, ``"inductor"``, ``"capacitor"``,
|
|
849
|
+
``"ic"``, ``"io"`` and ``"other"``.
|
|
850
|
+
"""
|
|
851
|
+
new_type = new_type.lower()
|
|
852
|
+
if new_type == "resistor":
|
|
853
|
+
self.component_type = GrpcComponentType.RESISTOR
|
|
854
|
+
elif new_type == "inductor":
|
|
855
|
+
self.component_type = GrpcComponentType.INDUCTOR
|
|
856
|
+
elif new_type == "capacitor":
|
|
857
|
+
self.component_type = GrpcComponentType.CAPACITOR
|
|
858
|
+
elif new_type == "ic":
|
|
859
|
+
self.component_type = GrpcComponentType.IC
|
|
860
|
+
elif new_type == "io":
|
|
861
|
+
self.component_type = GrpcComponentType.IO
|
|
862
|
+
elif new_type == "other":
|
|
863
|
+
self.component_type = GrpcComponentType.OTHER
|
|
864
|
+
else:
|
|
865
|
+
return
|
|
866
|
+
|
|
867
|
+
@property
|
|
868
|
+
def numpins(self):
|
|
869
|
+
"""Number of Pins of Component.
|
|
870
|
+
|
|
871
|
+
Returns
|
|
872
|
+
-------
|
|
873
|
+
int
|
|
874
|
+
Component pins number.
|
|
875
|
+
"""
|
|
876
|
+
return self.num_pins
|
|
877
|
+
|
|
878
|
+
@property
|
|
879
|
+
def partname(self): # pragma: no cover
|
|
880
|
+
"""Component part name.
|
|
881
|
+
|
|
882
|
+
Returns
|
|
883
|
+
-------
|
|
884
|
+
str
|
|
885
|
+
Component part name.
|
|
886
|
+
"""
|
|
887
|
+
return self.part_name
|
|
888
|
+
|
|
889
|
+
@partname.setter
|
|
890
|
+
def partname(self, name): # pragma: no cover
|
|
891
|
+
"""Set component part name."""
|
|
892
|
+
self.part_name = name
|
|
893
|
+
|
|
894
|
+
@property
|
|
895
|
+
def part_name(self):
|
|
896
|
+
"""Component part name.
|
|
897
|
+
|
|
898
|
+
Returns
|
|
899
|
+
-------
|
|
900
|
+
str
|
|
901
|
+
Component part name.
|
|
902
|
+
"""
|
|
903
|
+
return self.component_def.name
|
|
904
|
+
|
|
905
|
+
@part_name.setter
|
|
906
|
+
def part_name(self, name): # pragma: no cover
|
|
907
|
+
"""Set component part name."""
|
|
908
|
+
self.component_def.name = name
|
|
909
|
+
|
|
910
|
+
@property
|
|
911
|
+
def placement_layer(self):
|
|
912
|
+
"""Placement layern name.
|
|
913
|
+
|
|
914
|
+
Returns
|
|
915
|
+
-------
|
|
916
|
+
str
|
|
917
|
+
Placement layer name.
|
|
918
|
+
"""
|
|
919
|
+
return super().placement_layer.name
|
|
920
|
+
|
|
921
|
+
@property
|
|
922
|
+
def layer(self):
|
|
923
|
+
"""Placement layern object.
|
|
924
|
+
|
|
925
|
+
Returns
|
|
926
|
+
-------
|
|
927
|
+
:class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`
|
|
928
|
+
Placement layer.
|
|
929
|
+
"""
|
|
930
|
+
return StackupLayer(self._pedb, super().placement_layer)
|
|
931
|
+
|
|
932
|
+
@property
|
|
933
|
+
def is_top_mounted(self):
|
|
934
|
+
"""Check if a component is mounted on top or bottom of the layout.
|
|
935
|
+
|
|
936
|
+
Returns
|
|
937
|
+
-------
|
|
938
|
+
bool
|
|
939
|
+
``True`` component is mounted on top, ``False`` on down.
|
|
940
|
+
"""
|
|
941
|
+
signal_layers = [lay.name for lay in list(self._pedb.stackup.signal_layers.values())]
|
|
942
|
+
if self.placement_layer in signal_layers[: int(len(signal_layers) / 2)]:
|
|
943
|
+
return True
|
|
944
|
+
return False
|
|
945
|
+
|
|
946
|
+
@property
|
|
947
|
+
def lower_elevation(self):
|
|
948
|
+
"""Lower elevation of the placement layer.
|
|
949
|
+
|
|
950
|
+
Returns
|
|
951
|
+
-------
|
|
952
|
+
float
|
|
953
|
+
Placement layer lower elevation.
|
|
954
|
+
"""
|
|
955
|
+
return self.layer.lower_elevation
|
|
956
|
+
|
|
957
|
+
@property
|
|
958
|
+
def upper_elevation(self):
|
|
959
|
+
"""Upper elevation of the placement layer.
|
|
960
|
+
|
|
961
|
+
Returns
|
|
962
|
+
-------
|
|
963
|
+
float
|
|
964
|
+
Placement layer upper elevation.
|
|
965
|
+
|
|
966
|
+
"""
|
|
967
|
+
return self.layer.upper_elevation
|
|
968
|
+
|
|
969
|
+
@property
|
|
970
|
+
def top_bottom_association(self):
|
|
971
|
+
"""Top/bottom association of the placement layer.
|
|
972
|
+
|
|
973
|
+
Returns
|
|
974
|
+
-------
|
|
975
|
+
int
|
|
976
|
+
Top/bottom association of the placement layer, where:
|
|
977
|
+
|
|
978
|
+
* 0 - Top associated
|
|
979
|
+
* 1 - No association
|
|
980
|
+
* 2 - Bottom associated
|
|
981
|
+
* 4 - Number of top/bottom associations.
|
|
982
|
+
* -1 - Undefined
|
|
983
|
+
"""
|
|
984
|
+
return self.layer.top_bottom_association.value
|
|
985
|
+
|
|
986
|
+
def _set_model(self, model): # pragma: no cover
|
|
987
|
+
"""Set component model
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
Returns
|
|
991
|
+
-------
|
|
992
|
+
:class:`Model <ansys.edb.core.hierarchy.model.Model>`
|
|
993
|
+
Component Model.
|
|
994
|
+
|
|
995
|
+
"""
|
|
996
|
+
comp_prop = self.component_property
|
|
997
|
+
comp_prop.model = model
|
|
998
|
+
self.component_property = comp_prop
|
|
999
|
+
return model
|
|
1000
|
+
|
|
1001
|
+
def assign_spice_model(
|
|
1002
|
+
self,
|
|
1003
|
+
file_path: str,
|
|
1004
|
+
name: Optional[str] = None,
|
|
1005
|
+
sub_circuit_name: Optional[str] = None,
|
|
1006
|
+
terminal_pairs: Optional[list] = None,
|
|
1007
|
+
):
|
|
1008
|
+
"""Assign Spice model to this component.
|
|
1009
|
+
|
|
1010
|
+
Parameters
|
|
1011
|
+
----------
|
|
1012
|
+
file_path : str
|
|
1013
|
+
File path of the Spice model.
|
|
1014
|
+
name : str, optional
|
|
1015
|
+
Name of the Spice model.
|
|
1016
|
+
|
|
1017
|
+
Returns
|
|
1018
|
+
-------
|
|
1019
|
+
:class:`SpiceModel <pyedb.grpc.database.hierarchy.spice_model.SpiceModel>`
|
|
1020
|
+
Spice model.
|
|
1021
|
+
|
|
1022
|
+
"""
|
|
1023
|
+
if not name:
|
|
1024
|
+
name = get_filename_without_extension(file_path)
|
|
1025
|
+
|
|
1026
|
+
with open(file_path, "r") as f:
|
|
1027
|
+
for line in f:
|
|
1028
|
+
if "subckt" in line.lower():
|
|
1029
|
+
pin_names_sp = [i.strip() for i in re.split(" |\t", line) if i]
|
|
1030
|
+
pin_names_sp.remove(pin_names_sp[0])
|
|
1031
|
+
pin_names_sp.remove(pin_names_sp[0])
|
|
1032
|
+
break
|
|
1033
|
+
if not len(pin_names_sp) == self.numpins: # pragma: no cover
|
|
1034
|
+
raise ValueError(f"Pin counts doesn't match component {self.name}.")
|
|
1035
|
+
|
|
1036
|
+
model = SpiceModel(file_path=file_path, name=name, sub_circuit=name)
|
|
1037
|
+
if sub_circuit_name:
|
|
1038
|
+
model.sub_circuit = sub_circuit_name
|
|
1039
|
+
|
|
1040
|
+
if terminal_pairs:
|
|
1041
|
+
terminal_pairs = terminal_pairs if isinstance(terminal_pairs[0], list) else [terminal_pairs]
|
|
1042
|
+
for pair in terminal_pairs:
|
|
1043
|
+
pname, pnumber = pair
|
|
1044
|
+
if pname not in pin_names_sp: # pragma: no cover
|
|
1045
|
+
raise ValueError(f"Pin name {pname} doesn't exist in {file_path}.")
|
|
1046
|
+
model.add_terminal(str(pnumber), pname)
|
|
1047
|
+
else:
|
|
1048
|
+
for idx, pname in enumerate(pin_names_sp):
|
|
1049
|
+
model.add_terminal(pname, str(idx + 1))
|
|
1050
|
+
self._set_model(model)
|
|
1051
|
+
if not model.is_null:
|
|
1052
|
+
return model
|
|
1053
|
+
else:
|
|
1054
|
+
return False
|
|
1055
|
+
|
|
1056
|
+
def assign_s_param_model(self, file_path, name=None, reference_net=None):
|
|
1057
|
+
"""Assign S-parameter to this component.
|
|
1058
|
+
|
|
1059
|
+
Parameters
|
|
1060
|
+
----------
|
|
1061
|
+
file_path : str
|
|
1062
|
+
File path of the S-parameter model.
|
|
1063
|
+
name : str, optional
|
|
1064
|
+
Name of the S-parameter model.
|
|
1065
|
+
|
|
1066
|
+
Returns
|
|
1067
|
+
-------
|
|
1068
|
+
:class:`NPortComponentModel <ansys.edb.core.definition.component_model.ComponentModel>`
|
|
1069
|
+
ComponentModel.
|
|
1070
|
+
|
|
1071
|
+
"""
|
|
1072
|
+
if not name:
|
|
1073
|
+
name = get_filename_without_extension(file_path)
|
|
1074
|
+
for model in self.component_def.component_models:
|
|
1075
|
+
if model.model_name == name:
|
|
1076
|
+
self._pedb.logger.error(f"Model {name} already defined for component {self.refdes}")
|
|
1077
|
+
return False
|
|
1078
|
+
if not reference_net:
|
|
1079
|
+
self._pedb.logger.warning(
|
|
1080
|
+
f"No reference net provided for S parameter file {file_path}, net `GND` is " f"assigned by default"
|
|
1081
|
+
)
|
|
1082
|
+
reference_net = "GND"
|
|
1083
|
+
n_port_model = GrpcNPortComponentModel.find_by_name(self.component_def, name)
|
|
1084
|
+
if n_port_model.is_null:
|
|
1085
|
+
n_port_model = GrpcNPortComponentModel.create(name=name)
|
|
1086
|
+
n_port_model.reference_file = file_path
|
|
1087
|
+
self.component_def.add_component_model(n_port_model)
|
|
1088
|
+
|
|
1089
|
+
model = GrpcSParameterModel.create(name=name, ref_net=reference_net)
|
|
1090
|
+
return self._set_model(model)
|
|
1091
|
+
|
|
1092
|
+
def use_s_parameter_model(self, name, reference_net=None):
|
|
1093
|
+
"""Use S-parameter model on the component.
|
|
1094
|
+
|
|
1095
|
+
Parameters
|
|
1096
|
+
----------
|
|
1097
|
+
name: str
|
|
1098
|
+
Name of the S-parameter model.
|
|
1099
|
+
reference_net: str, optional
|
|
1100
|
+
Reference net of the model.
|
|
1101
|
+
|
|
1102
|
+
Returns
|
|
1103
|
+
-------
|
|
1104
|
+
bool
|
|
1105
|
+
``True`` when successful, ``False`` when failed.
|
|
1106
|
+
|
|
1107
|
+
Examples
|
|
1108
|
+
--------
|
|
1109
|
+
>>> edbapp = Edb()
|
|
1110
|
+
>>>comp_def = edbapp.definitions.components["CAPC3216X180X55ML20T25"]
|
|
1111
|
+
>>>comp_def.add_n_port_model("c:GRM32_DC0V_25degC_series.s2p", "GRM32_DC0V_25degC_series")
|
|
1112
|
+
>>>edbapp.components["C200"].use_s_parameter_model("GRM32_DC0V_25degC_series")
|
|
1113
|
+
"""
|
|
1114
|
+
from ansys.edb.core.definition.component_model import (
|
|
1115
|
+
ComponentModel as GrpcComponentModel,
|
|
1116
|
+
)
|
|
1117
|
+
|
|
1118
|
+
model = GrpcComponentModel.find_by_name(self.component_def, name)
|
|
1119
|
+
if not model.is_null:
|
|
1120
|
+
s_param_model = GrpcSParameterModel.create(name=name, ref_net="GND")
|
|
1121
|
+
if reference_net:
|
|
1122
|
+
s_param_model.reference_net = reference_net
|
|
1123
|
+
return self._set_model(s_param_model)
|
|
1124
|
+
return False
|
|
1125
|
+
|
|
1126
|
+
def assign_rlc_model(self, res=None, ind=None, cap=None, is_parallel=False):
|
|
1127
|
+
"""Assign RLC to this component.
|
|
1128
|
+
|
|
1129
|
+
Parameters
|
|
1130
|
+
----------
|
|
1131
|
+
res : int, float
|
|
1132
|
+
Resistance. Default is ``None``.
|
|
1133
|
+
ind : int, float
|
|
1134
|
+
Inductance. Default is ``None``.
|
|
1135
|
+
cap : int, float
|
|
1136
|
+
Capacitance. Default is ``None``.
|
|
1137
|
+
is_parallel : bool, optional
|
|
1138
|
+
Whether it is a parallel or series RLC component. The default is ``False``.
|
|
1139
|
+
|
|
1140
|
+
Returns
|
|
1141
|
+
-------
|
|
1142
|
+
:class:`Model <ansys.edb.core.hierarchy.model.Model>`
|
|
1143
|
+
Component Model.
|
|
1144
|
+
|
|
1145
|
+
"""
|
|
1146
|
+
if res is None and ind is None and cap is None:
|
|
1147
|
+
self._pedb.logger.error("At least one value has to be provided.")
|
|
1148
|
+
return False
|
|
1149
|
+
r_enabled = True if res else False
|
|
1150
|
+
l_enabled = True if ind else False
|
|
1151
|
+
c_enabled = True if cap else False
|
|
1152
|
+
res = 0 if res is None else res
|
|
1153
|
+
ind = 0 if ind is None else ind
|
|
1154
|
+
cap = 0 if cap is None else cap
|
|
1155
|
+
res, ind, cap = GrpcValue(res), GrpcValue(ind), GrpcValue(cap)
|
|
1156
|
+
model = PinPairModel(self._pedb, self._edb_model)
|
|
1157
|
+
pin_names = list(self.pins.keys())
|
|
1158
|
+
for idx, i in enumerate(np.arange(len(pin_names) // 2)):
|
|
1159
|
+
# pin_pair = GrpcPinPair(pin_names[idx], pin_names[idx + 1])
|
|
1160
|
+
rlc = GrpcRlc(
|
|
1161
|
+
r=res,
|
|
1162
|
+
r_enabled=r_enabled,
|
|
1163
|
+
l=ind,
|
|
1164
|
+
l_enabled=l_enabled,
|
|
1165
|
+
c=cap,
|
|
1166
|
+
c_enabled=c_enabled,
|
|
1167
|
+
is_parallel=is_parallel,
|
|
1168
|
+
)
|
|
1169
|
+
model.set_rlc(("1", "2"), rlc)
|
|
1170
|
+
return self._set_model(model)
|
|
1171
|
+
|
|
1172
|
+
def create_clearance_on_component(self, extra_soldermask_clearance=1e-4):
|
|
1173
|
+
"""Create a Clearance on Soldermask layer by drawing a rectangle.
|
|
1174
|
+
|
|
1175
|
+
Parameters
|
|
1176
|
+
----------
|
|
1177
|
+
extra_soldermask_clearance : float, optional
|
|
1178
|
+
Extra Soldermask value in meter to be applied on component bounding box.
|
|
1179
|
+
|
|
1180
|
+
Returns
|
|
1181
|
+
-------
|
|
1182
|
+
bool
|
|
1183
|
+
"""
|
|
1184
|
+
bounding_box = self.bounding_box
|
|
1185
|
+
opening = [bounding_box[0] - extra_soldermask_clearance]
|
|
1186
|
+
opening.append(bounding_box[1] - extra_soldermask_clearance)
|
|
1187
|
+
opening.append(bounding_box[2] + extra_soldermask_clearance)
|
|
1188
|
+
opening.append(bounding_box[3] + extra_soldermask_clearance)
|
|
1189
|
+
|
|
1190
|
+
comp_layer = self.layer
|
|
1191
|
+
layer_names = list(self._pedb.stackup.layers.keys())
|
|
1192
|
+
layer_index = layer_names.index(comp_layer.name)
|
|
1193
|
+
if comp_layer in [layer_names[0] + layer_names[-1]]:
|
|
1194
|
+
return False
|
|
1195
|
+
elif layer_index < len(layer_names) / 2:
|
|
1196
|
+
soldermask_layer = layer_names[layer_index - 1]
|
|
1197
|
+
else:
|
|
1198
|
+
soldermask_layer = layer_names[layer_index + 1]
|
|
1199
|
+
|
|
1200
|
+
if not self._pedb.modeler.get_primitives(layer_name=soldermask_layer):
|
|
1201
|
+
all_nets = list(self._pedb.nets.nets.values())
|
|
1202
|
+
poly = self._pedb._create_conformal(all_nets, 0, 1e-12, False, 0)
|
|
1203
|
+
self._pedb.modeler.create_polygon(poly, soldermask_layer, [], "")
|
|
1204
|
+
|
|
1205
|
+
void = self._pedb.modeler.create_rectangle(
|
|
1206
|
+
soldermask_layer,
|
|
1207
|
+
"{}_opening".format(self.refdes),
|
|
1208
|
+
lower_left_point=opening[:2],
|
|
1209
|
+
upper_right_point=opening[2:],
|
|
1210
|
+
)
|
|
1211
|
+
void.is_negative = True
|
|
1212
|
+
return True
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
class ICDieProperty:
|
|
1216
|
+
def __init__(self, component):
|
|
1217
|
+
self._component = component
|
|
1218
|
+
self._die_property = self._component.component_property.die_property
|
|
1219
|
+
|
|
1220
|
+
@property
|
|
1221
|
+
def die_orientation(self):
|
|
1222
|
+
"""Die orientation.
|
|
1223
|
+
|
|
1224
|
+
Returns
|
|
1225
|
+
-------
|
|
1226
|
+
str
|
|
1227
|
+
Die orientation, ``chip_up`` or ``chip_down``.
|
|
1228
|
+
|
|
1229
|
+
"""
|
|
1230
|
+
return self._die_property.die_orientation.name.lower()
|
|
1231
|
+
|
|
1232
|
+
@die_orientation.setter
|
|
1233
|
+
def die_orientation(self, value):
|
|
1234
|
+
component_property = self._component.component_property
|
|
1235
|
+
die_property = component_property.die_property
|
|
1236
|
+
if value.lower() == "chip_up":
|
|
1237
|
+
die_property.die_orientation = GrpcDieOrientation.CHIP_UP
|
|
1238
|
+
elif value.lower() == "chip_down":
|
|
1239
|
+
die_property.die_orientation = GrpcDieOrientation.CHIP_DOWN
|
|
1240
|
+
else:
|
|
1241
|
+
return
|
|
1242
|
+
component_property.die_property = die_property
|
|
1243
|
+
self._component.component_property = component_property
|
|
1244
|
+
|
|
1245
|
+
@property
|
|
1246
|
+
def die_type(self):
|
|
1247
|
+
"""Die type.
|
|
1248
|
+
|
|
1249
|
+
Returns
|
|
1250
|
+
-------
|
|
1251
|
+
str
|
|
1252
|
+
Die type, ``noine``, ``flipchip``, ``wirebond``.
|
|
1253
|
+
|
|
1254
|
+
"""
|
|
1255
|
+
return self._die_property.die_type.name.lower()
|
|
1256
|
+
|
|
1257
|
+
@die_type.setter
|
|
1258
|
+
def die_type(self, value):
|
|
1259
|
+
component_property = self._component.component_property
|
|
1260
|
+
die_property = component_property.die_property
|
|
1261
|
+
if value.lower() == "none":
|
|
1262
|
+
die_property.die_type = GrpcDieType.NONE
|
|
1263
|
+
elif value.lower() == "flipchip":
|
|
1264
|
+
die_property.die_type = GrpcDieType.FLIPCHIP
|
|
1265
|
+
elif value.lower() == "wirebond":
|
|
1266
|
+
die_property.die_type = GrpcDieType.WIREBOND
|
|
1267
|
+
else:
|
|
1268
|
+
return
|
|
1269
|
+
component_property.die_property = die_property
|
|
1270
|
+
self._component.component_property = component_property
|
|
1271
|
+
|
|
1272
|
+
@property
|
|
1273
|
+
def height(self):
|
|
1274
|
+
"""Die height.
|
|
1275
|
+
|
|
1276
|
+
Returns
|
|
1277
|
+
-------
|
|
1278
|
+
float
|
|
1279
|
+
Die height.
|
|
1280
|
+
|
|
1281
|
+
"""
|
|
1282
|
+
return self._die_property.height.value
|
|
1283
|
+
|
|
1284
|
+
@height.setter
|
|
1285
|
+
def height(self, value):
|
|
1286
|
+
component_property = self._component.component_property
|
|
1287
|
+
die_property = component_property.die_property
|
|
1288
|
+
die_property.height = GrpcValue(value)
|
|
1289
|
+
component_property.die_property = die_property
|
|
1290
|
+
self._component.component_property = component_property
|
|
1291
|
+
|
|
1292
|
+
@property
|
|
1293
|
+
def is_null(self):
|
|
1294
|
+
"""Test is die is null.
|
|
1295
|
+
|
|
1296
|
+
Returns
|
|
1297
|
+
-------
|
|
1298
|
+
bool
|
|
1299
|
+
|
|
1300
|
+
"""
|
|
1301
|
+
return self._die_property.is_null
|