pyedb 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +17 -0
- pyedb/dotnet/__init__.py +0 -0
- pyedb/dotnet/application/Variables.py +2261 -0
- pyedb/dotnet/application/__init__.py +0 -0
- pyedb/dotnet/clr_module.py +103 -0
- pyedb/dotnet/edb.py +4237 -0
- pyedb/dotnet/edb_core/__init__.py +1 -0
- pyedb/dotnet/edb_core/cell/__init__.py +0 -0
- pyedb/dotnet/edb_core/cell/hierarchy/__init__.py +0 -0
- pyedb/dotnet/edb_core/cell/hierarchy/model.py +66 -0
- pyedb/dotnet/edb_core/components.py +2669 -0
- pyedb/dotnet/edb_core/configuration.py +423 -0
- pyedb/dotnet/edb_core/definition/__init__.py +0 -0
- pyedb/dotnet/edb_core/definition/component_def.py +166 -0
- pyedb/dotnet/edb_core/definition/component_model.py +30 -0
- pyedb/dotnet/edb_core/definition/definition_obj.py +18 -0
- pyedb/dotnet/edb_core/definition/definitions.py +12 -0
- pyedb/dotnet/edb_core/dotnet/__init__.py +0 -0
- pyedb/dotnet/edb_core/dotnet/database.py +1218 -0
- pyedb/dotnet/edb_core/dotnet/layout.py +238 -0
- pyedb/dotnet/edb_core/dotnet/primitive.py +1517 -0
- pyedb/dotnet/edb_core/edb_data/__init__.py +0 -0
- pyedb/dotnet/edb_core/edb_data/components_data.py +938 -0
- pyedb/dotnet/edb_core/edb_data/connectable.py +113 -0
- pyedb/dotnet/edb_core/edb_data/control_file.py +1268 -0
- pyedb/dotnet/edb_core/edb_data/design_options.py +35 -0
- pyedb/dotnet/edb_core/edb_data/edbvalue.py +45 -0
- pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +330 -0
- pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +1607 -0
- pyedb/dotnet/edb_core/edb_data/layer_data.py +576 -0
- pyedb/dotnet/edb_core/edb_data/nets_data.py +281 -0
- pyedb/dotnet/edb_core/edb_data/obj_base.py +19 -0
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +2080 -0
- pyedb/dotnet/edb_core/edb_data/ports.py +287 -0
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +1397 -0
- pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +2914 -0
- pyedb/dotnet/edb_core/edb_data/simulation_setup.py +716 -0
- pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +1205 -0
- pyedb/dotnet/edb_core/edb_data/sources.py +514 -0
- pyedb/dotnet/edb_core/edb_data/terminals.py +632 -0
- pyedb/dotnet/edb_core/edb_data/utilities.py +148 -0
- pyedb/dotnet/edb_core/edb_data/variables.py +91 -0
- pyedb/dotnet/edb_core/general.py +181 -0
- pyedb/dotnet/edb_core/hfss.py +1646 -0
- pyedb/dotnet/edb_core/layout.py +1244 -0
- pyedb/dotnet/edb_core/layout_validation.py +272 -0
- pyedb/dotnet/edb_core/materials.py +939 -0
- pyedb/dotnet/edb_core/net_class.py +335 -0
- pyedb/dotnet/edb_core/nets.py +1215 -0
- pyedb/dotnet/edb_core/padstack.py +1389 -0
- pyedb/dotnet/edb_core/siwave.py +1427 -0
- pyedb/dotnet/edb_core/stackup.py +2703 -0
- pyedb/edb_logger.py +396 -0
- pyedb/generic/__init__.py +0 -0
- pyedb/generic/constants.py +1063 -0
- pyedb/generic/data_handlers.py +320 -0
- pyedb/generic/design_types.py +104 -0
- pyedb/generic/filesystem.py +150 -0
- pyedb/generic/general_methods.py +1535 -0
- pyedb/generic/plot.py +1840 -0
- pyedb/generic/process.py +285 -0
- pyedb/generic/settings.py +224 -0
- pyedb/ipc2581/__init__.py +0 -0
- pyedb/ipc2581/bom/__init__.py +0 -0
- pyedb/ipc2581/bom/bom.py +21 -0
- pyedb/ipc2581/bom/bom_item.py +32 -0
- pyedb/ipc2581/bom/characteristics.py +37 -0
- pyedb/ipc2581/bom/refdes.py +16 -0
- pyedb/ipc2581/content/__init__.py +0 -0
- pyedb/ipc2581/content/color.py +38 -0
- pyedb/ipc2581/content/content.py +55 -0
- pyedb/ipc2581/content/dictionary_color.py +29 -0
- pyedb/ipc2581/content/dictionary_fill.py +28 -0
- pyedb/ipc2581/content/dictionary_line.py +30 -0
- pyedb/ipc2581/content/entry_color.py +13 -0
- pyedb/ipc2581/content/entry_line.py +14 -0
- pyedb/ipc2581/content/fill.py +15 -0
- pyedb/ipc2581/content/layer_ref.py +10 -0
- pyedb/ipc2581/content/standard_geometries_dictionary.py +72 -0
- pyedb/ipc2581/ecad/__init__.py +0 -0
- pyedb/ipc2581/ecad/cad_data/__init__.py +0 -0
- pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +26 -0
- pyedb/ipc2581/ecad/cad_data/cad_data.py +37 -0
- pyedb/ipc2581/ecad/cad_data/component.py +41 -0
- pyedb/ipc2581/ecad/cad_data/drill.py +30 -0
- pyedb/ipc2581/ecad/cad_data/feature.py +54 -0
- pyedb/ipc2581/ecad/cad_data/layer.py +41 -0
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +151 -0
- pyedb/ipc2581/ecad/cad_data/logical_net.py +32 -0
- pyedb/ipc2581/ecad/cad_data/outline.py +25 -0
- pyedb/ipc2581/ecad/cad_data/package.py +104 -0
- pyedb/ipc2581/ecad/cad_data/padstack_def.py +38 -0
- pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +24 -0
- pyedb/ipc2581/ecad/cad_data/padstack_instance.py +62 -0
- pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +26 -0
- pyedb/ipc2581/ecad/cad_data/path.py +89 -0
- pyedb/ipc2581/ecad/cad_data/phy_net.py +80 -0
- pyedb/ipc2581/ecad/cad_data/pin.py +31 -0
- pyedb/ipc2581/ecad/cad_data/polygon.py +169 -0
- pyedb/ipc2581/ecad/cad_data/profile.py +40 -0
- pyedb/ipc2581/ecad/cad_data/stackup.py +31 -0
- pyedb/ipc2581/ecad/cad_data/stackup_group.py +42 -0
- pyedb/ipc2581/ecad/cad_data/stackup_layer.py +21 -0
- pyedb/ipc2581/ecad/cad_data/step.py +275 -0
- pyedb/ipc2581/ecad/cad_header.py +33 -0
- pyedb/ipc2581/ecad/ecad.py +19 -0
- pyedb/ipc2581/ecad/spec.py +46 -0
- pyedb/ipc2581/history_record.py +37 -0
- pyedb/ipc2581/ipc2581.py +387 -0
- pyedb/ipc2581/logistic_header.py +25 -0
- pyedb/misc/__init__.py +0 -0
- pyedb/misc/aedtlib_personalib_install.py +14 -0
- pyedb/misc/downloads.py +322 -0
- pyedb/misc/misc.py +67 -0
- pyedb/misc/pyedb.runtimeconfig.json +13 -0
- pyedb/misc/siw_feature_config/__init__.py +0 -0
- pyedb/misc/siw_feature_config/emc/__init__.py +0 -0
- pyedb/misc/siw_feature_config/emc/component_tags.py +46 -0
- pyedb/misc/siw_feature_config/emc/net_tags.py +37 -0
- pyedb/misc/siw_feature_config/emc/tag_library.py +62 -0
- pyedb/misc/siw_feature_config/emc/xml_generic.py +78 -0
- pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +179 -0
- pyedb/misc/utilities.py +27 -0
- pyedb/modeler/geometry_operators.py +2082 -0
- pyedb-0.2.0.dist-info/LICENSE +21 -0
- pyedb-0.2.0.dist-info/METADATA +208 -0
- pyedb-0.2.0.dist-info/RECORD +128 -0
- pyedb-0.2.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,938 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
from pyedb.dotnet.edb_core.cell.hierarchy.model import PinPairModel
|
|
6
|
+
from pyedb.dotnet.edb_core.edb_data.padstacks_data import EDBPadstackInstance
|
|
7
|
+
from pyedb.generic.general_methods import is_ironpython
|
|
8
|
+
|
|
9
|
+
if not is_ironpython:
|
|
10
|
+
try:
|
|
11
|
+
import numpy as np
|
|
12
|
+
except ImportError:
|
|
13
|
+
warnings.warn(
|
|
14
|
+
"The NumPy module is required to run some functionalities of EDB.\n"
|
|
15
|
+
"Install with \n\npip install numpy\n\nRequires CPython."
|
|
16
|
+
)
|
|
17
|
+
from pyedb.generic.general_methods import (
|
|
18
|
+
get_filename_without_extension,
|
|
19
|
+
pyedb_function_handler,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EDBComponent(object):
|
|
24
|
+
"""Manages EDB functionalities for components.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
parent : :class:`pyedb.dotnet.edb_core.components.Components`
|
|
29
|
+
Inherited AEDT object.
|
|
30
|
+
component : object
|
|
31
|
+
Edb Component Object
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
class _PinPair(object): # pragma: no cover
|
|
36
|
+
def __init__(self, pcomp, edb_comp, edb_comp_prop, edb_model, edb_pin_pair):
|
|
37
|
+
self._pedb_comp = pcomp
|
|
38
|
+
self._edb_comp = edb_comp
|
|
39
|
+
self._edb_comp_prop = edb_comp_prop
|
|
40
|
+
self._edb_model = edb_model
|
|
41
|
+
self._edb_pin_pair = edb_pin_pair
|
|
42
|
+
|
|
43
|
+
def _edb_value(self, value):
|
|
44
|
+
return self._pedb_comp._get_edb_value(value) # pragma: no cover
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def is_parallel(self):
|
|
48
|
+
return self._pin_pair_rlc.IsParallel # pragma: no cover
|
|
49
|
+
|
|
50
|
+
@is_parallel.setter
|
|
51
|
+
def is_parallel(self, value):
|
|
52
|
+
rlc = self._pin_pair_rlc
|
|
53
|
+
rlc.IsParallel = value
|
|
54
|
+
self._set_comp_prop() # pragma: no cover
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def _pin_pair_rlc(self):
|
|
58
|
+
return self._edb_model.GetPinPairRlc(self._edb_pin_pair)
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def rlc_enable(self):
|
|
62
|
+
rlc = self._pin_pair_rlc
|
|
63
|
+
return [rlc.REnabled, rlc.LEnabled, rlc.CEnabled]
|
|
64
|
+
|
|
65
|
+
@rlc_enable.setter
|
|
66
|
+
def rlc_enable(self, value):
|
|
67
|
+
rlc = self._pin_pair_rlc
|
|
68
|
+
rlc.REnabled = value[0]
|
|
69
|
+
rlc.LEnabled = value[1]
|
|
70
|
+
rlc.CEnabled = value[2]
|
|
71
|
+
self._set_comp_prop() # pragma: no cover
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def resistance(self):
|
|
75
|
+
return self._pin_pair_rlc.R.ToDouble() # pragma: no cover
|
|
76
|
+
|
|
77
|
+
@resistance.setter
|
|
78
|
+
def resistance(self, value):
|
|
79
|
+
self._pin_pair_rlc.R = value
|
|
80
|
+
self._set_comp_prop(self._pin_pair_rlc) # pragma: no cover
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def inductance(self):
|
|
84
|
+
return self._pin_pair_rlc.L.ToDouble() # pragma: no cover
|
|
85
|
+
|
|
86
|
+
@inductance.setter
|
|
87
|
+
def inductance(self, value):
|
|
88
|
+
self._pin_pair_rlc.L = value
|
|
89
|
+
self._set_comp_prop(self._pin_pair_rlc) # pragma: no cover
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def capacitance(self):
|
|
93
|
+
return self._pin_pair_rlc.C.ToDouble() # pragma: no cover
|
|
94
|
+
|
|
95
|
+
@capacitance.setter
|
|
96
|
+
def capacitance(self, value):
|
|
97
|
+
self._pin_pair_rlc.C = value
|
|
98
|
+
self._set_comp_prop(self._pin_pair_rlc) # pragma: no cover
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def rlc_values(self): # pragma: no cover
|
|
102
|
+
rlc = self._pin_pair_rlc
|
|
103
|
+
return [rlc.R.ToDouble(), rlc.L.ToDouble(), rlc.C.ToDouble()]
|
|
104
|
+
|
|
105
|
+
@rlc_values.setter
|
|
106
|
+
def rlc_values(self, values): # pragma: no cover
|
|
107
|
+
rlc = self._pin_pair_rlc
|
|
108
|
+
rlc.R = self._edb_value(values[0])
|
|
109
|
+
rlc.L = self._edb_value(values[1])
|
|
110
|
+
rlc.C = self._edb_value(values[2])
|
|
111
|
+
self._set_comp_prop() # pragma: no cover
|
|
112
|
+
|
|
113
|
+
def _set_comp_prop(self): # pragma: no cover
|
|
114
|
+
self._edb_model.SetPinPairRlc(self._edb_pin_pair, self._pin_pair_rlc)
|
|
115
|
+
self._edb_comp_prop.SetModel(self._edb_model)
|
|
116
|
+
self._edb_comp.SetComponentProperty(self._edb_comp_prop)
|
|
117
|
+
|
|
118
|
+
class _SpiceModel(object): # pragma: no cover
|
|
119
|
+
def __init__(self, edb_model):
|
|
120
|
+
self._edb_model = edb_model
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def file_path(self):
|
|
124
|
+
return self._edb_model.GetSPICEFilePath()
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def name(self):
|
|
128
|
+
return self._edb_model.GetSPICEName()
|
|
129
|
+
|
|
130
|
+
class _SparamModel(object): # pragma: no cover
|
|
131
|
+
def __init__(self, edb_model):
|
|
132
|
+
self._edb_model = edb_model
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def name(self):
|
|
136
|
+
return self._edb_model.GetComponentModelName()
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def reference_net(self):
|
|
140
|
+
return self._edb_model.GetReferenceNet()
|
|
141
|
+
|
|
142
|
+
class _NetlistModel(object): # pragma: no cover
|
|
143
|
+
def __init__(self, edb_model):
|
|
144
|
+
self._edb_model = edb_model
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def netlist(self):
|
|
148
|
+
return self._edb_model.GetNetlist()
|
|
149
|
+
|
|
150
|
+
def __init__(self, pedb, cmp):
|
|
151
|
+
self._pedb = pedb
|
|
152
|
+
self.edbcomponent = cmp
|
|
153
|
+
self._layout_instance = None
|
|
154
|
+
self._comp_instance = None
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def layout_instance(self):
|
|
158
|
+
"""EDB layout instance object."""
|
|
159
|
+
return self._pedb.layout_instance
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def component_instance(self):
|
|
163
|
+
"""Edb component instance."""
|
|
164
|
+
if self._comp_instance is None:
|
|
165
|
+
self._comp_instance = self.layout_instance.GetLayoutObjInstance(self.edbcomponent, None)
|
|
166
|
+
return self._comp_instance
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def _active_layout(self): # pragma: no cover
|
|
170
|
+
return self._pedb.active_layout
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def component_property(self):
|
|
174
|
+
"""``ComponentProperty`` object."""
|
|
175
|
+
return self.edbcomponent.GetComponentProperty().Clone()
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def _edb_model(self): # pragma: no cover
|
|
179
|
+
return self.component_property.GetModel().Clone()
|
|
180
|
+
|
|
181
|
+
@property # pragma: no cover
|
|
182
|
+
def _pin_pairs(self):
|
|
183
|
+
edb_comp_prop = self.component_property
|
|
184
|
+
edb_model = self._edb_model
|
|
185
|
+
return [
|
|
186
|
+
self._PinPair(self, self.edbcomponent, edb_comp_prop, edb_model, pin_pair)
|
|
187
|
+
for pin_pair in list(edb_model.PinPairs)
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def model(self):
|
|
192
|
+
"""Component model."""
|
|
193
|
+
edb_object = self.component_property.GetModel().Clone()
|
|
194
|
+
model_type = edb_object.ToString().split(".")[-1]
|
|
195
|
+
if model_type == "PinPairModel":
|
|
196
|
+
return PinPairModel(self._pedb, edb_object)
|
|
197
|
+
|
|
198
|
+
@model.setter
|
|
199
|
+
def model(self, value):
|
|
200
|
+
if not isinstance(value, PinPairModel):
|
|
201
|
+
self._pedb.logger.error("Invalid input. Set model failed.")
|
|
202
|
+
|
|
203
|
+
comp_prop = self.component_property
|
|
204
|
+
comp_prop.SetModel(value._edb_object)
|
|
205
|
+
self.edbcomponent.SetComponentProperty(comp_prop)
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def is_enabled(self):
|
|
209
|
+
"""Get or Set the component to active mode.
|
|
210
|
+
|
|
211
|
+
Returns
|
|
212
|
+
-------
|
|
213
|
+
bool
|
|
214
|
+
``True`` if component is active, ``False`` if is disabled..
|
|
215
|
+
"""
|
|
216
|
+
return self.component_property.IsEnabled()
|
|
217
|
+
|
|
218
|
+
@is_enabled.setter
|
|
219
|
+
def is_enabled(self, value):
|
|
220
|
+
cmp_prop = self.component_property.Clone()
|
|
221
|
+
cmp_prop.SetEnabled(value)
|
|
222
|
+
self.edbcomponent.SetComponentProperty(cmp_prop)
|
|
223
|
+
|
|
224
|
+
@property
|
|
225
|
+
def spice_model(self):
|
|
226
|
+
"""Get assigned Spice model properties."""
|
|
227
|
+
if not self.model_type == "SPICEModel":
|
|
228
|
+
return None
|
|
229
|
+
else:
|
|
230
|
+
return self._SpiceModel(self._edb_model)
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def s_param_model(self):
|
|
234
|
+
"""Get assigned S-parameter model properties."""
|
|
235
|
+
if not self.model_type == "SParameterModel":
|
|
236
|
+
return None
|
|
237
|
+
else:
|
|
238
|
+
return self._SparamModel(self._edb_model)
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def netlist_model(self):
|
|
242
|
+
"""Get assigned netlist model properties."""
|
|
243
|
+
if not self.model_type == "NetlistModel":
|
|
244
|
+
return None
|
|
245
|
+
else:
|
|
246
|
+
return self._NetlistModel(self._edb_model)
|
|
247
|
+
|
|
248
|
+
@property
|
|
249
|
+
def solder_ball_height(self):
|
|
250
|
+
"""Solder ball height if available."""
|
|
251
|
+
if "GetSolderBallProperty" in dir(self.component_property):
|
|
252
|
+
return self.component_property.GetSolderBallProperty().GetHeight()
|
|
253
|
+
return None
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def solder_ball_placement(self):
|
|
257
|
+
"""Solder ball placement if available.."""
|
|
258
|
+
if "GetSolderBallProperty" in dir(self.component_property):
|
|
259
|
+
return int(self.component_property.GetSolderBallProperty().GetPlacement())
|
|
260
|
+
return 2
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def refdes(self):
|
|
264
|
+
"""Reference Designator Name.
|
|
265
|
+
|
|
266
|
+
Returns
|
|
267
|
+
-------
|
|
268
|
+
str
|
|
269
|
+
Reference Designator Name.
|
|
270
|
+
"""
|
|
271
|
+
return self.edbcomponent.GetName()
|
|
272
|
+
|
|
273
|
+
@refdes.setter
|
|
274
|
+
def refdes(self, name):
|
|
275
|
+
self.edbcomponent.SetName(name)
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def is_null(self):
|
|
279
|
+
"""Flag indicating if the current object exists."""
|
|
280
|
+
return self.edbcomponent.IsNull()
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def is_enabled(self):
|
|
284
|
+
"""Flag indicating if the current object is enabled.
|
|
285
|
+
|
|
286
|
+
Returns
|
|
287
|
+
-------
|
|
288
|
+
bool
|
|
289
|
+
``True`` if current object is enabled, ``False`` otherwise.
|
|
290
|
+
"""
|
|
291
|
+
if self.type in ["Resistor", "Capacitor", "Inductor"]:
|
|
292
|
+
return self.component_property.IsEnabled()
|
|
293
|
+
else: # pragma: no cover
|
|
294
|
+
return True
|
|
295
|
+
|
|
296
|
+
@is_enabled.setter
|
|
297
|
+
def is_enabled(self, enabled):
|
|
298
|
+
"""Enables the current object."""
|
|
299
|
+
if self.type in ["Resistor", "Capacitor", "Inductor"]:
|
|
300
|
+
component_property = self.component_property
|
|
301
|
+
component_property.SetEnabled(enabled)
|
|
302
|
+
self.edbcomponent.SetComponentProperty(component_property)
|
|
303
|
+
|
|
304
|
+
@property
|
|
305
|
+
def model_type(self):
|
|
306
|
+
"""Retrieve assigned model type."""
|
|
307
|
+
_model_type = self._edb_model.ToString().split(".")[-1]
|
|
308
|
+
if _model_type == "PinPairModel":
|
|
309
|
+
return "RLC"
|
|
310
|
+
else:
|
|
311
|
+
return _model_type
|
|
312
|
+
|
|
313
|
+
@property
|
|
314
|
+
def rlc_values(self):
|
|
315
|
+
"""Get component rlc values."""
|
|
316
|
+
if not len(self._pin_pairs):
|
|
317
|
+
return [None, None, None]
|
|
318
|
+
pin_pair = self._pin_pairs[0]
|
|
319
|
+
return pin_pair.rlc_values
|
|
320
|
+
|
|
321
|
+
@rlc_values.setter
|
|
322
|
+
def rlc_values(self, value):
|
|
323
|
+
if isinstance(value, list): # pragma no cover
|
|
324
|
+
rlc_enabled = [True if i else False for i in value]
|
|
325
|
+
rlc_values = [self._get_edb_value(i) for i in value]
|
|
326
|
+
model = self._edb.cell.hierarchy._hierarchy.PinPairModel()
|
|
327
|
+
pin_names = list(self.pins.keys())
|
|
328
|
+
for idx, i in enumerate(np.arange(len(pin_names) // 2)):
|
|
329
|
+
pin_pair = self._edb.utility.utility.PinPair(pin_names[idx], pin_names[idx + 1])
|
|
330
|
+
rlc = self._edb.utility.utility.Rlc(
|
|
331
|
+
rlc_values[0], rlc_enabled[0], rlc_values[1], rlc_enabled[1], rlc_values[2], rlc_enabled[2], False
|
|
332
|
+
)
|
|
333
|
+
model.SetPinPairRlc(pin_pair, rlc)
|
|
334
|
+
self._set_model(model)
|
|
335
|
+
|
|
336
|
+
@property
|
|
337
|
+
def value(self):
|
|
338
|
+
"""Retrieve discrete component value.
|
|
339
|
+
|
|
340
|
+
Returns
|
|
341
|
+
-------
|
|
342
|
+
str
|
|
343
|
+
Value. ``None`` if not an RLC Type.
|
|
344
|
+
"""
|
|
345
|
+
if self.model_type == "RLC":
|
|
346
|
+
if not self._pin_pairs:
|
|
347
|
+
if self.type == "Inductor":
|
|
348
|
+
return 1e-9
|
|
349
|
+
elif self.type == "Resistor":
|
|
350
|
+
return 1e6
|
|
351
|
+
else:
|
|
352
|
+
return 1
|
|
353
|
+
else:
|
|
354
|
+
pin_pair = self._pin_pairs[0]
|
|
355
|
+
if len([i for i in pin_pair.rlc_enable if i]) == 1:
|
|
356
|
+
return [pin_pair.rlc_values[idx] for idx, val in enumerate(pin_pair.rlc_enable) if val][0]
|
|
357
|
+
else:
|
|
358
|
+
return pin_pair.rlc_values
|
|
359
|
+
elif self.model_type == "SPICEModel":
|
|
360
|
+
return self.spice_model.file_path
|
|
361
|
+
elif self.model_type == "SParameterModel":
|
|
362
|
+
return self.s_param_model.name
|
|
363
|
+
else:
|
|
364
|
+
return self.netlist_model.netlist
|
|
365
|
+
|
|
366
|
+
@value.setter
|
|
367
|
+
def value(self, value):
|
|
368
|
+
rlc_enabled = [True if i == self.type else False for i in ["Resistor", "Inductor", "Capacitor"]]
|
|
369
|
+
rlc_values = [value if i == self.type else 0 for i in ["Resistor", "Inductor", "Capacitor"]]
|
|
370
|
+
rlc_values = [self._get_edb_value(i) for i in rlc_values]
|
|
371
|
+
|
|
372
|
+
model = self._edb.cell.hierarchy._hierarchy.PinPairModel()
|
|
373
|
+
pin_names = list(self.pins.keys())
|
|
374
|
+
for idx, i in enumerate(np.arange(len(pin_names) // 2)):
|
|
375
|
+
pin_pair = self._edb.utility.utility.PinPair(pin_names[idx], pin_names[idx + 1])
|
|
376
|
+
rlc = self._edb.utility.utility.Rlc(
|
|
377
|
+
rlc_values[0], rlc_enabled[0], rlc_values[1], rlc_enabled[1], rlc_values[2], rlc_enabled[2], False
|
|
378
|
+
)
|
|
379
|
+
model.SetPinPairRlc(pin_pair, rlc)
|
|
380
|
+
self._set_model(model)
|
|
381
|
+
|
|
382
|
+
@property
|
|
383
|
+
def res_value(self):
|
|
384
|
+
"""Resistance value.
|
|
385
|
+
|
|
386
|
+
Returns
|
|
387
|
+
-------
|
|
388
|
+
str
|
|
389
|
+
Resistance value or ``None`` if not an RLC type.
|
|
390
|
+
"""
|
|
391
|
+
cmp_type = int(self.edbcomponent.GetComponentType())
|
|
392
|
+
if 0 < cmp_type < 4:
|
|
393
|
+
componentProperty = self.edbcomponent.GetComponentProperty()
|
|
394
|
+
model = componentProperty.GetModel().Clone()
|
|
395
|
+
pinpairs = model.PinPairs
|
|
396
|
+
if not list(pinpairs):
|
|
397
|
+
return "0"
|
|
398
|
+
for pinpair in pinpairs:
|
|
399
|
+
pair = model.GetPinPairRlc(pinpair)
|
|
400
|
+
return pair.R.ToString()
|
|
401
|
+
return None
|
|
402
|
+
|
|
403
|
+
@res_value.setter
|
|
404
|
+
def res_value(self, value): # pragma no cover
|
|
405
|
+
if value:
|
|
406
|
+
if self.rlc_values == [None, None, None]:
|
|
407
|
+
self.rlc_values = [value, 0, 0]
|
|
408
|
+
else:
|
|
409
|
+
self.rlc_values = [value, self.rlc_values[1], self.rlc_values[2]]
|
|
410
|
+
|
|
411
|
+
@property
|
|
412
|
+
def cap_value(self):
|
|
413
|
+
"""Capacitance Value.
|
|
414
|
+
|
|
415
|
+
Returns
|
|
416
|
+
-------
|
|
417
|
+
str
|
|
418
|
+
Capacitance Value. ``None`` if not an RLC Type.
|
|
419
|
+
"""
|
|
420
|
+
cmp_type = int(self.edbcomponent.GetComponentType())
|
|
421
|
+
if 0 < cmp_type < 4:
|
|
422
|
+
componentProperty = self.edbcomponent.GetComponentProperty()
|
|
423
|
+
model = componentProperty.GetModel().Clone()
|
|
424
|
+
pinpairs = model.PinPairs
|
|
425
|
+
if not list(pinpairs):
|
|
426
|
+
return "0"
|
|
427
|
+
for pinpair in pinpairs:
|
|
428
|
+
pair = model.GetPinPairRlc(pinpair)
|
|
429
|
+
return pair.C.ToString()
|
|
430
|
+
return None
|
|
431
|
+
|
|
432
|
+
@cap_value.setter
|
|
433
|
+
def cap_value(self, value): # pragma no cover
|
|
434
|
+
if value:
|
|
435
|
+
if self.rlc_values == [None, None, None]:
|
|
436
|
+
self.rlc_values = [0, 0, value]
|
|
437
|
+
else:
|
|
438
|
+
self.rlc_values = [self.rlc_values[1], self.rlc_values[2], value]
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def ind_value(self):
|
|
442
|
+
"""Inductance Value.
|
|
443
|
+
|
|
444
|
+
Returns
|
|
445
|
+
-------
|
|
446
|
+
str
|
|
447
|
+
Inductance Value. ``None`` if not an RLC Type.
|
|
448
|
+
"""
|
|
449
|
+
cmp_type = int(self.edbcomponent.GetComponentType())
|
|
450
|
+
if 0 < cmp_type < 4:
|
|
451
|
+
componentProperty = self.edbcomponent.GetComponentProperty()
|
|
452
|
+
model = componentProperty.GetModel().Clone()
|
|
453
|
+
pinpairs = model.PinPairs
|
|
454
|
+
if not list(pinpairs):
|
|
455
|
+
return "0"
|
|
456
|
+
for pinpair in pinpairs:
|
|
457
|
+
pair = model.GetPinPairRlc(pinpair)
|
|
458
|
+
return pair.L.ToString()
|
|
459
|
+
return None
|
|
460
|
+
|
|
461
|
+
@ind_value.setter
|
|
462
|
+
def ind_value(self, value): # pragma no cover
|
|
463
|
+
if value:
|
|
464
|
+
if self.rlc_values == [None, None, None]:
|
|
465
|
+
self.rlc_values = [0, value, 0]
|
|
466
|
+
else:
|
|
467
|
+
self.rlc_values = [self.rlc_values[1], value, self.rlc_values[2]]
|
|
468
|
+
|
|
469
|
+
@property
|
|
470
|
+
def is_parallel_rlc(self):
|
|
471
|
+
"""Define if model is Parallel or Series.
|
|
472
|
+
|
|
473
|
+
Returns
|
|
474
|
+
-------
|
|
475
|
+
bool
|
|
476
|
+
``True`` if it is a parallel rlc model. ``False`` for series RLC. ``None`` if not an RLC Type.
|
|
477
|
+
"""
|
|
478
|
+
cmp_type = int(self.edbcomponent.GetComponentType())
|
|
479
|
+
if 0 < cmp_type < 4:
|
|
480
|
+
model = self.component_property.GetModel().Clone()
|
|
481
|
+
pinpairs = model.PinPairs
|
|
482
|
+
for pinpair in pinpairs:
|
|
483
|
+
pair = model.GetPinPairRlc(pinpair)
|
|
484
|
+
return pair.IsParallel
|
|
485
|
+
return None
|
|
486
|
+
|
|
487
|
+
@is_parallel_rlc.setter
|
|
488
|
+
def is_parallel_rlc(self, value): # pragma no cover
|
|
489
|
+
if not len(self._pin_pairs):
|
|
490
|
+
logging.warning(self.refdes, " has no pin pair.")
|
|
491
|
+
else:
|
|
492
|
+
if isinstance(value, bool):
|
|
493
|
+
componentProperty = self.edbcomponent.GetComponentProperty()
|
|
494
|
+
model = componentProperty.GetModel().Clone()
|
|
495
|
+
pinpairs = model.PinPairs
|
|
496
|
+
if not list(pinpairs):
|
|
497
|
+
return "0"
|
|
498
|
+
for pin_pair in pinpairs:
|
|
499
|
+
pin_pair_rlc = model.GetPinPairRlc(pin_pair)
|
|
500
|
+
pin_pair_rlc.IsParallel = value
|
|
501
|
+
pin_pair_model = self._edb_model
|
|
502
|
+
pin_pair_model.SetPinPairRlc(pin_pair, pin_pair_rlc)
|
|
503
|
+
comp_prop = self.component_property
|
|
504
|
+
comp_prop.SetModel(pin_pair_model)
|
|
505
|
+
self.edbcomponent.SetComponentProperty(comp_prop)
|
|
506
|
+
|
|
507
|
+
@property
|
|
508
|
+
def center(self):
|
|
509
|
+
"""Compute the component center.
|
|
510
|
+
|
|
511
|
+
Returns
|
|
512
|
+
-------
|
|
513
|
+
list
|
|
514
|
+
"""
|
|
515
|
+
center = self.component_instance.GetCenter()
|
|
516
|
+
return [center.X.ToDouble(), center.Y.ToDouble()]
|
|
517
|
+
|
|
518
|
+
@property
|
|
519
|
+
def bounding_box(self):
|
|
520
|
+
"""Component's bounding box.
|
|
521
|
+
|
|
522
|
+
Returns
|
|
523
|
+
-------
|
|
524
|
+
List[float]
|
|
525
|
+
List of coordinates for the component's bounding box, with the list of
|
|
526
|
+
coordinates in this order: [X lower left corner, Y lower left corner,
|
|
527
|
+
X upper right corner, Y upper right corner].
|
|
528
|
+
"""
|
|
529
|
+
bbox = self.component_instance.GetBBox()
|
|
530
|
+
pt1 = bbox.Item1
|
|
531
|
+
pt2 = bbox.Item2
|
|
532
|
+
return [pt1.X.ToDouble(), pt1.Y.ToDouble(), pt2.X.ToDouble(), pt2.Y.ToDouble()]
|
|
533
|
+
|
|
534
|
+
@property
|
|
535
|
+
def rotation(self):
|
|
536
|
+
"""Compute the component rotation in radian.
|
|
537
|
+
|
|
538
|
+
Returns
|
|
539
|
+
-------
|
|
540
|
+
float
|
|
541
|
+
"""
|
|
542
|
+
return self.edbcomponent.GetTransform().Rotation.ToDouble()
|
|
543
|
+
|
|
544
|
+
@property
|
|
545
|
+
def pinlist(self):
|
|
546
|
+
"""Pins of the component.
|
|
547
|
+
|
|
548
|
+
Returns
|
|
549
|
+
-------
|
|
550
|
+
list
|
|
551
|
+
List of Pins of Component.
|
|
552
|
+
"""
|
|
553
|
+
pins = [
|
|
554
|
+
p
|
|
555
|
+
for p in self.edbcomponent.LayoutObjs
|
|
556
|
+
if p.GetObjType() == self._edb.cell.layout_object_type.PadstackInstance
|
|
557
|
+
and p.IsLayoutPin()
|
|
558
|
+
and p.GetComponent().GetName() == self.refdes
|
|
559
|
+
]
|
|
560
|
+
return pins
|
|
561
|
+
|
|
562
|
+
@property
|
|
563
|
+
def nets(self):
|
|
564
|
+
"""Nets of Component.
|
|
565
|
+
|
|
566
|
+
Returns
|
|
567
|
+
-------
|
|
568
|
+
list
|
|
569
|
+
List of Nets of Component.
|
|
570
|
+
"""
|
|
571
|
+
netlist = []
|
|
572
|
+
for pin in self.pinlist:
|
|
573
|
+
netlist.append(pin.GetNet().GetName())
|
|
574
|
+
return list(set(netlist))
|
|
575
|
+
|
|
576
|
+
@property
|
|
577
|
+
def pins(self):
|
|
578
|
+
"""EDBPadstackInstance of Component.
|
|
579
|
+
|
|
580
|
+
Returns
|
|
581
|
+
-------
|
|
582
|
+
dic[str, :class:`dotnet.edb_core.edb_data.definitions.EDBPadstackInstance`]
|
|
583
|
+
Dictionary of EDBPadstackInstance Components.
|
|
584
|
+
"""
|
|
585
|
+
pins = {}
|
|
586
|
+
for el in self.pinlist:
|
|
587
|
+
pins[el.GetName()] = EDBPadstackInstance(el, self._pedb)
|
|
588
|
+
return pins
|
|
589
|
+
|
|
590
|
+
@property
|
|
591
|
+
def type(self):
|
|
592
|
+
"""Component type.
|
|
593
|
+
|
|
594
|
+
Returns
|
|
595
|
+
-------
|
|
596
|
+
str
|
|
597
|
+
Component type.
|
|
598
|
+
"""
|
|
599
|
+
cmp_type = int(self.edbcomponent.GetComponentType())
|
|
600
|
+
if cmp_type == 1:
|
|
601
|
+
return "Resistor"
|
|
602
|
+
elif cmp_type == 2:
|
|
603
|
+
return "Inductor"
|
|
604
|
+
elif cmp_type == 3:
|
|
605
|
+
return "Capacitor"
|
|
606
|
+
elif cmp_type == 4:
|
|
607
|
+
return "IC"
|
|
608
|
+
elif cmp_type == 5:
|
|
609
|
+
return "IO"
|
|
610
|
+
elif cmp_type == 0:
|
|
611
|
+
return "Other"
|
|
612
|
+
|
|
613
|
+
@type.setter
|
|
614
|
+
def type(self, new_type):
|
|
615
|
+
"""Set component type
|
|
616
|
+
|
|
617
|
+
Parameters
|
|
618
|
+
----------
|
|
619
|
+
new_type : str
|
|
620
|
+
Type of the component. Options are ``"Resistor"``, ``"Inductor"``, ``"Capacitor"``,
|
|
621
|
+
``"IC"``, ``"IO"`` and ``"Other"``.
|
|
622
|
+
"""
|
|
623
|
+
if new_type == "Resistor":
|
|
624
|
+
type_id = self._pedb.definition.ComponentType.Resistor
|
|
625
|
+
elif new_type == "Inductor":
|
|
626
|
+
type_id = self._pedb.definition.ComponentType.Inductor
|
|
627
|
+
elif new_type == "Capacitor":
|
|
628
|
+
type_id = self._pedb.definition.ComponentType.Capacitor
|
|
629
|
+
elif new_type == "IC":
|
|
630
|
+
type_id = self._pedb.definition.ComponentType.IC
|
|
631
|
+
elif new_type == "IO":
|
|
632
|
+
type_id = self._pedb.definition.ComponentType.IO
|
|
633
|
+
elif new_type == "Other":
|
|
634
|
+
type_id = self._pedb.definition.ComponentType.Other
|
|
635
|
+
else:
|
|
636
|
+
return
|
|
637
|
+
self.edbcomponent.SetComponentType(type_id)
|
|
638
|
+
|
|
639
|
+
@property
|
|
640
|
+
def numpins(self):
|
|
641
|
+
"""Number of Pins of Component.
|
|
642
|
+
|
|
643
|
+
Returns
|
|
644
|
+
-------
|
|
645
|
+
int
|
|
646
|
+
Number of Pins of Component.
|
|
647
|
+
"""
|
|
648
|
+
return self.edbcomponent.GetNumberOfPins()
|
|
649
|
+
|
|
650
|
+
@property
|
|
651
|
+
def partname(self): # pragma: no cover
|
|
652
|
+
"""Component part name.
|
|
653
|
+
|
|
654
|
+
Returns
|
|
655
|
+
-------
|
|
656
|
+
str
|
|
657
|
+
Component Part Name.
|
|
658
|
+
"""
|
|
659
|
+
return self.part_name
|
|
660
|
+
|
|
661
|
+
@partname.setter
|
|
662
|
+
def partname(self, name): # pragma: no cover
|
|
663
|
+
"""Set component part name."""
|
|
664
|
+
self.part_name = name
|
|
665
|
+
|
|
666
|
+
@property
|
|
667
|
+
def part_name(self):
|
|
668
|
+
"""Component part name.
|
|
669
|
+
|
|
670
|
+
Returns
|
|
671
|
+
-------
|
|
672
|
+
str
|
|
673
|
+
Component part name.
|
|
674
|
+
"""
|
|
675
|
+
return self.edbcomponent.GetComponentDef().GetName()
|
|
676
|
+
|
|
677
|
+
@part_name.setter
|
|
678
|
+
def part_name(self, name): # pragma: no cover
|
|
679
|
+
"""Set component part name."""
|
|
680
|
+
self.edbcomponent.GetComponentDef().SetName(name)
|
|
681
|
+
|
|
682
|
+
@property
|
|
683
|
+
def _edb(self):
|
|
684
|
+
return self._pedb.edb_api
|
|
685
|
+
|
|
686
|
+
@property
|
|
687
|
+
def placement_layer(self):
|
|
688
|
+
"""Placement layer.
|
|
689
|
+
|
|
690
|
+
Returns
|
|
691
|
+
-------
|
|
692
|
+
str
|
|
693
|
+
Name of the placement layer.
|
|
694
|
+
"""
|
|
695
|
+
return self.edbcomponent.GetPlacementLayer().Clone().GetName()
|
|
696
|
+
|
|
697
|
+
@property
|
|
698
|
+
def is_top_mounted(self):
|
|
699
|
+
"""Check if a component is mounted on top or bottom of the layout.
|
|
700
|
+
Returns
|
|
701
|
+
-------
|
|
702
|
+
bool
|
|
703
|
+
``True`` component is mounted on top, ``False`` on down.
|
|
704
|
+
"""
|
|
705
|
+
signal_layers = [lay.name for lay in list(self._pedb.stackup.signal_layers.values())]
|
|
706
|
+
if self.placement_layer in signal_layers[: int(len(signal_layers) / 2)]:
|
|
707
|
+
return True
|
|
708
|
+
return False
|
|
709
|
+
|
|
710
|
+
@property
|
|
711
|
+
def lower_elevation(self):
|
|
712
|
+
"""Lower elevation of the placement layer.
|
|
713
|
+
|
|
714
|
+
Returns
|
|
715
|
+
-------
|
|
716
|
+
float
|
|
717
|
+
Lower elevation of the placement layer.
|
|
718
|
+
"""
|
|
719
|
+
return self.edbcomponent.GetPlacementLayer().Clone().GetLowerElevation()
|
|
720
|
+
|
|
721
|
+
@property
|
|
722
|
+
def upper_elevation(self):
|
|
723
|
+
"""Upper elevation of the placement layer.
|
|
724
|
+
|
|
725
|
+
Returns
|
|
726
|
+
-------
|
|
727
|
+
float
|
|
728
|
+
Upper elevation of the placement layer.
|
|
729
|
+
|
|
730
|
+
"""
|
|
731
|
+
return self.edbcomponent.GetPlacementLayer().Clone().GetUpperElevation()
|
|
732
|
+
|
|
733
|
+
@property
|
|
734
|
+
def top_bottom_association(self):
|
|
735
|
+
"""Top/bottom association of the placement layer.
|
|
736
|
+
|
|
737
|
+
Returns
|
|
738
|
+
-------
|
|
739
|
+
int
|
|
740
|
+
Top/bottom association of the placement layer, where:
|
|
741
|
+
|
|
742
|
+
* 0 - Top associated
|
|
743
|
+
* 1 - No association
|
|
744
|
+
* 2 - Bottom associated
|
|
745
|
+
* 4 - Number of top/bottom associations.
|
|
746
|
+
* -1 - Undefined
|
|
747
|
+
"""
|
|
748
|
+
return int(self.edbcomponent.GetPlacementLayer().GetTopBottomAssociation())
|
|
749
|
+
|
|
750
|
+
@pyedb_function_handler()
|
|
751
|
+
def _get_edb_value(self, value):
|
|
752
|
+
return self._pedb.edb_value(value)
|
|
753
|
+
|
|
754
|
+
@pyedb_function_handler()
|
|
755
|
+
def _set_model(self, model): # pragma: no cover
|
|
756
|
+
comp_prop = self.component_property
|
|
757
|
+
comp_prop.SetModel(model)
|
|
758
|
+
if not self.edbcomponent.SetComponentProperty(comp_prop):
|
|
759
|
+
logging.error("Fail to assign model on {}.".format(self.refdes))
|
|
760
|
+
return False
|
|
761
|
+
return True
|
|
762
|
+
|
|
763
|
+
@pyedb_function_handler()
|
|
764
|
+
def assign_spice_model(self, file_path, name=None):
|
|
765
|
+
"""Assign Spice model to this component.
|
|
766
|
+
|
|
767
|
+
Parameters
|
|
768
|
+
----------
|
|
769
|
+
file_path : str
|
|
770
|
+
File path of the Spice model.
|
|
771
|
+
name : str, optional
|
|
772
|
+
Name of the Spice model.
|
|
773
|
+
|
|
774
|
+
Returns
|
|
775
|
+
-------
|
|
776
|
+
|
|
777
|
+
"""
|
|
778
|
+
if not name:
|
|
779
|
+
name = get_filename_without_extension(file_path)
|
|
780
|
+
|
|
781
|
+
with open(file_path, "r") as f:
|
|
782
|
+
for line in f:
|
|
783
|
+
if "subckt" in line.lower():
|
|
784
|
+
pinNames = [i.strip() for i in re.split(" |\t", line) if i]
|
|
785
|
+
pinNames.remove(pinNames[0])
|
|
786
|
+
pinNames.remove(pinNames[0])
|
|
787
|
+
break
|
|
788
|
+
if len(pinNames) == self.numpins:
|
|
789
|
+
model = self._edb.cell.hierarchy._hierarchy.SPICEModel()
|
|
790
|
+
model.SetModelPath(file_path)
|
|
791
|
+
model.SetModelName(name)
|
|
792
|
+
terminal = 1
|
|
793
|
+
for pn in pinNames:
|
|
794
|
+
model.AddTerminalPinPair(pn, str(terminal))
|
|
795
|
+
terminal += 1
|
|
796
|
+
else: # pragma: no cover
|
|
797
|
+
logging.error("Wrong number of Pins")
|
|
798
|
+
return False
|
|
799
|
+
return self._set_model(model)
|
|
800
|
+
|
|
801
|
+
@pyedb_function_handler()
|
|
802
|
+
def assign_s_param_model(self, file_path, name=None, reference_net=None):
|
|
803
|
+
"""Assign S-parameter to this component.
|
|
804
|
+
|
|
805
|
+
Parameters
|
|
806
|
+
----------
|
|
807
|
+
file_path : str
|
|
808
|
+
File path of the S-parameter model.
|
|
809
|
+
name : str, optional
|
|
810
|
+
Name of the S-parameter model.
|
|
811
|
+
|
|
812
|
+
Returns
|
|
813
|
+
-------
|
|
814
|
+
|
|
815
|
+
"""
|
|
816
|
+
if not name:
|
|
817
|
+
name = get_filename_without_extension(file_path)
|
|
818
|
+
|
|
819
|
+
edbComponentDef = self.edbcomponent.GetComponentDef()
|
|
820
|
+
nPortModel = self._edb.definition.NPortComponentModel.FindByName(edbComponentDef, name)
|
|
821
|
+
if nPortModel.IsNull():
|
|
822
|
+
nPortModel = self._edb.definition.NPortComponentModel.Create(name)
|
|
823
|
+
nPortModel.SetReferenceFile(file_path)
|
|
824
|
+
edbComponentDef.AddComponentModel(nPortModel)
|
|
825
|
+
|
|
826
|
+
model = self._edb.cell.hierarchy._hierarchy.SParameterModel()
|
|
827
|
+
model.SetComponentModelName(name)
|
|
828
|
+
if reference_net:
|
|
829
|
+
model.SetReferenceNet(reference_net)
|
|
830
|
+
return self._set_model(model)
|
|
831
|
+
|
|
832
|
+
@pyedb_function_handler()
|
|
833
|
+
def use_s_parameter_model(self, name, reference_net=None):
|
|
834
|
+
"""Use S-parameter model on the component.
|
|
835
|
+
|
|
836
|
+
Parameters
|
|
837
|
+
----------
|
|
838
|
+
name: str
|
|
839
|
+
Name of the S-parameter model.
|
|
840
|
+
reference_net: str, optional
|
|
841
|
+
Reference net of the model.
|
|
842
|
+
|
|
843
|
+
Returns
|
|
844
|
+
-------
|
|
845
|
+
bool
|
|
846
|
+
``True`` when successful, ``False`` when failed.
|
|
847
|
+
|
|
848
|
+
Examples
|
|
849
|
+
--------
|
|
850
|
+
>>> edbapp = Edb()
|
|
851
|
+
>>>comp_def = edbapp.definitions.components["CAPC3216X180X55ML20T25"]
|
|
852
|
+
>>>comp_def.add_n_port_model("c:GRM32_DC0V_25degC_series.s2p", "GRM32_DC0V_25degC_series")
|
|
853
|
+
>>>edbapp.components["C200"].use_s_parameter_model("GRM32_DC0V_25degC_series")
|
|
854
|
+
"""
|
|
855
|
+
model = self._edb.cell.hierarchy._hierarchy.SParameterModel()
|
|
856
|
+
model.SetComponentModelName(name)
|
|
857
|
+
if reference_net:
|
|
858
|
+
model.SetReferenceNet(reference_net)
|
|
859
|
+
return self._set_model(model)
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
@pyedb_function_handler()
|
|
863
|
+
def assign_rlc_model(self, res=None, ind=None, cap=None, is_parallel=False):
|
|
864
|
+
"""Assign RLC to this component.
|
|
865
|
+
|
|
866
|
+
Parameters
|
|
867
|
+
----------
|
|
868
|
+
res : int, float
|
|
869
|
+
Resistance. Default is ``None``.
|
|
870
|
+
ind : int, float
|
|
871
|
+
Inductance. Default is ``None``.
|
|
872
|
+
cap : int, float
|
|
873
|
+
Capacitance. Default is ``None``.
|
|
874
|
+
is_parallel : bool, optional
|
|
875
|
+
Whether it is a parallel or series RLC component. The default is ``False``.
|
|
876
|
+
"""
|
|
877
|
+
if res is None and ind is None and cap is None:
|
|
878
|
+
self._pedb.logger.error("At least one value has to be provided.")
|
|
879
|
+
return False
|
|
880
|
+
r_enabled = True if res else False
|
|
881
|
+
l_enabled = True if ind else False
|
|
882
|
+
c_enabled = True if cap else False
|
|
883
|
+
res = 0 if res is None else res
|
|
884
|
+
ind = 0 if ind is None else ind
|
|
885
|
+
cap = 0 if cap is None else cap
|
|
886
|
+
res, ind, cap = self._get_edb_value(res), self._get_edb_value(ind), self._get_edb_value(cap)
|
|
887
|
+
model = self._edb.cell.hierarchy._hierarchy.PinPairModel()
|
|
888
|
+
|
|
889
|
+
pin_names = list(self.pins.keys())
|
|
890
|
+
for idx, i in enumerate(np.arange(len(pin_names) // 2)):
|
|
891
|
+
pin_pair = self._edb.utility.utility.PinPair(pin_names[idx], pin_names[idx + 1])
|
|
892
|
+
|
|
893
|
+
rlc = self._edb.utility.utility.Rlc(res, r_enabled, ind, l_enabled, cap, c_enabled, is_parallel)
|
|
894
|
+
model.SetPinPairRlc(pin_pair, rlc)
|
|
895
|
+
return self._set_model(model)
|
|
896
|
+
|
|
897
|
+
@pyedb_function_handler()
|
|
898
|
+
def create_clearance_on_component(self, extra_soldermask_clearance=1e-4):
|
|
899
|
+
"""Create a Clearance on Soldermask layer by drawing a rectangle.
|
|
900
|
+
|
|
901
|
+
Parameters
|
|
902
|
+
----------
|
|
903
|
+
extra_soldermask_clearance : float, optional
|
|
904
|
+
Extra Soldermask value in meter to be applied on component bounding box.
|
|
905
|
+
|
|
906
|
+
Returns
|
|
907
|
+
-------
|
|
908
|
+
bool
|
|
909
|
+
"""
|
|
910
|
+
bounding_box = self.bounding_box
|
|
911
|
+
opening = [bounding_box[0] - extra_soldermask_clearance]
|
|
912
|
+
opening.append(bounding_box[1] - extra_soldermask_clearance)
|
|
913
|
+
opening.append(bounding_box[2] + extra_soldermask_clearance)
|
|
914
|
+
opening.append(bounding_box[3] + extra_soldermask_clearance)
|
|
915
|
+
|
|
916
|
+
comp_layer = self.placement_layer
|
|
917
|
+
layer_names = list(self._pedb.stackup.stackup_layers.keys())
|
|
918
|
+
layer_index = layer_names.index(comp_layer)
|
|
919
|
+
if comp_layer in [layer_names[0] + layer_names[-1]]:
|
|
920
|
+
return False
|
|
921
|
+
elif layer_index < len(layer_names) / 2:
|
|
922
|
+
soldermask_layer = layer_names[layer_index - 1]
|
|
923
|
+
else:
|
|
924
|
+
soldermask_layer = layer_names[layer_index + 1]
|
|
925
|
+
|
|
926
|
+
if not self._pedb.modeler.get_primitives(layer_name=soldermask_layer):
|
|
927
|
+
all_nets = list(self._pedb.nets.nets.values())
|
|
928
|
+
poly = self._pedb._create_conformal(all_nets, 0, 1e-12, False, 0)
|
|
929
|
+
self._pedb.modeler.create_polygon(poly, soldermask_layer, [], "")
|
|
930
|
+
|
|
931
|
+
void = self._pedb.modeler.create_rectangle(
|
|
932
|
+
soldermask_layer,
|
|
933
|
+
"{}_opening".format(self.refdes),
|
|
934
|
+
lower_left_point=opening[:2],
|
|
935
|
+
upper_right_point=opening[2:],
|
|
936
|
+
)
|
|
937
|
+
void.is_negative = True
|
|
938
|
+
return True
|