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
@@ -33,6 +33,7 @@ from pyedb.dotnet.edb_core.cell.hierarchy.s_parameter_model import SparamModel
33
33
  from pyedb.dotnet.edb_core.cell.hierarchy.spice_model import SpiceModel
34
34
  from pyedb.dotnet.edb_core.definition.package_def import PackageDef
35
35
  from pyedb.dotnet.edb_core.edb_data.padstacks_data import EDBPadstackInstance
36
+ from pyedb.dotnet.edb_core.general import pascal_to_snake, snake_to_pascal
36
37
 
37
38
  try:
38
39
  import numpy as np
@@ -1008,3 +1009,204 @@ class EDBComponent(Group):
1008
1009
  )
1009
1010
  void.is_negative = True
1010
1011
  return True
1012
+
1013
+ @property
1014
+ def model_properties(self):
1015
+ pp = {}
1016
+ c_p = self.component_property
1017
+ model = c_p.GetModel().Clone()
1018
+ netlist_model = {}
1019
+ pin_pair_model = []
1020
+ s_parameter_model = {}
1021
+ spice_model = {}
1022
+ if model.GetModelType().ToString() == "NetlistModel":
1023
+ netlist_model["netlist"] = model.GetNetlist()
1024
+ elif model.GetModelType().ToString() == "PinPairModel":
1025
+ temp = {}
1026
+ for i in model.PinPairs:
1027
+ temp["first_pin"] = i.FirstPin
1028
+ temp["second_pin"] = i.SecondPin
1029
+ rlc = model.GetPinPairRlc(i)
1030
+ temp["is_parallel"] = rlc.IsParallel
1031
+ temp["resistance"] = rlc.R.ToString()
1032
+ temp["resistance_enabled"] = rlc.REnabled
1033
+ temp["inductance"] = rlc.L.ToString()
1034
+ temp["inductance_enabled"] = rlc.LEnabled
1035
+ temp["capacitance"] = rlc.C.ToString()
1036
+ temp["capacitance_enabled"] = rlc.CEnabled
1037
+ pin_pair_model.append(temp)
1038
+ elif model.GetModelType().ToString() == "SParameterModel":
1039
+ s_parameter_model["reference_net"] = model.GetReferenceNet()
1040
+ s_parameter_model["model_name"] = model.GetComponentModelName()
1041
+ elif model.GetModelType().ToString() == "SPICEModel":
1042
+ spice_model["model_name"] = model.GetModelName()
1043
+ spice_model["model_path"] = model.GetModelPath()
1044
+ spice_model["sub_circuit"] = model.GetSubCkt()
1045
+ spice_model["terminal_pairs"] = [[i, j] for i, j in dict(model.GetTerminalPinPairs()).items()]
1046
+
1047
+ if netlist_model:
1048
+ pp["netlist_model"] = netlist_model
1049
+ if pin_pair_model:
1050
+ pp["pin_pair_model"] = pin_pair_model
1051
+ if s_parameter_model:
1052
+ pp["s_parameter_model"] = s_parameter_model
1053
+ if spice_model:
1054
+ pp["spice_model"] = spice_model
1055
+ return pp
1056
+
1057
+ @model_properties.setter
1058
+ def model_properties(self, kwargs):
1059
+ netlist_model = kwargs.get("netlist_model")
1060
+ pin_pair_model = kwargs.get("pin_pair_model")
1061
+ s_parameter_model = kwargs.get("s_parameter_model")
1062
+ spice_model = kwargs.get("spice_model")
1063
+
1064
+ c_p = self.component_property
1065
+ if netlist_model:
1066
+ m = self._pedb._edb.Cell.Hierarchy.SParameterModel()
1067
+ m.SetNetlist(netlist_model["netlist"])
1068
+ c_p.SetModel(m)
1069
+ self.component_property = c_p
1070
+ elif pin_pair_model:
1071
+ m = self._pedb._edb.Cell.Hierarchy.PinPairModel()
1072
+ for i in pin_pair_model:
1073
+ p = self._pedb._edb.Utility.PinPair(str(i["first_pin"]), str(i["second_pin"]))
1074
+ rlc = self._pedb._edb.Utility.Rlc(
1075
+ self._pedb.edb_value(i["resistance"]),
1076
+ i["resistance_enabled"],
1077
+ self._pedb.edb_value(i["inductance"]),
1078
+ i["inductance_enabled"],
1079
+ self._pedb.edb_value(i["capacitance"]),
1080
+ i["capacitance_enabled"],
1081
+ i["is_parallel"],
1082
+ )
1083
+ m.SetPinPairRlc(p, rlc)
1084
+ c_p.SetModel(m)
1085
+ self.component_property = c_p
1086
+ elif s_parameter_model:
1087
+ m = self._pedb._edb.Cell.Hierarchy.SParameterModel()
1088
+ m.SetComponentModelName(s_parameter_model["model_name"])
1089
+ m.SetReferenceNet(s_parameter_model["reference_net"])
1090
+ c_p.SetModel(m)
1091
+ self.component_property = c_p
1092
+ elif spice_model:
1093
+ self.assign_spice_model(
1094
+ spice_model["model_path"],
1095
+ spice_model["model_name"],
1096
+ spice_model["sub_circuit"],
1097
+ spice_model["terminal_pairs"],
1098
+ )
1099
+
1100
+ @property
1101
+ def ic_die_properties(self):
1102
+ temp = dict()
1103
+ cp = self.component_property
1104
+ c_type = self.type.lower()
1105
+ if not c_type == "ic":
1106
+ return temp
1107
+ else:
1108
+ ic_die_prop = cp.GetDieProperty().Clone()
1109
+ die_type = pascal_to_snake(ic_die_prop.GetType().ToString())
1110
+ temp["type"] = die_type
1111
+ if not die_type == "no_die":
1112
+ temp["orientation"] = pascal_to_snake(ic_die_prop.GetOrientation().ToString())
1113
+ if die_type == "wire_bond":
1114
+ temp["height"] = ic_die_prop.GetHeightValue().ToString()
1115
+ return temp
1116
+
1117
+ @ic_die_properties.setter
1118
+ def ic_die_properties(self, kwargs):
1119
+ cp = self.component_property
1120
+ c_type = self.type.lower()
1121
+ if not c_type == "ic":
1122
+ return
1123
+ else:
1124
+ ic_die_prop = cp.GetDieProperty().Clone()
1125
+ die_type = kwargs.get("type")
1126
+ ic_die_prop.SetType(getattr(self._edb.definition.DieType, snake_to_pascal(die_type)))
1127
+ if not die_type == "no_die":
1128
+ orientation = kwargs.get("orientation")
1129
+ if orientation:
1130
+ ic_die_prop.SetOrientation(
1131
+ getattr(self._edb.definition.DieOrientation, snake_to_pascal(orientation))
1132
+ )
1133
+ if die_type == "wire_bond":
1134
+ height = kwargs.get("height")
1135
+ if height:
1136
+ ic_die_prop.SetHeight(self._pedb.edb_value(height))
1137
+ cp.SetDieProperty(ic_die_prop)
1138
+ self.component_property = cp
1139
+
1140
+ @property
1141
+ def solder_ball_properties(self):
1142
+ temp = dict()
1143
+ cp = self.component_property
1144
+ c_type = self.type.lower()
1145
+ if c_type not in ["io", "other"]:
1146
+ return temp
1147
+ else:
1148
+ solder_ball_prop = cp.GetSolderBallProperty().Clone()
1149
+ _, diam, mid_diam = solder_ball_prop.GetDiameterValue()
1150
+ height = solder_ball_prop.GetHeightValue().ToString()
1151
+ shape = solder_ball_prop.GetShape().ToString()
1152
+ uses_solder_ball = solder_ball_prop.UsesSolderball()
1153
+ temp["uses_solder_ball"] = uses_solder_ball
1154
+ temp["shape"] = pascal_to_snake(shape)
1155
+ temp["diameter"] = diam.ToString()
1156
+ temp["mid_diameter"] = mid_diam.ToString()
1157
+ temp["height"] = height
1158
+ return temp
1159
+
1160
+ @solder_ball_properties.setter
1161
+ def solder_ball_properties(self, kwargs):
1162
+ cp = self.component_property
1163
+ solder_ball_prop = cp.GetSolderBallProperty().Clone()
1164
+ shape = kwargs.get("shape")
1165
+ if shape:
1166
+ solder_ball_prop.SetShape(getattr(self._edb.definition.SolderballShape, snake_to_pascal(shape)))
1167
+ if shape == "cylinder":
1168
+ diameter = kwargs["diameter"]
1169
+ solder_ball_prop.SetDiameter(self._pedb.edb_value(diameter), self._pedb.edb_value(diameter))
1170
+ elif shape == "spheroid":
1171
+ diameter = kwargs["diameter"]
1172
+ mid_diameter = kwargs["mid_diameter"]
1173
+ solder_ball_prop.SetDiameter(self._pedb.edb_value(diameter), self._pedb.edb_value(mid_diameter))
1174
+ else:
1175
+ return
1176
+ solder_ball_prop.SetHeight(self._get_edb_value(kwargs["height"]))
1177
+ cp.SetSolderBallProperty(solder_ball_prop)
1178
+ self.component_property = cp
1179
+
1180
+ @property
1181
+ def port_properties(self):
1182
+ temp = dict()
1183
+ cp = self.component_property
1184
+ c_type = self.type.lower()
1185
+ if c_type not in ["ic", "io", "other"]:
1186
+ return temp
1187
+ else:
1188
+ port_prop = cp.GetPortProperty().Clone()
1189
+ reference_height = port_prop.GetReferenceHeightValue().ToString()
1190
+ reference_size_auto = port_prop.GetReferenceSizeAuto()
1191
+ _, reference_size_x, reference_size_y = port_prop.GetReferenceSize()
1192
+ temp["reference_height"] = reference_height
1193
+ temp["reference_size_auto"] = reference_size_auto
1194
+ temp["reference_size_x"] = str(reference_size_x)
1195
+ temp["reference_size_y"] = str(reference_size_y)
1196
+ return temp
1197
+
1198
+ @port_properties.setter
1199
+ def port_properties(self, kwargs):
1200
+ cp = self.component_property
1201
+ port_prop = cp.GetPortProperty().Clone()
1202
+ height = kwargs.get("reference_height")
1203
+ if height:
1204
+ port_prop.SetReferenceHeight(self._pedb.edb_value(height))
1205
+ reference_size_auto = kwargs.get("reference_size_auto")
1206
+ if reference_size_auto:
1207
+ port_prop.SetReferenceSizeAuto(reference_size_auto)
1208
+ reference_size_x = kwargs.get("reference_size_x", 0)
1209
+ reference_size_y = kwargs.get("reference_size_y", 0)
1210
+ port_prop.SetReferenceSize(self._pedb.edb_value(reference_size_x), self._pedb.edb_value(reference_size_y))
1211
+ cp.SetPortProperty(port_prop)
1212
+ self.component_property = cp
@@ -230,11 +230,7 @@ class Layout(ObjBase):
230
230
  -------
