pyedb 0.28.0__py3-none-any.whl → 0.30.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 (33) hide show
  1. pyedb/__init__.py +29 -3
  2. pyedb/configuration/cfg_boundaries.py +44 -74
  3. pyedb/configuration/cfg_common.py +1 -1
  4. pyedb/configuration/cfg_components.py +31 -105
  5. pyedb/configuration/cfg_data.py +4 -9
  6. pyedb/configuration/cfg_general.py +19 -8
  7. pyedb/configuration/cfg_operations.py +14 -10
  8. pyedb/configuration/cfg_padstacks.py +41 -61
  9. pyedb/configuration/cfg_ports_sources.py +4 -2
  10. pyedb/configuration/cfg_s_parameter_models.py +85 -29
  11. pyedb/configuration/cfg_setup.py +5 -0
  12. pyedb/configuration/cfg_stackup.py +2 -6
  13. pyedb/configuration/configuration.py +42 -9
  14. pyedb/dotnet/edb.py +116 -57
  15. pyedb/dotnet/edb_core/cell/hierarchy/component.py +202 -0
  16. pyedb/dotnet/edb_core/cell/layout.py +2 -13
  17. pyedb/dotnet/edb_core/cell/primitive/primitive.py +10 -2
  18. pyedb/dotnet/edb_core/cell/terminal/terminal.py +4 -3
  19. pyedb/dotnet/edb_core/components.py +1 -2
  20. pyedb/dotnet/edb_core/definition/component_def.py +17 -1
  21. pyedb/dotnet/edb_core/definition/component_model.py +0 -4
  22. pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +3 -3
  23. pyedb/dotnet/edb_core/edb_data/layer_data.py +95 -1
  24. pyedb/dotnet/edb_core/edb_data/nets_data.py +10 -7
  25. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +67 -5
  26. pyedb/dotnet/edb_core/layout_validation.py +27 -4
  27. pyedb/dotnet/edb_core/nets.py +162 -181
  28. pyedb/dotnet/edb_core/padstack.py +0 -1
  29. pyedb/siwave.py +5 -1
  30. {pyedb-0.28.0.dist-info → pyedb-0.30.0.dist-info}/METADATA +3 -3
  31. {pyedb-0.28.0.dist-info → pyedb-0.30.0.dist-info}/RECORD +33 -33
  32. {pyedb-0.28.0.dist-info → pyedb-0.30.0.dist-info}/LICENSE +0 -0
  33. {pyedb-0.28.0.dist-info → pyedb-0.30.0.dist-info}/WHEEL +0 -0
pyedb/__init__.py CHANGED
@@ -3,14 +3,21 @@ import os
3
3
  import sys
4
4
  import warnings
5
5
 
6
- if os.name == "nt":
7
- os.environ["PYTHONMALLOC"] = "malloc"
6
+ # if os.name == "nt":
7
+ # os.environ["PYTHONMALLOC"] = "malloc"
8
8
 
9
9
  # By default we use pyedb legacy implementation
10
10
  if "PYEDB_USE_DOTNET" not in os.environ:
11
11
  os.environ["PYEDB_USE_DOTNET"] = "0"
12
12
 
13
13
  LATEST_DEPRECATED_PYTHON_VERSION = (3, 7)
14
+ LINUX_WARNING = (
15
+ "Due to compatibility issues between .NET Core and libssl on some Linux versions, "
16
+ "for example Ubuntu 22.04, we are going to stop depending on `dotnetcore2`."
17
+ "Instead of using this package which embeds .NET Core 3, users will be required to "
18
+ "install .NET themselves. For more information, see "
19
+ "https://edb.docs.pyansys.com/version/stable/build_breaking_change.html"
20
+ )
14
21
 
15
22
 
16
23
  def deprecation_warning():
@@ -39,12 +46,31 @@ def deprecation_warning():
39
46
  warnings.showwarning = existing_showwarning
40
47
 
41
48
 
49
+ def linux_warning():
50
+ """Warning message informing Linux users a future breaking change is coming."""
51
+ # Store warnings showwarning
52
+ existing_showwarning = warnings.showwarning
53
+
54
+ # Define and use custom showwarning
55
+ def custom_show_warning(message, category, filename, lineno, file=None, line=None):
56
+ """Custom warning used to remove <stdin>:loc: pattern."""
57
+ print("{}: {}".format(category.__name__, message))
58
+
59
+ warnings.showwarning = custom_show_warning
60
+
61
+ if os.name == "posix":
62
+ warnings.warn(LINUX_WARNING, FutureWarning)
63
+
64
+ # Restore warnings showwarning
65
+ warnings.showwarning = existing_showwarning
66
+
67
+
42
68
  deprecation_warning()
