pyedb 0.38.0__py3-none-any.whl → 0.39.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (205) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/common/nets.py +53 -139
  3. pyedb/configuration/cfg_components.py +1 -1
  4. pyedb/configuration/cfg_general.py +4 -2
  5. pyedb/configuration/cfg_modeler.py +1 -1
  6. pyedb/configuration/cfg_package_definition.py +1 -1
  7. pyedb/configuration/cfg_padstacks.py +1 -1
  8. pyedb/configuration/cfg_ports_sources.py +56 -23
  9. pyedb/configuration/configuration.py +18 -1
  10. pyedb/dotnet/{application → database}/Variables.py +21 -21
  11. pyedb/dotnet/{edb_core → database}/cell/connectable.py +5 -5
  12. pyedb/dotnet/{edb_core → database}/cell/hierarchy/component.py +11 -11
  13. pyedb/dotnet/{edb_core → database}/cell/hierarchy/hierarchy_obj.py +1 -1
  14. pyedb/dotnet/{edb_core → database}/cell/hierarchy/model.py +1 -1
  15. pyedb/dotnet/{edb_core → database}/cell/layout.py +17 -17
  16. pyedb/dotnet/{edb_core → database}/cell/layout_obj.py +3 -3
  17. pyedb/dotnet/{edb_core → database}/cell/primitive/bondwire.py +1 -1
  18. pyedb/dotnet/{edb_core → database}/cell/primitive/path.py +4 -4
  19. pyedb/dotnet/{edb_core → database}/cell/primitive/primitive.py +14 -14
  20. pyedb/dotnet/{edb_core → database}/cell/terminal/bundle_terminal.py +2 -2
  21. pyedb/dotnet/{edb_core → database}/cell/terminal/edge_terminal.py +4 -4
  22. pyedb/dotnet/{edb_core → database}/cell/terminal/padstack_instance_terminal.py +2 -2
  23. pyedb/dotnet/{edb_core → database}/cell/terminal/pingroup_terminal.py +2 -2
  24. pyedb/dotnet/{edb_core → database}/cell/terminal/point_terminal.py +2 -2
  25. pyedb/dotnet/{edb_core → database}/cell/terminal/terminal.py +11 -11
  26. pyedb/dotnet/{edb_core → database}/cell/voltage_regulator.py +2 -2
  27. pyedb/dotnet/{edb_core → database}/components.py +101 -124
  28. pyedb/dotnet/{edb_core → database}/definition/component_def.py +5 -5
  29. pyedb/dotnet/{edb_core → database}/definition/component_model.py +1 -1
  30. pyedb/dotnet/{edb_core → database}/definition/definition_obj.py +1 -1
  31. pyedb/dotnet/{edb_core → database}/definition/definitions.py +2 -2
  32. pyedb/dotnet/{edb_core → database}/definition/package_def.py +4 -4
  33. pyedb/dotnet/{edb_core → database}/dotnet/database.py +8 -8
  34. pyedb/dotnet/{edb_core → database}/dotnet/primitive.py +9 -9
  35. pyedb/dotnet/{edb_core → database}/edb_data/control_file.py +12 -12
  36. pyedb/dotnet/{edb_core → database}/edb_data/hfss_extent_info.py +7 -7
  37. pyedb/dotnet/{edb_core → database}/edb_data/nets_data.py +10 -13
  38. pyedb/dotnet/{edb_core → database}/edb_data/padstacks_data.py +16 -16
  39. pyedb/dotnet/{edb_core → database}/edb_data/ports.py +4 -4
  40. pyedb/dotnet/{edb_core → database}/edb_data/primitives_data.py +5 -5
  41. pyedb/dotnet/{edb_core → database}/edb_data/raptor_x_simulation_setup_data.py +4 -4
  42. pyedb/dotnet/{edb_core → database}/edb_data/simulation_configuration.py +10 -10
  43. pyedb/dotnet/{edb_core → database}/edb_data/sources.py +4 -4
  44. pyedb/dotnet/{edb_core → database}/edb_data/variables.py +1 -1
  45. pyedb/dotnet/{edb_core → database}/geometry/polygon_data.py +4 -4
  46. pyedb/dotnet/{edb_core → database}/hfss.py +8 -8
  47. pyedb/dotnet/{edb_core → database}/layout_obj_instance.py +1 -1
  48. pyedb/dotnet/{edb_core → database}/layout_validation.py +2 -2
  49. pyedb/dotnet/{edb_core → database}/materials.py +23 -8
  50. pyedb/dotnet/{edb_core → database}/modeler.py +27 -27
  51. pyedb/dotnet/{edb_core → database}/net_class.py +8 -8
  52. pyedb/dotnet/{edb_core → database}/nets.py +12 -12
  53. pyedb/dotnet/{edb_core → database}/padstack.py +15 -15
  54. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/mesh_operation.py +1 -1
  55. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/settings.py +3 -3
  56. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sim_setup_info.py +2 -2
  57. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/simulation_settings.py +1 -1
  58. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/siw_dc_ir_settings.py +1 -1
  59. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sweep_data.py +1 -1
  60. pyedb/dotnet/{edb_core → database}/siwave.py +10 -10
  61. pyedb/dotnet/{edb_core → database}/stackup.py +12 -12
  62. pyedb/dotnet/{edb_core → database}/utilities/hfss_simulation_setup.py +15 -15
  63. pyedb/dotnet/{edb_core → database}/utilities/obj_base.py +1 -1
  64. pyedb/dotnet/{edb_core → database}/utilities/simulation_setup.py +3 -3
  65. pyedb/dotnet/{edb_core → database}/utilities/siwave_simulation_setup.py +6 -6
  66. pyedb/dotnet/edb.py +117 -112
  67. pyedb/generic/design_types.py +26 -19
  68. pyedb/generic/general_methods.py +1 -1
  69. pyedb/generic/plot.py +0 -2
  70. pyedb/grpc/database/__init__.py +1 -0
  71. pyedb/grpc/database/components.py +2354 -0
  72. pyedb/grpc/database/control_file.py +1277 -0
  73. pyedb/grpc/database/definition/component_def.py +218 -0
  74. pyedb/grpc/database/definition/component_model.py +39 -0
  75. pyedb/grpc/database/definition/component_pin.py +32 -0
  76. pyedb/grpc/database/definition/materials.py +1207 -0
  77. pyedb/grpc/database/definition/n_port_component_model.py +34 -0
  78. pyedb/grpc/database/definition/package_def.py +227 -0
  79. pyedb/grpc/database/definition/padstack_def.py +842 -0
  80. pyedb/grpc/database/definitions.py +70 -0
  81. pyedb/grpc/database/general.py +43 -0
  82. pyedb/grpc/database/geometry/__init__.py +0 -0
  83. pyedb/grpc/database/geometry/arc_data.py +93 -0
  84. pyedb/grpc/database/geometry/point_3d_data.py +79 -0
  85. pyedb/grpc/database/geometry/point_data.py +30 -0
  86. pyedb/grpc/database/geometry/polygon_data.py +133 -0
  87. pyedb/grpc/database/hfss.py +1279 -0
  88. pyedb/grpc/database/hierarchy/__init__.py +0 -0
  89. pyedb/grpc/database/hierarchy/component.py +1301 -0
  90. pyedb/grpc/database/hierarchy/model.py +31 -0
  91. pyedb/grpc/database/hierarchy/netlist_model.py +30 -0
  92. pyedb/grpc/database/hierarchy/pin_pair_model.py +128 -0
  93. pyedb/grpc/database/hierarchy/pingroup.py +245 -0
  94. pyedb/grpc/database/hierarchy/s_parameter_model.py +33 -0
  95. pyedb/grpc/database/hierarchy/spice_model.py +48 -0
  96. pyedb/grpc/database/layers/__init__.py +0 -0
  97. pyedb/grpc/database/layers/layer.py +57 -0
  98. pyedb/grpc/database/layers/stackup_layer.py +410 -0
  99. pyedb/grpc/database/layout/__init__.py +0 -0
  100. pyedb/grpc/database/layout/cell.py +30 -0
  101. pyedb/grpc/database/layout/layout.py +196 -0
  102. pyedb/grpc/database/layout/voltage_regulator.py +149 -0
  103. pyedb/grpc/database/layout_validation.py +319 -0
  104. pyedb/grpc/database/modeler.py +1468 -0
  105. pyedb/grpc/database/net/__init__.py +0 -0
  106. pyedb/grpc/database/net/differential_pair.py +138 -0
  107. pyedb/grpc/database/net/extended_net.py +340 -0
  108. pyedb/grpc/database/net/net.py +198 -0
  109. pyedb/grpc/database/net/net_class.py +93 -0
  110. pyedb/grpc/database/nets.py +633 -0
  111. pyedb/grpc/database/padstacks.py +1500 -0
  112. pyedb/grpc/database/ports/__init__.py +0 -0
  113. pyedb/grpc/database/ports/ports.py +396 -0
  114. pyedb/grpc/database/primitive/__init__.py +3 -0
  115. pyedb/grpc/database/primitive/bondwire.py +181 -0
  116. pyedb/grpc/database/primitive/circle.py +75 -0
  117. pyedb/grpc/database/primitive/padstack_instance.py +1116 -0
  118. pyedb/grpc/database/primitive/path.py +346 -0
  119. pyedb/grpc/database/primitive/polygon.py +276 -0
  120. pyedb/grpc/database/primitive/primitive.py +739 -0
  121. pyedb/grpc/database/primitive/rectangle.py +146 -0
  122. pyedb/grpc/database/simulation_setup/__init__.py +0 -0
  123. pyedb/grpc/database/simulation_setup/adaptive_frequency.py +33 -0
  124. pyedb/grpc/database/simulation_setup/hfss_advanced_meshing_settings.py +32 -0
  125. pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +59 -0
  126. pyedb/grpc/database/simulation_setup/hfss_dcr_settings.py +35 -0
  127. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +61 -0
  128. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +78 -0
  129. pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +118 -0
  130. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +355 -0
  131. pyedb/grpc/database/simulation_setup/hfss_solver_settings.py +34 -0
  132. pyedb/grpc/database/simulation_setup/mesh_operation.py +34 -0
  133. pyedb/grpc/database/simulation_setup/raptor_x_advanced_settings.py +34 -0
  134. pyedb/grpc/database/simulation_setup/raptor_x_general_settings.py +33 -0
  135. pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +64 -0
  136. pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +125 -0
  137. pyedb/grpc/database/simulation_setup/siwave_dcir_simulation_setup.py +34 -0
  138. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +119 -0
  139. pyedb/grpc/database/simulation_setup/sweep_data.py +32 -0
  140. pyedb/grpc/database/siwave.py +1023 -0
  141. pyedb/grpc/database/source_excitations.py +2572 -0
  142. pyedb/grpc/database/stackup.py +2574 -0
  143. pyedb/grpc/database/terminal/__init__.py +0 -0
  144. pyedb/grpc/database/terminal/bundle_terminal.py +218 -0
  145. pyedb/grpc/database/terminal/edge_terminal.py +51 -0
  146. pyedb/grpc/database/terminal/padstack_instance_terminal.py +171 -0
  147. pyedb/grpc/database/terminal/pingroup_terminal.py +162 -0
  148. pyedb/grpc/database/terminal/point_terminal.py +99 -0
  149. pyedb/grpc/database/terminal/terminal.py +470 -0
  150. pyedb/grpc/database/utility/__init__.py +3 -0
  151. pyedb/grpc/database/utility/constants.py +25 -0
  152. pyedb/grpc/database/utility/heat_sink.py +124 -0
  153. pyedb/grpc/database/utility/hfss_extent_info.py +448 -0
  154. pyedb/grpc/database/utility/layout_statistics.py +277 -0
  155. pyedb/grpc/database/utility/rlc.py +80 -0
  156. pyedb/grpc/database/utility/simulation_configuration.py +3305 -0
  157. pyedb/grpc/database/utility/sources.py +388 -0
  158. pyedb/grpc/database/utility/sweep_data_distribution.py +83 -0
  159. pyedb/grpc/database/utility/xml_control_file.py +1277 -0
  160. pyedb/grpc/edb.py +4151 -0
  161. pyedb/grpc/edb_init.py +481 -0
  162. pyedb/grpc/rpc_session.py +177 -0
  163. pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +3 -2
  164. pyedb/ipc2581/ecad/cad_data/feature.py +4 -3
  165. pyedb/ipc2581/ecad/cad_data/layer_feature.py +32 -20
  166. pyedb/ipc2581/ecad/cad_data/outline.py +3 -2
  167. pyedb/ipc2581/ecad/cad_data/package.py +4 -3
  168. pyedb/ipc2581/ecad/cad_data/path.py +82 -31
  169. pyedb/ipc2581/ecad/cad_data/polygon.py +122 -60
  170. pyedb/ipc2581/ecad/cad_data/profile.py +13 -12
  171. pyedb/ipc2581/ecad/cad_data/step.py +53 -21
  172. pyedb/ipc2581/ipc2581.py +47 -49
  173. pyedb/modeler/geometry_operators.py +1 -1
  174. {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/METADATA +5 -2
  175. pyedb-0.39.0.dist-info/RECORD +288 -0
  176. pyedb-0.38.0.dist-info/RECORD +0 -195
  177. /pyedb/dotnet/{edb_core → database}/__init__.py +0 -0
  178. /pyedb/dotnet/{application → database/cell}/__init__.py +0 -0
  179. /pyedb/dotnet/{edb_core/cell → database/cell/hierarchy}/__init__.py +0 -0
  180. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/netlist_model.py +0 -0
  181. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/pin_pair_model.py +0 -0
  182. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/s_parameter_model.py +0 -0
  183. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/spice_model.py +0 -0
  184. /pyedb/dotnet/{edb_core → database}/cell/primitive/__init__.py +0 -0
  185. /pyedb/dotnet/{edb_core/cell/hierarchy → database/cell/terminal}/__init__.py +0 -0
  186. /pyedb/dotnet/{edb_core/cell/terminal → database/definition}/__init__.py +0 -0
  187. /pyedb/dotnet/{edb_core/definition → database/dotnet}/__init__.py +0 -0
  188. /pyedb/dotnet/{edb_core/dotnet → database/edb_data}/__init__.py +0 -0
  189. /pyedb/dotnet/{edb_core → database}/edb_data/design_options.py +0 -0
  190. /pyedb/dotnet/{edb_core → database}/edb_data/edbvalue.py +0 -0
  191. /pyedb/dotnet/{edb_core → database}/edb_data/layer_data.py +0 -0
  192. /pyedb/dotnet/{edb_core → database}/edb_data/utilities.py +0 -0
  193. /pyedb/dotnet/{edb_core → database}/general.py +0 -0
  194. /pyedb/dotnet/{edb_core/edb_data → database/geometry}/__init__.py +0 -0
  195. /pyedb/dotnet/{edb_core → database}/geometry/point_data.py +0 -0
  196. /pyedb/dotnet/{edb_core → database}/sim_setup_data/__init__.py +0 -0
  197. /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/__init__.py +0 -0
  198. /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/adaptive_frequency_data.py +0 -0
  199. /pyedb/dotnet/{edb_core/geometry → database/sim_setup_data/io}/__init__.py +0 -0
  200. /pyedb/dotnet/{edb_core → database}/sim_setup_data/io/siwave.py +0 -0
  201. /pyedb/dotnet/{edb_core → database}/utilities/__init__.py +0 -0
  202. /pyedb/dotnet/{edb_core → database}/utilities/heatsink.py +0 -0
  203. /pyedb/{dotnet/edb_core/sim_setup_data/io → grpc/database/definition}/__init__.py +0 -0
  204. {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/LICENSE +0 -0
  205. {pyedb-0.38.0.dist-info → pyedb-0.39.0.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