231
231
  list of :class:`dotnet.edb_core.dotnet.primitive.PrimitiveDotNet` cast objects.
232
232
  """
233
- prims = []
234
- for p in self._edb_object.Primitives:
235
- obj = primitive_cast(self._pedb, p)
236
- prims.append(obj)
237
- return prims
233
+ return [primitive_cast(self._pedb, p) for p in self._edb_object.Primitives]
238
234
 
239
235
  @property
240
236
  def bondwires(self):
@@ -249,14 +245,7 @@ class Layout(ObjBase):
249
245
 
250
246
  @property
251
247
  def groups(self):
252
- temp = []
253
- for i in list(self._edb_object.Groups):
254
- group_type = i.ToString().split(".")[-1].lower()
255
- if group_type == "component":
256
- temp.append(EDBComponent(self._pedb, i))
257
- else:
258
- pass
259
- return temp
248
+ return [EDBComponent(self._pedb, i) for i in self._edb_object.Groups if i.ToString().endswith(".Component")]
260
249
 
261
250
  @property
262
251
  def pin_groups(self):
@@ -43,8 +43,6 @@ class Primitive(Connectable):
43
43
  def __init__(self, pedb, edb_object):
44
44
  super().__init__(pedb, edb_object)
45
45
  self._app = self._pedb
46
- self._core_stackup = pedb.stackup
47
- self._core_net = pedb.nets
48
46
  self.primitive_object = self._edb_object
49
47
 
50
48
  bondwire_type = self._pedb._edb.Cell.Primitive.BondwireType
@@ -62,6 +60,14 @@ class Primitive(Connectable):
62
60
  "rectangle": bondwire_cross_section_type.BondwireRectangle,
63
61
  }
64
62
 
63
+ @property
64
+ def _core_stackup(self):
65
+ return self._app.stackup
66
+
67
+ @property
68
+ def _core_net(self):
69
+ return self._app.nets
70
+
65
71
  @property
66
72
  def type(self):
67
73
  """Return the type of the primitive.