43
69
 
44
70
  #
45
71
 
46
72
  pyedb_path = os.path.dirname(__file__)
47
- __version__ = "0.28.0"
73
+ __version__ = "0.30.0"
48
74
  version = __version__
49
75
 
50
76
  #
@@ -20,97 +20,50 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- from enum import Enum
23
+ from pyedb.configuration.cfg_common import CfgBase
24
24
 
25
25
 
26
- class CfgBoundaries:
27
- def __init__(self, pdata, boundaries_dict):
28
- self._pedb = pdata._pedb
29
- self._boundaries_dict = boundaries_dict
30
- self.open_region = self._boundaries_dict.get("open_region", None)
31
- self._map_open_region_type()
32
- self.pml_visible = self._boundaries_dict.get("pml_visible", None)
33
- self.pml_operation_frequency = self._boundaries_dict.get("pml_operation_frequency", None)
34
- self.pml_radiation_factor = self._boundaries_dict.get("pml_radiation_factor", None)
35
- self._map_dielectric_extend_type()
36
- self.dielectric_base_polygon = self._boundaries_dict.get("dielectric_base_polygon", None)
37
- self.horizontal_padding = self._boundaries_dict.get("horizontal_padding", None)
38
- self.honor_primitives_on_dielectric_layers = self._boundaries_dict.get(
39
- "honor_primitives_on_dielectric_layers", False
40
- )
41
- self._map_air_box_extend_type()
42
- self.air_box_base_polygon = self._boundaries_dict.get("air_box_base_polygon", None)
43
- self.air_box_truncate_model_ground_layers = self._boundaries_dict.get(
44
- "air_box_truncate_model_ground_layers", None
45
- )
46
- self.air_box_horizontal_padding = self._boundaries_dict.get("air_box_horizontal_padding", None)
47
- self.air_box_positive_vertical_padding = self._boundaries_dict.get("air_box_positive_vertical_padding", None)
48
- self.air_box_negative_vertical_padding = self._boundaries_dict.get("air_box_negative_vertical_padding", None)
49
-
50
- def _map_air_box_extend_type(self):
51
- air_box_type = self._boundaries_dict.get("air_box_extents_type", None)
52
- if air_box_type == "bounding_box":
53
- self.air_box_extents_type = self.ExtentType.BOUNDING_BOX
54
- elif air_box_type == "conformal":
55
- self.air_box_extents_type = self.ExtentType.CONFORMAL
56
- elif air_box_type == "convex_hull":
57
- self.air_box_extents_type = self.ExtentType.CONVEX_HULL
58
- elif air_box_type == "polygon":
59
- self.air_box_extents_type = self.ExtentType.POLYGON
60
- else:
61
- self.air_box_extents_type = self.ExtentType.BOUNDING_BOX
62
-
63
- def _map_open_region_type(self):
64
- open_region = self._boundaries_dict.get("open_region_type", None)
65
- if open_region == "radiation":
66
- self.open_region_type = self.OpenRegionType.RADIATION
67
- elif open_region == "pec":
68
- self.open_region_type = self.OpenRegionType.PEC
69
- else:
70
- self.open_region_type = self.OpenRegionType.RADIATION
71
-
72
- def _map_dielectric_extend_type(self):
73
- extend_type = self._boundaries_dict.get("dielectric_extents_type", None)
74
- if extend_type == "bounding_box":
75
- self.dielectric_extents_type = self.ExtentType.BOUNDING_BOX
76
- elif extend_type == "conformal":
77
- self.dielectric_extents_type = self.ExtentType.CONFORMAL
78
- elif extend_type == "convex_hull":
79
- self.dielectric_extents_type = self.ExtentType.CONVEX_HULL
80
- elif extend_type == "polygon":
81
- self.dielectric_extents_type = self.ExtentType.POLYGON
82
- else:
83
- self.dielectric_extents_type = self.ExtentType.BOUNDING_BOX
84
-
85
- class OpenRegionType(Enum):
86
- RADIATION = 0
87
- PEC = 1
88
-
89
- class ExtentType(Enum):
90
- BOUNDING_BOX = 0
91
- CONFORMAL = 1
92
- CONVEX_HULL = 2
93
- POLYGON = 3
26
+ class CfgBoundaries(CfgBase):
27
+ def __init__(self, pedb, boundary_data):
28
+ self._pedb = pedb
29
+ self.open_region = boundary_data.get("open_region", None)
30
+ self.open_region_type = boundary_data.get("map_open_region_type", None)
31
+ self.pml_visible = boundary_data.get("pml_visible", None)
32
+ self.pml_operation_frequency = boundary_data.get("pml_operation_frequency", None)
33
+ self.pml_radiation_factor = boundary_data.get("pml_radiation_factor", None)
34
+ self.dielectric_extent_type = boundary_data.get("dielectric_extent_type", None)
35
+ # self.dielectric_base_polygon = self.**kwargs.get("dielectric_base_polygon", None)
36
+ self.horizontal_padding = boundary_data.get("horizontal_padding", None)
37
+ self.honor_primitives_on_dielectric_layers = boundary_data.get("honor_primitives_on_dielectric_layers", False)
38
+ self.air_box_extent_type = boundary_data.get("air_box_extent_type", None)
39
+ self.air_box_base_polygon = boundary_data.get("air_box_base_polygon", None)
40
+ self.air_box_truncate_model_ground_layers = boundary_data.get("air_box_truncate_model_ground_layers", None)
41
+ self.air_box_horizontal_padding = boundary_data.get("air_box_horizontal_padding", None)
42
+ self.air_box_positive_vertical_padding = boundary_data.get("air_box_positive_vertical_padding", None)
43
+ self.air_box_negative_vertical_padding = boundary_data.get("air_box_negative_vertical_padding", None)
94
44
 
