pyedb 0.52.0__py3-none-any.whl → 0.54.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_common.py +12 -15
- pyedb/configuration/cfg_data.py +2 -2
- pyedb/configuration/cfg_modeler.py +163 -234
- pyedb/configuration/cfg_ports_sources.py +6 -8
- pyedb/configuration/cfg_stackup.py +62 -249
- pyedb/configuration/configuration.py +272 -170
- pyedb/dotnet/database/cell/hierarchy/model.py +1 -1
- pyedb/dotnet/database/cell/layout.py +1 -1
- pyedb/dotnet/database/cell/layout_obj.py +3 -3
- pyedb/dotnet/database/cell/primitive/path.py +1 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +8 -8
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +24 -26
- pyedb/dotnet/database/components.py +33 -27
- pyedb/dotnet/database/definition/component_def.py +3 -3
- pyedb/dotnet/database/definition/component_model.py +1 -1
- pyedb/dotnet/database/definition/package_def.py +1 -1
- pyedb/dotnet/database/dotnet/database.py +47 -38
- pyedb/dotnet/database/dotnet/primitive.py +16 -16
- pyedb/dotnet/database/edb_data/hfss_extent_info.py +6 -6
- pyedb/dotnet/database/edb_data/layer_data.py +17 -15
- pyedb/dotnet/database/edb_data/padstacks_data.py +12 -12
- pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
- pyedb/dotnet/database/edb_data/sources.py +6 -6
- pyedb/dotnet/database/edb_data/variables.py +7 -3
- pyedb/dotnet/database/geometry/point_data.py +1 -1
- pyedb/dotnet/database/geometry/polygon_data.py +2 -4
- pyedb/dotnet/database/hfss.py +7 -7
- pyedb/dotnet/database/materials.py +2 -2
- pyedb/dotnet/database/modeler.py +8 -11
- pyedb/dotnet/database/nets.py +1 -1
- pyedb/dotnet/database/padstack.py +72 -1
- pyedb/dotnet/database/sim_setup_data/data/settings.py +24 -0
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +26 -1
- pyedb/dotnet/database/siwave.py +19 -5
- pyedb/dotnet/database/stackup.py +80 -137
- pyedb/dotnet/database/utilities/heatsink.py +4 -4
- pyedb/dotnet/database/utilities/obj_base.py +1 -1
- pyedb/dotnet/database/utilities/simulation_setup.py +1 -1
- pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +894 -0
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +15 -0
- pyedb/dotnet/database/utilities/value.py +116 -0
- pyedb/dotnet/edb.py +58 -45
- pyedb/generic/design_types.py +39 -1
- pyedb/generic/grpc_warnings.py +5 -0
- pyedb/grpc/__init__.py +0 -0
- pyedb/grpc/database/components.py +155 -98
- pyedb/grpc/database/control_file.py +240 -193
- pyedb/grpc/database/definition/materials.py +23 -30
- pyedb/grpc/database/definition/package_def.py +15 -15
- pyedb/grpc/database/definition/padstack_def.py +51 -51
- pyedb/grpc/database/definitions.py +7 -5
- pyedb/grpc/database/geometry/arc_data.py +7 -5
- pyedb/grpc/database/geometry/point_3d_data.py +8 -7
- pyedb/grpc/database/geometry/polygon_data.py +3 -2
- pyedb/grpc/database/hierarchy/component.py +43 -38
- pyedb/grpc/database/hierarchy/pin_pair_model.py +15 -14
- pyedb/grpc/database/hierarchy/pingroup.py +9 -9
- pyedb/grpc/database/layers/stackup_layer.py +45 -44
- pyedb/grpc/database/layout/layout.py +9 -8
- pyedb/grpc/database/layout/voltage_regulator.py +7 -7
- pyedb/grpc/database/layout_validation.py +13 -12
- pyedb/grpc/database/modeler.py +156 -131
- pyedb/grpc/database/nets.py +42 -31
- pyedb/grpc/database/padstacks.py +270 -175
- pyedb/grpc/database/ports/ports.py +5 -6
- pyedb/grpc/database/primitive/bondwire.py +8 -7
- pyedb/grpc/database/primitive/circle.py +4 -4
- pyedb/grpc/database/primitive/padstack_instance.py +18 -18
- pyedb/grpc/database/primitive/path.py +7 -7
- pyedb/grpc/database/primitive/polygon.py +3 -3
- pyedb/grpc/database/primitive/primitive.py +13 -17
- pyedb/grpc/database/primitive/rectangle.py +13 -13
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +10 -0
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +961 -0
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +17 -1
- pyedb/grpc/database/siwave.py +44 -24
- pyedb/grpc/database/source_excitations.py +333 -229
- pyedb/grpc/database/stackup.py +164 -147
- pyedb/grpc/database/terminal/bundle_terminal.py +17 -7
- pyedb/grpc/database/terminal/edge_terminal.py +10 -0
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +15 -4
- pyedb/grpc/database/terminal/pingroup_terminal.py +11 -10
- pyedb/grpc/database/terminal/point_terminal.py +4 -3
- pyedb/grpc/database/terminal/terminal.py +9 -9
- pyedb/grpc/database/utility/value.py +109 -0
- pyedb/grpc/edb.py +129 -45
- pyedb/grpc/edb_init.py +0 -7
- pyedb/siwave_core/cpa/simulation_setup_data_model.py +132 -0
- pyedb/siwave_core/product_properties.py +198 -0
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/METADATA +15 -13
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/RECORD +97 -89
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/WHEEL +1 -1
- {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info/licenses}/LICENSE +0 -0
|
@@ -27,14 +27,14 @@ import warnings
|
|
|
27
27
|
|
|
28
28
|
import toml
|
|
29
29
|
|
|
30
|
+
from pyedb import Edb
|
|
30
31
|
from pyedb.configuration.cfg_data import CfgData
|
|
31
|
-
from pyedb.dotnet.database.definition.package_def import PackageDef
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class Configuration:
|
|
35
35
|
"""Enables export and import of a JSON configuration file that can be applied to a new or existing design."""
|
|
36
36
|
|
|
37
|
-
def __init__(self, pedb):
|
|
37
|
+
def __init__(self, pedb: Edb):
|
|
38
38
|
self._pedb = pedb
|
|
39
39
|
|
|
40
40
|
self._components = self._pedb.components.instances
|
|
@@ -43,6 +43,11 @@ class Configuration:
|
|
|
43
43
|
self._spice_model_library = ""
|
|
44
44
|
self.cfg_data = CfgData(self._pedb)
|
|
45
45
|
|
|
46
|
+
def __apply_with_logging(self, label: str, func):
|
|
47
|
+
start = datetime.now()
|
|
48
|
+
func()
|
|
49
|
+
self._pedb.logger.info(f"{label} finished. Time lapse {datetime.now() - start}")
|
|
50
|
+
|
|
46
51
|
def load(self, config_file, append=True, apply_file=False, output_file=None, open_at_the_end=True):
|
|
47
52
|
"""Import configuration settings from a configure file.
|
|
48
53
|
|
|
@@ -110,206 +115,293 @@ class Configuration:
|
|
|
110
115
|
if kwargs.get("fix_padstack_def"):
|
|
111
116
|
warnings.warn("fix_padstack_def is deprecated.", DeprecationWarning)
|
|
112
117
|
|
|
113
|
-
|
|
114
|
-
self.cfg_data.variables.apply()
|
|
118
|
+
self.apply_variables()
|
|
115
119
|
|
|
116
120
|
if self.cfg_data.general:
|
|
117
121
|
self.cfg_data.general.apply()
|
|
118
122
|
|
|
119
123
|
# Configure boundary settings
|
|
120
|
-
now = datetime.now()
|
|
121
124
|
if self.cfg_data.boundaries:
|
|
122
|
-
self.cfg_data.boundaries.apply
|
|
123
|
-
self._pedb.logger.info(f"Updating boundaries finished. Time lapse {datetime.now() - now}")
|
|
124
|
-
now = datetime.now()
|
|
125
|
+
self.__apply_with_logging("Updating boundaries", self.cfg_data.boundaries.apply)
|
|
125
126
|
|
|
126
|
-
# Configure nets
|
|
127
127
|
if self.cfg_data.nets:
|
|
128
|
-
self.cfg_data.nets.apply
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
self.cfg_data.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
self.cfg_data.pin_groups.apply()
|
|
139
|
-
self._pedb.logger.info(f"Creating pin groups finished. Time lapse {datetime.now() - now}")
|
|
140
|
-
now = datetime.now()
|
|
141
|
-
|
|
142
|
-
# Configure sources
|
|
143
|
-
self.cfg_data.sources.apply()
|
|
144
|
-
self._pedb.logger.info(f"Placing sources finished. Time lapse {datetime.now() - now}")
|
|
145
|
-
now = datetime.now()
|
|
146
|
-
|
|
147
|
-
# Configure setup
|
|
148
|
-
self.cfg_data.setups.apply()
|
|
149
|
-
self._pedb.logger.info(f"Creating setups finished. Time lapse {datetime.now() - now}")
|
|
150
|
-
now = datetime.now()
|
|
151
|
-
|
|
152
|
-
# Configure stackup
|
|
153
|
-
self.configuration_stackup()
|
|
154
|
-
self._pedb.logger.info(f"Updating stackup finished. Time lapse {datetime.now() - now}")
|
|
155
|
-
now = datetime.now()
|
|
156
|
-
|
|
157
|
-
# Configure padstacks
|
|
128
|
+
self.__apply_with_logging("Updating nets", self.cfg_data.nets.apply)
|
|
129
|
+
|
|
130
|
+
self.__apply_with_logging("Updating components", self.cfg_data.components.apply)
|
|
131
|
+
self.__apply_with_logging("Creating pin groups", self.cfg_data.pin_groups.apply)
|
|
132
|
+
self.__apply_with_logging("Placing sources", self.cfg_data.sources.apply)
|
|
133
|
+
self.__apply_with_logging("Creating setups", self.cfg_data.setups.apply)
|
|
134
|
+
|
|
135
|
+
self.__apply_with_logging("Applying materials", self.apply_materials)
|
|
136
|
+
self.__apply_with_logging("Updating stackup", self.apply_stackup)
|
|
137
|
+
|
|
158
138
|
if self.cfg_data.padstacks:
|
|
159
|
-
self.cfg_data.padstacks.apply
|
|
160
|
-
self._pedb.logger.info(f"Applying padstacks finished. Time lapse {datetime.now() - now}")
|
|
161
|
-
now = datetime.now()
|
|
139
|
+
self.__apply_with_logging("Applying padstacks", self.cfg_data.padstacks.apply)
|
|
162
140
|
|
|
163
|
-
|
|
164
|
-
self.cfg_data.s_parameters.apply()
|
|
165
|
-
self._pedb.logger.info(f"Applying S-parameters finished. Time lapse {datetime.now() - now}")
|
|
166
|
-
now = datetime.now()
|
|
141
|
+
self.__apply_with_logging("Applying S-parameters", self.cfg_data.s_parameters.apply)
|
|
167
142
|
|
|
168
|
-
# Configure SPICE models
|
|
169
143
|
for spice_model in self.cfg_data.spice_models:
|
|
170
|
-
spice_model.apply
|
|
171
|
-
self._pedb.logger.info(f"Assigning Spice models finished. Time lapse {datetime.now() - now}")
|
|
172
|
-
now = datetime.now()
|
|
144
|
+
self.__apply_with_logging(f"Assigning Spice model {spice_model}", spice_model.apply)
|
|
173
145
|
|
|
174
|
-
|
|
175
|
-
self.
|
|
176
|
-
self.
|
|
177
|
-
|
|
146
|
+
self.__apply_with_logging("Applying package definitions", self.cfg_data.package_definitions.apply)
|
|
147
|
+
self.__apply_with_logging("Applying modeler", self.apply_modeler)
|
|
148
|
+
self.__apply_with_logging("Placing ports", self.cfg_data.ports.apply)
|
|
149
|
+
self.__apply_with_logging("Placing probes", self.cfg_data.probes.apply)
|
|
150
|
+
self.__apply_with_logging("Applying operations", self.cfg_data.operations.apply)
|
|
178
151
|
|
|
179
|
-
|
|
180
|
-
|
|
152
|
+
return True
|
|
153
|
+
|
|
154
|
+
def apply_modeler(self):
|
|
155
|
+
modeler = self.cfg_data.modeler
|
|
156
|
+
if modeler.traces:
|
|
157
|
+
for t in modeler.traces:
|
|
158
|
+
if t.path:
|
|
159
|
+
obj = self._pedb.modeler.create_trace(
|
|
160
|
+
path_list=t.path,
|
|
161
|
+
layer_name=t.layer,
|
|
162
|
+
net_name=t.net_name,
|
|
163
|
+
width=t.width,
|
|
164
|
+
start_cap_style=t.start_cap_style,
|
|
165
|
+
end_cap_style=t.end_cap_style,
|
|
166
|
+
corner_style=t.corner_style,
|
|
167
|
+
)
|
|
168
|
+
obj.aedt_name = t.name
|
|
169
|
+
else:
|
|
170
|
+
obj = self._pedb.modeler.create_trace(
|
|
171
|
+
path_list=[t.incremental_path[0]],
|
|
172
|
+
layer_name=t.layer,
|
|
173
|
+
net_name=t.net_name,
|
|
174
|
+
width=t.width,
|
|
175
|
+
start_cap_style=t.start_cap_style,
|
|
176
|
+
end_cap_style=t.end_cap_style,
|
|
177
|
+
corner_style=t.corner_style,
|
|
178
|
+
)
|
|
179
|
+
obj.aedt_name = t.name
|
|
180
|
+
for x, y in t.incremental_path[1:]:
|
|
181
|
+
obj.add_point(x, y, True)
|
|
182
|
+
|
|
183
|
+
if modeler.padstack_defs:
|
|
184
|
+
for p in modeler.padstack_defs:
|
|
185
|
+
pdata = self._pedb._edb.Definition.PadstackDefData.Create()
|
|
186
|
+
pdef = self._pedb._edb.Definition.PadstackDef.Create(self._pedb.active_db, p.name)
|
|
187
|
+
pdef.SetData(pdata)
|
|
188
|
+
pdef = self._pedb.pedb_class.database.edb_data.padstacks_data.EDBPadstack(pdef, self._pedb.padstacks)
|
|
189
|
+
p.pyedb_obj = pdef
|
|
190
|
+
p.api.set_parameters_to_edb()
|
|
191
|
+
|
|
192
|
+
if modeler.padstack_instances:
|
|
193
|
+
for p in modeler.padstack_instances:
|
|
194
|
+
p_inst = self._pedb.padstacks.place(
|
|
195
|
+
via_name=p.name,
|
|
196
|
+
net_name=p.net_name,
|
|
197
|
+
position=p.position,
|
|
198
|
+
definition_name=p.definition,
|
|
199
|
+
rotation=p.rotation if p.rotation is not None else 0,
|
|
200
|
+
)
|
|
201
|
+
p.pyedb_obj = p_inst
|
|
202
|
+
p.api.set_parameters_to_edb()
|
|
203
|
+
|
|
204
|
+
if modeler.planes:
|
|
205
|
+
for p in modeler.planes:
|
|
206
|
+
if p.type == "rectangle":
|
|
207
|
+
obj = self._pedb.modeler.create_rectangle(
|
|
208
|
+
layer_name=p.layer,
|
|
209
|
+
net_name=p.net_name,
|
|
210
|
+
lower_left_point=p.lower_left_point,
|
|
211
|
+
upper_right_point=p.upper_right_point,
|
|
212
|
+
corner_radius=p.corner_radius,
|
|
213
|
+
rotation=p.rotation,
|
|
214
|
+
)
|
|
215
|
+
obj.aedt_name = p.name
|
|
216
|
+
elif p.type == "polygon":
|
|
217
|
+
obj = self._pedb.modeler.create_polygon(
|
|
218
|
+
main_shape=p.points, layer_name=p.layer, net_name=p.net_name
|
|
219
|
+
)
|
|
220
|
+
obj.aedt_name = p.name
|
|
221
|
+
elif p.type == "circle":
|
|
222
|
+
obj = self._pedb.modeler.create_circle(
|
|
223
|
+
layer_name=p.layer,
|
|
224
|
+
net_name=p.net_name,
|
|
225
|
+
x=p.position[0],
|
|
226
|
+
y=p.position[1],
|
|
227
|
+
radius=p.radius,
|
|
228
|
+
)
|
|
229
|
+
obj.aedt_name = p.name
|
|
230
|
+
else:
|
|
231
|
+
raise RuntimeError(f"Plane type {p.type} not supported")
|
|
232
|
+
|
|
233
|
+
for v in p.voids:
|
|
234
|
+
for i in self._pedb.layout.primitives:
|
|
235
|
+
if i.aedt_name == v:
|
|
236
|
+
self._pedb.modeler.add_void(obj, i)
|
|
237
|
+
|
|
238
|
+
if modeler.components:
|
|
239
|
+
for c in modeler.components:
|
|
240
|
+
obj = self._pedb.components.create(
|
|
241
|
+
c.pins,
|
|
242
|
+
component_name=c.reference_designator,
|
|
243
|
+
placement_layer=c.placement_layer,
|
|
244
|
+
component_part_name=c.definition,
|
|
245
|
+
)
|
|
246
|
+
c.pyedb_obj = obj
|
|
247
|
+
c.api.set_parameters_to_edb()
|
|
248
|
+
|
|
249
|
+
primitives = self._pedb.layout.find_primitive(**modeler.primitives_to_delete)
|
|
250
|
+
for i in primitives:
|
|
251
|
+
i.delete()
|
|
252
|
+
|
|
253
|
+
def apply_variables(self):
|
|
254
|
+
"""Set variables into database."""
|
|
255
|
+
inst = self.cfg_data.variables
|
|
256
|
+
for i in inst.variables:
|
|
257
|
+
if i.name.startswith("$"):
|
|
258
|
+
self._pedb.add_project_variable(i.name, i.value, i.description)
|
|
259
|
+
else:
|
|
260
|
+
self._pedb.add_design_variable(i.name, i.value, description=i.description)
|
|
261
|
+
|
|
262
|
+
def get_variables(self):
|
|
263
|
+
"""Retrieve variables from database."""
|
|
264
|
+
self.cfg_data.variables.variables = []
|
|
265
|
+
for name, obj in self._pedb.design_variables.items():
|
|
266
|
+
self.cfg_data.variables.add_variable(name, obj.value_string, obj.description)
|
|
267
|
+
for name, obj in self._pedb.project_variables.items():
|
|
268
|
+
self.cfg_data.variables.add_variable(name, obj.value_string, obj.description)
|
|
269
|
+
|
|
270
|
+
def apply_materials(self):
|
|
271
|
+
"""Apply material settings to the current design"""
|
|
272
|
+
cfg_stackup = self.cfg_data.stackup
|
|
273
|
+
if len(cfg_stackup.materials):
|
|
274
|
+
materials_in_db = {i.lower(): i for i, _ in self._pedb.materials.materials.items()}
|
|
275
|
+
for mat_in_cfg in cfg_stackup.materials:
|
|
276
|
+
if mat_in_cfg.name.lower() in materials_in_db:
|
|
277
|
+
self._pedb.materials.delete_material(materials_in_db[mat_in_cfg.name.lower()])
|
|
278
|
+
|
|
279
|
+
attrs = mat_in_cfg.model_dump(exclude_none=True)
|
|
280
|
+
mat = self._pedb.materials.add_material(**attrs)
|
|
281
|
+
|
|
282
|
+
for i in attrs.get("thermal_modifiers", []):
|
|
283
|
+
mat.set_thermal_modifier(**i.to_dict())
|
|
284
|
+
|
|
285
|
+
def get_materials(self):
|
|
286
|
+
"""Retrieve materials from the current design.
|
|
181
287
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
288
|
+
Parameters
|
|
289
|
+
----------
|
|
290
|
+
append: bool, optional
|
|
291
|
+
If `True`, append materials to the current material list.
|
|
292
|
+
"""
|
|
186
293
|
|
|
187
|
-
|
|
188
|
-
self.
|
|
189
|
-
|
|
294
|
+
self.cfg_data.stackup.materials = []
|
|
295
|
+
for name, mat in self._pedb.materials.materials.items():
|
|
296
|
+
self.cfg_data.stackup.add_material(**mat.to_dict())
|
|
297
|
+
|
|
298
|
+
def apply_stackup(self):
|
|
299
|
+
layers = self.cfg_data.stackup.layers
|
|
300
|
+
input_signal_layers = [i for i in layers if i.type.lower() == "signal"]
|
|
301
|
+
if len(input_signal_layers) == 0:
|
|
302
|
+
return
|
|
303
|
+
else: # Create materials with default properties used in stackup but not defined
|
|
304
|
+
materials = [m.name for m in self.cfg_data.stackup.materials]
|
|
305
|
+
for i in self.cfg_data.stackup.layers:
|
|
306
|
+
if i.type == "signal":
|
|
307
|
+
if i.material not in materials:
|
|
308
|
+
self.cfg_data.stackup.add_material(
|
|
309
|
+
name=i.material, **self._pedb.materials.default_conductor_property_values
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
if i.fill_material not in materials:
|
|
313
|
+
self.cfg_data.stackup.add_material(
|
|
314
|
+
name=i.material, **self._pedb.materials.default_dielectric_property_values
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
elif i.type == "dielectric":
|
|
318
|
+
if i.material not in materials:
|
|
319
|
+
self.cfg_data.stackup.add_material(
|
|
320
|
+
name=i.material, **self._pedb.materials.default_dielectric_property_values
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
if len(self._pedb.stackup.signal_layers) == 0:
|
|
324
|
+
self.__create_stackup()
|
|
325
|
+
elif not len(input_signal_layers) == len(self._pedb.stackup.signal_layers):
|
|
326
|
+
raise Exception(f"Input signal layer count do not match.")
|
|
327
|
+
else:
|
|
328
|
+
self.__update_stackup()
|
|
190
329
|
|
|
191
|
-
|
|
192
|
-
|
|
330
|
+
def __create_stackup(self):
|
|
331
|
+
layers_ = list()
|
|
332
|
+
layers_.extend(self.cfg_data.stackup.layers)
|
|
333
|
+
for l_attrs in layers_:
|
|
334
|
+
attrs = l_attrs.model_dump(exclude_none=True)
|
|
335
|
+
self._pedb.stackup.add_layer_bottom(**attrs)
|
|
193
336
|
|
|
194
|
-
|
|
337
|
+
def __update_stackup(self):
|
|
338
|
+
"""Apply layer settings to the current design"""
|
|
195
339
|
|
|
196
|
-
|
|
340
|
+
# After import stackup, padstacks lose their definitions. They need to be fixed after loading stackup
|
|
341
|
+
# step 1, archive padstack definitions
|
|
197
342
|
temp_pdef_data = {}
|
|
198
343
|
for pdef_name, pdef in self._pedb.padstacks.definitions.items():
|
|
199
344
|
pdef_edb_object = pdef._padstack_def_data
|
|
200
345
|
temp_pdef_data[pdef_name] = pdef_edb_object
|
|
201
|
-
|
|
346
|
+
# step 2, archive padstack instance layer map
|
|
202
347
|
temp_p_inst_layer_map = {}
|
|
203
348
|
for p_inst in self._pedb.layout.padstack_instances:
|
|
204
349
|
temp_p_inst_layer_map[p_inst.id] = p_inst._edb_object.GetLayerMap()
|
|
205
350
|
|
|
206
|
-
|
|
207
|
-
|
|
351
|
+
# ----------------------------------------------------------------------
|
|
352
|
+
# Apply stackup
|
|
353
|
+
layers = list()
|
|
354
|
+
layers.extend(self.cfg_data.stackup.layers)
|
|
355
|
+
|
|
356
|
+
removal_list = []
|
|
357
|
+
lc_signal_layers = []
|
|
358
|
+
for name, obj in self._pedb.stackup.all_layers.items():
|
|
359
|
+
if obj.type == "dielectric":
|
|
360
|
+
removal_list.append(name)
|
|
361
|
+
elif obj.type == "signal":
|
|
362
|
+
lc_signal_layers.append(obj.id)
|
|
363
|
+
for l in removal_list:
|
|
364
|
+
self._pedb.stackup.remove_layer(l)
|
|
365
|
+
|
|
366
|
+
# update all signal layers
|
|
367
|
+
id_name = {i[0]: i[1] for i in self._pedb.stackup.layers_by_id}
|
|
368
|
+
signal_idx = 0
|
|
369
|
+
for l in layers:
|
|
370
|
+
if l.type == "signal":
|
|
371
|
+
layer_id = lc_signal_layers[signal_idx]
|
|
372
|
+
layer_name = id_name[layer_id]
|
|
373
|
+
attrs = l.model_dump(exclude_none=True)
|
|
374
|
+
self._pedb.stackup.layers[layer_name].update(**attrs)
|
|
375
|
+
signal_idx = signal_idx + 1
|
|
376
|
+
|
|
377
|
+
# add all dielectric layers. Dielectric layers must be added last. Otherwise,
|
|
378
|
+
# dielectric layer will occupy signal and document layer id.
|
|
379
|
+
l = layers.pop(0)
|
|
380
|
+
if l.type == "signal":
|
|
381
|
+
prev_layer_clone = self._pedb.stackup.layers[l.name]
|
|
382
|
+
else:
|
|
383
|
+
attrs = l.model_dump(exclude_none=True)
|
|
384
|
+
prev_layer_clone = self._pedb.stackup.add_layer_top(**attrs)
|
|
385
|
+
for idx, l in enumerate(layers):
|
|
386
|
+
if l.type == "dielectric":
|
|
387
|
+
attrs = l.model_dump(exclude_none=True)
|
|
388
|
+
prev_layer_clone = self._pedb.stackup.add_layer_below(base_layer_name=prev_layer_clone.name, **attrs)
|
|
389
|
+
elif l.type == "signal":
|
|
390
|
+
prev_layer_clone = self._pedb.stackup.layers[l.name]
|
|
391
|
+
|
|
392
|
+
# ----------------------------------------------------------------------
|
|
393
|
+
# restore padstack definitions
|
|
208
394
|
for pdef_name, pdef_data in temp_pdef_data.items():
|
|
209
395
|
pdef = self._pedb.padstacks.definitions[pdef_name]
|
|
210
396
|
pdef._padstack_def_data = pdef_data
|
|
211
|
-
|
|
397
|
+
# restore padstack instance layer map
|
|
212
398
|
for p_inst in self._pedb.layout.padstack_instances:
|
|
213
399
|
p_inst._edb_object.SetLayerMap(temp_p_inst_layer_map[p_inst.id])
|
|
214
400
|
|
|
215
|
-
def
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if materials:
|
|
221
|
-
edb_materials = {i.lower(): i for i, _ in self._pedb.materials.materials.items()}
|
|
222
|
-
for mat in materials:
|
|
223
|
-
name = mat["name"].lower()
|
|
224
|
-
if name in edb_materials:
|
|
225
|
-
self._pedb.materials.delete_material(edb_materials[name])
|
|
226
|
-
for mat in materials:
|
|
227
|
-
self._pedb.materials.add_material(**mat)
|
|
228
|
-
|
|
229
|
-
layers = data.get("layers")
|
|
230
|
-
|
|
231
|
-
if layers:
|
|
232
|
-
input_signal_layers = [i for i in layers if i["type"].lower() == "signal"]
|
|
233
|
-
if not len(input_signal_layers) == len(self._pedb.stackup.signal_layers):
|
|
234
|
-
self._pedb.logger.error("Input signal layer count do not match.")
|
|
235
|
-
return False
|
|
236
|
-
|
|
237
|
-
removal_list = []
|
|
238
|
-
lc_signal_layers = []
|
|
239
|
-
for name, obj in self._pedb.stackup.all_layers.items():
|
|
240
|
-
if obj.type == "dielectric":
|
|
241
|
-
removal_list.append(name)
|
|
242
|
-
elif obj.type == "signal":
|
|
243
|
-
lc_signal_layers.append(obj.id)
|
|
244
|
-
for l in removal_list:
|
|
245
|
-
self._pedb.stackup.remove_layer(l)
|
|
246
|
-
|
|
247
|
-
# update all signal layers
|
|
248
|
-
id_name = {i[0]: i[1] for i in self._pedb.stackup.layers_by_id}
|
|
249
|
-
signal_idx = 0
|
|
250
|
-
for l in layers:
|
|
251
|
-
if l["type"] == "signal":
|
|
252
|
-
layer_id = lc_signal_layers[signal_idx]
|
|
253
|
-
layer_name = id_name[layer_id]
|
|
254
|
-
self._pedb.stackup.layers[layer_name].update(**l)
|
|
255
|
-
signal_idx = signal_idx + 1
|
|
256
|
-
|
|
257
|
-
# add all dielectric layers. Dielectric layers must be added last. Otherwise,
|
|
258
|
-
# dielectric layer will occupy signal and document layer id.
|
|
259
|
-
prev_layer_clone = None
|
|
260
|
-
l = layers.pop(0)
|
|
261
|
-
if l["type"] == "signal":
|
|
262
|
-
prev_layer_clone = self._pedb.stackup.layers[l["name"]]
|
|
263
|
-
else:
|
|
264
|
-
prev_layer_clone = self._pedb.stackup.add_layer_top(**l)
|
|
265
|
-
for idx, l in enumerate(layers):
|
|
266
|
-
if l["type"] == "dielectric":
|
|
267
|
-
prev_layer_clone = self._pedb.stackup.add_layer_below(base_layer_name=prev_layer_clone.name, **l)
|
|
268
|
-
elif l["type"] == "signal":
|
|
269
|
-
prev_layer_clone = self._pedb.stackup.layers[l["name"]]
|
|
270
|
-
|
|
271
|
-
def _load_package_def(self):
|
|
272
|
-
"""Imports package definition information from JSON."""
|
|
273
|
-
comps = self._pedb.components.instances
|
|
274
|
-
for pkgd in self.data["package_definitions"]:
|
|
275
|
-
name = pkgd["name"]
|
|
276
|
-
if name in self._pedb.definitions.package:
|
|
277
|
-
self._pedb.definitions.package[name].delete()
|
|
278
|
-
extent_bounding_box = pkgd.get("extent_bounding_box", None)
|
|
279
|
-
if extent_bounding_box:
|
|
280
|
-
package_def = PackageDef(self._pedb, name=name, extent_bounding_box=extent_bounding_box)
|
|
281
|
-
else:
|
|
282
|
-
package_def = PackageDef(self._pedb, name=name, component_part_name=pkgd["component_definition"])
|
|
283
|
-
package_def.maximum_power = pkgd["maximum_power"]
|
|
284
|
-
package_def.therm_cond = pkgd["therm_cond"]
|
|
285
|
-
package_def.theta_jb = pkgd["theta_jb"]
|
|
286
|
-
package_def.theta_jc = pkgd["theta_jc"]
|
|
287
|
-
package_def.height = pkgd["height"]
|
|
288
|
-
|
|
289
|
-
heatsink = pkgd.get("heatsink", None)
|
|
290
|
-
if heatsink:
|
|
291
|
-
package_def.set_heatsink(
|
|
292
|
-
heatsink["fin_base_height"],
|
|
293
|
-
heatsink["fin_height"],
|
|
294
|
-
heatsink["fin_orientation"],
|
|
295
|
-
heatsink["fin_spacing"],
|
|
296
|
-
heatsink["fin_thickness"],
|
|
297
|
-
)
|
|
298
|
-
|
|
299
|
-
comp_def_name = pkgd["component_definition"]
|
|
300
|
-
comp_def = self._pedb.definitions.component[comp_def_name]
|
|
301
|
-
|
|
302
|
-
comp_list = dict()
|
|
303
|
-
if pkgd["apply_to_all"]:
|
|
304
|
-
comp_list.update(
|
|
305
|
-
{refdes: comp for refdes, comp in comp_def.components.items() if refdes not in pkgd["components"]}
|
|
306
|
-
)
|
|
307
|
-
else:
|
|
308
|
-
comp_list.update(
|
|
309
|
-
{refdes: comp for refdes, comp in comp_def.components.items() if refdes in pkgd["components"]}
|
|
310
|
-
)
|
|
311
|
-
for _, i in comp_list.items():
|
|
312
|
-
i.package_def = name
|
|
401
|
+
def get_stackup(self):
|
|
402
|
+
self.cfg_data.stackup.layers = []
|
|
403
|
+
for name, obj in self._pedb.stackup.all_layers.items():
|
|
404
|
+
self.cfg_data.stackup.add_layer_at_bottom(**obj.properties)
|
|
313
405
|
|
|
314
406
|
def get_data_from_db(self, **kwargs):
|
|
315
407
|
"""Get configuration data from layout.
|
|
@@ -323,11 +415,17 @@ class Configuration:
|
|
|
323
415
|
|
|
324
416
|
"""
|
|
325
417
|
self._pedb.logger.info("Getting data from layout database.")
|
|
418
|
+
self.get_variables()
|
|
419
|
+
self.get_materials()
|
|
420
|
+
self.get_stackup()
|
|
421
|
+
|
|
326
422
|
data = {}
|
|
327
423
|
if kwargs.get("general", False):
|
|
328
424
|
data["general"] = self.cfg_data.general.get_data_from_db()
|
|
425
|
+
if kwargs.get("variables", False):
|
|
426
|
+
data.update(self.cfg_data.variables.model_dump(exclude_none=True))
|
|
329
427
|
if kwargs.get("stackup", False):
|
|
330
|
-
data["stackup"] = self.cfg_data.stackup.
|
|
428
|
+
data["stackup"] = self.cfg_data.stackup.model_dump(exclude_none=True)
|
|
331
429
|
if kwargs.get("package_definitions", False):
|
|
332
430
|
data["package_definitions"] = self.cfg_data.package_definitions.get_data_from_db()
|
|
333
431
|
if kwargs.get("setups", False):
|
|
@@ -389,6 +487,7 @@ class Configuration:
|
|
|
389
487
|
s_parameters=True,
|
|
390
488
|
padstacks=True,
|
|
391
489
|
general=True,
|
|
490
|
+
variables=True,
|
|
392
491
|
):
|
|
393
492
|
"""Export the configuration data from layout to a file.
|
|
394
493
|
|
|
@@ -422,6 +521,8 @@ class Configuration:
|
|
|
422
521
|
Whether to export padstacks.
|
|
423
522
|
general : bool
|
|
424
523
|
Whether to export general information.
|
|
524
|
+
variables : bool
|
|
525
|
+
Whether to export variable.
|
|
425
526
|
Returns
|
|
426
527
|
-------
|
|
427
528
|
bool
|
|
@@ -440,6 +541,7 @@ class Configuration:
|
|
|
440
541
|
s_parameters=s_parameters,
|
|
441
542
|
padstacks=padstacks,
|
|
442
543
|
general=general,
|
|
544
|
+
variables=variables,
|
|
443
545
|
)
|
|
444
546
|
|
|
445
547
|
file_path = file_path if isinstance(file_path, Path) else Path(file_path)
|
|
@@ -28,7 +28,7 @@ class Model(ObjBase):
|
|
|
28
28
|
|
|
29
29
|
def __init__(self, pedb, edb_object):
|
|
30
30
|
super().__init__(pedb, edb_object)
|
|
31
|
-
self._model_type_mapping = {"PinPairModel": self._pedb.
|
|
31
|
+
self._model_type_mapping = {"PinPairModel": self._pedb.core.cell}
|
|
32
32
|
|
|
33
33
|
@property
|
|
34
34
|
def model_type(self):
|
|
@@ -102,7 +102,7 @@ class Layout(ObjBase):
|
|
|
102
102
|
|
|
103
103
|
@property
|
|
104
104
|
def _edb(self):
|
|
105
|
-
return self._pedb.
|
|
105
|
+
return self._pedb.core
|
|
106
106
|
|
|
107
107
|
def expanded_extent(self, nets, extent, expansion_factor, expansion_unitless, use_round_corner, num_increments):
|
|
108
108
|
"""Get an expanded polygon for the Nets collection.
|
|
@@ -38,7 +38,7 @@ class LayoutObj(ObjBase):
|
|
|
38
38
|
-------
|
|
39
39
|
Ansys.Ansoft.Edb
|
|
40
40
|
"""
|
|
41
|
-
return self._pedb.
|
|
41
|
+
return self._pedb.core
|
|
42
42
|
|
|
43
43
|
@property
|
|
44
44
|
def _layout_obj_instance(self):
|
|
@@ -48,12 +48,12 @@ class LayoutObj(ObjBase):
|
|
|
48
48
|
|
|
49
49
|
@property
|
|
50
50
|
def _edb_properties(self):
|
|
51
|
-
p = self._edb_object.GetProductSolverOption(self._edb.
|
|
51
|
+
p = self._edb_object.GetProductSolverOption(self._edb.core.ProductId.Designer, "HFSS")
|
|
52
52
|
return p
|
|
53
53
|
|
|
54
54
|
@_edb_properties.setter
|
|
55
55
|
def _edb_properties(self, value):
|
|
56
|
-
self._edb_object.SetProductSolverOption(self._edb.
|
|
56
|
+
self._edb_object.SetProductSolverOption(self._edb.core.ProductId.Designer, "HFSS", value)
|
|
57
57
|
|
|
58
58
|
@property
|
|
59
59
|
def _obj_type(self):
|
|
@@ -155,7 +155,7 @@ class Path(Primitive):
|
|
|
155
155
|
width = self.width
|
|
156
156
|
corner_style = self.corner_style
|
|
157
157
|
end_cap_style = self.get_end_cap_style()
|
|
158
|
-
cloned_path = self._app.
|
|
158
|
+
cloned_path = self._app.core.cell.primitive.path.create(
|
|
159
159
|
self._app.active_layout,
|
|
160
160
|
self.layer_name,
|
|
161
161
|
self.net,
|
|
@@ -264,10 +264,10 @@ class Primitive(Connectable):
|
|
|
264
264
|
"""
|
|
265
265
|
bbox = self.polygon_data._edb_object.GetBBox()
|
|
266
266
|
return [
|
|
267
|
-
round(bbox.Item1.X.ToDouble(),
|
|
268
|
-
round(bbox.Item1.Y.ToDouble(),
|
|
269
|
-
round(bbox.Item2.X.ToDouble(),
|
|
270
|
-
round(bbox.Item2.Y.ToDouble(),
|
|
267
|
+
round(bbox.Item1.X.ToDouble(), 9),
|
|
268
|
+
round(bbox.Item1.Y.ToDouble(), 9),
|
|
269
|
+
round(bbox.Item2.X.ToDouble(), 9),
|
|
270
|
+
round(bbox.Item2.Y.ToDouble(), 9),
|
|
271
271
|
]
|
|
272
272
|
|
|
273
273
|
def convert_to_polygon(self):
|
|
@@ -336,7 +336,7 @@ class Primitive(Connectable):
|
|
|
336
336
|
list of float
|
|
337
337
|
"""
|
|
338
338
|
if isinstance(point, (list, tuple)):
|
|
339
|
-
point = self._app.
|
|
339
|
+
point = self._app.core.geometry.point_data(self._app.edb_value(point[0]), self._app.edb_value(point[1]))
|
|
340
340
|
|
|
341
341
|
p0 = self.polygon_data._edb_object.GetClosestPoint(point)
|
|
342
342
|
return [p0.X.ToDouble(), p0.Y.ToDouble()]
|
|
@@ -540,7 +540,7 @@ class Primitive(Connectable):
|
|
|
540
540
|
-------
|
|
541
541
|
list of float
|
|
542
542
|
"""
|
|
543
|
-
if isinstance(point, self._app.
|
|
543
|
+
if isinstance(point, self._app.core.geometry.geometry.PointData):
|
|
544
544
|
point = [point.X.ToDouble(), point.Y.ToDouble()]
|
|
545
545
|
dist = 1e12
|
|
546
546
|
out = None
|
|
@@ -821,7 +821,7 @@ class Primitive(Connectable):
|
|
|
821
821
|
r"$end 'EM properties'\n"
|
|
822
822
|
)
|
|
823
823
|
|
|
824
|
-
pid = self._pedb.
|
|
824
|
+
pid = self._pedb.core.ProductId.Designer
|
|
825
825
|
_, p = self._edb_object.GetProductProperty(pid, 18, "")
|
|
826
826
|
if p:
|
|
827
827
|
return p
|
|
@@ -831,7 +831,7 @@ class Primitive(Connectable):
|
|
|
831
831
|
@_em_properties.setter
|
|
832
832
|
def _em_properties(self, em_prop):
|
|
833
833
|
"""Set EM properties"""
|
|
834
|
-
pid = self._pedb.
|
|
834
|
+
pid = self._pedb.core.ProductId.Designer
|
|
835
835
|
self._edb_object.SetProductProperty(pid, 18, em_prop)
|
|
836
836
|
|
|
837
837
|
@property
|
|
@@ -48,7 +48,7 @@ class PinGroupTerminal(Terminal):
|
|
|
48
48
|
:class:`pyedb.dotnet.database.edb_data.terminals.PinGroupTerminal`
|
|
49
49
|
"""
|
|
50
50
|
net_obj = self._pedb.layout.find_net_by_name(net_name)
|
|
51
|
-
term = self._pedb.
|
|
51
|
+
term = self._pedb.core.cell.terminal.PinGroupTerminal.Create(
|
|
52
52
|
self._pedb.active_layout,
|
|
53
53
|
net_obj._edb_object,
|
|
54
54
|
name,
|
|
@@ -50,7 +50,7 @@ class PointTerminal(Terminal):
|
|
|
50
50
|
-------
|
|
51
51
|
:class:`pyedb.dotnet.database.edb_data.terminals.PointTerminal`
|
|
52
52
|
"""
|
|
53
|
-
terminal = self._pedb.
|
|
53
|
+
terminal = self._pedb.core.cell.terminal.PointTerminal.Create(
|
|
54
54
|
self._pedb.active_layout,
|
|
55
55
|
self._pedb.layout.find_net_by_name(net)._edb_object,
|
|
56
56
|
name,
|