@@ -160,6 +166,8 @@ class Primitive(Connectable):
160
166
  -------
161
167
  float
162
168
  """
169
+ if "GetPolygonData" not in dir(self._edb_object):
170
+ return 0
163
171
  area = self._edb_object.GetPolygonData().Area()
164
172
  if include_voids:
165
173
  for el in self._edb_object.Voids:
@@ -223,9 +223,10 @@ class Terminal(Connectable):
223
223
  """Get reference terminal."""
224
224
 
225
225
  edb_terminal = self._edb_object.GetReferenceTerminal()
226
- terminal = self._pedb.terminals[edb_terminal.GetName()]
227
- if not terminal.is_null:
228
- return terminal
226
+ if not edb_terminal.IsNull():
227
+ return self._pedb.terminals[edb_terminal.GetName()]
228
+ else:
229
+ return None
229
230
 
230
231
  @ref_terminal.setter
231
232
  def ref_terminal(self, value):
@@ -313,8 +313,7 @@ class Components(object):
313
313
  # self._logger.info("Refreshing the Components dictionary.")
314
314
  self._cmp = {}
315
315
  for i in self._pedb.layout.groups:
316
- if i.group_type == "component":
317
- self._cmp[i.name] = i
316
+ self._cmp[i.name] = i
318
317
  return True
319
318
 
320
319
  @property
@@ -23,6 +23,7 @@
23
23
  import os
24
24
 
25
25
  from pyedb.dotnet.edb_core.definition.component_model import NPortComponentModel
26
+ from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
26
27
  from pyedb.dotnet.edb_core.utilities.obj_base import ObjBase
27
28
 
28
29
 
@@ -171,7 +172,7 @@ class EDBComponentDef(ObjBase):
171
172
  def component_models(self):
172
173
  temp = {}
173
174
  for i in list(self._edb_object.GetComponentModels()):
174
- temp_type = i.ToString().split(".")[0]
175
+ temp_type = i.ToString().split(".")[-1]
175
176
  if temp_type == "NPortComponentModel":
176
177
  edb_object = NPortComponentModel(self._pedb, i)
177
178
  temp[edb_object.name] = edb_object
@@ -197,3 +198,18 @@ class EDBComponentDef(ObjBase):
197
198
  footprint_cell = self._pedb._active_cell.cell.Create(self._pedb.active_db, cell_type, name)
198
199
  edb_object = self._pedb.edb_api.definition.ComponentDef.Create(self._pedb.active_db, name, footprint_cell)
199
200
  return EDBComponentDef(self._pedb, edb_object)
201
+
202
+ def get_properties(self):
203
+ data = {}
204
+ temp = []
205
+ for i in list(self._edb_object.ComponentDefPins):
206
+ temp.append(i.GetName())
207
+ data["pin_order"] = temp
208
+ return data
209
+
210
+ def set_properties(self, **kwargs):
211
+ pin_order = kwargs.get("pin_order")
212
+ if pin_order:
213
+ old = {i.GetName(): i for i in list(self._edb_object.ComponentDefPins)}
214
+ temp = convert_py_list_to_net_list([old[str(i)] for i in pin_order])
215
+ self._edb_object.ReorderPins(temp)
@@ -30,10 +30,6 @@ class ComponentModel(ObjBase):
30
30
  super().__init__(pedb, edb_object)
31
31
  self._model_type_mapping = {"PinPairModel": self._pedb.edb_api.cell}
32
32
 
33
- def name(self):
34
- """Name of the component model."""
35
- return self._edb_object.GetName()
36
-
37
33
 
38
34
  class NPortComponentModel(ComponentModel):
39
35
  """Class for n-port component models."""
@@ -22,7 +22,7 @@
22
22
 
23
23
  from pyedb.dotnet.edb_core.edb_data.edbvalue import EdbValue
24
24
  from pyedb.dotnet.edb_core.edb_data.primitives_data import cast
25
- from pyedb.dotnet.edb_core.general import convert_pytuple_to_nettuple
25
+ from pyedb.dotnet.edb_core.general import convert_pytuple_to_nettuple, pascal_to_snake
26
26
 
27
27
 
28
28
  class HfssExtentInfo:
@@ -192,7 +192,7 @@ class HfssExtentInfo:
192
192
  @property
193
193
  def dielectric_extent_type(self):
194
194
  """Dielectric extent type."""
195
- return self._edb_hfss_extent_info.DielectricExtentType.ToString().lower()
195
+ return pascal_to_snake(self._edb_hfss_extent_info.DielectricExtentType.ToString())
196
196
 
197
197
  @dielectric_extent_type.setter
198
198
  def dielectric_extent_type(self, value):
@@ -204,7 +204,7 @@ class HfssExtentInfo:
204
204
  @property
205
205
  def extent_type(self):
206
206
  """Extent type."""
207
- return self._edb_hfss_extent_info.ExtentType.ToString().lower()
207
+ return pascal_to_snake(self._edb_hfss_extent_info.ExtentType.ToString())
208
208
 
209
209
  @extent_type.setter
210
210
  def extent_type(self, value):
@@ -58,6 +58,8 @@ class LayerEdbClass(object):
58
58
  for k, v in kwargs.items():
59
59
  if k in dir(self):
60
60
  self.__setattr__(k, v)
61
+ elif k == "roughness":
62
+ self.properties = {"roughness": v}
61
63
  else:
62
64
  self._pedb.logger.error(f"{k} is not a valid layer attribute")
63
65
 
@@ -178,7 +180,7 @@ class LayerEdbClass(object):
178
180
  RGB.
179
181
  """