95
45
  def apply(self):
96
46
  """Imports boundary information from JSON."""
97
47
  if self.open_region is not None:
98
48
  self._pedb.hfss.hfss_extent_info.use_open_region = self.open_region
99
- self._pedb.hfss.hfss_extent_info.open_region_type = self.open_region_type.name.lower()
49
+ if self.open_region_type:
50
+ self._pedb.hfss.hfss_extent_info.open_region_type = self.open_region_type.lower()
100
51
  if self.pml_visible is not None:
101
52
  self._pedb.hfss.hfss_extent_info.is_pml_visible = self.pml_visible
102
53
  if self.pml_operation_frequency:
103
54
  self._pedb.hfss.hfss_extent_info.operating_freq = self.pml_operation_frequency
104
55
  if self.pml_radiation_factor:
105
56
  self._pedb.hfss.hfss_extent_info.radiation_level = self.pml_radiation_factor
106
- self._pedb.hfss.hfss_extent_info.extent_type = self.dielectric_extents_type.name.lower()
107
- if self.dielectric_base_polygon:
108
- self._pedb.hfss.hfss_extent_info.dielectric_base_polygon = self.dielectric_base_polygon
57
+ if self.dielectric_extent_type:
58
+ self._pedb.hfss.hfss_extent_info.extent_type = self.dielectric_extent_type.lower()
59
+ # if self.dielectric_base_polygon:
60
+ # self._pedb.hfss.hfss_extent_info.dielectric_base_polygon = self.dielectric_base_polygon
109
61
  if self.horizontal_padding:
110
62
  self._pedb.hfss.hfss_extent_info.dielectric_extent_size = float(self.horizontal_padding)
111
63
  if self.honor_primitives_on_dielectric_layers is not None:
112
64
  self._pedb.hfss.hfss_extent_info.honor_user_dielectric = self.honor_primitives_on_dielectric_layers
113
- self._pedb.hfss.hfss_extent_info.extent_type = self.air_box_extents_type.name.lower()
65
+ if self.air_box_extent_type:
66
+ self._pedb.hfss.hfss_extent_info.extent_type = self.air_box_extent_type.lower()
114
67
  if self.air_box_truncate_model_ground_layers is not None:
115
68
  self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground = self.air_box_truncate_model_ground_layers
116
69
  if self.air_box_horizontal_padding:
@@ -123,3 +76,20 @@ class CfgBoundaries:
123
76
  self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent = float(
124
77
  self.air_box_negative_vertical_padding
125
78
  )
