pyedb 0.43.0__py3-none-any.whl → 0.44.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_boundaries.py +20 -14
- pyedb/configuration/cfg_components.py +1 -1
- pyedb/configuration/cfg_general.py +6 -4
- pyedb/configuration/cfg_modeler.py +1 -0
- pyedb/configuration/cfg_package_definition.py +41 -1
- pyedb/configuration/cfg_padstacks.py +611 -256
- pyedb/configuration/cfg_ports_sources.py +75 -15
- pyedb/configuration/cfg_s_parameter_models.py +30 -0
- pyedb/configuration/cfg_setup.py +94 -21
- pyedb/configuration/cfg_stackup.py +44 -0
- pyedb/dotnet/database/edb_data/design_options.py +19 -1
- pyedb/dotnet/database/edb_data/padstacks_data.py +9 -4
- pyedb/dotnet/database/geometry/polygon_data.py +4 -2
- pyedb/dotnet/database/padstack.py +6 -2
- pyedb/dotnet/database/utilities/simulation_setup.py +7 -17
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +30 -0
- pyedb/grpc/database/components.py +1 -1
- pyedb/grpc/database/definition/component_def.py +15 -0
- pyedb/grpc/database/definition/component_pin.py +1 -1
- pyedb/grpc/database/definition/materials.py +27 -0
- pyedb/grpc/database/definition/package_def.py +20 -2
- pyedb/grpc/database/definition/padstack_def.py +5 -2
- pyedb/grpc/database/hierarchy/component.py +4 -2
- pyedb/grpc/database/hierarchy/pingroup.py +12 -8
- pyedb/grpc/database/layers/layer.py +28 -0
- pyedb/grpc/database/layers/stackup_layer.py +281 -40
- pyedb/grpc/database/layout/layout.py +12 -6
- pyedb/grpc/database/modeler.py +8 -8
- pyedb/grpc/database/primitive/bondwire.py +3 -3
- pyedb/grpc/database/primitive/circle.py +1 -1
- pyedb/grpc/database/primitive/padstack_instance.py +13 -3
- pyedb/grpc/database/primitive/path.py +2 -2
- pyedb/grpc/database/primitive/polygon.py +3 -3
- pyedb/grpc/database/primitive/primitive.py +1 -1
- pyedb/grpc/database/primitive/rectangle.py +2 -2
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +73 -30
- pyedb/grpc/database/source_excitations.py +7 -7
- pyedb/grpc/database/stackup.py +14 -6
- pyedb/grpc/database/terminal/bundle_terminal.py +3 -3
- pyedb/grpc/database/terminal/edge_terminal.py +2 -2
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +42 -2
- pyedb/grpc/database/terminal/pingroup_terminal.py +35 -2
- pyedb/grpc/database/terminal/point_terminal.py +10 -1
- pyedb/grpc/database/terminal/terminal.py +4 -4
- pyedb/grpc/database/utility/hfss_extent_info.py +14 -10
- pyedb/grpc/edb.py +8 -8
- pyedb/misc/misc.py +13 -0
- {pyedb-0.43.0.dist-info → pyedb-0.44.0.dist-info}/METADATA +1 -1
- {pyedb-0.43.0.dist-info → pyedb-0.44.0.dist-info}/RECORD +52 -52
- {pyedb-0.43.0.dist-info → pyedb-0.44.0.dist-info}/LICENSE +0 -0
- {pyedb-0.43.0.dist-info → pyedb-0.44.0.dist-info}/WHEEL +0 -0
|
@@ -33,9 +33,33 @@ from pyedb.dotnet.database.geometry.point_data import PointData
|
|
|
33
33
|
class CfgTerminalInfo(CfgBase):
|
|
34
34
|
CFG_TERMINAL_TYPES = ["pin", "net", "pin_group", "nearest_pin", "coordinates"]
|
|
35
35
|
|
|
36
|
+
class Grpc:
|
|
37
|
+
def __init__(self, parent):
|
|
38
|
+
self.parent = parent
|
|
39
|
+
self._pedb = parent._pedb
|
|
40
|
+
|
|
41
|
+
def update_contact_radius(self, radius):
|
|
42
|
+
from ansys.edb.core.utility.value import Value as GrpcValue
|
|
43
|
+
|
|
44
|
+
self.parent.contact_radius = GrpcValue(radius).value
|
|
45
|
+
|
|
46
|
+
class DotNet(Grpc):
|
|
47
|
+
def __init__(self, parent):
|
|
48
|
+
super().__init__(parent)
|
|
49
|
+
|
|
50
|
+
def update_contact_radius(self, radius):
|
|
51
|
+
self.parent.contact_radius = self._pedb.edb_value(radius).ToDouble()
|
|
52
|
+
|
|
36
53
|
def __init__(self, pedb, **kwargs):
|
|
37
54
|
self._pedb = pedb
|
|
38
|
-
if
|
|
55
|
+
if self._pedb.grpc:
|
|
56
|
+
self.api = self.Grpc(self)
|
|
57
|
+
else:
|
|
58
|
+
self.api = self.DotNet(self)
|
|
59
|
+
|
|
60
|
+
if kwargs.get("padstack"):
|
|
61
|
+
self.type = "padstack"
|
|
62
|
+
elif "pin" in kwargs:
|
|
39
63
|
self.type = "pin"
|
|
40
64
|
elif "net" in kwargs:
|
|
41
65
|
self.type = "net"
|
|
@@ -52,7 +76,7 @@ class CfgTerminalInfo(CfgBase):
|
|
|
52
76
|
|
|
53
77
|
self.contact_type = kwargs.get("contact_type", "default") # options are full, center, quad, inline
|
|
54
78
|
contact_radius = "0.1mm" if kwargs.get("contact_radius") is None else kwargs.get("contact_radius")
|
|
55
|
-
self.
|
|
79
|
+
self.api.update_contact_radius(contact_radius)
|
|
56
80
|
self.num_of_contact = kwargs.get("num_of_contact", 4)
|
|
57
81
|
self.contact_expansion = kwargs.get("contact_expansion", 1)
|
|
58
82
|
|
|
@@ -60,7 +84,7 @@ class CfgTerminalInfo(CfgBase):
|
|
|
60
84
|
return {self.type: self.value}
|
|
61
85
|
|
|
62
86
|
|
|
63
|
-
class
|
|
87
|
+
class CfgCoordinateTerminalInfo(CfgTerminalInfo):
|
|
64
88
|
def __init__(self, pedb, **kwargs):
|
|
65
89
|
super().__init__(pedb, **kwargs)
|
|
66
90
|
|
|
@@ -108,14 +132,14 @@ class CfgSources:
|
|
|
108
132
|
pos_term_info = {"pin_group": pg.name}
|
|
109
133
|
elif src.terminal_type == "PadstackInstanceTerminal":
|
|
110
134
|
refdes = src.component.refdes if src.component else ""
|
|
111
|
-
pos_term_info = {"
|
|
135
|
+
pos_term_info = {"padstack": src.padstack_instance.aedt_name}
|
|
112
136
|
|
|
113
137
|
neg_term = self._pedb.terminals[src.ref_terminal.name]
|
|
114
138
|
if neg_term.terminal_type == "PinGroupTerminal":
|
|
115
139
|
pg = self._pedb.siwave.pin_groups[neg_term._edb_object.GetPinGroup().GetName()]
|
|
116
140
|
neg_term_info = {"pin_group": pg.name}
|
|
117
141
|
elif neg_term.terminal_type == "PadstackInstanceTerminal":
|
|
118
|
-
neg_term_info = {"
|
|
142
|
+
neg_term_info = {"padstack": neg_term.padstack_instance.aedt_name}
|
|
119
143
|
|
|
120
144
|
cfg_src = CfgSource(
|
|
121
145
|
self._pedb,
|
|
@@ -137,9 +161,30 @@ class CfgSources:
|
|
|
137
161
|
|
|
138
162
|
|
|
139
163
|
class CfgPorts:
|
|
164
|
+
class Grpc:
|
|
165
|
+
def __init__(self, parent):
|
|
166
|
+
self.parent = parent
|
|
167
|
+
self._pedb = parent._pedb
|
|
168
|
+
|
|
169
|
+
def get_pin_group(self, port):
|
|
170
|
+
return self._pedb.siwave.pin_groups[port._edb_object.pin_group.name]
|
|
171
|
+
|
|
172
|
+
def get_edge_info(self, port):
|
|
173
|
+
return port._edb_object.GetEdges()[0].GetParameters()
|
|
174
|
+
|
|
175
|
+
class DotNet(Grpc):
|
|
176
|
+
def __init__(self, parent):
|
|
177
|
+
super().__init__(parent)
|
|
178
|
+
|
|
179
|
+
def get_pin_group(self, port):
|
|
180
|
+
return self._pedb.siwave.pin_groups[port._edb_object.GetPinGroup().GetName()]
|
|
181
|
+
|
|
140
182
|
def __init__(self, pedb, ports_data):
|
|
141
183
|
self._pedb = pedb
|
|
142
|
-
|
|
184
|
+
if self._pedb.grpc:
|
|
185
|
+
self.api = self.Grpc(self)
|
|
186
|
+
else:
|
|
187
|
+
self.api = self.DotNet(self)
|
|
143
188
|
self.ports = []
|
|
144
189
|
for p in ports_data:
|
|
145
190
|
if p["type"] == "wave_port":
|
|
@@ -156,6 +201,9 @@ class CfgPorts:
|
|
|
156
201
|
for i in self._pedb.layout.primitives:
|
|
157
202
|
if i.aedt_name:
|
|
158
203
|
edb_primitives[i.aedt_name] = i
|
|
204
|
+
for i in self._pedb.layout.padstack_instances:
|
|
205
|
+
if i.aedt_name:
|
|
206
|
+
edb_primitives[i.aedt_name] = i
|
|
159
207
|
for p in self.ports:
|
|
160
208
|
if p.type in ["wave_port", "diff_wave_port"]:
|
|
161
209
|
p.set_parameters_to_edb(edb_primitives)
|
|
@@ -171,6 +219,8 @@ class CfgPorts:
|
|
|
171
219
|
if not p.ref_terminal:
|
|
172
220
|
if p.terminal_type == "PadstackInstanceTerminal":
|
|
173
221
|
port_type = "coax"
|
|
222
|
+
elif p.terminal_type == "PinGroupTerminal":
|
|
223
|
+
port_type = "circuit"
|
|
174
224
|
elif p.hfss_type == "Wave":
|
|
175
225
|
port_type = "wave_port"
|
|
176
226
|
else:
|
|
@@ -180,11 +230,11 @@ class CfgPorts:
|
|
|
180
230
|
|
|
181
231
|
if p.terminal_type == "PinGroupTerminal":
|
|
182
232
|
refdes = ""
|
|
183
|
-
pg = self.
|
|
233
|
+
pg = self.api.get_pin_group(p)
|
|
184
234
|
pos_term_info = {"pin_group": pg.name}
|
|
185
235
|
elif p.terminal_type == "PadstackInstanceTerminal":
|
|
186
236
|
refdes = p.component.refdes if p.component else ""
|
|
187
|
-
pos_term_info = {"
|
|
237
|
+
pos_term_info = {"padstack": p.padstack_instance.aedt_name}
|
|
188
238
|
elif p.terminal_type == "PointTerminal":
|
|
189
239
|
refdes = ""
|
|
190
240
|
pos_term_info = {"coordinates": {"layer": p.layer.name, "point": p.location, "net": p.net.name}}
|
|
@@ -192,10 +242,11 @@ class CfgPorts:
|
|
|
192
242
|
if port_type == "circuit":
|
|
193
243
|
neg_term = self._pedb.terminals[p.ref_terminal.name]
|
|
194
244
|
if neg_term.terminal_type == "PinGroupTerminal":
|
|
195
|
-
pg = self.
|
|
245
|
+
pg = self.api.get_pin_group(neg_term)
|
|
246
|
+
# pg = self._pedb.siwave.pin_groups[neg_term._edb_object.GetPinGroup().GetName()]
|
|
196
247
|
neg_term_info = {"pin_group": pg.name}
|
|
197
248
|
elif neg_term.terminal_type == "PadstackInstanceTerminal":
|
|
198
|
-
neg_term_info = {"
|
|
249
|
+
neg_term_info = {"padstack": neg_term.padstack_instance.aedt_name}
|
|
199
250
|
elif neg_term.terminal_type == "PointTerminal":
|
|
200
251
|
neg_term_info = {
|
|
201
252
|
"coordinates": {
|
|
@@ -269,7 +320,7 @@ class CfgCircuitElement(CfgBase):
|
|
|
269
320
|
|
|
270
321
|
pos = kwargs["positive_terminal"] # {"pin" : "A1"}
|
|
271
322
|
if list(pos.keys())[0] == "coordinates":
|
|
272
|
-
self.positive_terminal_info =
|
|
323
|
+
self.positive_terminal_info = CfgCoordinateTerminalInfo(self._pedb, **pos)
|
|
273
324
|
else:
|
|
274
325
|
self.positive_terminal_info = CfgTerminalInfo(self._pedb, **pos)
|
|
275
326
|
if not self.positive_terminal_info.reference_designator:
|
|
@@ -279,7 +330,7 @@ class CfgCircuitElement(CfgBase):
|
|
|
279
330
|
if len(neg) == 0:
|
|
280
331
|
self.negative_terminal_info = None
|
|
281
332
|
elif list(neg.keys())[0] == "coordinates":
|
|
282
|
-
self.negative_terminal_info =
|
|
333
|
+
self.negative_terminal_info = CfgCoordinateTerminalInfo(self._pedb, **neg)
|
|
283
334
|
elif list(neg.keys())[0] == "nearest_pin":
|
|
284
335
|
self.negative_terminal_info = CfgNearestPinTerminalInfo(self._pedb, **neg)
|
|
285
336
|
else:
|
|
@@ -306,6 +357,11 @@ class CfgCircuitElement(CfgBase):
|
|
|
306
357
|
self._pedb.nets.find_or_create_net(net_name)
|
|
307
358
|
pos_coor_terminal[self.name] = self._pedb.get_point_terminal(self.name, net_name, point, layer)
|
|
308
359
|
|
|
360
|
+
elif pos_type == "padstack":
|
|
361
|
+
for pds in self._pedb.layout.padstack_instances:
|
|
362
|
+
if pds.aedt_name == pos_value:
|
|
363
|
+
pos_objs.update({pos_value: pds})
|
|
364
|
+
break
|
|
309
365
|
elif pos_type == "pin":
|
|
310
366
|
pins = {
|
|
311
367
|
pos_value: self._pedb.components.instances[self.positive_terminal_info.reference_designator].pins[
|
|
@@ -403,6 +459,11 @@ class CfgCircuitElement(CfgBase):
|
|
|
403
459
|
) # terminal type pin or net
|
|
404
460
|
# create pin group
|
|
405
461
|
neg_obj = self._create_pin_group(pins, self.negative_terminal_info.reference_designator, True)
|
|
462
|
+
elif neg_type == "padstack":
|
|
463
|
+
for pds in self._pedb.layout.padstack_instances:
|
|
464
|
+
if pds.aedt_name == neg_value:
|
|
465
|
+
neg_obj = {neg_value: pds}
|
|
466
|
+
break
|
|
406
467
|
elif neg_type == "pin":
|
|
407
468
|
terminal_name = f"{self.negative_terminal_info.reference_designator}_{neg_value}"
|
|
408
469
|
neg_obj = {
|
|
@@ -412,9 +473,8 @@ class CfgCircuitElement(CfgBase):
|
|
|
412
473
|
}
|
|
413
474
|
else:
|
|
414
475
|
raise Exception(f"Wrong negative terminal type {neg_type}.")
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
][0]
|
|
476
|
+
neg_term = [j.create_terminal(i) if not j.terminal else j.terminal for i, j in neg_obj.items()][0]
|
|
477
|
+
self.neg_terminal = neg_term
|
|
418
478
|
|
|
419
479
|
def _get_pins(self, terminal_type, terminal_value, reference_designator):
|
|
420
480
|
terminal_value = terminal_value if isinstance(terminal_value, list) else [terminal_value]
|
|
@@ -125,6 +125,36 @@ class CfgSParameters:
|
|
|
125
125
|
def __init__(self, parent):
|
|
126
126
|
super().__init__(parent)
|
|
127
127
|
|
|
128
|
+
def apply(self):
|
|
129
|
+
for s_param in self.parent.s_parameters_models:
|
|
130
|
+
fpath = s_param.file_path
|
|
131
|
+
if not Path(fpath).anchor:
|
|
132
|
+
fpath = str(Path(self.parent.path_libraries) / fpath)
|
|
133
|
+
comp_def = self._pedb.definitions.component[s_param.component_definition]
|
|
134
|
+
if s_param.pin_order:
|
|
135
|
+
comp_def.set_properties(pin_order=s_param.pin_order)
|
|
136
|
+
comp_def.add_n_port_model(fpath, s_param.name)
|
|
137
|
+
comp_list = dict()
|
|
138
|
+
if s_param.apply_to_all:
|
|
139
|
+
comp_list.update(
|
|
140
|
+
{
|
|
141
|
+
refdes: comp
|
|
142
|
+
for refdes, comp in comp_def.components.items()
|
|
143
|
+
if refdes not in s_param.components
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
comp_list.update(
|
|
148
|
+
{refdes: comp for refdes, comp in comp_def.components.items() if refdes in s_param.components}
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
for refdes, comp in comp_list.items():
|
|
152
|
+
if refdes in s_param.reference_net_per_component:
|
|
153
|
+
ref_net = s_param.reference_net_per_component[refdes]
|
|
154
|
+
else:
|
|
155
|
+
ref_net = s_param.reference_net
|
|
156
|
+
comp.use_s_parameter_model(s_param.name, reference_net=ref_net)
|
|
157
|
+
|
|
128
158
|
def __init__(self, pedb, data, path_lib=None):
|
|
129
159
|
self._pedb = pedb
|
|
130
160
|
if self._pedb.grpc:
|
pyedb/configuration/cfg_setup.py
CHANGED
|
@@ -148,9 +148,8 @@ class CfgSIwaveDCSetup(CfgSetup):
|
|
|
148
148
|
edb_setup = self.pedb.create_siwave_dc_setup(
|
|
149
149
|
name=self.parent.name, dc_slider_position=self.parent.dc_slider_position
|
|
150
150
|
)
|
|
151
|
-
edb_setup.
|
|
152
|
-
|
|
153
|
-
edb_setup.dc_ir_settings.export_dc_thermal_data = dc_ir_settings["export_dc_thermal_data"]
|
|
151
|
+
edb_setup.settings.dc.dc_slider_pos = self.parent.dc_slider_position
|
|
152
|
+
edb_setup.settings.export_dc_thermal_data = self.parent.dc_ir_settings["export_dc_thermal_data"]
|
|
154
153
|
|
|
155
154
|
def retrieve_parameters_from_edb(self):
|
|
156
155
|
self._retrieve_parameters_from_edb_common()
|
|
@@ -163,6 +162,14 @@ class CfgSIwaveDCSetup(CfgSetup):
|
|
|
163
162
|
def __init__(self, parent):
|
|
164
163
|
super().__init__(parent)
|
|
165
164
|
|
|
165
|
+
def set_parameters_to_edb(self):
|
|
166
|
+
edb_setup = self.pedb.create_siwave_dc_setup(
|
|
167
|
+
name=self.parent.name, dc_slider_position=self.parent.dc_slider_position
|
|
168
|
+
)
|
|
169
|
+
edb_setup.dc_settings.dc_slider_position = self.parent.dc_slider_position
|
|
170
|
+
dc_ir_settings = self.parent.dc_ir_settings
|
|
171
|
+
edb_setup.dc_ir_settings.export_dc_thermal_data = dc_ir_settings["export_dc_thermal_data"]
|
|
172
|
+
|
|
166
173
|
def __init__(self, pedb, pyedb_obj, **kwargs):
|
|
167
174
|
super().__init__(pedb, pyedb_obj, **kwargs)
|
|
168
175
|
self.type = "siwave_dc"
|
|
@@ -202,6 +209,42 @@ class CfgHFSSSetup(CfgSetup):
|
|
|
202
209
|
net_layer_list=i.get("nets_layers_list", {}),
|
|
203
210
|
)
|
|
204
211
|
|
|
212
|
+
def retrieve_parameters_from_edb(self):
|
|
213
|
+
self._retrieve_parameters_from_edb_common()
|
|
214
|
+
single_frequency_adaptive_solution = self.pyedb_obj.settings.general.single_frequency_adaptive_solution
|
|
215
|
+
self.parent.f_adapt = single_frequency_adaptive_solution.adaptive_frequency
|
|
216
|
+
self.parent.max_num_passes = single_frequency_adaptive_solution.max_passes
|
|
217
|
+
self.parent.max_mag_delta_s = float(single_frequency_adaptive_solution.max_delta)
|
|
218
|
+
self.parent.freq_sweep = []
|
|
219
|
+
for sw in self.pyedb_obj.sweep_data:
|
|
220
|
+
self.parent.freq_sweep.append({"name": sw.name, "type": sw.type, "frequencies": sw.frequency_string})
|
|
221
|
+
|
|
222
|
+
self.parent.mesh_operations = []
|
|
223
|
+
from ansys.edb.core.simulation_setup.mesh_operation import (
|
|
224
|
+
LengthMeshOperation as GrpcLengthMeshOperation,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
for mesh_op in self.pyedb_obj.mesh_operations:
|
|
228
|
+
if isinstance(mesh_op, GrpcLengthMeshOperation):
|
|
229
|
+
mop_type = "length"
|
|
230
|
+
else:
|
|
231
|
+
mop_type = "skin"
|
|
232
|
+
self.parent.mesh_operations.append(
|
|
233
|
+
{
|
|
234
|
+
"name": mesh_op.name,
|
|
235
|
+
"type": mop_type,
|
|
236
|
+
"max_elements": mesh_op.max_elements,
|
|
237
|
+
"max_length": mesh_op.max_length,
|
|
238
|
+
"restrict_length": mesh_op.restrict_max_length,
|
|
239
|
+
"refine_inside": mesh_op.refine_inside,
|
|
240
|
+
"nets_layers_list": mesh_op.net_layer_info,
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
class DotNet(Grpc):
|
|
245
|
+
def __init__(self, parent):
|
|
246
|
+
super().__init__(parent)
|
|
247
|
+
|
|
205
248
|
def retrieve_parameters_from_edb(self):
|
|
206
249
|
self._retrieve_parameters_from_edb_common()
|
|
207
250
|
adaptive_frequency_data_list = list(self.pyedb_obj.adaptive_settings.adaptive_frequency_data_list)[0]
|
|
@@ -226,10 +269,6 @@ class CfgHFSSSetup(CfgSetup):
|
|
|
226
269
|
}
|
|
227
270
|
)
|
|
228
271
|
|
|
229
|
-
class DotNet(Grpc):
|
|
230
|
-
def __init__(self, parent):
|
|
231
|
-
super().__init__(parent)
|
|
232
|
-
|
|
233
272
|
def __init__(self, pedb, pyedb_obj, **kwargs):
|
|
234
273
|
super().__init__(pedb, pyedb_obj, **kwargs)
|
|
235
274
|
self.type = "hfss"
|
|
@@ -254,9 +293,56 @@ class CfgHFSSSetup(CfgSetup):
|
|
|
254
293
|
|
|
255
294
|
|
|
256
295
|
class CfgSetups:
|
|
296
|
+
class Grpc:
|
|
297
|
+
def __init__(self, parent):
|
|
298
|
+
self.parent = parent
|
|
299
|
+
self._pedb = parent.pedb
|
|
300
|
+
|
|
301
|
+
def retrieve_parameters_from_edb(self):
|
|
302
|
+
self.parent.setups = []
|
|
303
|
+
for _, setup in self._pedb.setups.items():
|
|
304
|
+
if setup.type.name.lower() == "hfss":
|
|
305
|
+
hfss = CfgHFSSSetup(self._pedb, setup)
|
|
306
|
+
hfss.api.retrieve_parameters_from_edb()
|
|
307
|
+
self.parent.setups.append(hfss)
|
|
308
|
+
elif setup.type.name.lower() == "si_wave_dcir":
|
|
309
|
+
siwave_dc = CfgSIwaveDCSetup(self._pedb, setup)
|
|
310
|
+
siwave_dc.api.retrieve_parameters_from_edb()
|
|
311
|
+
self.parent.setups.append(siwave_dc)
|
|
312
|
+
elif setup.type.name.lower() == "si_wave":
|
|
313
|
+
siwave_ac = CfgSIwaveACSetup(self._pedb, setup)
|
|
314
|
+
siwave_ac.api.retrieve_parameters_from_edb()
|
|
315
|
+
self.parent.setups.append(siwave_ac)
|
|
316
|
+
elif setup.type.name.lower() == "raptor_x":
|
|
317
|
+
pass
|
|
318
|
+
|
|
319
|
+
class DotNet(Grpc):
|
|
320
|
+
def __init__(self, parent):
|
|
321
|
+
super().__init__(parent)
|
|
322
|
+
|
|
323
|
+
def retrieve_parameters_from_edb(self):
|
|
324
|
+
self.parent.setups = []
|
|
325
|
+
for _, setup in self._pedb.setups.items():
|
|
326
|
+
if setup.type == "hfss":
|
|
327
|
+
hfss = CfgHFSSSetup(self._pedb, setup)
|
|
328
|
+
hfss.api.retrieve_parameters_from_edb()
|
|
329
|
+
self.parent.setups.append(hfss)
|
|
330
|
+
elif setup.type == "siwave_dc":
|
|
331
|
+
siwave_dc = CfgSIwaveDCSetup(self._pedb, setup)
|
|
332
|
+
siwave_dc.api.retrieve_parameters_from_edb()
|
|
333
|
+
self.parent.setups.append(siwave_dc)
|
|
334
|
+
elif setup.type == "siwave_ac":
|
|
335
|
+
siwave_ac = CfgSIwaveACSetup(self._pedb, setup)
|
|
336
|
+
siwave_ac.api.retrieve_parameters_from_edb()
|
|
337
|
+
self.parent.setups.append(siwave_ac)
|
|
338
|
+
|
|
257
339
|
def __init__(self, pedb, setups_data):
|
|
258
340
|
self.pedb = pedb
|
|
259
341
|
self.setups = []
|
|
342
|
+
if self.pedb.grpc:
|
|
343
|
+
self.api = self.Grpc(self)
|
|
344
|
+
else:
|
|
345
|
+
self.api = self.DotNet(self)
|
|
260
346
|
for stp in setups_data:
|
|
261
347
|
if stp["type"].lower() == "hfss":
|
|
262
348
|
self.setups.append(CfgHFSSSetup(self.pedb, None, **stp))
|
|
@@ -273,17 +359,4 @@ class CfgSetups:
|
|
|
273
359
|
return [i.to_dict() for i in self.setups]
|
|
274
360
|
|
|
275
361
|
def retrieve_parameters_from_edb(self):
|
|
276
|
-
self.
|
|
277
|
-
for _, setup in self.pedb.setups.items():
|
|
278
|
-
if setup.type == "hfss":
|
|
279
|
-
hfss = CfgHFSSSetup(self.pedb, setup)
|
|
280
|
-
hfss.api.retrieve_parameters_from_edb()
|
|
281
|
-
self.setups.append(hfss)
|
|
282
|
-
elif setup.type == "siwave_dc":
|
|
283
|
-
siwave_dc = CfgSIwaveDCSetup(self.pedb, setup)
|
|
284
|
-
siwave_dc.api.retrieve_parameters_from_edb()
|
|
285
|
-
self.setups.append(siwave_dc)
|
|
286
|
-
elif setup.type == "siwave_ac":
|
|
287
|
-
siwave_ac = CfgSIwaveACSetup(self.pedb, setup)
|
|
288
|
-
siwave_ac.api.retrieve_parameters_from_edb()
|
|
289
|
-
self.setups.append(siwave_ac)
|
|
362
|
+
self.api.retrieve_parameters_from_edb()
|
|
@@ -164,6 +164,50 @@ class CfgStackup:
|
|
|
164
164
|
def __init__(self, parent):
|
|
165
165
|
super().__init__(parent)
|
|
166
166
|
|
|
167
|
+
def __apply_layers(self):
|
|
168
|
+
"""Apply layer settings to the current design"""
|
|
169
|
+
layers = list()
|
|
170
|
+
layers.extend(self.parent.layers)
|
|
171
|
+
|
|
172
|
+
removal_list = []
|
|
173
|
+
lc_signal_layers = []
|
|
174
|
+
for name, obj in self._pedb.stackup.all_layers.items():
|
|
175
|
+
if obj.type == "dielectric":
|
|
176
|
+
removal_list.append(name)
|
|
177
|
+
elif obj.type == "signal":
|
|
178
|
+
lc_signal_layers.append(obj.id)
|
|
179
|
+
for l in removal_list:
|
|
180
|
+
self._pedb.stackup.remove_layer(l)
|
|
181
|
+
|
|
182
|
+
# update all signal layers
|
|
183
|
+
id_name = {i[0]: i[1] for i in self._pedb.stackup.layers_by_id}
|
|
184
|
+
signal_idx = 0
|
|
185
|
+
for l in layers:
|
|
186
|
+
if l.type == "signal":
|
|
187
|
+
layer_id = lc_signal_layers[signal_idx]
|
|
188
|
+
layer_name = id_name[layer_id]
|
|
189
|
+
attrs = l.get_attributes()
|
|
190
|
+
self._pedb.stackup.layers[layer_name].update(**attrs)
|
|
191
|
+
signal_idx = signal_idx + 1
|
|
192
|
+
|
|
193
|
+
# add all dielectric layers. Dielectric layers must be added last. Otherwise,
|
|
194
|
+
# dielectric layer will occupy signal and document layer id.
|
|
195
|
+
prev_layer_clone = None
|
|
196
|
+
l = layers.pop(0)
|
|
197
|
+
if l.type == "signal":
|
|
198
|
+
prev_layer_clone = self._pedb.stackup.layers[l.name]
|
|
199
|
+
else:
|
|
200
|
+
attrs = l.get_attributes()
|
|
201
|
+
prev_layer_clone = self._pedb.stackup.add_layer_top(**attrs)
|
|
202
|
+
for idx, l in enumerate(layers):
|
|
203
|
+
if l.type == "dielectric":
|
|
204
|
+
attrs = l.get_attributes()
|
|
205
|
+
prev_layer_clone = self._pedb.stackup.add_layer_below(
|
|
206
|
+
base_layer_name=prev_layer_clone.name, **attrs
|
|
207
|
+
)
|
|
208
|
+
elif l.type == "signal":
|
|
209
|
+
prev_layer_clone = self._pedb.stackup.layers[l.name]
|
|
210
|
+
|
|
167
211
|
def __init__(self, pedb: Edb, data):
|
|
168
212
|
self._pedb = pedb
|
|
169
213
|
if self._pedb.grpc:
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
|
+
import warnings
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class EdbDesignOptions:
|
|
@@ -51,8 +52,25 @@ class EdbDesignOptions:
|
|
|
51
52
|
``True`` if antipad is always on, ``False`` otherwise.
|
|
52
53
|
|
|
53
54
|
"""
|
|
54
|
-
|
|
55
|
+
warnings.warn("Use new property :func:`anti_pads_always_on` instead.", DeprecationWarning)
|
|
56
|
+
return self.anti_pads_always_on
|
|
55
57
|
|
|
56
58
|
@antipads_always_on.setter
|
|
57
59
|
def antipads_always_on(self, value):
|
|
60
|
+
self.anti_pads_always_on = value
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def anti_pads_always_on(self):
|
|
64
|
+
"""Whether to always turn on antipad.
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
bool
|
|
69
|
+
``True`` if antipad is always on, ``False`` otherwise.
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
return self._active_cell.GetAntiPadsAlwaysOn()
|
|
73
|
+
|
|
74
|
+
@anti_pads_always_on.setter
|
|
75
|
+
def anti_pads_always_on(self, value):
|
|
58
76
|
self._active_cell.SetAntiPadsAlwaysOn(value)
|
|
@@ -35,6 +35,7 @@ from pyedb.dotnet.database.general import (
|
|
|
35
35
|
snake_to_pascal,
|
|
36
36
|
)
|
|
37
37
|
from pyedb.dotnet.database.geometry.polygon_data import PolygonData
|
|
38
|
+
from pyedb.generic.data_handlers import float_units
|
|
38
39
|
from pyedb.generic.general_methods import generate_unique_name
|
|
39
40
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
40
41
|
|
|
@@ -1958,15 +1959,18 @@ class EDBPadstackInstance(Primitive):
|
|
|
1958
1959
|
pad_shape = padstack_pad.geometry_type
|
|
1959
1960
|
params = padstack_pad.parameters_values
|
|
1960
1961
|
polygon_data = padstack_pad._polygon_data_dotnet
|
|
1962
|
+
pad_offset = [float_units(padstack_pad.offset_x), float_units(padstack_pad.offset_y)]
|
|
1961
1963
|
|
|
1962
1964
|
def _rotate(p):
|
|
1963
1965
|
x = p[0] * math.cos(rotation) - p[1] * math.sin(rotation)
|
|
1964
1966
|
y = p[0] * math.sin(rotation) + p[1] * math.cos(rotation)
|
|
1965
1967
|
return [x, y]
|
|
1966
1968
|
|
|
1967
|
-
def _translate(p):
|
|
1968
|
-
|
|
1969
|
-
|
|
1969
|
+
def _translate(p, t=None):
|
|
1970
|
+
if t is None:
|
|
1971
|
+
t = padstack_center
|
|
1972
|
+
x = p[0] + t[0]
|
|
1973
|
+
y = p[1] + t[1]
|
|
1970
1974
|
return [x, y]
|
|
1971
1975
|
|
|
1972
1976
|
rect = None
|
|
@@ -2092,7 +2096,8 @@ class EDBPadstackInstance(Primitive):
|
|
|
2092
2096
|
|
|
2093
2097
|
if rect is None or len(rect) != 4:
|
|
2094
2098
|
return False
|
|
2095
|
-
|
|
2099
|
+
offset_rect = [_translate(p, _rotate(pad_offset)) for p in rect]
|
|
2100
|
+
path = self._pedb.modeler.Shape("polygon", points=offset_rect)
|
|
2096
2101
|
pdata = self._pedb.modeler.shape_to_polygon_data(path)
|
|
2097
2102
|
new_rect = []
|
|
2098
2103
|
for point in pdata.Points:
|
|
@@ -89,8 +89,10 @@ class PolygonData:
|
|
|
89
89
|
def create_from_points(self, points, closed=True):
|
|
90
90
|
list_of_point_data = []
|
|
91
91
|
for pt in points:
|
|
92
|
-
list_of_point_data.append(PointData(self._pedb, x=pt[0], y=pt[1]))
|
|
93
|
-
return self._pedb.edb_api.geometry.api_class.PolygonData(
|
|
92
|
+
list_of_point_data.append(PointData(self._pedb, x=pt[0], y=pt[1])._edb_object)
|
|
93
|
+
return self._pedb.edb_api.geometry.api_class.PolygonData(
|
|
94
|
+
convert_py_list_to_net_list(list_of_point_data), closed
|
|
95
|
+
)
|
|
94
96
|
|
|
95
97
|
def create_from_bounding_box(self, points):
|
|
96
98
|
bbox = BBox(self._pedb, point_1=points[0], point_2=points[1])
|
|
@@ -1153,7 +1153,7 @@ class EdbPadstacks(object):
|
|
|
1153
1153
|
Name of the net. The default is ``""``.
|
|
1154
1154
|
via_name : str, optional
|
|
1155
1155
|
The default is ``""``.
|
|
1156
|
-
rotation : float, optional
|
|
1156
|
+
rotation : float, str, optional
|
|
1157
1157
|
Rotation of the padstack in degrees. The default
|
|
1158
1158
|
is ``0``.
|
|
1159
1159
|
fromlayer :
|
|
@@ -1175,7 +1175,11 @@ class EdbPadstacks(object):
|
|
|
1175
1175
|
padstack = self.definitions[pad].edb_padstack
|
|
1176
1176
|
position = self._edb.geometry.point_data(position[0], position[1])
|
|
1177
1177
|
net = self._pedb.nets.find_or_create_net(net_name)
|
|
1178
|
-
rotation =
|
|
1178
|
+
rotation = (
|
|
1179
|
+
self._get_edb_value(rotation * math.pi / 180)
|
|
1180
|
+
if not isinstance(rotation, str)
|
|
1181
|
+
else self._get_edb_value(rotation)
|
|
1182
|
+
)
|
|
1179
1183
|
sign_layers_values = {i: v for i, v in self._pedb.stackup.signal_layers.items()}
|
|
1180
1184
|
sign_layers = list(sign_layers_values.keys())
|
|
1181
1185
|
if not fromlayer:
|
|
@@ -96,8 +96,6 @@ class SimulationSetup(object):
|
|
|
96
96
|
if self._edb_object:
|
|
97
97
|
self._name = self._edb_object.GetName()
|
|
98
98
|
|
|
99
|
-
self._sweep_list = {}
|
|
100
|
-
|
|
101
99
|
@property
|
|
102
100
|
def sim_setup_info(self):
|
|
103
101
|
return SimSetupInfo(self._pedb, sim_setup=self, edb_object=self._edb_object.GetSimSetupInfo())
|
|
@@ -239,7 +237,7 @@ class SimulationSetup(object):
|
|
|
239
237
|
"""List of frequency sweeps."""
|
|
240
238
|
return {i.name: i for i in self.sim_setup_info.sweep_data_list}
|
|
241
239
|
|
|
242
|
-
def add_sweep(self, name, frequency_set: list = None, sweep_type: str = "interpolation", **kwargs):
|
|
240
|
+
def add_sweep(self, name: str = None, frequency_set: list = None, sweep_type: str = "interpolation", **kwargs):
|
|
243
241
|
"""Add frequency sweep.
|
|
244
242
|
|
|
245
243
|
Parameters
|
|
@@ -292,15 +290,7 @@ class SimulationSetup(object):
|
|
|
292
290
|
sweep_data: SweepData
|
|
293
291
|
"""
|
|
294
292
|
warnings.warn("Use new property :func:`add_sweep_data` instead.", DeprecationWarning)
|
|
295
|
-
self.
|
|
296
|
-
edb_setup_info = self.sim_setup_info
|
|
297
|
-
|
|
298
|
-
if self._setup_type in ["kSIwave", "kHFSS", "kRaptorX", "kHFSSPI"]:
|
|
299
|
-
for _, v in self._sweep_list.items():
|
|
300
|
-
edb_setup_info.SweepDataList.Add(v._edb_object)
|
|
301
|
-
|
|
302
|
-
self._edb_object = self._set_edb_setup_info(edb_setup_info)
|
|
303
|
-
self._update_setup()
|
|
293
|
+
return self.sim_setup_info.add_sweep_data(sweep_data)
|
|
304
294
|
|
|
305
295
|
def delete_frequency_sweep(self, sweep_data):
|
|
306
296
|
"""Delete a frequency sweep.
|
|
@@ -310,17 +300,17 @@ class SimulationSetup(object):
|
|
|
310
300
|
sweep_data : EdbFrequencySweep.
|
|
311
301
|
"""
|
|
312
302
|
name = sweep_data.name
|
|
313
|
-
if name in self.
|
|
314
|
-
self.
|
|
303
|
+
if name in self.sweeps:
|
|
304
|
+
self.sweeps.pop(name)
|
|
315
305
|
|
|
316
306
|
fsweep = []
|
|
317
|
-
if self.
|
|
318
|
-
fsweep = [val for key, val in self.
|
|
307
|
+
if self.sweeps:
|
|
308
|
+
fsweep = [val for key, val in self.sweeps.items() if not key == name]
|
|
319
309
|
self.sim_setup_info._edb_object.SweepDataList.Clear()
|
|
320
310
|
for i in fsweep:
|
|
321
311
|
self.sim_setup_info._edb_object.SweepDataList.Add(i._edb_object)
|
|
322
312
|
self._update_setup()
|
|
323
|
-
return
|
|
313
|
+
return False if name in self.sweeps else True
|
|
324
314
|
|
|
325
315
|
def add_frequency_sweep(self, name=None, frequency_sweep=None):
|
|
326
316
|
"""Add frequency sweep.
|
|
@@ -95,6 +95,8 @@ class SiwaveSimulationSetup(SimulationSetup):
|
|
|
95
95
|
self._edb_object = self._simulation_setup_builder(sim_setup_info._edb_object)
|
|
96
96
|
self._update_setup()
|
|
97
97
|
|
|
98
|
+
self._siwave_sweeps_list = []
|
|
99
|
+
|
|
98
100
|
def create(self, name=None):
|
|
99
101
|
"""Create a SIwave SYZ setup.
|
|
100
102
|
|
|
@@ -248,6 +250,34 @@ class SiwaveSimulationSetup(SimulationSetup):
|
|
|
248
250
|
self._edb_object = self._set_edb_setup_info(edb_setup_info)
|
|
249
251
|
self._update_setup()
|
|
250
252
|
|
|
253
|
+
def add_sweep(self, name: str = None, frequency_set: list = None, sweep_type: str = "interpolation", **kwargs):
|
|
254
|
+
"""Add frequency sweep.
|
|
255
|
+
|
|
256
|
+
Parameters
|
|
257
|
+
----------
|
|
258
|
+
name : str, optional
|
|
259
|
+
Name of the frequency sweep. The default is ``None``.
|
|
260
|
+
frequency_set : list, optional
|
|
261
|
+
List of frequency points. The default is ``None``.
|
|
262
|
+
sweep_type : str, optional
|
|
263
|
+
Sweep type. The default is ``"interpolation"``. Options are ``"discrete"``,"discrete"``.
|
|
264
|
+
Returns
|
|
265
|
+
-------
|
|
266
|
+
|
|
267
|
+
Examples
|
|
268
|
+
--------
|
|
269
|
+
>>> setup1 = edbapp.create_siwave_syz_setup("setup1")
|
|
270
|
+
>>> setup1.add_sweep(name="sw1", frequency_set=["linear count", "1MHz", "100MHz", 10])
|
|
271
|
+
"""
|
|
272
|
+
sweep_data = SimulationSetup.add_sweep(self, name, frequency_set, sweep_type, **kwargs)
|
|
273
|
+
self._siwave_sweeps_list.append(sweep_data)
|
|
274
|
+
return sweep_data
|
|
275
|
+
|
|
276
|
+
@property
|
|
277
|
+
def sweeps(self):
|
|
278
|
+
"""List of frequency sweeps."""
|
|
279
|
+
return {i.name: i for i in self._siwave_sweeps_list}
|
|
280
|
+
|
|
251
281
|
|
|
252
282
|
class SiwaveDCSimulationSetup(SimulationSetup):
|
|
253
283
|
"""Manages EDB methods for SIwave DC simulation setup."""
|
|
@@ -2280,7 +2280,7 @@ class Components(object):
|
|
|
2280
2280
|
if not pin.net.is_null:
|
|
2281
2281
|
if pin.net.name:
|
|
2282
2282
|
pingroup.net = pin.net
|
|
2283
|
-
return group_name
|
|
2283
|
+
return group_name, PinGroup(self._pedb, pingroup)
|
|
2284
2284
|
return False
|
|
2285
2285
|
|
|
2286
2286
|
def create_pin_group_on_net(self, reference_designator, net_name, group_name=None):
|