pyedb 0.50.0__py3-none-any.whl → 0.50.1__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/dotnet/database/cell/hierarchy/component.py +3 -3
- pyedb/dotnet/database/edb_data/padstacks_data.py +13 -0
- pyedb/grpc/database/components.py +494 -652
- pyedb/grpc/database/control_file.py +458 -149
- pyedb/grpc/database/definition/component_def.py +17 -14
- pyedb/grpc/database/definition/materials.py +27 -27
- pyedb/grpc/database/definition/package_def.py +8 -8
- pyedb/grpc/database/definition/padstack_def.py +31 -33
- pyedb/grpc/database/geometry/arc_data.py +5 -5
- pyedb/grpc/database/geometry/point_3d_data.py +3 -3
- pyedb/grpc/database/geometry/polygon_data.py +5 -5
- pyedb/grpc/database/hfss.py +397 -395
- pyedb/grpc/database/hierarchy/component.py +58 -57
- pyedb/grpc/database/hierarchy/pin_pair_model.py +6 -6
- pyedb/grpc/database/hierarchy/pingroup.py +13 -11
- pyedb/grpc/database/hierarchy/s_parameter_model.py +1 -1
- pyedb/grpc/database/hierarchy/spice_model.py +1 -1
- pyedb/grpc/database/layers/layer.py +2 -2
- pyedb/grpc/database/layers/stackup_layer.py +26 -23
- pyedb/grpc/database/layout/layout.py +12 -12
- pyedb/grpc/database/layout/voltage_regulator.py +8 -8
- pyedb/grpc/database/modeler.py +248 -245
- pyedb/grpc/database/net/differential_pair.py +4 -4
- pyedb/grpc/database/net/extended_net.py +7 -8
- pyedb/grpc/database/net/net.py +57 -46
- pyedb/grpc/database/nets.py +139 -122
- pyedb/grpc/database/padstacks.py +174 -190
- pyedb/grpc/database/ports/ports.py +23 -17
- pyedb/grpc/database/primitive/padstack_instance.py +45 -30
- pyedb/grpc/database/primitive/path.py +6 -6
- pyedb/grpc/database/primitive/polygon.py +9 -9
- pyedb/grpc/database/primitive/primitive.py +21 -21
- pyedb/grpc/database/primitive/rectangle.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_settings_options.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +6 -6
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +2 -2
- pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +2 -2
- pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +1 -1
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +3 -3
- pyedb/grpc/database/siwave.py +166 -214
- pyedb/grpc/database/stackup.py +365 -292
- pyedb/grpc/database/terminal/bundle_terminal.py +12 -12
- pyedb/grpc/database/terminal/edge_terminal.py +6 -5
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +13 -13
- pyedb/grpc/database/terminal/pingroup_terminal.py +12 -12
- pyedb/grpc/database/terminal/point_terminal.py +6 -6
- pyedb/grpc/database/terminal/terminal.py +26 -26
- pyedb/grpc/database/utility/heat_sink.py +5 -5
- pyedb/grpc/database/utility/hfss_extent_info.py +21 -21
- pyedb/grpc/database/utility/layout_statistics.py +13 -13
- pyedb/grpc/database/utility/rlc.py +3 -3
- pyedb/grpc/database/utility/sources.py +1 -1
- pyedb/grpc/database/utility/sweep_data_distribution.py +1 -1
- pyedb/grpc/edb.py +422 -672
- {pyedb-0.50.0.dist-info → pyedb-0.50.1.dist-info}/METADATA +1 -1
- {pyedb-0.50.0.dist-info → pyedb-0.50.1.dist-info}/RECORD +61 -62
- pyedb/grpc/database/utility/simulation_configuration.py +0 -3305
- {pyedb-0.50.0.dist-info → pyedb-0.50.1.dist-info}/LICENSE +0 -0
- {pyedb-0.50.0.dist-info → pyedb-0.50.1.dist-info}/WHEEL +0 -0
|
@@ -33,21 +33,25 @@ from pyedb.misc.misc import list_installed_ansysem
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
def convert_technology_file(tech_file, edbversion=None, control_file=None):
|
|
36
|
-
"""Convert a technology file to
|
|
36
|
+
"""Convert a technology file to EDB control file (XML).
|
|
37
37
|
|
|
38
38
|
Parameters
|
|
39
39
|
----------
|
|
40
40
|
tech_file : str
|
|
41
|
-
Full path to technology file
|
|
42
|
-
edbversion : str,
|
|
43
|
-
|
|
44
|
-
control_file : str,
|
|
45
|
-
|
|
41
|
+
Full path to technology file.
|
|
42
|
+
edbversion : str, optional
|
|
43
|
+
EDB version to use. If ``None``, uses latest available version.
|
|
44
|
+
control_file : str, optional
|
|
45
|
+
Output control file path. If ``None``, uses same path and name as ``tech_file``.
|
|
46
46
|
|
|
47
47
|
Returns
|
|
48
48
|
-------
|
|
49
|
-
str
|
|
50
|
-
|
|
49
|
+
str or bool
|
|
50
|
+
Full path to created control file if successful, ``False`` otherwise.
|
|
51
|
+
|
|
52
|
+
Notes
|
|
53
|
+
-----
|
|
54
|
+
This function is only supported on Linux systems.
|
|
51
55
|
"""
|
|
52
56
|
if is_linux: # pragma: no cover
|
|
53
57
|
if not edbversion:
|
|
@@ -56,7 +60,7 @@ def convert_technology_file(tech_file, edbversion=None, control_file=None):
|
|
|
56
60
|
base_path = env_path(edbversion)
|
|
57
61
|
sys.path.append(base_path)
|
|
58
62
|
else:
|
|
59
|
-
pyedb_logger.error("No
|
|
63
|
+
pyedb_logger.error("No EDB installation found. Check environment variables")
|
|
60
64
|
return False
|
|
61
65
|
os.environ["HELIC_ROOT"] = os.path.join(base_path, "helic")
|
|
62
66
|
if os.getenv("ANSYSLMD_LICENCE_FILE", None) is None:
|
|
@@ -103,13 +107,23 @@ def convert_technology_file(tech_file, edbversion=None, control_file=None):
|
|
|
103
107
|
p = subprocess.Popen(command, env=my_env)
|
|
104
108
|
p.wait()
|
|
105
109
|
if os.path.exists(control_file):
|
|
106
|
-
pyedb_logger.info("
|
|
110
|
+
pyedb_logger.info("XML file created.")
|
|
107
111
|
return control_file
|
|
108
112
|
pyedb_logger.error("Technology files are supported only in Linux. Use control file instead.")
|
|
109
113
|
return False
|
|
110
114
|
|
|
111
115
|
|
|
112
116
|
class ControlProperty:
|
|
117
|
+
"""Represents a property in the control file with name, value, and type.
|
|
118
|
+
|
|
119
|
+
Parameters
|
|
120
|
+
----------
|
|
121
|
+
property_name : str
|
|
122
|
+
Name of the property.
|
|
123
|
+
value : str, float, or list
|
|
124
|
+
Value of the property.
|
|
125
|
+
"""
|
|
126
|
+
|
|
113
127
|
def __init__(self, property_name, value):
|
|
114
128
|
self.name = property_name
|
|
115
129
|
self.value = value
|
|
@@ -125,6 +139,13 @@ class ControlProperty:
|
|
|
125
139
|
pass
|
|
126
140
|
|
|
127
141
|
def _write_xml(self, root):
|
|
142
|
+
"""Write the property to XML element.
|
|
143
|
+
|
|
144
|
+
Parameters
|
|
145
|
+
----------
|
|
146
|
+
root : xml.etree.ElementTree.Element
|
|
147
|
+
Parent XML element to append to.
|
|
148
|
+
"""
|
|
128
149
|
try:
|
|
129
150
|
if self.type == 0:
|
|
130
151
|
content = ET.SubElement(root, self.name)
|
|
@@ -137,6 +158,16 @@ class ControlProperty:
|
|
|
137
158
|
|
|
138
159
|
|
|
139
160
|
class ControlFileMaterial:
|
|
161
|
+
"""Represents a material in the control file.
|
|
162
|
+
|
|
163
|
+
Parameters
|
|
164
|
+
----------
|
|
165
|
+
name : str
|
|
166
|
+
Material name.
|
|
167
|
+
properties : dict
|
|
168
|
+
Material properties dictionary.
|
|
169
|
+
"""
|
|
170
|
+
|
|
140
171
|
def __init__(self, name, properties):
|
|
141
172
|
self.name = name
|
|
142
173
|
self.properties = {}
|
|
@@ -144,6 +175,13 @@ class ControlFileMaterial:
|
|
|
144
175
|
self.properties[name] = ControlProperty(name, property)
|
|
145
176
|
|
|
146
177
|
def _write_xml(self, root):
|
|
178
|
+
"""Write material to XML element.
|
|
179
|
+
|
|
180
|
+
Parameters
|
|
181
|
+
----------
|
|
182
|
+
root : xml.etree.ElementTree.Element
|
|
183
|
+
Parent XML element to append to.
|
|
184
|
+
"""
|
|
147
185
|
content = ET.SubElement(root, "Material")
|
|
148
186
|
content.set("Name", self.name)
|
|
149
187
|
for property_name, property in self.properties.items():
|
|
@@ -151,6 +189,16 @@ class ControlFileMaterial:
|
|
|
151
189
|
|
|
152
190
|
|
|
153
191
|
class ControlFileDielectric:
|
|
192
|
+
"""Represents a dielectric layer in the control file.
|
|
193
|
+
|
|
194
|
+
Parameters
|
|
195
|
+
----------
|
|
196
|
+
name : str
|
|
197
|
+
Layer name.
|
|
198
|
+
properties : dict
|
|
199
|
+
Layer properties dictionary.
|
|
200
|
+
"""
|
|
201
|
+
|
|
154
202
|
def __init__(self, name, properties):
|
|
155
203
|
self.name = name
|
|
156
204
|
self.properties = {}
|
|
@@ -158,6 +206,13 @@ class ControlFileDielectric:
|
|
|
158
206
|
self.properties[name] = prop
|
|
159
207
|
|
|
160
208
|
def _write_xml(self, root):
|
|
209
|
+
"""Write dielectric layer to XML element.
|
|
210
|
+
|
|
211
|
+
Parameters
|
|
212
|
+
----------
|
|
213
|
+
root : xml.etree.ElementTree.Element
|
|
214
|
+
Parent XML element to append to.
|
|
215
|
+
"""
|
|
161
216
|
content = ET.SubElement(root, "Layer")
|
|
162
217
|
for property_name, property in self.properties.items():
|
|
163
218
|
if not property_name == "Index":
|
|
@@ -165,6 +220,16 @@ class ControlFileDielectric:
|
|
|
165
220
|
|
|
166
221
|
|
|
167
222
|
class ControlFileLayer:
|
|
223
|
+
"""Represents a general layer in the control file.
|
|
224
|
+
|
|
225
|
+
Parameters
|
|
226
|
+
----------
|
|
227
|
+
name : str
|
|
228
|
+
Layer name.
|
|
229
|
+
properties : dict
|
|
230
|
+
Layer properties dictionary.
|
|
231
|
+
"""
|
|
232
|
+
|
|
168
233
|
def __init__(self, name, properties):
|
|
169
234
|
self.name = name
|
|
170
235
|
self.properties = {}
|
|
@@ -172,6 +237,13 @@ class ControlFileLayer:
|
|
|
172
237
|
self.properties[name] = prop
|
|
173
238
|
|
|
174
239
|
def _write_xml(self, root):
|
|
240
|
+
"""Write layer to XML element.
|
|
241
|
+
|
|
242
|
+
Parameters
|
|
243
|
+
----------
|
|
244
|
+
root : xml.etree.ElementTree.Element
|
|
245
|
+
Parent XML element to append to.
|
|
246
|
+
"""
|
|
175
247
|
content = ET.SubElement(root, "Layer")
|
|
176
248
|
content.set("Color", self.properties.get("Color", "#5c4300"))
|
|
177
249
|
if self.properties.get("Elevation"):
|
|
@@ -196,6 +268,16 @@ class ControlFileLayer:
|
|
|
196
268
|
|
|
197
269
|
|
|
198
270
|
class ControlFileVia(ControlFileLayer):
|
|
271
|
+
"""Represents a via layer in the control file.
|
|
272
|
+
|
|
273
|
+
Parameters
|
|
274
|
+
----------
|
|
275
|
+
name : str
|
|
276
|
+
Via name.
|
|
277
|
+
properties : dict
|
|
278
|
+
Via properties dictionary.
|
|
279
|
+
"""
|
|
280
|
+
|
|
199
281
|
def __init__(self, name, properties):
|
|
200
282
|
ControlFileLayer.__init__(self, name, properties)
|
|
201
283
|
self.create_via_group = False
|
|
@@ -209,6 +291,13 @@ class ControlFileVia(ControlFileLayer):
|
|
|
209
291
|
self.snap_tolerance = 3
|
|
210
292
|
|
|
211
293
|
def _write_xml(self, root):
|
|
294
|
+
"""Write via to XML element.
|
|
295
|
+
|
|
296
|
+
Parameters
|
|
297
|
+
----------
|
|
298
|
+
root : xml.etree.ElementTree.Element
|
|
299
|
+
Parent XML element to append to.
|
|
300
|
+
"""
|
|
212
301
|
content = ET.SubElement(root, "Layer")
|
|
213
302
|
content.set("Color", self.properties.get("Color", "#5c4300"))
|
|
214
303
|
if self.properties.get("Elevation"):
|
|
@@ -240,7 +329,13 @@ class ControlFileVia(ControlFileLayer):
|
|
|
240
329
|
|
|
241
330
|
|
|
242
331
|
class ControlFileStackup:
|
|
243
|
-
"""
|
|
332
|
+
"""Manages stackup information for the control file.
|
|
333
|
+
|
|
334
|
+
Parameters
|
|
335
|
+
----------
|
|
336
|
+
units : str, optional
|
|
337
|
+
Length units (e.g., "mm", "um"). Default is "mm".
|
|
338
|
+
"""
|
|
244
339
|
|
|
245
340
|
def __init__(self, units="mm"):
|
|
246
341
|
self._materials = {}
|
|
@@ -253,45 +348,42 @@ class ControlFileStackup:
|
|
|
253
348
|
|
|
254
349
|
@property
|
|
255
350
|
def vias(self):
|
|
256
|
-
"""
|
|
351
|
+
"""List of via objects.
|
|
257
352
|
|
|
258
353
|
Returns
|
|
259
354
|
-------
|
|
260
|
-
list of
|
|
261
|
-
|
|
355
|
+
list of ControlFileVia
|
|
262
356
|
"""
|
|
263
357
|
return self._vias
|
|
264
358
|
|
|
265
359
|
@property
|
|
266
360
|
def materials(self):
|
|
267
|
-
"""
|
|
361
|
+
"""Dictionary of material objects.
|
|
268
362
|
|
|
269
363
|
Returns
|
|
270
364
|
-------
|
|
271
|
-
|
|
272
|
-
|
|
365
|
+
dict
|
|
366
|
+
Dictionary of material names to ControlFileMaterial objects.
|
|
273
367
|
"""
|
|
274
368
|
return self._materials
|
|
275
369
|
|
|
276
370
|
@property
|
|
277
371
|
def dielectrics(self):
|
|
278
|
-
"""
|
|
372
|
+
"""List of dielectric layers.
|
|
279
373
|
|
|
280
374
|
Returns
|
|
281
375
|
-------
|
|
282
|
-
list of
|
|
283
|
-
|
|
376
|
+
list of ControlFileDielectric
|
|
284
377
|
"""
|
|
285
378
|
return self._dielectrics
|
|
286
379
|
|
|
287
380
|
@property
|
|
288
381
|
def layers(self):
|
|
289
|
-
"""
|
|
382
|
+
"""List of general layers.
|
|
290
383
|
|
|
291
384
|
Returns
|
|
292
385
|
-------
|
|
293
|
-
list of
|
|
294
|
-
|
|
386
|
+
list of ControlFileLayer
|
|
295
387
|
"""
|
|
296
388
|
return self._layers
|
|
297
389
|
|
|
@@ -304,27 +396,27 @@ class ControlFileStackup:
|
|
|
304
396
|
conductivity=0.0,
|
|
305
397
|
properties=None,
|
|
306
398
|
):
|
|
307
|
-
"""Add a new material
|
|
399
|
+
"""Add a new material.
|
|
308
400
|
|
|
309
401
|
Parameters
|
|
310
402
|
----------
|
|
311
403
|
material_name : str
|
|
312
404
|
Material name.
|
|
313
405
|
permittivity : float, optional
|
|
314
|
-
|
|
406
|
+
Relative permittivity. Default is ``1.0``.
|
|
315
407
|
dielectric_loss_tg : float, optional
|
|
316
|
-
|
|
408
|
+
Dielectric loss tangent. Default is ``0.0``.
|
|
317
409
|
permeability : float, optional
|
|
318
|
-
|
|
410
|
+
Relative permeability. Default is ``1.0``.
|
|
319
411
|
conductivity : float, optional
|
|
320
|
-
|
|
412
|
+
Conductivity (S/m). Default is ``0.0``.
|
|
321
413
|
properties : dict, optional
|
|
322
|
-
|
|
323
|
-
Dictionary with key and material property value.
|
|
414
|
+
Additional material properties. Overrides default parameters.
|
|
324
415
|
|
|
325
416
|
Returns
|
|
326
417
|
-------
|
|
327
|
-
|
|
418
|
+
ControlFileMaterial
|
|
419
|
+
Created material object.
|
|
328
420
|
"""
|
|
329
421
|
if isinstance(properties, dict):
|
|
330
422
|
self._materials[material_name] = ControlFileMaterial(material_name, properties)
|
|
@@ -359,26 +451,26 @@ class ControlFileStackup:
|
|
|
359
451
|
layer_name : str
|
|
360
452
|
Layer name.
|
|
361
453
|
elevation : float
|
|
362
|
-
Layer elevation.
|
|
454
|
+
Layer elevation (Z-position).
|
|
363
455
|
material : str
|
|
364
|
-
Material
|
|
456
|
+
Material name.
|
|
365
457
|
gds_type : int
|
|
366
|
-
GDS type
|
|
367
|
-
imported.
|
|
458
|
+
GDS data type for layer.
|
|
368
459
|
target_layer : str
|
|
369
|
-
|
|
460
|
+
Target layer name in EDB/HFSS.
|
|
370
461
|
thickness : float
|
|
371
|
-
Layer thickness
|
|
372
|
-
layer_type : str
|
|
373
|
-
|
|
374
|
-
solve_inside : bool
|
|
375
|
-
|
|
376
|
-
properties : dict
|
|
377
|
-
|
|
462
|
+
Layer thickness.
|
|
463
|
+
layer_type : str, optional
|
|
464
|
+
Layer type ("conductor", "signal", etc.). Default is "conductor".
|
|
465
|
+
solve_inside : bool, optional
|
|
466
|
+
Whether to solve inside metal. Default is ``True``.
|
|
467
|
+
properties : dict, optional
|
|
468
|
+
Additional layer properties. Overrides default parameters.
|
|
378
469
|
|
|
379
470
|
Returns
|
|
380
471
|
-------
|
|
381
|
-
|
|
472
|
+
ControlFileLayer
|
|
473
|
+
Created layer object.
|
|
382
474
|
"""
|
|
383
475
|
if isinstance(properties, dict):
|
|
384
476
|
self._layers.append(ControlFileLayer(layer_name, properties))
|
|
@@ -407,31 +499,29 @@ class ControlFileStackup:
|
|
|
407
499
|
base_layer=None,
|
|
408
500
|
add_on_top=True,
|
|
409
501
|
):
|
|
410
|
-
"""Add a new dielectric.
|
|
502
|
+
"""Add a new dielectric layer.
|
|
411
503
|
|
|
412
504
|
Parameters
|
|
413
505
|
----------
|
|
414
506
|
layer_name : str
|
|
415
|
-
|
|
507
|
+
Dielectric layer name.
|
|
416
508
|
layer_index : int, optional
|
|
417
|
-
|
|
509
|
+
Stacking order index. Auto-assigned if ``None``.
|
|
418
510
|
material : str
|
|
419
511
|
Material name.
|
|
420
512
|
thickness : float
|
|
421
513
|
Layer thickness.
|
|
422
|
-
properties : dict
|
|
423
|
-
|
|
424
|
-
base_layer : str,
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
on top of
|
|
428
|
-
method : bool, Optional.
|
|
429
|
-
Provides the method to use when the argument ``base_layer`` is provided. When ``True`` the layer is added
|
|
430
|
-
on top on the base layer, when ``False`` it will be added below.
|
|
514
|
+
properties : dict, optional
|
|
515
|
+
Additional properties. Overrides default parameters.
|
|
516
|
+
base_layer : str, optional
|
|
517
|
+
Existing layer name for relative placement.
|
|
518
|
+
add_on_top : bool, optional
|
|
519
|
+
Whether to add on top of base layer. Default is ``True``.
|
|
431
520
|
|
|
432
521
|
Returns
|
|
433
522
|
-------
|
|
434
|
-
|
|
523
|
+
ControlFileDielectric
|
|
524
|
+
Created dielectric layer object.
|
|
435
525
|
"""
|
|
436
526
|
if isinstance(properties, dict):
|
|
437
527
|
self._dielectrics.append(ControlFileDielectric(layer_name, properties))
|
|
@@ -481,35 +571,36 @@ class ControlFileStackup:
|
|
|
481
571
|
Parameters
|
|
482
572
|
----------
|
|
483
573
|
layer_name : str
|
|
484
|
-
|
|
574
|
+
Via layer name.
|
|
485
575
|
material : str
|
|
486
|
-
|
|
576
|
+
Material name.
|
|
487
577
|
gds_type : int
|
|
488
|
-
|
|
578
|
+
GDS data type for via layer.
|
|
489
579
|
target_layer : str
|
|
490
|
-
Target layer
|
|
580
|
+
Target layer name in EDB/HFSS.
|
|
491
581
|
start_layer : str
|
|
492
|
-
|
|
582
|
+
Starting layer name.
|
|
493
583
|
stop_layer : str
|
|
494
|
-
|
|
495
|
-
solve_inside : bool
|
|
496
|
-
|
|
497
|
-
via_group_method : str
|
|
498
|
-
|
|
499
|
-
via_group_tol : float
|
|
500
|
-
|
|
501
|
-
via_group_persistent : bool
|
|
502
|
-
|
|
503
|
-
snap_via_group_method : str
|
|
504
|
-
|
|
505
|
-
snap_via_group_tol : float
|
|
506
|
-
|
|
507
|
-
properties : dict
|
|
508
|
-
|
|
584
|
+
Stopping layer name.
|
|
585
|
+
solve_inside : bool, optional
|
|
586
|
+
Whether to solve inside via. Default is ``True``.
|
|
587
|
+
via_group_method : str, optional
|
|
588
|
+
Via grouping method. Default is "proximity".
|
|
589
|
+
via_group_tol : float, optional
|
|
590
|
+
Via grouping tolerance. Default is 1e-6.
|
|
591
|
+
via_group_persistent : bool, optional
|
|
592
|
+
Whether via groups are persistent. Default is ``True``.
|
|
593
|
+
snap_via_group_method : str, optional
|
|
594
|
+
Snap via group method. Default is "distance".
|
|
595
|
+
snap_via_group_tol : float, optional
|
|
596
|
+
Snap via group tolerance. Default is 10e-9.
|
|
597
|
+
properties : dict, optional
|
|
598
|
+
Additional properties. Overrides default parameters.
|
|
509
599
|
|
|
510
600
|
Returns
|
|
511
601
|
-------
|
|
512
|
-
|
|
602
|
+
ControlFileVia
|
|
603
|
+
Created via object.
|
|
513
604
|
"""
|
|
514
605
|
if isinstance(properties, dict):
|
|
515
606
|
self._vias.append(ControlFileVia(layer_name, properties))
|
|
@@ -533,6 +624,13 @@ class ControlFileStackup:
|
|
|
533
624
|
return self._vias[-1]
|
|
534
625
|
|
|
535
626
|
def _write_xml(self, root):
|
|
627
|
+
"""Write stackup to XML element.
|
|
628
|
+
|
|
629
|
+
Parameters
|
|
630
|
+
----------
|
|
631
|
+
root : xml.etree.ElementTree.Element
|
|
632
|
+
Parent XML element to append to.
|
|
633
|
+
"""
|
|
536
634
|
content = ET.SubElement(root, "Stackup")
|
|
537
635
|
content.set("schemaVersion", "1.0")
|
|
538
636
|
materials = ET.SubElement(content, "Materials")
|
|
@@ -559,7 +657,7 @@ class ControlFileStackup:
|
|
|
559
657
|
|
|
560
658
|
|
|
561
659
|
class ControlFileImportOptions:
|
|
562
|
-
"""
|
|
660
|
+
"""Manages import options for the control file."""
|
|
563
661
|
|
|
564
662
|
def __init__(self):
|
|
565
663
|
self.auto_close = False
|
|
@@ -579,6 +677,13 @@ class ControlFileImportOptions:
|
|
|
579
677
|
self.delte_empty_non_laminate_signal_layers = False
|
|
580
678
|
|
|
581
679
|
def _write_xml(self, root):
|
|
680
|
+
"""Write import options to XML element.
|
|
681
|
+
|
|
682
|
+
Parameters
|
|
683
|
+
----------
|
|
684
|
+
root : xml.etree.ElementTree.Element
|
|
685
|
+
Parent XML element to append to.
|
|
686
|
+
"""
|
|
582
687
|
content = ET.SubElement(root, "ImportOptions")
|
|
583
688
|
content.set("AutoClose", str(self.auto_close).lower())
|
|
584
689
|
if self.round_to != 0:
|
|
@@ -603,7 +708,29 @@ class ControlFileImportOptions:
|
|
|
603
708
|
|
|
604
709
|
|
|
605
710
|
class ControlExtent:
|
|
606
|
-
"""
|
|
711
|
+
"""Represents extent options for boundaries.
|
|
712
|
+
|
|
713
|
+
Parameters
|
|
714
|
+
----------
|
|
715
|
+
type : str, optional
|
|
716
|
+
Extent type. Default is "bbox".
|
|
717
|
+
dieltype : str, optional
|
|
718
|
+
Dielectric extent type. Default is "bbox".
|
|
719
|
+
diel_hactor : float, optional
|
|
720
|
+
Dielectric horizontal factor. Default is 0.25.
|
|
721
|
+
airbox_hfactor : float, optional
|
|
722
|
+
Airbox horizontal factor. Default is 0.25.
|
|
723
|
+
airbox_vr_p : float, optional
|
|
724
|
+
Airbox vertical factor (positive). Default is 0.25.
|
|
725
|
+
airbox_vr_n : float, optional
|
|
726
|
+
Airbox vertical factor (negative). Default is 0.25.
|
|
727
|
+
useradiation : bool, optional
|
|
728
|
+
Use radiation boundary. Default is ``True``.
|
|
729
|
+
honor_primitives : bool, optional
|
|
730
|
+
Honor primitives. Default is ``True``.
|
|
731
|
+
truncate_at_gnd : bool, optional
|
|
732
|
+
Truncate at ground. Default is ``True``.
|
|
733
|
+
"""
|
|
607
734
|
|
|
608
735
|
def __init__(
|
|
609
736
|
self,
|
|
@@ -628,6 +755,13 @@ class ControlExtent:
|
|
|
628
755
|
self.truncate_at_gnd = truncate_at_gnd
|
|
629
756
|
|
|
630
757
|
def _write_xml(self, root):
|
|
758
|
+
"""Write extent options to XML element.
|
|
759
|
+
|
|
760
|
+
Parameters
|
|
761
|
+
----------
|
|
762
|
+
root : xml.etree.ElementTree.Element
|
|
763
|
+
Parent XML element to append to.
|
|
764
|
+
"""
|
|
631
765
|
content = ET.SubElement(root, "Extents")
|
|
632
766
|
content.set("Type", self.type)
|
|
633
767
|
content.set("DielType", self.dieltype)
|
|
@@ -641,7 +775,27 @@ class ControlExtent:
|
|
|
641
775
|
|
|
642
776
|
|
|
643
777
|
class ControlCircuitPt:
|
|
644
|
-
"""
|
|
778
|
+
"""Represents a circuit port.
|
|
779
|
+
|
|
780
|
+
Parameters
|
|
781
|
+
----------
|
|
782
|
+
name : str
|
|
783
|
+
Port name.
|
|
784
|
+
x1 : float
|
|
785
|
+
X-coordinate of first point.
|
|
786
|
+
y1 : float
|
|
787
|
+
Y-coordinate of first point.
|
|
788
|
+
lay1 : str
|
|
789
|
+
Layer of first point.
|
|
790
|
+
x2 : float
|
|
791
|
+
X-coordinate of second point.
|
|
792
|
+
y2 : float
|
|
793
|
+
Y-coordinate of second point.
|
|
794
|
+
lay2 : str
|
|
795
|
+
Layer of second point.
|
|
796
|
+
z0 : float
|
|
797
|
+
Characteristic impedance.
|
|
798
|
+
"""
|
|
645
799
|
|
|
646
800
|
def __init__(self, name, x1, y1, lay1, x2, y2, lay2, z0):
|
|
647
801
|
self.name = name
|
|
@@ -654,6 +808,13 @@ class ControlCircuitPt:
|
|
|
654
808
|
self.z0 = z0
|
|
655
809
|
|
|
656
810
|
def _write_xml(self, root):
|
|
811
|
+
"""Write circuit port to XML element.
|
|
812
|
+
|
|
813
|
+
Parameters
|
|
814
|
+
----------
|
|
815
|
+
root : xml.etree.ElementTree.Element
|
|
816
|
+
Parent XML element to append to.
|
|
817
|
+
"""
|
|
657
818
|
content = ET.SubElement(root, "CircuitPortPt")
|
|
658
819
|
content.set("Name", self.name)
|
|
659
820
|
content.set("x1", self.x1)
|
|
@@ -666,7 +827,7 @@ class ControlCircuitPt:
|
|
|
666
827
|
|
|
667
828
|
|
|
668
829
|
class ControlFileComponent:
|
|
669
|
-
"""
|
|
830
|
+
"""Represents a component in the control file."""
|
|
670
831
|
|
|
671
832
|
def __init__(self):
|
|
672
833
|
self.refdes = "U1"
|
|
@@ -682,9 +843,39 @@ class ControlFileComponent:
|
|
|
682
843
|
self.ports = []
|
|
683
844
|
|
|
684
845
|
def add_pin(self, name, x, y, layer):
|
|
846
|
+
"""Add a pin to the component.
|
|
847
|
+
|
|
848
|
+
Parameters
|
|
849
|
+
----------
|
|
850
|
+
name : str
|
|
851
|
+
Pin name.
|
|
852
|
+
x : float
|
|
853
|
+
X-coordinate.
|
|
854
|
+
y : float
|
|
855
|
+
Y-coordinate.
|
|
856
|
+
layer : str
|
|
857
|
+
Layer name.
|
|
858
|
+
"""
|
|
685
859
|
self.pins.append({"Name": name, "x": x, "y": y, "Layer": layer})
|
|
686
860
|
|
|
687
861
|
def add_port(self, name, z0, pospin, refpin=None, pos_type="pin", ref_type="pin"):
|
|
862
|
+
"""Add a port to the component.
|
|
863
|
+
|
|
864
|
+
Parameters
|
|
865
|
+
----------
|
|
866
|
+
name : str
|
|
867
|
+
Port name.
|
|
868
|
+
z0 : float
|
|
869
|
+
Characteristic impedance.
|
|
870
|
+
pospin : str
|
|
871
|
+
Positive pin/group name.
|
|
872
|
+
refpin : str, optional
|
|
873
|
+
Reference pin/group name.
|
|
874
|
+
pos_type : str, optional
|
|
875
|
+
Positive element type ("pin" or "pingroup"). Default is "pin".
|
|
876
|
+
ref_type : str, optional
|
|
877
|
+
Reference element type ("pin", "pingroup", or "net"). Default is "pin".
|
|
878
|
+
"""
|
|
688
879
|
args = {"Name": name, "Z0": z0}
|
|
689
880
|
if pos_type == "pin":
|
|
690
881
|
args["PosPin"] = pospin
|
|
@@ -700,6 +891,13 @@ class ControlFileComponent:
|
|
|
700
891
|
self.ports.append(args)
|
|
701
892
|
|
|
702
893
|
def _write_xml(self, root):
|
|
894
|
+
"""Write component to XML element.
|
|
895
|
+
|
|
896
|
+
Parameters
|
|
897
|
+
----------
|
|
898
|
+
root : xml.etree.ElementTree.Element
|
|
899
|
+
Parent XML element to append to.
|
|
900
|
+
"""
|
|
703
901
|
content = ET.SubElement(root, "GDS_COMPONENT")
|
|
704
902
|
for p in self.pins:
|
|
705
903
|
prop = ET.SubElement(content, "GDS_PIN")
|
|
@@ -725,31 +923,32 @@ class ControlFileComponent:
|
|
|
725
923
|
|
|
726
924
|
|
|
727
925
|
class ControlFileComponents:
|
|
728
|
-
"""
|
|
926
|
+
"""Manages components for the control file."""
|
|
729
927
|
|
|
730
928
|
def __init__(self):
|
|
731
929
|
self.units = "um"
|
|
732
930
|
self.components = []
|
|
733
931
|
|
|
734
932
|
def add_component(self, ref_des, partname, component_type, die_type="None", solderball_shape="None"):
|
|
735
|
-
"""
|
|
933
|
+
"""Add a new component.
|
|
736
934
|
|
|
737
935
|
Parameters
|
|
738
936
|
----------
|
|
739
937
|
ref_des : str
|
|
740
|
-
Reference
|
|
938
|
+
Reference designator.
|
|
741
939
|
partname : str
|
|
742
940
|
Part name.
|
|
743
941
|
component_type : str
|
|
744
|
-
Component
|
|
942
|
+
Component type ("IC", "IO", or "Other").
|
|
745
943
|
die_type : str, optional
|
|
746
|
-
Die
|
|
944
|
+
Die type ("None", "Flip chip", or "Wire bond"). Default is "None".
|
|
747
945
|
solderball_shape : str, optional
|
|
748
|
-
Solderball
|
|
946
|
+
Solderball shape ("None", "Cylinder", or "Spheroid"). Default is "None".
|
|
749
947
|
|
|
750
948
|
Returns
|
|
751
949
|
-------
|
|
752
|
-
|
|
950
|
+
ControlFileComponent
|
|
951
|
+
Created component object.
|
|
753
952
|
"""
|
|
754
953
|
comp = ControlFileComponent()
|
|
755
954
|
comp.refdes = ref_des
|
|
@@ -762,7 +961,13 @@ class ControlFileComponents:
|
|
|
762
961
|
|
|
763
962
|
|
|
764
963
|
class ControlFileBoundaries:
|
|
765
|
-
"""
|
|
964
|
+
"""Manages boundaries for the control file.
|
|
965
|
+
|
|
966
|
+
Parameters
|
|
967
|
+
----------
|
|
968
|
+
units : str, optional
|
|
969
|
+
Length units. Default is "um".
|
|
970
|
+
"""
|
|
766
971
|
|
|
767
972
|
def __init__(self, units="um"):
|
|
768
973
|
self.ports = {}
|
|
@@ -772,30 +977,31 @@ class ControlFileBoundaries:
|
|
|
772
977
|
self.units = units
|
|
773
978
|
|
|
774
979
|
def add_port(self, name, x1, y1, layer1, x2, y2, layer2, z0=50):
|
|
775
|
-
"""Add a
|
|
980
|
+
"""Add a port.
|
|
776
981
|
|
|
777
982
|
Parameters
|
|
778
983
|
----------
|
|
779
984
|
name : str
|
|
780
985
|
Port name.
|
|
781
|
-
x1 :
|
|
782
|
-
|
|
783
|
-
y1 :
|
|
784
|
-
|
|
986
|
+
x1 : float
|
|
987
|
+
X-coordinate of first point.
|
|
988
|
+
y1 : float
|
|
989
|
+
Y-coordinate of first point.
|
|
785
990
|
layer1 : str
|
|
786
|
-
|
|
787
|
-
x2 :
|
|
788
|
-
|
|
789
|
-
y2 :
|
|
790
|
-
|
|
991
|
+
Layer of first point.
|
|
992
|
+
x2 : float
|
|
993
|
+
X-coordinate of second point.
|
|
994
|
+
y2 : float
|
|
995
|
+
Y-coordinate of second point.
|
|
791
996
|
layer2 : str
|
|
792
|
-
|
|
793
|
-
z0 :
|
|
794
|
-
Characteristic impedance.
|
|
997
|
+
Layer of second point.
|
|
998
|
+
z0 : float, optional
|
|
999
|
+
Characteristic impedance. Default is 50.
|
|
795
1000
|
|
|
796
1001
|
Returns
|
|
797
1002
|
-------
|
|
798
|
-
|
|
1003
|
+
ControlCircuitPt
|
|
1004
|
+
Created port object.
|
|
799
1005
|
"""
|
|
800
1006
|
self.ports[name] = ControlCircuitPt(name, str(x1), str(y1), layer1, str(x2), str(y2), layer2, str(z0))
|
|
801
1007
|
return self.ports[name]
|
|
@@ -812,23 +1018,33 @@ class ControlFileBoundaries:
|
|
|
812
1018
|
honor_primitives=True,
|
|
813
1019
|
truncate_at_gnd=True,
|
|
814
1020
|
):
|
|
815
|
-
"""Add
|
|
1021
|
+
"""Add an extent.
|
|
816
1022
|
|
|
817
1023
|
Parameters
|
|
818
1024
|
----------
|
|
819
|
-
type
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1025
|
+
type : str, optional
|
|
1026
|
+
Extent type. Default is "bbox".
|
|
1027
|
+
dieltype : str, optional
|
|
1028
|
+
Dielectric extent type. Default is "bbox".
|
|
1029
|
+
diel_hactor : float, optional
|
|
1030
|
+
Dielectric horizontal factor. Default is 0.25.
|
|
1031
|
+
airbox_hfactor : float, optional
|
|
1032
|
+
Airbox horizontal factor. Default is 0.25.
|
|
1033
|
+
airbox_vr_p : float, optional
|
|
1034
|
+
Airbox vertical factor (positive). Default is 0.25.
|
|
1035
|
+
airbox_vr_n : float, optional
|
|
1036
|
+
Airbox vertical factor (negative). Default is 0.25.
|
|
1037
|
+
useradiation : bool, optional
|
|
1038
|
+
Use radiation boundary. Default is ``True``.
|
|
1039
|
+
honor_primitives : bool, optional
|
|
1040
|
+
Honor primitives. Default is ``True``.
|
|
1041
|
+
truncate_at_gnd : bool, optional
|
|
1042
|
+
Truncate at ground. Default is ``True``.
|
|
828
1043
|
|
|
829
1044
|
Returns
|
|
830
1045
|
-------
|
|
831
|
-
|
|
1046
|
+
ControlExtent
|
|
1047
|
+
Created extent object.
|
|
832
1048
|
"""
|
|
833
1049
|
self.extents.append(
|
|
834
1050
|
ControlExtent(
|
|
@@ -846,6 +1062,13 @@ class ControlFileBoundaries:
|
|
|
846
1062
|
return self.extents[-1]
|
|
847
1063
|
|
|
848
1064
|
def _write_xml(self, root):
|
|
1065
|
+
"""Write boundaries to XML element.
|
|
1066
|
+
|
|
1067
|
+
Parameters
|
|
1068
|
+
----------
|
|
1069
|
+
root : xml.etree.ElementTree.Element
|
|
1070
|
+
Parent XML element to append to.
|
|
1071
|
+
"""
|
|
849
1072
|
content = ET.SubElement(root, "Boundaries")
|
|
850
1073
|
content.set("LengthUnit", self.units)
|
|
851
1074
|
for p in self.circuit_models.values():
|
|
@@ -859,6 +1082,26 @@ class ControlFileBoundaries:
|
|
|
859
1082
|
|
|
860
1083
|
|
|
861
1084
|
class ControlFileSweep:
|
|
1085
|
+
"""Represents a frequency sweep.
|
|
1086
|
+
|
|
1087
|
+
Parameters
|
|
1088
|
+
----------
|
|
1089
|
+
name : str
|
|
1090
|
+
Sweep name.
|
|
1091
|
+
start : str
|
|
1092
|
+
Start frequency.
|
|
1093
|
+
stop : str
|
|
1094
|
+
Stop frequency.
|
|
1095
|
+
step : str
|
|
1096
|
+
Frequency step/count.
|
|
1097
|
+
sweep_type : str
|
|
1098
|
+
Sweep type ("Discrete" or "Interpolating").
|
|
1099
|
+
step_type : str
|
|
1100
|
+
Step type ("LinearStep", "DecadeCount", or "LinearCount").
|
|
1101
|
+
use_q3d : bool
|
|
1102
|
+
Whether to use Q3D for DC point.
|
|
1103
|
+
"""
|
|
1104
|
+
|
|
862
1105
|
def __init__(self, name, start, stop, step, sweep_type, step_type, use_q3d):
|
|
863
1106
|
self.name = name
|
|
864
1107
|
self.start = start
|
|
@@ -869,6 +1112,13 @@ class ControlFileSweep:
|
|
|
869
1112
|
self.use_q3d = use_q3d
|
|
870
1113
|
|
|
871
1114
|
def _write_xml(self, root):
|
|
1115
|
+
"""Write sweep to XML element.
|
|
1116
|
+
|
|
1117
|
+
Parameters
|
|
1118
|
+
----------
|
|
1119
|
+
root : xml.etree.ElementTree.Element
|
|
1120
|
+
Parent XML element to append to.
|
|
1121
|
+
"""
|
|
872
1122
|
sweep = ET.SubElement(root, "FreqSweep")
|
|
873
1123
|
prop = ET.SubElement(sweep, "Name")
|
|
874
1124
|
prop.text = self.name
|
|
@@ -889,6 +1139,20 @@ class ControlFileSweep:
|
|
|
889
1139
|
|
|
890
1140
|
|
|
891
1141
|
class ControlFileMeshOp:
|
|
1142
|
+
"""Represents a mesh operation.
|
|
1143
|
+
|
|
1144
|
+
Parameters
|
|
1145
|
+
----------
|
|
1146
|
+
name : str
|
|
1147
|
+
Operation name.
|
|
1148
|
+
region : str
|
|
1149
|
+
Region name.
|
|
1150
|
+
type : str
|
|
1151
|
+
Operation type ("MeshOperationLength" or "MeshOperationSkinDepth").
|
|
1152
|
+
nets_layers : dict
|
|
1153
|
+
Dictionary of nets and layers.
|
|
1154
|
+
"""
|
|
1155
|
+
|
|
892
1156
|
def __init__(self, name, region, type, nets_layers):
|
|
893
1157
|
self.name = name
|
|
894
1158
|
self.region = name
|
|
@@ -904,6 +1168,13 @@ class ControlFileMeshOp:
|
|
|
904
1168
|
self.region_solve_inside = False
|
|
905
1169
|
|
|
906
1170
|
def _write_xml(self, root):
|
|
1171
|
+
"""Write mesh operation to XML element.
|
|
1172
|
+
|
|
1173
|
+
Parameters
|
|
1174
|
+
----------
|
|
1175
|
+
root : xml.etree.ElementTree.Element
|
|
1176
|
+
Parent XML element to append to.
|
|
1177
|
+
"""
|
|
907
1178
|
mop = ET.SubElement(root, "MeshOperation")
|
|
908
1179
|
prop = ET.SubElement(mop, "Name")
|
|
909
1180
|
prop.text = self.name
|
|
@@ -941,7 +1212,13 @@ class ControlFileMeshOp:
|
|
|
941
1212
|
|
|
942
1213
|
|
|
943
1214
|
class ControlFileSetup:
|
|
944
|
-
"""
|
|
1215
|
+
"""Represents a simulation setup.
|
|
1216
|
+
|
|
1217
|
+
Parameters
|
|
1218
|
+
----------
|
|
1219
|
+
name : str
|
|
1220
|
+
Setup name.
|
|
1221
|
+
"""
|
|
945
1222
|
|
|
946
1223
|
def __init__(self, name):
|
|
947
1224
|
self.name = name
|
|
@@ -962,55 +1239,64 @@ class ControlFileSetup:
|
|
|
962
1239
|
self.sweeps = []
|
|
963
1240
|
|
|
964
1241
|
def add_sweep(self, name, start, stop, step, sweep_type="Interpolating", step_type="LinearStep", use_q3d=True):
|
|
965
|
-
"""Add a
|
|
1242
|
+
"""Add a frequency sweep.
|
|
966
1243
|
|
|
967
1244
|
Parameters
|
|
968
1245
|
----------
|
|
969
1246
|
name : str
|
|
970
1247
|
Sweep name.
|
|
971
1248
|
start : str
|
|
972
|
-
|
|
1249
|
+
Start frequency.
|
|
973
1250
|
stop : str
|
|
974
|
-
|
|
1251
|
+
Stop frequency.
|
|
975
1252
|
step : str
|
|
976
|
-
Frequency step
|
|
977
|
-
sweep_type : str
|
|
978
|
-
Sweep type
|
|
979
|
-
step_type : str
|
|
980
|
-
|
|
981
|
-
use_q3d
|
|
1253
|
+
Frequency step/count.
|
|
1254
|
+
sweep_type : str, optional
|
|
1255
|
+
Sweep type ("Discrete" or "Interpolating"). Default is "Interpolating".
|
|
1256
|
+
step_type : str, optional
|
|
1257
|
+
Step type ("LinearStep", "DecadeCount", or "LinearCount"). Default is "LinearStep".
|
|
1258
|
+
use_q3d : bool, optional
|
|
1259
|
+
Whether to use Q3D for DC point. Default is ``True``.
|
|
982
1260
|
|
|
983
1261
|
Returns
|
|
984
1262
|
-------
|
|
985
|
-
|
|
1263
|
+
ControlFileSweep
|
|
1264
|
+
Created sweep object.
|
|
986
1265
|
"""
|
|
987
1266
|
self.sweeps.append(ControlFileSweep(name, start, stop, step, sweep_type, step_type, use_q3d))
|
|
988
1267
|
return self.sweeps[-1]
|
|
989
1268
|
|
|
990
1269
|
def add_mesh_operation(self, name, region, type, nets_layers):
|
|
991
|
-
"""Add mesh
|
|
1270
|
+
"""Add a mesh operation.
|
|
992
1271
|
|
|
993
1272
|
Parameters
|
|
994
1273
|
----------
|
|
995
1274
|
name : str
|
|
996
|
-
|
|
1275
|
+
Operation name.
|
|
997
1276
|
region : str
|
|
998
|
-
Region
|
|
1277
|
+
Region name.
|
|
999
1278
|
type : str
|
|
1000
|
-
|
|
1279
|
+
Operation type ("MeshOperationLength" or "MeshOperationSkinDepth").
|
|
1001
1280
|
nets_layers : dict
|
|
1002
|
-
Dictionary
|
|
1281
|
+
Dictionary of nets and layers.
|
|
1003
1282
|
|
|
1004
1283
|
Returns
|
|
1005
1284
|
-------
|
|
1006
|
-
|
|
1007
|
-
|
|
1285
|
+
ControlFileMeshOp
|
|
1286
|
+
Created mesh operation object.
|
|
1008
1287
|
"""
|
|
1009
1288
|
mop = ControlFileMeshOp(name, region, type, nets_layers)
|
|
1010
1289
|
self.mesh_operations.append(mop)
|
|
1011
1290
|
return mop
|
|
1012
1291
|
|
|
1013
1292
|
def _write_xml(self, root):
|
|
1293
|
+
"""Write setup to XML element.
|
|
1294
|
+
|
|
1295
|
+
Parameters
|
|
1296
|
+
----------
|
|
1297
|
+
root : xml.etree.ElementTree.Element
|
|
1298
|
+
Parent XML element to append to.
|
|
1299
|
+
"""
|
|
1014
1300
|
setups = ET.SubElement(root, "HFSSSetup")
|
|
1015
1301
|
setups.set("schemaVersion", "1.0")
|
|
1016
1302
|
setups.set("Name", self.name)
|
|
@@ -1056,24 +1342,25 @@ class ControlFileSetup:
|
|
|
1056
1342
|
|
|
1057
1343
|
|
|
1058
1344
|
class ControlFileSetups:
|
|
1059
|
-
"""
|
|
1345
|
+
"""Manages simulation setups."""
|
|
1060
1346
|
|
|
1061
1347
|
def __init__(self):
|
|
1062
1348
|
self.setups = []
|
|
1063
1349
|
|
|
1064
1350
|
def add_setup(self, name, frequency):
|
|
1065
|
-
"""Add a
|
|
1351
|
+
"""Add a simulation setup.
|
|
1066
1352
|
|
|
1067
1353
|
Parameters
|
|
1068
1354
|
----------
|
|
1069
1355
|
name : str
|
|
1070
1356
|
Setup name.
|
|
1071
1357
|
frequency : str
|
|
1072
|
-
|
|
1358
|
+
Adaptive frequency.
|
|
1073
1359
|
|
|
1074
1360
|
Returns
|
|
1075
1361
|
-------
|
|
1076
|
-
|
|
1362
|
+
ControlFileSetup
|
|
1363
|
+
Created setup object.
|
|
1077
1364
|
"""
|
|
1078
1365
|
setup = ControlFileSetup(name)
|
|
1079
1366
|
setup.frequency = frequency
|
|
@@ -1081,13 +1368,30 @@ class ControlFileSetups:
|
|
|
1081
1368
|
return setup
|
|
1082
1369
|
|
|
1083
1370
|
def _write_xml(self, root):
|
|
1371
|
+
"""Write setups to XML element.
|
|
1372
|
+
|
|
1373
|
+
Parameters
|
|
1374
|
+
----------
|
|
1375
|
+
root : xml.etree.ElementTree.Element
|
|
1376
|
+
Parent XML element to append to.
|
|
1377
|
+
"""
|
|
1084
1378
|
content = ET.SubElement(root, "SimulationSetups")
|
|
1085
1379
|
for setup in self.setups:
|
|
1086
1380
|
setup._write_xml(content)
|
|
1087
1381
|
|
|
1088
1382
|
|
|
1089
1383
|
class ControlFile:
|
|
1090
|
-
"""
|
|
1384
|
+
"""Main class for EDB control file creation and management.
|
|
1385
|
+
|
|
1386
|
+
Parameters
|
|
1387
|
+
----------
|
|
1388
|
+
xml_input : str, optional
|
|
1389
|
+
Path to existing XML file to parse.
|
|
1390
|
+
tecnhology : str, optional
|
|
1391
|
+
Path to technology file to convert.
|
|
1392
|
+
layer_map : str, optional
|
|
1393
|
+
Path to layer map file.
|
|
1394
|
+
"""
|
|
1091
1395
|
|
|
1092
1396
|
def __init__(self, xml_input=None, tecnhology=None, layer_map=None):
|
|
1093
1397
|
self.stackup = ControlFileStackup()
|
|
@@ -1107,16 +1411,19 @@ class ControlFile:
|
|
|
1107
1411
|
pass
|
|
1108
1412
|
|
|
1109
1413
|
def parse_technology(self, tecnhology, edbversion=None):
|
|
1110
|
-
"""Parse technology
|
|
1414
|
+
"""Parse a technology file and convert to XML control file.
|
|
1111
1415
|
|
|
1112
1416
|
Parameters
|
|
1113
1417
|
----------
|
|
1114
|
-
|
|
1115
|
-
|
|
1418
|
+
tecnhology : str
|
|
1419
|
+
Path to technology file.
|
|
1420
|
+
edbversion : str, optional
|
|
1421
|
+
EDB version to use for conversion.
|
|
1116
1422
|
|
|
1117
1423
|
Returns
|
|
1118
1424
|
-------
|
|
1119
1425
|
bool
|
|
1426
|
+
``True`` if successful, ``False`` otherwise.
|
|
1120
1427
|
"""
|
|
1121
1428
|
xml_temp = os.path.splitext(tecnhology)[0] + "_temp.xml"
|
|
1122
1429
|
xml_temp = convert_technology_file(tech_file=tecnhology, edbversion=edbversion, control_file=xml_temp)
|
|
@@ -1124,17 +1431,17 @@ class ControlFile:
|
|
|
1124
1431
|
return self.parse_xml(xml_temp)
|
|
1125
1432
|
|
|
1126
1433
|
def parse_layer_map(self, layer_map):
|
|
1127
|
-
"""Parse layer map and
|
|
1128
|
-
This operation must be performed after a tech file is imported.
|
|
1434
|
+
"""Parse a layer map file and update stackup.
|
|
1129
1435
|
|
|
1130
1436
|
Parameters
|
|
1131
1437
|
----------
|
|
1132
1438
|
layer_map : str
|
|
1133
|
-
|
|
1439
|
+
Path to layer map file.
|
|
1134
1440
|
|
|
1135
1441
|
Returns
|
|
1136
1442
|
-------
|
|
1137
|
-
|
|
1443
|
+
bool
|
|
1444
|
+
``True`` if successful, ``False`` otherwise.
|
|
1138
1445
|
"""
|
|
1139
1446
|
with open(layer_map, "r") as f:
|
|
1140
1447
|
lines = f.readlines()
|
|
@@ -1174,16 +1481,17 @@ class ControlFile:
|
|
|
1174
1481
|
return True
|
|
1175
1482
|
|
|
1176
1483
|
def parse_xml(self, xml_input):
|
|
1177
|
-
"""Parse an
|
|
1484
|
+
"""Parse an XML control file and populate the object.
|
|
1178
1485
|
|
|
1179
1486
|
Parameters
|
|
1180
1487
|
----------
|
|
1181
1488
|
xml_input : str
|
|
1182
|
-
|
|
1489
|
+
Path to XML control file.
|
|
1183
1490
|
|
|
1184
1491
|
Returns
|
|
1185
1492
|
-------
|
|
1186
1493
|
bool
|
|
1494
|
+
``True`` if successful, ``False`` otherwise.
|
|
1187
1495
|
"""
|
|
1188
1496
|
tree = ET.parse(xml_input)
|
|
1189
1497
|
root = tree.getroot()
|
|
@@ -1244,16 +1552,17 @@ class ControlFile:
|
|
|
1244
1552
|
return True
|
|
1245
1553
|
|
|
1246
1554
|
def write_xml(self, xml_output):
|
|
1247
|
-
"""Write
|
|
1555
|
+
"""Write control file to XML.
|
|
1248
1556
|
|
|
1249
1557
|
Parameters
|
|
1250
1558
|
----------
|
|
1251
1559
|
xml_output : str
|
|
1252
|
-
|
|
1560
|
+
Output XML file path.
|
|
1253
1561
|
|
|
1254
1562
|
Returns
|
|
1255
1563
|
-------
|
|
1256
1564
|
bool
|
|
1565
|
+
``True`` if file created successfully, ``False`` otherwise.
|
|
1257
1566
|
"""
|
|
1258
1567
|
control = ET.Element("{http://www.ansys.com/control}Control", attrib={"schemaVersion": "1.0"})
|
|
1259
1568
|
self.stackup._write_xml(control)
|