79
+
80
+ def get_data_from_db(self):
81
+ self.open_region = self._pedb.hfss.hfss_extent_info.use_open_region
82
+ self.open_region_type = self._pedb.hfss.hfss_extent_info.open_region_type
83
+ self.pml_visible = self._pedb.hfss.hfss_extent_info.is_pml_visible
84
+ self.pml_operation_frequency = self._pedb.hfss.hfss_extent_info.operating_freq.tostring
85
+ self.pml_radiation_factor = self._pedb.hfss.hfss_extent_info.radiation_level.tostring
86
+ self.dielectric_extent_type = self._pedb.hfss.hfss_extent_info.extent_type
87
+ # self.dielectric_base_polygon = self._pedb.hfss.hfss_extent_info.dielectric_base_polygon
88
+ self.horizontal_padding = self._pedb.hfss.hfss_extent_info.dielectric_extent_size
89
+ self.honor_primitives_on_dielectric_layers = self._pedb.hfss.hfss_extent_info.honor_user_dielectric
90
+ self.air_box_extent_type = self._pedb.hfss.hfss_extent_info.extent_type
91
+ self.air_box_truncate_model_ground_layers = self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground
92
+ self.air_box_horizontal_padding = self._pedb.hfss.hfss_extent_info.air_box_horizontal_extent
93
+ self.air_box_positive_vertical_padding = self._pedb.hfss.hfss_extent_info.air_box_positive_vertical_extent
94
+ self.air_box_negative_vertical_padding = self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent
95
+ return self.get_attributes()
@@ -30,7 +30,7 @@ class CfgBase:
30
30
  exclude = exclude if isinstance(exclude, list) else [exclude]
31
31
  attrs = {i: j for i, j in attrs.items() if i not in exclude}
32
32
  attrs = {i: j for i, j in attrs.items() if not i.startswith("_")}
33
- attrs = {i: j for i, j in attrs.items() if j is not None}
33
+ attrs = {i: j for i, j in attrs.items() if j not in [None, [], {}]}
34
34
  return attrs
35
35
 
36
36
  def set_attributes(self, pedb_object):
@@ -23,23 +23,6 @@
23
23
  from pyedb.configuration.cfg_common import CfgBase
24
24
 
25
25
 
26
- class CfgPortProperties(CfgBase):
27
- def __init__(self, **kwargs):
28
- self.reference_offset = kwargs.pop("reference_offset", 0)
29
- self.reference_size_auto = kwargs.pop("reference_size_auto", 0)
30
- self.reference_size_x = kwargs.pop("reference_size_x", 0)
31
- self.reference_size_y = kwargs.pop("reference_size_y", 0)
32
-
33
-
34
- class CfgSolderBallsProperties(CfgBase):
35
- def __init__(self, **kwargs):
36
- self.shape = kwargs.pop("shape", None)
37
- self.diameter = kwargs.pop("diameter", None)
38
- self.mid_diameter = kwargs.pop("mid_diameter", None)
39
- self.height = kwargs.pop("height", None)
40
- self.enabled = kwargs.pop("enabled", None)
41
-
42
-
43
26
  class CfgRlcModel(CfgBase):
44
27
  def __init__(self, **kwargs):
45
28
  self.resistance = kwargs.get("resistance", None)
@@ -51,45 +34,17 @@ class CfgRlcModel(CfgBase):
51
34
 
52
35
 
53
36
  class CfgComponent(CfgBase):
54
- protected_attributes = ["reference_designator", "definition", "location", "angle", "placement_layer"]
55
-
56
37
  def __init__(self, **kwargs):
57
38
  self.enabled = kwargs.get("enabled", None)
58
-
59
39
  self.reference_designator = kwargs.get("reference_designator", None)
60
40
  self.definition = kwargs.get("definition", None)