180
182
  layer_color = self._edb_layer.GetColor()
181
- return layer_color.Item1, layer_color.Item2, layer_color.Item3
183
+ return [layer_color.Item1, layer_color.Item2, layer_color.Item3]
182
184
 
183
185
  @color.setter
184
186
  def color(self, rgb):
@@ -238,6 +240,26 @@ class LayerEdbClass(object):
238
240
  self._type = value
239
241
  self._pedb.stackup._set_layout_stackup(layer_clone, "change_attribute")
240
242
 
243
+ @property
244
+ def properties(self):
245
+ data = {}
246
+ data["name"] = self.name
247
+ data["type"] = self.type
248
+ data["color"] = self.color
249
+ return data
250
+
251
+ @properties.setter
252
+ def properties(self, params):
253
+ name = params.get("name", "")
254
+ if name:
255
+ self.name = name
256
+ type = params.get("type", "")
257
+ if type:
258
+ self.type = type
259
+ color = params.get("color", "")
260
+ if color:
261
+ self.color = color
262
+
241
263
 
242
264
  class StackupLayerEdbClass(LayerEdbClass):
243
265
  def __init__(self, pedb, edb_object=None, name="", layer_type="signal", **kwargs):
@@ -705,3 +727,75 @@ class StackupLayerEdbClass(LayerEdbClass):
705
727
  layer["side_hallhuray_surface_ratio"],
