pyedb 0.52.0__py3-none-any.whl → 0.53.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_stackup.py +62 -249
- pyedb/configuration/configuration.py +271 -170
- pyedb/dotnet/database/components.py +9 -3
- pyedb/dotnet/database/dotnet/database.py +4 -0
- pyedb/dotnet/database/edb_data/layer_data.py +3 -1
- pyedb/dotnet/database/siwave.py +14 -0
- pyedb/dotnet/database/stackup.py +6 -60
- 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/edb.py +15 -2
- pyedb/generic/design_types.py +29 -0
- pyedb/generic/grpc_warnings.py +5 -0
- pyedb/grpc/database/components.py +102 -81
- pyedb/grpc/database/control_file.py +240 -193
- pyedb/grpc/database/definitions.py +7 -5
- pyedb/grpc/database/modeler.py +105 -77
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +961 -0
- pyedb/grpc/database/siwave.py +14 -0
- pyedb/grpc/edb.py +70 -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.53.0.dist-info}/METADATA +13 -11
- {pyedb-0.52.0.dist-info → pyedb-0.53.0.dist-info}/RECORD +30 -25
- {pyedb-0.52.0.dist-info → pyedb-0.53.0.dist-info}/WHEEL +1 -1
- {pyedb-0.52.0.dist-info → pyedb-0.53.0.dist-info/licenses}/LICENSE +0 -0
|
@@ -25,6 +25,7 @@ import os
|
|
|
25
25
|
import re
|
|
26
26
|
import subprocess
|
|
27
27
|
import sys
|
|
28
|
+
from typing import Any, Dict, List, Optional, Union
|
|
28
29
|
|
|
29
30
|
from pyedb.edb_logger import pyedb_logger
|
|
30
31
|
from pyedb.generic.general_methods import ET, env_path, env_value, is_linux
|
|
@@ -257,21 +258,24 @@ class ControlProperty:
|
|
|
257
258
|
Value of the property.
|
|
258
259
|
"""
|
|
259
260
|
|
|
260
|
-
def __init__(self, property_name, value):
|
|
261
|
-
self.name = property_name
|
|
262
|
-
self.value = value
|
|
261
|
+
def __init__(self, property_name: str, value: Union[str, float, list]) -> None:
|
|
262
|
+
self.name: str = property_name
|
|
263
|
+
self.value: Union[str, float, list] = value
|
|
264
|
+
self.type: int = self._get_type(value)
|
|
265
|
+
|
|
266
|
+
def _get_type(self, value: Any) -> int:
|
|
263
267
|
if isinstance(value, str):
|
|
264
|
-
|
|
268
|
+
return 1
|
|
265
269
|
elif isinstance(value, list):
|
|
266
|
-
|
|
270
|
+
return 2
|
|
267
271
|
else:
|
|
268
272
|
try:
|
|
269
273
|
float(value)
|
|
270
|
-
|
|
274
|
+
return 0
|
|
271
275
|
except TypeError:
|
|
272
|
-
|
|
276
|
+
return -1
|
|
273
277
|
|
|
274
|
-
def _write_xml(self, root):
|
|
278
|
+
def _write_xml(self, root) -> None:
|
|
275
279
|
"""Write the property to XML element.
|
|
276
280
|
|
|
277
281
|
Parameters
|
|
@@ -301,13 +305,13 @@ class ControlFileMaterial:
|
|
|
301
305
|
Material properties dictionary.
|
|
302
306
|
"""
|
|
303
307
|
|
|
304
|
-
def __init__(self, name, properties):
|
|
305
|
-
self.name = name
|
|
306
|
-
self.properties = {
|
|
307
|
-
|
|
308
|
-
|
|
308
|
+
def __init__(self, name: str, properties: Dict[str, Any]) -> None:
|
|
309
|
+
self.name: str = name
|
|
310
|
+
self.properties: Dict[str, ControlProperty] = {
|
|
311
|
+
name: ControlProperty(name, prop) for name, prop in properties.items()
|
|
312
|
+
}
|
|
309
313
|
|
|
310
|
-
def _write_xml(self, root):
|
|
314
|
+
def _write_xml(self, root) -> None:
|
|
311
315
|
"""Write material to XML element.
|
|
312
316
|
|
|
313
317
|
Parameters
|
|
@@ -332,13 +336,13 @@ class ControlFileDielectric:
|
|
|
332
336
|
Layer properties dictionary.
|
|
333
337
|
"""
|
|
334
338
|
|
|
335
|
-
def __init__(self, name, properties):
|
|
336
|
-
self.name = name
|
|
337
|
-
self.properties = {}
|
|
339
|
+
def __init__(self, name: str, properties: Dict[str, Any]) -> None:
|
|
340
|
+
self.name: str = name
|
|
341
|
+
self.properties: Dict[str, Any] = {}
|
|
338
342
|
for name, prop in properties.items():
|
|
339
343
|
self.properties[name] = prop
|
|
340
344
|
|
|
341
|
-
def _write_xml(self, root):
|
|
345
|
+
def _write_xml(self, root) -> None:
|
|
342
346
|
"""Write dielectric layer to XML element.
|
|
343
347
|
|
|
344
348
|
Parameters
|
|
@@ -411,19 +415,19 @@ class ControlFileVia(ControlFileLayer):
|
|
|
411
415
|
Via properties dictionary.
|
|
412
416
|
"""
|
|
413
417
|
|
|
414
|
-
def __init__(self, name, properties):
|
|
415
|
-
|
|
416
|
-
self.create_via_group = False
|
|
417
|
-
self.check_containment = True
|
|
418
|
-
self.method = "proximity"
|
|
419
|
-
self.persistent = False
|
|
420
|
-
self.tolerance = "1um"
|
|
421
|
-
self.snap_via_groups = False
|
|
422
|
-
self.snap_method = "areaFactor"
|
|
423
|
-
self.remove_unconnected = True
|
|
424
|
-
self.snap_tolerance = 3
|
|
425
|
-
|
|
426
|
-
def _write_xml(self, root):
|
|
418
|
+
def __init__(self, name: str, properties: Dict[str, Any]) -> None:
|
|
419
|
+
super().__init__(name, properties)
|
|
420
|
+
self.create_via_group: bool = False
|
|
421
|
+
self.check_containment: bool = True
|
|
422
|
+
self.method: str = "proximity"
|
|
423
|
+
self.persistent: bool = False
|
|
424
|
+
self.tolerance: str = "1um"
|
|
425
|
+
self.snap_via_groups: bool = False
|
|
426
|
+
self.snap_method: str = "areaFactor"
|
|
427
|
+
self.remove_unconnected: bool = True
|
|
428
|
+
self.snap_tolerance: int = 3
|
|
429
|
+
|
|
430
|
+
def _write_xml(self, root) -> None:
|
|
427
431
|
"""Write via to XML element.
|
|
428
432
|
|
|
429
433
|
Parameters
|
|
@@ -470,14 +474,14 @@ class ControlFileStackup:
|
|
|
470
474
|
Length units (e.g., "mm", "um"). Default is "mm".
|
|
471
475
|
"""
|
|
472
476
|
|
|
473
|
-
def __init__(self, units="mm"):
|
|
474
|
-
self._materials = {}
|
|
475
|
-
self._layers = []
|
|
476
|
-
self._dielectrics = []
|
|
477
|
-
self._vias = []
|
|
478
|
-
self.units = units
|
|
479
|
-
self.metal_layer_snapping_tolerance = None
|
|
480
|
-
self.dielectrics_base_elevation = 0
|
|
477
|
+
def __init__(self, units: str = "mm") -> None:
|
|
478
|
+
self._materials: Dict[str, ControlFileMaterial] = {}
|
|
479
|
+
self._layers: List[ControlFileLayer] = []
|
|
480
|
+
self._dielectrics: List[Any] = []
|
|
481
|
+
self._vias: List[ControlFileVia] = []
|
|
482
|
+
self.units: str = units
|
|
483
|
+
self.metal_layer_snapping_tolerance: Optional[float] = None
|
|
484
|
+
self.dielectrics_base_elevation: float = 0.0
|
|
481
485
|
|
|
482
486
|
@property
|
|
483
487
|
def vias(self):
|
|
@@ -490,7 +494,7 @@ class ControlFileStackup:
|
|
|
490
494
|
return self._vias
|
|
491
495
|
|
|
492
496
|
@property
|
|
493
|
-
def materials(self):
|
|
497
|
+
def materials(self) -> Dict[str, ControlFileMaterial]:
|
|
494
498
|
"""Dictionary of material objects.
|
|
495
499
|
|
|
496
500
|
Returns
|
|
@@ -511,7 +515,7 @@ class ControlFileStackup:
|
|
|
511
515
|
return self._dielectrics
|
|
512
516
|
|
|
513
517
|
@property
|
|
514
|
-
def layers(self):
|
|
518
|
+
def layers(self) -> List[ControlFileLayer]:
|
|
515
519
|
"""List of general layers.
|
|
516
520
|
|
|
517
521
|
Returns
|
|
@@ -522,13 +526,13 @@ class ControlFileStackup:
|
|
|
522
526
|
|
|
523
527
|
def add_material(
|
|
524
528
|
self,
|
|
525
|
-
material_name,
|
|
526
|
-
permittivity=1.0,
|
|
527
|
-
dielectric_loss_tg=0.0,
|
|
528
|
-
permeability=1.0,
|
|
529
|
-
conductivity=0.0,
|
|
530
|
-
properties=None,
|
|
531
|
-
):
|
|
529
|
+
material_name: str,
|
|
530
|
+
permittivity: float = 1.0,
|
|
531
|
+
dielectric_loss_tg: float = 0.0,
|
|
532
|
+
permeability: float = 1.0,
|
|
533
|
+
conductivity: float = 0.0,
|
|
534
|
+
properties: Optional[Dict[str, Any]] = None,
|
|
535
|
+
) -> ControlFileMaterial:
|
|
532
536
|
"""Add a new material.
|
|
533
537
|
|
|
534
538
|
Parameters
|
|
@@ -567,16 +571,16 @@ class ControlFileStackup:
|
|
|
567
571
|
|
|
568
572
|
def add_layer(
|
|
569
573
|
self,
|
|
570
|
-
layer_name,
|
|
571
|
-
elevation=0.0,
|
|
572
|
-
material="",
|
|
573
|
-
gds_type=0,
|
|
574
|
-
target_layer="",
|
|
575
|
-
thickness=0.0,
|
|
576
|
-
layer_type="conductor",
|
|
577
|
-
solve_inside=True,
|
|
578
|
-
properties=None,
|
|
579
|
-
):
|
|
574
|
+
layer_name: str,
|
|
575
|
+
elevation: float = 0.0,
|
|
576
|
+
material: str = "",
|
|
577
|
+
gds_type: int = 0,
|
|
578
|
+
target_layer: str = "",
|
|
579
|
+
thickness: float = 0.0,
|
|
580
|
+
layer_type: str = "conductor",
|
|
581
|
+
solve_inside: bool = True,
|
|
582
|
+
properties: Optional[Dict[str, Any]] = None,
|
|
583
|
+
) -> ControlFileLayer:
|
|
580
584
|
"""Add a new layer.
|
|
581
585
|
|
|
582
586
|
Parameters
|
|
@@ -624,14 +628,14 @@ class ControlFileStackup:
|
|
|
624
628
|
|
|
625
629
|
def add_dielectric(
|
|
626
630
|
self,
|
|
627
|
-
layer_name,
|
|
628
|
-
layer_index=None,
|
|
629
|
-
material="",
|
|
630
|
-
thickness=0.0,
|
|
631
|
-
properties=None,
|
|
632
|
-
base_layer=None,
|
|
633
|
-
add_on_top=True,
|
|
634
|
-
):
|
|
631
|
+
layer_name: str,
|
|
632
|
+
layer_index: Optional[int] = None,
|
|
633
|
+
material: str = "",
|
|
634
|
+
thickness: float = 0.0,
|
|
635
|
+
properties: Optional[Dict[str, Any]] = None,
|
|
636
|
+
base_layer: Optional[str] = None,
|
|
637
|
+
add_on_top: bool = True,
|
|
638
|
+
) -> ControlFileDielectric:
|
|
635
639
|
"""Add a new dielectric layer.
|
|
636
640
|
|
|
637
641
|
Parameters
|
|
@@ -685,20 +689,20 @@ class ControlFileStackup:
|
|
|
685
689
|
|
|
686
690
|
def add_via(
|
|
687
691
|
self,
|
|
688
|
-
layer_name,
|
|
689
|
-
material="",
|
|
690
|
-
gds_type=0,
|
|
691
|
-
target_layer="",
|
|
692
|
-
start_layer="",
|
|
693
|
-
stop_layer="",
|
|
694
|
-
solve_inside=True,
|
|
695
|
-
via_group_method="proximity",
|
|
696
|
-
via_group_tol=1e-6,
|
|
697
|
-
via_group_persistent=True,
|
|
698
|
-
snap_via_group_method="distance",
|
|
699
|
-
snap_via_group_tol=10e-9,
|
|
700
|
-
properties=None,
|
|
701
|
-
):
|
|
692
|
+
layer_name: str,
|
|
693
|
+
material: str = "",
|
|
694
|
+
gds_type: int = 0,
|
|
695
|
+
target_layer: str = "",
|
|
696
|
+
start_layer: str = "",
|
|
697
|
+
stop_layer: str = "",
|
|
698
|
+
solve_inside: bool = True,
|
|
699
|
+
via_group_method: str = "proximity",
|
|
700
|
+
via_group_tol: float = 1e-6,
|
|
701
|
+
via_group_persistent: bool = True,
|
|
702
|
+
snap_via_group_method: str = "distance",
|
|
703
|
+
snap_via_group_tol: float = 10e-9,
|
|
704
|
+
properties: Optional[Dict[str, Any]] = None,
|
|
705
|
+
) -> ControlFileVia:
|
|
702
706
|
"""Add a new via layer.
|
|
703
707
|
|
|
704
708
|
Parameters
|
|
@@ -756,7 +760,7 @@ class ControlFileStackup:
|
|
|
756
760
|
self._vias.append(ControlFileVia(layer_name, properties))
|
|
757
761
|
return self._vias[-1]
|
|
758
762
|
|
|
759
|
-
def _write_xml(self, root):
|
|
763
|
+
def _write_xml(self, root: ET.Element) -> None:
|
|
760
764
|
"""Write stackup to XML element.
|
|
761
765
|
|
|
762
766
|
Parameters
|
|
@@ -792,31 +796,37 @@ class ControlFileStackup:
|
|
|
792
796
|
class ControlFileImportOptions:
|
|
793
797
|
"""Manages import options for the control file."""
|
|
794
798
|
|
|
795
|
-
def __init__(self):
|
|
796
|
-
self.auto_close = False
|
|
797
|
-
self.convert_closed_wide_lines_to_polys = False
|
|
798
|
-
self.round_to = 0
|
|
799
|
-
self.defeature_tolerance = 0.0
|
|
800
|
-
self.flatten = True
|
|
801
|
-
self.enable_default_component_values = True
|
|
802
|
-
self.import_dummy_nets = False
|
|
803
|
-
self.gdsii_convert_polygon_to_circles = False
|
|
804
|
-
self.import_cross_hatch_shapes_as_lines = True
|
|
805
|
-
self.max_antipad_radius = 0.0
|
|
806
|
-
self.extracta_use_pin_names = False
|
|
807
|
-
self.min_bondwire_width = 0.0
|
|
808
|
-
self.
|
|
809
|
-
self.gdsii_scaling_factor = 0.0
|
|
810
|
-
self.
|
|
811
|
-
|
|
812
|
-
def _write_xml(self, root):
|
|
813
|
-
"""Write
|
|
799
|
+
def __init__(self) -> None:
|
|
800
|
+
self.auto_close: bool = False
|
|
801
|
+
self.convert_closed_wide_lines_to_polys: bool = False
|
|
802
|
+
self.round_to: int = 0
|
|
803
|
+
self.defeature_tolerance: float = 0.0
|
|
804
|
+
self.flatten: bool = True
|
|
805
|
+
self.enable_default_component_values: bool = True
|
|
806
|
+
self.import_dummy_nets: bool = False
|
|
807
|
+
self.gdsii_convert_polygon_to_circles: bool = False
|
|
808
|
+
self.import_cross_hatch_shapes_as_lines: bool = True
|
|
809
|
+
self.max_antipad_radius: float = 0.0
|
|
810
|
+
self.extracta_use_pin_names: bool = False
|
|
811
|
+
self.min_bondwire_width: float = 0.0
|
|
812
|
+
self.antipad_replace_radius: float = 0.0
|
|
813
|
+
self.gdsii_scaling_factor: float = 0.0
|
|
814
|
+
self.delete_empty_non_laminate_signal_layers: bool = False
|
|
815
|
+
|
|
816
|
+
def _write_xml(self, root: ET.Element) -> bool:
|
|
817
|
+
"""Write control file to XML element.
|
|
814
818
|
|
|
815
819
|
Parameters
|
|
816
820
|
----------
|
|
817
821
|
root : xml.etree.ElementTree.Element
|
|
818
822
|
Parent XML element to append to.
|
|
823
|
+
|
|
824
|
+
Returns
|
|
825
|
+
-------
|
|
826
|
+
bool
|
|
827
|
+
True if XML content was written successfully.
|
|
819
828
|
"""
|
|
829
|
+
|
|
820
830
|
content = ET.SubElement(root, "ImportOptions")
|
|
821
831
|
content.set("AutoClose", str(self.auto_close).lower())
|
|
822
832
|
if self.round_to != 0:
|
|
@@ -838,6 +848,7 @@ class ControlFileImportOptions:
|
|
|
838
848
|
if self.gdsii_scaling_factor != 0.0:
|
|
839
849
|
content.set("GDSIIScalingFactor", str(self.gdsii_scaling_factor))
|
|
840
850
|
content.set("DeleteEmptyNonLaminateSignalLayers", str(self.delte_empty_non_laminate_signal_layers).lower())
|
|
851
|
+
return True
|
|
841
852
|
|
|
842
853
|
|
|
843
854
|
class ControlExtent:
|
|
@@ -867,16 +878,16 @@ class ControlExtent:
|
|
|
867
878
|
|
|
868
879
|
def __init__(
|
|
869
880
|
self,
|
|
870
|
-
type="bbox",
|
|
871
|
-
dieltype="bbox",
|
|
872
|
-
diel_hactor=0.25,
|
|
873
|
-
airbox_hfactor=0.25,
|
|
874
|
-
airbox_vr_p=0.25,
|
|
875
|
-
airbox_vr_n=0.25,
|
|
876
|
-
useradiation=True,
|
|
877
|
-
honor_primitives=True,
|
|
878
|
-
truncate_at_gnd=True,
|
|
879
|
-
):
|
|
881
|
+
type: str = "bbox",
|
|
882
|
+
dieltype: str = "bbox",
|
|
883
|
+
diel_hactor: float = 0.25,
|
|
884
|
+
airbox_hfactor: float = 0.25,
|
|
885
|
+
airbox_vr_p: float = 0.25,
|
|
886
|
+
airbox_vr_n: float = 0.25,
|
|
887
|
+
useradiation: bool = True,
|
|
888
|
+
honor_primitives: bool = True,
|
|
889
|
+
truncate_at_gnd: bool = True,
|
|
890
|
+
) -> None:
|
|
880
891
|
self.type = type
|
|
881
892
|
self.dieltype = dieltype
|
|
882
893
|
self.diel_hactor = diel_hactor
|
|
@@ -962,20 +973,20 @@ class ControlCircuitPt:
|
|
|
962
973
|
class ControlFileComponent:
|
|
963
974
|
"""Represents a component in the control file."""
|
|
964
975
|
|
|
965
|
-
def __init__(self):
|
|
966
|
-
self.refdes = "U1"
|
|
967
|
-
self.partname = "BGA"
|
|
968
|
-
self.parttype = "IC"
|
|
969
|
-
self.die_type = "None"
|
|
970
|
-
self.die_orientation = "Chip down"
|
|
971
|
-
self.solderball_shape = "None"
|
|
972
|
-
self.solder_diameter = "65um"
|
|
973
|
-
self.solder_height = "65um"
|
|
974
|
-
self.solder_material = "solder"
|
|
975
|
-
self.pins = []
|
|
976
|
-
self.ports = []
|
|
977
|
-
|
|
978
|
-
def add_pin(self, name, x, y, layer):
|
|
976
|
+
def __init__(self) -> None:
|
|
977
|
+
self.refdes: str = "U1"
|
|
978
|
+
self.partname: str = "BGA"
|
|
979
|
+
self.parttype: str = "IC"
|
|
980
|
+
self.die_type: str = "None"
|
|
981
|
+
self.die_orientation: str = "Chip down"
|
|
982
|
+
self.solderball_shape: str = "None"
|
|
983
|
+
self.solder_diameter: str = "65um"
|
|
984
|
+
self.solder_height: str = "65um"
|
|
985
|
+
self.solder_material: str = "solder"
|
|
986
|
+
self.pins: List[Dict[str, Union[str, float]]] = []
|
|
987
|
+
self.ports: List[Dict[str, Union[str, float, None]]] = []
|
|
988
|
+
|
|
989
|
+
def add_pin(self, name: str, x: float, y: float, layer: str) -> None:
|
|
979
990
|
"""Add a pin to the component.
|
|
980
991
|
|
|
981
992
|
Parameters
|
|
@@ -991,7 +1002,15 @@ class ControlFileComponent:
|
|
|
991
1002
|
"""
|
|
992
1003
|
self.pins.append({"Name": name, "x": x, "y": y, "Layer": layer})
|
|
993
1004
|
|
|
994
|
-
def add_port(
|
|
1005
|
+
def add_port(
|
|
1006
|
+
self,
|
|
1007
|
+
name: str,
|
|
1008
|
+
z0: float,
|
|
1009
|
+
pospin: str,
|
|
1010
|
+
refpin: Optional[str] = None,
|
|
1011
|
+
pos_type: str = "pin",
|
|
1012
|
+
ref_type: str = "pin",
|
|
1013
|
+
) -> None:
|
|
995
1014
|
"""Add a port to the component.
|
|
996
1015
|
|
|
997
1016
|
Parameters
|
|
@@ -1059,10 +1078,12 @@ class ControlFileComponents:
|
|
|
1059
1078
|
"""Manages components for the control file."""
|
|
1060
1079
|
|
|
1061
1080
|
def __init__(self):
|
|
1062
|
-
self.units = "um"
|
|
1063
|
-
self.components = []
|
|
1081
|
+
self.units: str = "um"
|
|
1082
|
+
self.components: List[str] = []
|
|
1064
1083
|
|
|
1065
|
-
def add_component(
|
|
1084
|
+
def add_component(
|
|
1085
|
+
self, ref_des: str, partname: str, component_type: str, die_type: str = "None", solderball_shape: str = "None"
|
|
1086
|
+
) -> ControlFileComponent:
|
|
1066
1087
|
"""Add a new component.
|
|
1067
1088
|
|
|
1068
1089
|
Parameters
|
|
@@ -1102,14 +1123,16 @@ class ControlFileBoundaries:
|
|
|
1102
1123
|
Length units. Default is "um".
|
|
1103
1124
|
"""
|
|
1104
1125
|
|
|
1105
|
-
def __init__(self, units="um"):
|
|
1106
|
-
self.ports = {}
|
|
1107
|
-
self.extents = []
|
|
1108
|
-
self.circuit_models = {}
|
|
1109
|
-
self.circuit_elements = {}
|
|
1110
|
-
self.units = units
|
|
1126
|
+
def __init__(self, units: str = "um") -> None:
|
|
1127
|
+
self.ports: Dict[str, ControlCircuitPt] = {}
|
|
1128
|
+
self.extents: List[ControlExtent] = []
|
|
1129
|
+
self.circuit_models: Dict[str, Any] = {}
|
|
1130
|
+
self.circuit_elements: Dict[str, Any] = {}
|
|
1131
|
+
self.units: str = units
|
|
1111
1132
|
|
|
1112
|
-
def add_port(
|
|
1133
|
+
def add_port(
|
|
1134
|
+
self, name: str, x1: float, y1: float, layer1: str, x2: float, y2: float, layer2: str, z0: float = 50
|
|
1135
|
+
) -> ControlCircuitPt:
|
|
1113
1136
|
"""Add a port.
|
|
1114
1137
|
|
|
1115
1138
|
Parameters
|
|
@@ -1141,16 +1164,16 @@ class ControlFileBoundaries:
|
|
|
1141
1164
|
|
|
1142
1165
|
def add_extent(
|
|
1143
1166
|
self,
|
|
1144
|
-
type="bbox",
|
|
1145
|
-
dieltype="bbox",
|
|
1146
|
-
diel_hactor=0.25,
|
|
1147
|
-
airbox_hfactor=0.25,
|
|
1148
|
-
airbox_vr_p=0.25,
|
|
1149
|
-
airbox_vr_n=0.25,
|
|
1150
|
-
useradiation=True,
|
|
1151
|
-
honor_primitives=True,
|
|
1152
|
-
truncate_at_gnd=True,
|
|
1153
|
-
):
|
|
1167
|
+
type: str = "bbox",
|
|
1168
|
+
dieltype: str = "bbox",
|
|
1169
|
+
diel_hactor: float = 0.25,
|
|
1170
|
+
airbox_hfactor: float = 0.25,
|
|
1171
|
+
airbox_vr_p: float = 0.25,
|
|
1172
|
+
airbox_vr_n: float = 0.25,
|
|
1173
|
+
useradiation: bool = True,
|
|
1174
|
+
honor_primitives: bool = True,
|
|
1175
|
+
truncate_at_gnd: bool = True,
|
|
1176
|
+
) -> ControlExtent:
|
|
1154
1177
|
"""Add an extent.
|
|
1155
1178
|
|
|
1156
1179
|
Parameters
|
|
@@ -1235,14 +1258,16 @@ class ControlFileSweep:
|
|
|
1235
1258
|
Whether to use Q3D for DC point.
|
|
1236
1259
|
"""
|
|
1237
1260
|
|
|
1238
|
-
def __init__(
|
|
1239
|
-
self
|
|
1240
|
-
|
|
1241
|
-
self.
|
|
1242
|
-
self.
|
|
1243
|
-
self.
|
|
1244
|
-
self.
|
|
1245
|
-
self.
|
|
1261
|
+
def __init__(
|
|
1262
|
+
self, name: str, start: str, stop: str, step: str, sweep_type: str, step_type: str, use_q3d: bool
|
|
1263
|
+
) -> None:
|
|
1264
|
+
self.name: str = name
|
|
1265
|
+
self.start: str = start
|
|
1266
|
+
self.stop: str = stop
|
|
1267
|
+
self.step: str = step
|
|
1268
|
+
self.sweep_type: str = sweep_type
|
|
1269
|
+
self.step_type: str = step_type
|
|
1270
|
+
self.use_q3d: bool = use_q3d
|
|
1246
1271
|
|
|
1247
1272
|
def _write_xml(self, root):
|
|
1248
1273
|
"""Write sweep to XML element.
|
|
@@ -1286,19 +1311,19 @@ class ControlFileMeshOp:
|
|
|
1286
1311
|
Dictionary of nets and layers.
|
|
1287
1312
|
"""
|
|
1288
1313
|
|
|
1289
|
-
def __init__(self, name, region, type, nets_layers):
|
|
1290
|
-
self.name = name
|
|
1291
|
-
self.region =
|
|
1292
|
-
self.type = type
|
|
1293
|
-
self.nets_layers = nets_layers
|
|
1294
|
-
self.num_max_elem = 1000
|
|
1295
|
-
self.restrict_elem = False
|
|
1296
|
-
self.restrict_length = True
|
|
1297
|
-
self.max_length = "20um"
|
|
1298
|
-
self.skin_depth = "1um"
|
|
1299
|
-
self.surf_tri_length = "1mm"
|
|
1300
|
-
self.num_layers = 2
|
|
1301
|
-
self.region_solve_inside = False
|
|
1314
|
+
def __init__(self, name: str, region: str, type: str, nets_layers: Dict[str, str]) -> None:
|
|
1315
|
+
self.name: str = name
|
|
1316
|
+
self.region: str = region
|
|
1317
|
+
self.type: str = type
|
|
1318
|
+
self.nets_layers: Dict[str, str] = nets_layers
|
|
1319
|
+
self.num_max_elem: int = 1000
|
|
1320
|
+
self.restrict_elem: bool = False
|
|
1321
|
+
self.restrict_length: bool = True
|
|
1322
|
+
self.max_length: str = "20um"
|
|
1323
|
+
self.skin_depth: str = "1um"
|
|
1324
|
+
self.surf_tri_length: str = "1mm"
|
|
1325
|
+
self.num_layers: int = 2
|
|
1326
|
+
self.region_solve_inside: bool = False
|
|
1302
1327
|
|
|
1303
1328
|
def _write_xml(self, root):
|
|
1304
1329
|
"""Write mesh operation to XML element.
|
|
@@ -1353,25 +1378,34 @@ class ControlFileSetup:
|
|
|
1353
1378
|
Setup name.
|
|
1354
1379
|
"""
|
|
1355
1380
|
|
|
1356
|
-
def __init__(self, name):
|
|
1357
|
-
self.name = name
|
|
1358
|
-
self.enabled = True
|
|
1359
|
-
self.save_fields = False
|
|
1360
|
-
self.save_rad_fields = False
|
|
1361
|
-
self.frequency = "1GHz"
|
|
1362
|
-
self.maxpasses = 10
|
|
1363
|
-
self.max_delta = 0.02
|
|
1364
|
-
self.union_polygons = True
|
|
1365
|
-
self.small_voids_area = 0
|
|
1366
|
-
self.mode_type = "IC"
|
|
1367
|
-
self.ic_model_resolution = "Auto"
|
|
1368
|
-
self.order_basis = "FirstOrder"
|
|
1369
|
-
self.solver_type = "Auto"
|
|
1370
|
-
self.low_freq_accuracy = False
|
|
1371
|
-
self.mesh_operations = []
|
|
1372
|
-
self.sweeps = []
|
|
1373
|
-
|
|
1374
|
-
def add_sweep(
|
|
1381
|
+
def __init__(self, name: str) -> None:
|
|
1382
|
+
self.name: str = name
|
|
1383
|
+
self.enabled: bool = True
|
|
1384
|
+
self.save_fields: bool = False
|
|
1385
|
+
self.save_rad_fields: bool = False
|
|
1386
|
+
self.frequency: str = "1GHz"
|
|
1387
|
+
self.maxpasses: int = 10
|
|
1388
|
+
self.max_delta: float = 0.02
|
|
1389
|
+
self.union_polygons: bool = True
|
|
1390
|
+
self.small_voids_area: int = 0
|
|
1391
|
+
self.mode_type: str = "IC"
|
|
1392
|
+
self.ic_model_resolution: str = "Auto"
|
|
1393
|
+
self.order_basis: str = "FirstOrder"
|
|
1394
|
+
self.solver_type: str = "Auto"
|
|
1395
|
+
self.low_freq_accuracy: bool = False
|
|
1396
|
+
self.mesh_operations: List[ControlFileMeshOp] = []
|
|
1397
|
+
self.sweeps: List[ControlFileSweep] = []
|
|
1398
|
+
|
|
1399
|
+
def add_sweep(
|
|
1400
|
+
self,
|
|
1401
|
+
name: str,
|
|
1402
|
+
start: str,
|
|
1403
|
+
stop: str,
|
|
1404
|
+
step: str,
|
|
1405
|
+
sweep_type: str = "Interpolating",
|
|
1406
|
+
step_type: str = "LinearStep",
|
|
1407
|
+
use_q3d: bool = True,
|
|
1408
|
+
) -> ControlFileSweep:
|
|
1375
1409
|
"""Add a frequency sweep.
|
|
1376
1410
|
|
|
1377
1411
|
Parameters
|
|
@@ -1399,7 +1433,7 @@ class ControlFileSetup:
|
|
|
1399
1433
|
self.sweeps.append(ControlFileSweep(name, start, stop, step, sweep_type, step_type, use_q3d))
|
|
1400
1434
|
return self.sweeps[-1]
|
|
1401
1435
|
|
|
1402
|
-
def add_mesh_operation(self, name, region, type, nets_layers):
|
|
1436
|
+
def add_mesh_operation(self, name: str, region: str, type: str, nets_layers: Dict[str, str]) -> ControlFileMeshOp:
|
|
1403
1437
|
"""Add a mesh operation.
|
|
1404
1438
|
|
|
1405
1439
|
Parameters
|
|
@@ -1480,7 +1514,7 @@ class ControlFileSetups:
|
|
|
1480
1514
|
def __init__(self):
|
|
1481
1515
|
self.setups = []
|
|
1482
1516
|
|
|
1483
|
-
def add_setup(self, name, frequency):
|
|
1517
|
+
def add_setup(self, name: str, frequency: str) -> ControlFileSetup:
|
|
1484
1518
|
"""Add a simulation setup.
|
|
1485
1519
|
|
|
1486
1520
|
Parameters
|
|
@@ -1526,12 +1560,25 @@ class ControlFile:
|
|
|
1526
1560
|
Path to layer map file.
|
|
1527
1561
|
"""
|
|
1528
1562
|
|
|
1529
|
-
def __init__(
|
|
1563
|
+
def __init__(
|
|
1564
|
+
self, xml_input: Optional[str] = None, technology: Optional[str] = None, layer_map: Optional[str] = None
|
|
1565
|
+
) -> None:
|
|
1566
|
+
"""Initialize control file object.
|
|
1567
|
+
|
|
1568
|
+
Parameters
|
|
1569
|
+
----------
|
|
1570
|
+
xml_input : str, optional
|
|
1571
|
+
Path to existing XML file to parse.
|
|
1572
|
+
tecnhology : str, optional
|
|
1573
|
+
Path to technology file to convert.
|
|
1574
|
+
layer_map : str, optional
|
|
1575
|
+
Path to layer map file.
|
|
1576
|
+
"""
|
|
1530
1577
|
self.stackup = ControlFileStackup()
|
|
1531
1578
|
if xml_input:
|
|
1532
1579
|
self.parse_xml(xml_input)
|
|
1533
|
-
if
|
|
1534
|
-
self.parse_technology(
|
|
1580
|
+
if technology:
|
|
1581
|
+
self.parse_technology(technology)
|
|
1535
1582
|
if layer_map:
|
|
1536
1583
|
self.parse_layer_map(layer_map)
|
|
1537
1584
|
self.boundaries = ControlFileBoundaries()
|
|
@@ -1543,7 +1590,7 @@ class ControlFile:
|
|
|
1543
1590
|
self.import_options = ControlFileImportOptions()
|
|
1544
1591
|
pass
|
|
1545
1592
|
|
|
1546
|
-
def parse_technology(self, tecnhology, edbversion=None):
|
|
1593
|
+
def parse_technology(self, tecnhology: str, edbversion: Optional[str] = None) -> bool:
|
|
1547
1594
|
"""Parse a technology file and convert to XML control file.
|
|
1548
1595
|
|
|
1549
1596
|
Parameters
|
|
@@ -1563,7 +1610,7 @@ class ControlFile:
|
|
|
1563
1610
|
if xml_temp:
|
|
1564
1611
|
return self.parse_xml(xml_temp)
|
|
1565
1612
|
|
|
1566
|
-
def parse_layer_map(self, layer_map):
|
|
1613
|
+
def parse_layer_map(self, layer_map: str) -> bool:
|
|
1567
1614
|
"""Parse a layer map file and update stackup.
|
|
1568
1615
|
|
|
1569
1616
|
Parameters
|
|
@@ -1613,7 +1660,7 @@ class ControlFile:
|
|
|
1613
1660
|
break
|
|
1614
1661
|
return True
|
|
1615
1662
|
|
|
1616
|
-
def parse_xml(self, xml_input):
|
|
1663
|
+
def parse_xml(self, xml_input: str) -> bool:
|
|
1617
1664
|
"""Parse an XML control file and populate the object.
|
|
1618
1665
|
|
|
1619
1666
|
Parameters
|