61
- self.type = kwargs.get("part_type", None)
62
- self.value = kwargs.get("value", None)
63
- self.port_properties = CfgPortProperties(**kwargs["port_properties"]) if "port_properties" in kwargs else None
64
- self.solder_ball_properties = (
65
- CfgSolderBallsProperties(**kwargs["solder_ball_properties"]) if "solder_ball_properties" in kwargs else None
66
- )
67
- rlc_models = kwargs.get("rlc_model", [])
68
-
69
- self.rlc_model = [CfgRlcModel(**rlc_m) for rlc_m in rlc_models]
70
-
71
- self.x_location, self.y_location = kwargs.get("location", [None, None])
72
- self.angle = kwargs.get("angle", None)
73
- self.placement_layer = kwargs.get("placement_layer", None)
74
-
75
- def export_properties(self):
76
- """Export component properties.
77
-
78
- Returns
79
- -------
80
- Dict
81
- """
82
- data_comp = {}
83
- data_comp["enabled"] = self.enabled
84
- data_comp["reference_designator"] = self.reference_designator
85
- data_comp["definition"] = self.definition
86
- data_comp["type"] = self.type
87
- data_comp["value"] = self.value
88
- data_comp["x_location"] = self.x_location
89
- data_comp["y_location"] = self.y_location
90
- # data_comp["angle"] = self.angle
91
- data_comp["placement_layer"] = self.placement_layer
92
- return data_comp
41
+ self.type = kwargs["part_type"].lower() if kwargs.get("part_type") else None
42
+ self.port_properties = kwargs.get("port_properties", {})
43
+ self.solder_ball_properties = kwargs.get("solder_ball_properties", {})
44
+ self.ic_die_properties = kwargs.get("ic_die_properties", {})
45
+ self.pin_pair_model = kwargs.get("pin_pair_model", None)
46
+ self.spice_model = kwargs.get("spice_model", None)
47
+ self.s_parameter_model = kwargs.get("s_parameter_model", None)
93
48
 
94
49
 
95
50
  class CfgComponents:
@@ -100,57 +55,23 @@ class CfgComponents:
100
55
  def apply(self):
101
56
  comps_in_db = self._pedb.components
102
57
  for comp in self.components:
103
- c_db = comps_in_db[comp.reference_designator]
104
-
105
- for attr, value in comp.get_attributes().items(): # All component properties
106
- if attr == "solder_ball_properties":
107
- solder_ball_properties = value
108
- port_properties = comp.port_properties
109
- self._pedb.components.set_solder_ball(
110
- component=comp.reference_designator,
111
- sball_diam=solder_ball_properties.diameter,
112
- sball_mid_diam=solder_ball_properties.mid_diameter,
113
- sball_height=solder_ball_properties.height,
114
- shape=solder_ball_properties.shape,
115
- auto_reference_size=port_properties.reference_size_auto,
116
- reference_height=port_properties.reference_offset,
117
- reference_size_x=port_properties.reference_size_x,
118
- reference_size_y=port_properties.reference_size_y,
119
- )
120
- elif attr == "port_properties":
121
- pass
122
- elif attr == "rlc_model":
123
- rlc_models = value
124
- model_layout = c_db.model
125
- for pp in model_layout.pin_pairs:
126
- model_layout.delete_pin_pair_rlc(pp)
127
- for pp in rlc_models:
128
- pin_pair = self._pedb.edb_api.utility.PinPair(pp.p1, pp.p2)
129
- rlc = self._pedb.edb_api.utility.Rlc()
130
- rlc.IsParallel = False if pp.type else True
131
- if pp.resistance is not None:
132
- rlc.REnabled = True
133
- rlc.R = self._pedb.edb_value(pp.resistance)
134
- else:
135
- rlc.REnabled = False
136
- if pp.inductance is not None:
137
- rlc.LEnabled = True
138
- rlc.L = self._pedb.edb_value(pp.inductance)
139
- else:
140
- rlc.LEnabled = False
141
-
142
- if pp.capacitance is not None:
143
- rlc.CEnabled = True
144
- rlc.C = self._pedb.edb_value(pp.capacitance)
145
- else:
146
- rlc.CEnabled = False
147
- model_layout._set_pin_pair_rlc(pin_pair, rlc)
148
- comps_in_db.model = model_layout
149
- else:
150
- if attr in dir(c_db):
151
- setattr(c_db, attr, value)
152
- else:
153
- raise AttributeError(f"'{attr}' is not valid component attribute.")
58
+ c_db = comps_in_db.instances[comp.reference_designator]
59
+ if comp.definition:
60
+ c_db.definition = comp.definition
61
+ if comp.type:
62
+ c_db.type = comp.type
63
+ if comp.solder_ball_properties:
64
+ c_db.solder_ball_properties = comp.solder_ball_properties
65
+ if comp.port_properties:
66
+ c_db.port_properties = comp.port_properties
67
+ if comp.ic_die_properties:
68
+ c_db.ic_die_properties = comp.ic_die_properties
69
+ if comp.pin_pair_model:
70
+ c_db.model_properties = {"pin_pair_model": comp.pin_pair_model}
71
+ if comp.spice_model:
72
+ c_db.model_properties = {"spice_model": comp.spice_model}
73
+ if comp.s_parameter_model:
74
+ c_db.model_properties = {"s_parameter_model": comp.s_parameter_model}
154
75
 