706
728
  apply_on_surface="side",
707
729
  )
730
+
731
+ @property
732
+ def properties(self):
733
+ data = {}
734
+ data["name"] = self.name
735
+ data["type"] = self.type
736
+ data["material"] = self.material
737
+ data["fill_material"] = self.fill_material
738
+ data["thickness"] = self._edb_object.GetThicknessValue().ToString()
739
+ data["color"] = self.color
740
+
741
+ roughness = {}
742
+ for region in ["top", "bottom", "side"]:
743
+ temp = {}
744
+ r_model = self._edb_object.GetRoughnessModel(
745
+ getattr(self._pedb._edb.Cell.RoughnessModel.Region, region.capitalize())
746
+ )
747
+ if r_model.ToString().split(".")[-1] == "HurrayRoughnessModel":
748
+ temp["model"] = "huray"
749
+ temp["nodule_radius"] = r_model.NoduleRadius.ToString()
750
+ temp["surface_ratio"] = r_model.SurfaceRatio.ToString()
751
+ else:
752
+ temp["model"] = "groisse"
753
+ temp["roughness"] = r_model.Roughness.ToString()
754
+ roughness[region] = temp
755
+ roughness["enabled"] = self._edb_object.IsRoughnessEnabled()
756
+ data["roughness"] = roughness
757
+ return data
758
+
759
+ @properties.setter
760
+ def properties(self, params):
761
+ name = params.get("name")
762
+ if name:
763
+ self.name = name
764
+ type = params.get("type")
765
+ if type:
766
+ self.type = type
767
+ material = params.get("material")
768
+ if material:
769
+ self.material = material
770
+ fill_material = params.get("fill_material")
771
+ if fill_material:
772
+ self.fill_material = fill_material
773
+ thickness = params.get("thickness")
774
+ if thickness:
775
+ self.thickness = self._pedb.edb_value(thickness)
776
+ color = params.get("color")
777
+ if color:
778
+ self.color = color
779
+ roughness = params.get("roughness")
780
+ if roughness:
781
+ layer_clone = self._edb_layer
782
+ layer_clone.SetRoughnessEnabled(roughness["enabled"])
783
+ for region in ["top", "bottom", "side"]:
784
+ r_data = roughness.get(region)
785
+ if r_data:
786
+ if r_data["model"] == "huray":
787
+ r_model = self._pedb._edb.Cell.HurrayRoughnessModel(
788
+ self._pedb.edb_value(r_data["nodule_radius"]), self._pedb.edb_value(r_data["surface_ratio"])
789
+ )
790
+ else:
791
+ r_model = self._pedb._edb.Cell.GroisseRoughnessModel(self._pedb.edb_value(r_data["roughness"]))
792
+ else:
793
+ r_model = self._pedb._edb.Cell.HurrayRoughnessModel(
794
+ self._pedb.edb_value("0"), self._pedb.edb_value("0")
795
+ )
796
+ layer_clone.SetRoughnessModel(
797
+ getattr(self._pedb._edb.Cell.RoughnessModel.Region, region.capitalize()), r_model
798
+ )
799
+ self._pedb.stackup._set_layout_stackup(layer_clone, "change_attribute")
800
+
801
+ layer_clone.SetRoughnessEnabled(True)
@@ -19,7 +19,6 @@
19
19
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
-
23
22
  from pyedb.dotnet.edb_core.dotnet.database import (
24
23
  DifferentialPairDotNet,
25
24
  ExtendedNetDotNet,
@@ -58,7 +57,10 @@ class EDBNetsData(NetDotNet):
58
57
  -------
59
58
  list of :class:`pyedb.dotnet.edb_core.edb_data.primitives_data.EDBPrimitives`
60
59
  """
61
- return [self._app.layout.find_object_by_id(i.GetId()) for i in self.net_object.Primitives]
60
+ from pyedb.dotnet.edb_core.cell.layout import primitive_cast
61
+
62
+ return [primitive_cast(self._app, i) for i in self.net_object.Primitives]
63
+ # return [self._app.layout.find_object_by_id(i.GetId()) for i in self.net_object.Primitives]
62
64
 
63
65
  @property
64
66
  def padstack_instances(self):
@@ -67,10 +69,11 @@ class EDBNetsData(NetDotNet):
67
69
  Returns
68
70
  -------
69
71
  list of :class:`pyedb.dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance`"""
70
- name = self.name
71
- return [
72
- EDBPadstackInstance(i, self._app) for i in self.net_object.PadstackInstances if i.GetNet().GetName() == name
73
- ]
72
+ # name = self.name
73
+ # return [
74
+ # EDBPadstackInstance(i, self._app) for i in self.net_object.PadstackInstances if i.GetNet().GetName() == name
75
+ # ]
76
+ return [EDBPadstackInstance(i, self._app) for i in self.net_object.PadstackInstances]
74
77
 
75
78
  @property
76
79
  def components(self):
@@ -133,7 +136,7 @@ class EDBNetsData(NetDotNet):
133
136
  Whether to show the plot or not. Default is `True`.
134
137
  """
135
138
 
136
- self._app.nets.plot(
139
+ return self._app.nets.plot(
137
140
  self.name,
138
141
  layers=layers,
139
142
  show_legend=show_legend,
@@ -499,7 +499,8 @@ class EDBPadstack(object):
499
499
  self._ppadstack._pedb._edb.Definition.PadType.RegularPad,
500
500
  self._ppadstack._pedb._edb.Definition.PadType.AntiPad,
501
501
  self._ppadstack._pedb._edb.Definition.PadType.ThermalPad,
502
- self._ppadstack._pedb._edb.Definition.PadType.Hole,
502
+ # self._ppadstack._pedb._edb.Definition.PadType.Hole,
503
+ # This property doesn't appear in UI. It is unclear what it is used for. Suppressing this property for now.
503
504
  ]
504
505
  data = {}
505
506
  for pad_type in pad_type_list:
@@ -588,15 +589,14 @@ class EDBPadstack(object):
588
589
  continue
589
590
 
590
591
  # Set pad parameters for the current layer
591
- default = original_params[pad_type_name]
592
592
  pdef_data.SetPadParameters(
593
593
  layer_data["layer_name"],
594
594
  pad_type,
595
595
  pad_shape,
596
596
  convert_py_list_to_net_list([self._ppadstack._pedb.edb_value(i) for i in temp_param]),
597
- self._ppadstack._pedb.edb_value(layer_data.get("offset_x", default[idx].get("offset_x", 0))),
598
- self._ppadstack._pedb.edb_value(layer_data.get("offset_y", default[idx].get("offset_y", 0))),
599
- self._ppadstack._pedb.edb_value(layer_data.get("rotation", default[idx].get("rotation", 0))),
597
+ self._ppadstack._pedb.edb_value(layer_data.get("offset_x", 0)),
598
+ self._ppadstack._pedb.edb_value(layer_data.get("offset_y", 0)),
599
+ self._ppadstack._pedb.edb_value(layer_data.get("rotation", 0)),
600
600
  )
601
601
  self._padstack_def_data = pdef_data
602
602
 
@@ -1672,6 +1672,56 @@ class EDBPadstackInstance(Primitive):
1672
1672
  else:
1673
1673
  return
1674
1674
 
1675
+ @property
1676
+ def backdrill_parameters(self):
1677
+ data = {}
1678
+ flag, drill_to_layer, offset, diameter = self._edb_object.GetBackDrillParametersLayerValue(
1679
+ self._pedb.edb_api.cell.layer("", self._pedb.edb_api.cell.layer_type.SignalLayer),
1680
+ self._pedb.edb_value(0),
1681
+ self._pedb.edb_value(0.0),
1682
+ True,
1683
+ )
1684
+ if flag:
1685
+ if drill_to_layer.GetName():
1686
+ data["from_bottom"] = {
1687
+ "drill_to_layer": drill_to_layer.GetName(),
1688
+ "diameter": diameter.ToString(),
1689
+ "stub_length": offset.ToString(),
1690
+ }
1691
+ flag, drill_to_layer, offset, diameter = self._edb_object.GetBackDrillParametersLayerValue(
1692
+ self._pedb.edb_api.cell.layer("", self._pedb.edb_api.cell.layer_type.SignalLayer),
1693
+ self._pedb.edb_value(0),
1694
+ self._pedb.edb_value(0.0),
1695
+ False,
1696
+ )
1697
+ if flag:
1698
+ if drill_to_layer.GetName():
1699
+ data["from_top"] = {
1700
+ "drill_to_layer": drill_to_layer.GetName(),
1701
+ "diameter": diameter.ToString(),
1702
+ "stub_length": offset.ToString(),
1703
+ }
1704
+ return data
1705
+
1706
+ @backdrill_parameters.setter
1707
+ def backdrill_parameters(self, params):
1708
+ from_bottom = params.get("from_bottom")
1709
+ if from_bottom:
1710
+ self._edb_object.SetBackDrillParameters(
1711
+ self._pedb.stackup.layers[from_bottom.get("drill_to_layer")]._edb_object,
1712
+ self._pedb.edb_value(from_bottom.get("stub_length")),
1713
+ self._pedb.edb_value(from_bottom.get("diameter")),
1714
+ True,
1715
+ )
1716
+ from_top = params.get("from_top")
1717
+ if from_top:
1718
+ self._edb_object.SetBackDrillParameters(
1719
+ self._pedb.stackup.layers[from_top.get("drill_to_layer")]._edb_object,
1720
+ self._pedb.edb_value(from_top.get("stub_length")),
1721
+ self._pedb.edb_value(from_top.get("diameter")),
1722
+ False,
1723
+ )
1724
+
1675
1725
  def set_backdrill_bottom(self, drill_depth, drill_diameter, offset=0.0):
1676
1726
  """Set backdrill from bottom.
1677
1727
 
@@ -2274,3 +2324,15 @@ class EDBPadstackInstance(Primitive):
2274
2324
  max_limit=max_limit,
2275
2325
  component_only=component_only,
2276
2326
  )
2327
+
2328
+ @property
2329
+ def properties(self):
2330
+ data = {}
2331
+ data["name"] = self.aedt_name
2332
+ data["definition"] = self.padstack_definition
2333
+ data["backdrill_parameters"] = self.backdrill_parameters
2334
+ _, position, rotation = self._edb_object.GetPositionAndRotationValue()
2335
+ data["position"] = [position.X.ToString(), position.Y.ToString()]
2336
+ data["rotation"] = [rotation.ToString()]
2337
+ data["id"] = self.id
2338
+ return data