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.

Files changed (97) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_common.py +12 -15
  3. pyedb/configuration/cfg_data.py +2 -2
  4. pyedb/configuration/cfg_modeler.py +163 -234
  5. pyedb/configuration/cfg_ports_sources.py +6 -8
  6. pyedb/configuration/cfg_stackup.py +62 -249
  7. pyedb/configuration/configuration.py +272 -170
  8. pyedb/dotnet/database/cell/hierarchy/model.py +1 -1
  9. pyedb/dotnet/database/cell/layout.py +1 -1
  10. pyedb/dotnet/database/cell/layout_obj.py +3 -3
  11. pyedb/dotnet/database/cell/primitive/path.py +1 -1
  12. pyedb/dotnet/database/cell/primitive/primitive.py +8 -8
  13. pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
  14. pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
  15. pyedb/dotnet/database/cell/terminal/terminal.py +24 -26
  16. pyedb/dotnet/database/components.py +33 -27
  17. pyedb/dotnet/database/definition/component_def.py +3 -3
  18. pyedb/dotnet/database/definition/component_model.py +1 -1
  19. pyedb/dotnet/database/definition/package_def.py +1 -1
  20. pyedb/dotnet/database/dotnet/database.py +47 -38
  21. pyedb/dotnet/database/dotnet/primitive.py +16 -16
  22. pyedb/dotnet/database/edb_data/hfss_extent_info.py +6 -6
  23. pyedb/dotnet/database/edb_data/layer_data.py +17 -15
  24. pyedb/dotnet/database/edb_data/padstacks_data.py +12 -12
  25. pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
  26. pyedb/dotnet/database/edb_data/sources.py +6 -6
  27. pyedb/dotnet/database/edb_data/variables.py +7 -3
  28. pyedb/dotnet/database/geometry/point_data.py +1 -1
  29. pyedb/dotnet/database/geometry/polygon_data.py +2 -4
  30. pyedb/dotnet/database/hfss.py +7 -7
  31. pyedb/dotnet/database/materials.py +2 -2
  32. pyedb/dotnet/database/modeler.py +8 -11
  33. pyedb/dotnet/database/nets.py +1 -1
  34. pyedb/dotnet/database/padstack.py +72 -1
  35. pyedb/dotnet/database/sim_setup_data/data/settings.py +24 -0
  36. pyedb/dotnet/database/sim_setup_data/io/siwave.py +26 -1
  37. pyedb/dotnet/database/siwave.py +19 -5
  38. pyedb/dotnet/database/stackup.py +80 -137
  39. pyedb/dotnet/database/utilities/heatsink.py +4 -4
  40. pyedb/dotnet/database/utilities/obj_base.py +1 -1
  41. pyedb/dotnet/database/utilities/simulation_setup.py +1 -1
  42. pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +894 -0
  43. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +15 -0
  44. pyedb/dotnet/database/utilities/value.py +116 -0
  45. pyedb/dotnet/edb.py +58 -45
  46. pyedb/generic/design_types.py +39 -1
  47. pyedb/generic/grpc_warnings.py +5 -0
  48. pyedb/grpc/__init__.py +0 -0
  49. pyedb/grpc/database/components.py +155 -98
  50. pyedb/grpc/database/control_file.py +240 -193
  51. pyedb/grpc/database/definition/materials.py +23 -30
  52. pyedb/grpc/database/definition/package_def.py +15 -15
  53. pyedb/grpc/database/definition/padstack_def.py +51 -51
  54. pyedb/grpc/database/definitions.py +7 -5
  55. pyedb/grpc/database/geometry/arc_data.py +7 -5
  56. pyedb/grpc/database/geometry/point_3d_data.py +8 -7
  57. pyedb/grpc/database/geometry/polygon_data.py +3 -2
  58. pyedb/grpc/database/hierarchy/component.py +43 -38
  59. pyedb/grpc/database/hierarchy/pin_pair_model.py +15 -14
  60. pyedb/grpc/database/hierarchy/pingroup.py +9 -9
  61. pyedb/grpc/database/layers/stackup_layer.py +45 -44
  62. pyedb/grpc/database/layout/layout.py +9 -8
  63. pyedb/grpc/database/layout/voltage_regulator.py +7 -7
  64. pyedb/grpc/database/layout_validation.py +13 -12
  65. pyedb/grpc/database/modeler.py +156 -131
  66. pyedb/grpc/database/nets.py +42 -31
  67. pyedb/grpc/database/padstacks.py +270 -175
  68. pyedb/grpc/database/ports/ports.py +5 -6
  69. pyedb/grpc/database/primitive/bondwire.py +8 -7
  70. pyedb/grpc/database/primitive/circle.py +4 -4
  71. pyedb/grpc/database/primitive/padstack_instance.py +18 -18
  72. pyedb/grpc/database/primitive/path.py +7 -7
  73. pyedb/grpc/database/primitive/polygon.py +3 -3
  74. pyedb/grpc/database/primitive/primitive.py +13 -17
  75. pyedb/grpc/database/primitive/rectangle.py +13 -13
  76. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
  77. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +10 -0
  78. pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +961 -0
  79. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +17 -1
  80. pyedb/grpc/database/siwave.py +44 -24
  81. pyedb/grpc/database/source_excitations.py +333 -229
  82. pyedb/grpc/database/stackup.py +164 -147
  83. pyedb/grpc/database/terminal/bundle_terminal.py +17 -7
  84. pyedb/grpc/database/terminal/edge_terminal.py +10 -0
  85. pyedb/grpc/database/terminal/padstack_instance_terminal.py +15 -4
  86. pyedb/grpc/database/terminal/pingroup_terminal.py +11 -10
  87. pyedb/grpc/database/terminal/point_terminal.py +4 -3
  88. pyedb/grpc/database/terminal/terminal.py +9 -9
  89. pyedb/grpc/database/utility/value.py +109 -0
  90. pyedb/grpc/edb.py +129 -45
  91. pyedb/grpc/edb_init.py +0 -7
  92. pyedb/siwave_core/cpa/simulation_setup_data_model.py +132 -0
  93. pyedb/siwave_core/product_properties.py +198 -0
  94. {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/METADATA +15 -13
  95. {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/RECORD +97 -89
  96. {pyedb-0.52.0.dist-info → pyedb-0.54.0.dist-info}/WHEEL +1 -1
  97. {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
- if self.cfg_data.variables:
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
- self._pedb.logger.info(f"Updating nets finished. Time lapse {datetime.now() - now}")
130
- now = datetime.now()
131
-
132
- # Configure components
133
- self.cfg_data.components.apply()
134
- self._pedb.logger.info(f"Updating components finished. Time lapse {datetime.now() - now}")
135
- now = datetime.now()
136
-
137
- # Configure pin groups
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
- # Configure S-parameter
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
- # Configure package definitions
175
- self.cfg_data.package_definitions.apply()
176
- self._pedb.logger.info(f"Applying package definitions finished. Time lapse {datetime.now() - now}")
177
- now = datetime.now()
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
- # Modeler
180
- self.cfg_data.modeler.apply()
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
- # Configure ports
183
- self.cfg_data.ports.apply()
184
- self._pedb.logger.info(f"Placing ports finished. Time lapse {datetime.now() - now}")
185
- now = datetime.now()
288
+ Parameters
289
+ ----------
290
+ append: bool, optional
291
+ If `True`, append materials to the current material list.
292
+ """
186
293
 
187
- # Configure probes
188
- self.cfg_data.probes.apply()
189
- self._pedb.logger.info(f"Placing probes finished. Time lapse {datetime.now() - now}")
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
- # Configure operations
192
- self.cfg_data.operations.apply()
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
- return True
337
+ def __update_stackup(self):
338
+ """Apply layer settings to the current design"""
195
339
 
196
- def configuration_stackup(self):
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
- self.cfg_data.stackup.apply()
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 _load_stackup(self):
216
- """Imports stackup information from json."""
217
- data = self.data["stackup"]
218
- materials = data.get("materials")
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.get_data_from_db()
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.edb_api.cell}
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.edb_api
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.edb_api
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.edb_api.ProductId.Designer, "HFSS")
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.edb_api.ProductId.Designer, "HFSS", value)
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.edb_api.cell.primitive.path.create(
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(), 6),
268
- round(bbox.Item1.Y.ToDouble(), 6),
269
- round(bbox.Item2.X.ToDouble(), 6),
270
- round(bbox.Item2.Y.ToDouble(), 6),
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.edb_api.geometry.point_data(self._app.edb_value(point[0]), self._app.edb_value(point[1]))
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.edb_api.geometry.geometry.PointData):
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.edb_api.ProductId.Designer
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.edb_api.ProductId.Designer
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.edb_api.cell.terminal.PinGroupTerminal.Create(
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.edb_api.cell.terminal.PointTerminal.Create(
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,