155
76
  def _load_data_from_db(self):
156
77
  self.components = []
@@ -160,10 +81,15 @@ class CfgComponents:
160
81
  enabled=comp.enabled,
161
82
  reference_designator=comp.name,
162
83
  part_type=comp.type,
163
- value=comp.value,
84
+ pin_pair_model=comp.model_properties.get("pin_pair_model"),
85
+ spice_model=comp.model_properties.get("spice_model"),
86
+ s_parameter_model=comp.model_properties.get("s_parameter_model"),
164
87
  definition=comp.component_def,
165
88
  location=comp.location,
166
89
  placement_layer=comp.placement_layer,
90
+ solder_ball_properties=comp.solder_ball_properties,
91
+ ic_die_properties=comp.ic_die_properties,
92
+ port_properties=comp.port_properties,
167
93
  )
168
94
  self.components.append(cfg_comp)
169
95
 
@@ -171,5 +97,5 @@ class CfgComponents:
171
97
  self._load_data_from_db()
172
98
  data = []
173
99
  for comp in self.components:
174
- data.append(comp.export_properties())
100
+ data.append(comp.get_attributes())
175
101
  return data
@@ -30,7 +30,7 @@ from pyedb.configuration.cfg_package_definition import CfgPackageDefinitions
30
30
  from pyedb.configuration.cfg_padstacks import CfgPadstacks
31
31
  from pyedb.configuration.cfg_pin_groups import CfgPinGroups
32
32
  from pyedb.configuration.cfg_ports_sources import CfgPorts, CfgSources
33
- from pyedb.configuration.cfg_s_parameter_models import CfgSParameterModel
33
+ from pyedb.configuration.cfg_s_parameter_models import CfgSParameters
34
34
  from pyedb.configuration.cfg_setup import CfgSetups
35
35
  from pyedb.configuration.cfg_spice_models import CfgSpiceModel
36
36
  from pyedb.configuration.cfg_stackup import CfgStackup
@@ -41,11 +41,9 @@ class CfgData(object):
41
41
 
42
42
  def __init__(self, pedb, **kwargs):
43
43
  self._pedb = pedb
44
- self.general = CfgGeneral(self, kwargs.get("general", None))
44
+ self.general = CfgGeneral(self._pedb, kwargs.get("general", {}))
45
45
 
46
- self.boundaries = {}
47
- if kwargs.get("boundaries", None):
48
- self.boundaries = CfgBoundaries(self, kwargs.get("boundaries", None))
46
+ self.boundaries = CfgBoundaries(self._pedb, kwargs.get("boundaries", {}))
49
47
 
50
48
  self.nets = CfgNets(
51
49
  self, kwargs.get("nets", {}).get("signal_nets", []), kwargs.get("nets", {}).get("power_ground_nets", [])
@@ -65,10 +63,7 @@ class CfgData(object):
65
63
 
66
64
  self.stackup = CfgStackup(self._pedb, data=kwargs.get("stackup", {}))
67
65
 
68
- self.s_parameters = [
69
- CfgSParameterModel(self, self.general.s_parameter_library, sparam_model)
70
- for sparam_model in kwargs.get("s_parameters", [])
71
- ]
66
+ self.s_parameters = CfgSParameters(self._pedb, kwargs.get("s_parameters", []), self.general.s_parameter_library)
72
67
 
73
68
  self.spice_models = [
74
69
  CfgSpiceModel(self, self.general.spice_model_library, spice_model)
@@ -24,11 +24,22 @@
24
24
  class CfgGeneral:
25
25
  """Manage configuration general settings."""
26
26
 
27
- def __init__(self, pdata, general_dict):
28
- self._pedb = pdata._pedb
29
- self.spice_model_library = ""
30
- self.s_parameter_library = ""
31
- if general_dict:
32
- self._general_dict = general_dict
33
- self.spice_model_library = self._general_dict.get("spice_model_library", "")
34
- self.s_parameter_library = self._general_dict.get("s_parameter_library", "")
27
+ def __init__(self, pedb, data):
28
+ self._pedb = pedb
29
+ self.spice_model_library = data.get("spice_model_library", "")
30
+ self.s_parameter_library = data.get("s_parameter_library", "")
31
+ self.anti_pads_always_on = data.get("anti_pads_always_on", False)
32
+ self.suppress_pads = data.get("suppress_pads", True)
33
+
34
+ def apply(self):
35
+ self._pedb.design_options.antipads_always_on = self.anti_pads_always_on
36
+ self._pedb.design_options.suppress_pads = self.suppress_pads
37
+
38
+ def get_data_from_db(self):
39
+ self.anti_pads_always_on = self._pedb.design_options.antipads_always_on
40
+ self.suppress_pads = self._pedb.design_options.suppress_pads
41
+
42
+ data = {}
43
+ data["anti_pads_always_on"] = self.anti_pads_always_on
44
+ data["suppress_pads"] = self.suppress_pads
45
+ return data
@@ -53,18 +53,20 @@ class CfgCutout(CfgBase):
53
53
 
54
54
  def get_data_from_db(self):
55
55
  if "pyedb_cutout" in self._pedb.stackup.all_layers:
56
- poly = self._pedb.layout.find_primitive(layer_name="pyedb_cutout")[0]
57
- self.custom_extent = poly.polygon_data.points
56
+ polygons = self._pedb.layout.find_primitive(layer_name="pyedb_cutout")
57
+ if polygons:
58
+ poly = polygons[0]
59
+ self.custom_extent = poly.polygon_data.points
58
60
 
59
- net_names = []
60
- for name, obj in self._pedb.nets.nets.items():
61
- if obj.primitives[0].layer.name == "pyedb_cutout":
62
- continue
63
- if len(obj.primitives) > 0:
64
- net_names.append(name)
61
+ net_names = []
62
+ for name, obj in self._pedb.nets.nets.items():
63
+ if obj.primitives[0].layer.name == "pyedb_cutout":
64
+ continue
65
+ if len(obj.primitives) > 0:
66
+ net_names.append(name)
65
67
 
66
- self.reference_list = []
67
- self.signal_list = net_names
68
+ self.reference_list = []
69
+ self.signal_list = net_names
68
70
  return self.export_properties()
69
71
 
70
72
  def export_properties(self):
@@ -95,3 +97,5 @@ class CfgOperations(CfgBase):
95
97
  data_from_db = self.op_cutout.get_data_from_db()
96
98
  if data_from_db:
97
99
  return {"cutout": data_from_db}
100
+ else:
101
+ return {}
@@ -20,9 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
-
24
- from enum import Enum
25
-
26
23
  from pyedb.configuration.cfg_common import CfgBase
27
24
 
28
25
 
@@ -37,16 +34,25 @@ class CfgPadstacks:
37
34
  for pdef in padstack_dict.get("definitions", []):
38
35
  self.definitions.append(Definition(**pdef))
39
36
  for inst in padstack_dict.get("instances", []):
40
- self.instances.append(Instance(self._pedb, inst))
37
+ self.instances.append(Instance(**inst))
41
38
 
42
39
  def apply(self):
43
40
  """Apply padstack definition and instances on layout."""
44
- padstack_defs_layout = self._pedb.padstacks.definitions
45
- for pdef in self.definitions:
46
- pdef_layout = padstack_defs_layout[pdef.name]
47
- pdef_layout.set_properties(**pdef.get_attributes())
48
- for instance in self.instances:
49
- instance.apply()
41
+ if self.definitions:
42
+ padstack_defs_layout = self._pedb.padstacks.definitions
43
+ for pdef in self.definitions:
44
+ pdef_layout = padstack_defs_layout[pdef.name]
45
+ pdef_layout.set_properties(**pdef.get_attributes())
46
+ if self.instances:
47
+ instances_layout = self._pedb.padstacks.instances_by_name
48
+ for inst in self.instances:
49
+ inst_layout = instances_layout[inst.name]
50
+ if inst.definition:
51
+ # inst_layout.padstack_definition = inst.definition
52
+ # Not supported by EDB API
53
+ pass
54
+ if inst.backdrill_parameters:
55
+ inst_layout.backdrill_parameters = inst.backdrill_parameters
50
56
 
51
57
  def get_data_from_db(self):
52
58
  self.definitions = []
@@ -66,6 +72,23 @@ class CfgPadstacks:
66
72
  for i in self.definitions:
67
73
  definitions.append(i.get_attributes())
68
74
  data["definitions"] = definitions
75
+
76
+ for obj in self._pedb.layout.padstack_instances:
77
+ temp = obj.properties
78
+ self.instances.append(
79
+ Instance(
80
+ name=temp["name"],
81
+ definition=temp["definition"],
82
+ backdrill_parameters=temp["backdrill_parameters"],
83
+ id=temp["id"],
84
+ position=temp["position"],
85
+ rotation=temp["rotation"],
86
+ )
87
+ )
88
+ instances = []
89
+ for i in self.instances:
90
+ instances.append(i.get_attributes("id"))
91
+ data["instances"] = instances
69
92
  return data
70
93
 
71
94
 
@@ -81,56 +104,13 @@ class Definition(CfgBase):
81
104
  self.hole_parameters = kwargs.get("hole_parameters", None)
82
105
 
83
106
 
84
- class Instance:
107
+ class Instance(CfgBase):
85
108
  """Instance data class."""
86
109
 
87
- def __init__(self, pedb, instances_dict):
88
- self._pedb = pedb
89
- self._instances_dict = instances_dict
90
- self.name = self._instances_dict.get("name", "")
91
- self.backdrill_top = None
92
- self.backdrill_bottom = None
93
- self._update_backdrill()
94
-
95
- def _update_backdrill(self):
96
- if "backdrill_top" in self._instances_dict:
97
- self.backdrill_top = self.BackDrill()
98
- self.backdrill_top.type = self.backdrill_top.BackDrillType.TOP
99
- backdrill_top_dict = self._instances_dict["backdrill_top"]
100
- self.backdrill_top.drill_to_layer = backdrill_top_dict.get("drill_to_layer", "")
101
- self.backdrill_top.drill_diameter = backdrill_top_dict.get("drill_diameter", "")
102
- self.backdrill_top.stub_length = backdrill_top_dict.get("stub_length", "")
103
- if "backdrill_bottom" in self._instances_dict:
104
- self.backdrill_bottom = self.BackDrill()
105
- backdrill_bottom_dict = self._instances_dict["backdrill_bottom"]
106
- self.backdrill_bottom.drill_to_layer = backdrill_bottom_dict.get("drill_to_layer", "")
107
- self.backdrill_bottom.drill_diameter = backdrill_bottom_dict.get("drill_diameter", "")
108
- self.backdrill_bottom.stub_length = backdrill_bottom_dict.get("stub_length", "")
109
-
110
- class BackDrill:
111
- """Backdrill data class."""
112
-
113
- def __init__(self):
114
- self.type = self.BackDrillType.BOTTOM
115
- self.drill_to_layer = ""
116
- self.drill_diameter = ""
117
- self.stub_length = ""
118
-
119
- class BackDrillType(Enum):
120
- TOP = 0
121
- BOTTOM = 1
122
-
123
- def apply(self):
124
- """Apply padstack instance on layout."""
125
- padstack_instances = self._pedb.padstacks.instances_by_name
126
- inst = padstack_instances[self.name]
127
- if self.backdrill_top:
128
- inst.set_backdrill_top(
129
- self.backdrill_top.drill_to_layer, self.backdrill_top.drill_diameter, self.backdrill_top.stub_length
130
- )
131
- if self.backdrill_bottom:
132
- inst.set_backdrill_bottom(
133
- self.backdrill_bottom.drill_to_layer,
134
- self.backdrill_bottom.drill_diameter,
135
- self.backdrill_bottom.stub_length,
136
- )
110
+ def __init__(self, **kwargs):
111
+ self.name = kwargs["name"]
112
+ self.definition = kwargs.get("definition", None)
113
+ self.backdrill_parameters = kwargs.get("backdrill_parameters", None)
114
+ self.id = kwargs.get("id", None)
115
+ self.position = kwargs.get("position", [])
116
+ self.rotation = kwargs.get("rotation", None)
@@ -337,13 +337,15 @@ class CfgPort(CfgCircuitElement):
337
337
  return circuit_elements
338
338
 
339
339
  def export_properties(self):
340
- return {
340
+ data = {
341
341
  "name": self.name,
342
342
  "type": self.type,
343
343
  "reference_designator": self.reference_designator,
344
344
  "positive_terminal": self.positive_terminal_info.export_properties(),
345
- "negative_terminal": self.negative_terminal_info.export_properties(),
346
345
  }
346
+ if self.negative_terminal_info:
347
+ data.update({"negative_terminal": self.negative_terminal_info.export_properties()})
348
+ return data
347
349
 
348
350
 
349
351
  class CfgSource(CfgCircuitElement):