pyedb 0.22.1__py3-none-any.whl → 0.24.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_components.py +1 -1
- pyedb/configuration/cfg_ports_sources.py +3 -3
- pyedb/configuration/configuration.py +2 -2
- pyedb/dotnet/edb.py +55 -56
- pyedb/dotnet/edb_core/cell/hierarchy/component.py +1 -1
- pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py +11 -0
- pyedb/dotnet/edb_core/cell/layout.py +30 -23
- pyedb/dotnet/edb_core/cell/layout_obj.py +0 -9
- pyedb/dotnet/edb_core/cell/primitive/__init__.py +3 -0
- pyedb/dotnet/edb_core/cell/{primitive.py → primitive/bondwire.py} +1 -146
- pyedb/dotnet/edb_core/cell/primitive/path.py +351 -0
- pyedb/dotnet/edb_core/cell/primitive/primitive.py +895 -0
- pyedb/dotnet/edb_core/cell/terminal/bundle_terminal.py +0 -4
- pyedb/dotnet/edb_core/cell/terminal/edge_terminal.py +1 -1
- pyedb/dotnet/edb_core/cell/terminal/terminal.py +1 -1
- pyedb/dotnet/edb_core/components.py +26 -18
- pyedb/dotnet/edb_core/dotnet/database.py +1 -23
- pyedb/dotnet/edb_core/dotnet/primitive.py +3 -139
- pyedb/dotnet/edb_core/edb_data/nets_data.py +1 -11
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +12 -38
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +56 -868
- pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +0 -18
- pyedb/dotnet/edb_core/geometry/polygon_data.py +43 -0
- pyedb/dotnet/edb_core/hfss.py +27 -23
- pyedb/dotnet/edb_core/layout_validation.py +3 -3
- pyedb/dotnet/edb_core/materials.py +1 -1
- pyedb/dotnet/edb_core/modeler.py +65 -82
- pyedb/dotnet/edb_core/nets.py +8 -7
- pyedb/dotnet/edb_core/padstack.py +16 -17
- pyedb/dotnet/edb_core/siwave.py +2 -2
- pyedb/dotnet/edb_core/stackup.py +64 -87
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +1 -1
- pyedb/ipc2581/ecad/cad_data/polygon.py +2 -2
- pyedb/ipc2581/ecad/cad_data/step.py +3 -3
- pyedb/ipc2581/ipc2581.py +2 -2
- pyedb/siwave.py +99 -0
- {pyedb-0.22.1.dist-info → pyedb-0.24.0.dist-info}/METADATA +3 -3
- {pyedb-0.22.1.dist-info → pyedb-0.24.0.dist-info}/RECORD +41 -38
- {pyedb-0.22.1.dist-info → pyedb-0.24.0.dist-info}/LICENSE +0 -0
- {pyedb-0.22.1.dist-info → pyedb-0.24.0.dist-info}/WHEEL +0 -0
pyedb/dotnet/edb_core/nets.py
CHANGED
|
@@ -206,10 +206,11 @@ class EdbNets(object):
|
|
|
206
206
|
for net in self._layout.nets[:]:
|
|
207
207
|
total_plane_area = 0.0
|
|
208
208
|
total_trace_area = 0.0
|
|
209
|
-
for primitive in net.
|
|
210
|
-
|
|
209
|
+
for primitive in net.primitives:
|
|
210
|
+
primitive = primitive._edb_object
|
|
211
|
+
if primitive.GetPrimitiveType() == self._edb.cell.primitive.api_class.PrimitiveType.Bondwire:
|
|
211
212
|
continue
|
|
212
|
-
if primitive.GetPrimitiveType() != self._edb.cell.primitive.PrimitiveType.Path:
|
|
213
|
+
if primitive.GetPrimitiveType() != self._edb.cell.primitive.api_class.PrimitiveType.Path:
|
|
213
214
|
total_plane_area += float(primitive.GetPolygonData().Area())
|
|
214
215
|
else:
|
|
215
216
|
total_trace_area += float(primitive.GetPolygonData().Area())
|
|
@@ -521,7 +522,7 @@ class EdbNets(object):
|
|
|
521
522
|
bottom_layer = list(self._pedb.stackup.signal_layers.keys())[-1]
|
|
522
523
|
if plot_components_on_top or plot_components_on_bottom:
|
|
523
524
|
nc = 0
|
|
524
|
-
for comp in self._pedb.components.
|
|
525
|
+
for comp in self._pedb.components.instances.values():
|
|
525
526
|
if not comp.is_enabled:
|
|
526
527
|
continue
|
|
527
528
|
net_names = comp.nets
|
|
@@ -1088,7 +1089,7 @@ class EdbNets(object):
|
|
|
1088
1089
|
else:
|
|
1089
1090
|
if not start_with and not contain and not end_with:
|
|
1090
1091
|
net = self._edb.cell.net.find_by_name(self._active_layout, net_name)
|
|
1091
|
-
if net.
|
|
1092
|
+
if net.is_null:
|
|
1092
1093
|
net = self._edb.cell.net.create(self._active_layout, net_name)
|
|
1093
1094
|
return net
|
|
1094
1095
|
elif start_with:
|
|
@@ -1149,9 +1150,9 @@ class EdbNets(object):
|
|
|
1149
1150
|
``True`` if the net is found in component pins.
|
|
1150
1151
|
|
|
1151
1152
|
"""
|
|
1152
|
-
if component_name not in self._pedb.components.
|
|
1153
|
+
if component_name not in self._pedb.components.instances:
|
|
1153
1154
|
return False
|
|
1154
|
-
for net in self._pedb.components.
|
|
1155
|
+
for net in self._pedb.components.instances[component_name].nets:
|
|
1155
1156
|
if net_name == net:
|
|
1156
1157
|
return True
|
|
1157
1158
|
return False
|
|
@@ -29,12 +29,12 @@ import warnings
|
|
|
29
29
|
import rtree
|
|
30
30
|
|
|
31
31
|
from pyedb.dotnet.clr_module import Array
|
|
32
|
-
from pyedb.dotnet.edb_core.dotnet.database import PolygonDataDotNet
|
|
33
32
|
from pyedb.dotnet.edb_core.edb_data.padstacks_data import (
|
|
34
33
|
EDBPadstack,
|
|
35
34
|
EDBPadstackInstance,
|
|
36
35
|
)
|
|
37
36
|
from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
|
|
37
|
+
from pyedb.dotnet.edb_core.geometry.polygon_data import PolygonData
|
|
38
38
|
from pyedb.generic.general_methods import generate_unique_name
|
|
39
39
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
40
40
|
|
|
@@ -108,7 +108,7 @@ class EdbPadstacks(object):
|
|
|
108
108
|
@property
|
|
109
109
|
def _layers(self):
|
|
110
110
|
""" """
|
|
111
|
-
return self._pedb.stackup.
|
|
111
|
+
return self._pedb.stackup.layers
|
|
112
112
|
|
|
113
113
|
def int_to_pad_type(self, val=0):
|
|
114
114
|
"""Convert an integer to an EDB.PadGeometryType.
|
|
@@ -240,9 +240,7 @@ class EdbPadstacks(object):
|
|
|
240
240
|
padstack_instances = {}
|
|
241
241
|
for _, edb_padstack_instance in self.instances.items():
|
|
242
242
|
if edb_padstack_instance.aedt_name:
|
|
243
|
-
padstack_instances[edb_padstack_instance.aedt_name] =
|
|
244
|
-
edb_padstack_instance, self._pedb
|
|
245
|
-
)
|
|
243
|
+
padstack_instances[edb_padstack_instance.aedt_name] = edb_padstack_instance
|
|
246
244
|
return padstack_instances
|
|
247
245
|
|
|
248
246
|
def find_instance_by_id(self, value: int):
|
|
@@ -491,7 +489,7 @@ class EdbPadstacks(object):
|
|
|
491
489
|
padstackInst = self.instances[padstackInst]._edb_padstackinstance
|
|
492
490
|
|
|
493
491
|
else:
|
|
494
|
-
psdef = padstackInst.GetPadstackDef()
|
|
492
|
+
psdef = padstackInst._edb_object.GetPadstackDef()
|
|
495
493
|
newdefdata = self._edb.definition.PadstackDefData(psdef.GetData())
|
|
496
494
|
newdefdata.SetSolderBallShape(self._edb.definition.SolderballShape.Cylinder)
|
|
497
495
|
newdefdata.SetSolderBallParameter(self._get_edb_value(ballDiam), self._get_edb_value(ballDiam))
|
|
@@ -504,7 +502,7 @@ class EdbPadstacks(object):
|
|
|
504
502
|
psdef.SetData(newdefdata)
|
|
505
503
|
sball_layer = [lay._edb_layer for lay in list(self._layers.values()) if lay.name == sballLayer_name][0]
|
|
506
504
|
if sball_layer is not None:
|
|
507
|
-
padstackInst.SetSolderBallLayer(sball_layer)
|
|
505
|
+
padstackInst._edb_object.SetSolderBallLayer(sball_layer)
|
|
508
506
|
return True
|
|
509
507
|
|
|
510
508
|
return False
|
|
@@ -592,13 +590,13 @@ class EdbPadstacks(object):
|
|
|
592
590
|
"""
|
|
593
591
|
pinlist = []
|
|
594
592
|
if refdes:
|
|
595
|
-
if refdes in self._pedb.components.
|
|
593
|
+
if refdes in self._pedb.components.instances:
|
|
596
594
|
if netname:
|
|
597
|
-
for pin, val in self._pedb.components.
|
|
595
|
+
for pin, val in self._pedb.components.instances[refdes].pins.items():
|
|
598
596
|
if val.net_name == netname:
|
|
599
597
|
pinlist.append(val)
|
|
600
598
|
else:
|
|
601
|
-
for pin in self._pedb.components.
|
|
599
|
+
for pin in self._pedb.components.instances[refdes].pins.values():
|
|
602
600
|
pinlist.append(pin)
|
|
603
601
|
elif netname:
|
|
604
602
|
for pin in self._pedb.pins:
|
|
@@ -757,6 +755,7 @@ class EdbPadstacks(object):
|
|
|
757
755
|
if not isinstance(net_list, list):
|
|
758
756
|
net_list = [net_list]
|
|
759
757
|
layout_lobj_collection = self._layout.padstack_instances
|
|
758
|
+
layout_lobj_collection = [i._edb_object for i in layout_lobj_collection]
|
|
760
759
|
via_list = []
|
|
761
760
|
for lobj in layout_lobj_collection:
|
|
762
761
|
pad_layers_name = lobj.GetPadstackDef().GetData().GetLayerNames()
|
|
@@ -955,8 +954,8 @@ class EdbPadstacks(object):
|
|
|
955
954
|
_poly.delete()
|
|
956
955
|
else:
|
|
957
956
|
return False
|
|
958
|
-
elif isinstance(polygon_hole,
|
|
959
|
-
hole_param = polygon_hole.
|
|
957
|
+
elif isinstance(polygon_hole, PolygonData):
|
|
958
|
+
hole_param = polygon_hole._edb_object
|
|
960
959
|
else:
|
|
961
960
|
return False
|
|
962
961
|
padstackData.SetPolygonalHoleParameters(hole_param, value0, value0, value0)
|
|
@@ -1007,7 +1006,7 @@ class EdbPadstacks(object):
|
|
|
1007
1006
|
_poly.delete()
|
|
1008
1007
|
else:
|
|
1009
1008
|
return False
|
|
1010
|
-
elif isinstance(pad_polygon,
|
|
1009
|
+
elif isinstance(pad_polygon, PolygonData):
|
|
1011
1010
|
pad_array = pad_polygon
|
|
1012
1011
|
if antipad_shape == "Bullet": # pragma no cover
|
|
1013
1012
|
antipad_array = Array[type(x_size)]([x_size, y_size, corner_radius])
|
|
@@ -1023,7 +1022,7 @@ class EdbPadstacks(object):
|
|
|
1023
1022
|
_poly.delete()
|
|
1024
1023
|
else:
|
|
1025
1024
|
return False
|
|
1026
|
-
elif isinstance(antipad_polygon,
|
|
1025
|
+
elif isinstance(antipad_polygon, PolygonData):
|
|
1027
1026
|
antipad_array = antipad_polygon
|
|
1028
1027
|
else: # pragma no cover
|
|
1029
1028
|
antipad_array = Array[type(antipaddiam)]([antipaddiam])
|
|
@@ -1035,7 +1034,7 @@ class EdbPadstacks(object):
|
|
|
1035
1034
|
padstackData.SetPolygonalPadParameters(
|
|
1036
1035
|
layer,
|
|
1037
1036
|
self._edb.definition.PadType.RegularPad,
|
|
1038
|
-
pad_array.
|
|
1037
|
+
pad_array._edb_object,
|
|
1039
1038
|
pad_offset_x,
|
|
1040
1039
|
pad_offset_y,
|
|
1041
1040
|
pad_rotation,
|
|
@@ -1043,7 +1042,7 @@ class EdbPadstacks(object):
|
|
|
1043
1042
|
padstackData.SetPolygonalPadParameters(
|
|
1044
1043
|
layer,
|
|
1045
1044
|
self._edb.definition.PadType.AntiPad,
|
|
1046
|
-
antipad_array.
|
|
1045
|
+
antipad_array._edb_object,
|
|
1047
1046
|
pad_offset_x,
|
|
1048
1047
|
pad_offset_y,
|
|
1049
1048
|
pad_rotation,
|
|
@@ -1208,7 +1207,7 @@ class EdbPadstacks(object):
|
|
|
1208
1207
|
solderlayer,
|
|
1209
1208
|
None,
|
|
1210
1209
|
)
|
|
1211
|
-
padstack_instance.
|
|
1210
|
+
padstack_instance.is_layout_pin = is_pin
|
|
1212
1211
|
py_padstack_instance = EDBPadstackInstance(padstack_instance.api_object, self._pedb)
|
|
1213
1212
|
|
|
1214
1213
|
return py_padstack_instance
|
pyedb/dotnet/edb_core/siwave.py
CHANGED
|
@@ -912,7 +912,7 @@ class EdbSiwave(object):
|
|
|
912
912
|
Name of the source.
|
|
913
913
|
|
|
914
914
|
"""
|
|
915
|
-
if source.name in [i.
|
|
915
|
+
if source.name in [i.name for i in self._layout.terminals]:
|
|
916
916
|
source.name = generate_unique_name(source.name, n=3)
|
|
917
917
|
self._logger.warning("Port already exists with same name. Renaming to {}".format(source.name))
|
|
918
918
|
pos_pin_group = self._pedb.components.create_pingroup_from_pins(source.positive_node.node_pins)
|
|
@@ -1235,7 +1235,7 @@ class EdbSiwave(object):
|
|
|
1235
1235
|
pin_numbers = [str(p) for p in pin_numbers]
|
|
1236
1236
|
if group_name is None:
|
|
1237
1237
|
group_name = self._edb.cell.hierarchy.pin_group.GetUniqueName(self._active_layout)
|
|
1238
|
-
comp = self._pedb.components.
|
|
1238
|
+
comp = self._pedb.components.instances[reference_designator]
|
|
1239
1239
|
pins = [pin.pin for name, pin in comp.pins.items() if name in pin_numbers]
|
|
1240
1240
|
edb_pingroup = self._edb.cell.hierarchy.pin_group.Create(
|
|
1241
1241
|
self._active_layout, group_name, convert_py_list_to_net_list(pins)
|
pyedb/dotnet/edb_core/stackup.py
CHANGED
|
@@ -217,7 +217,7 @@ class LayerCollection(object):
|
|
|
217
217
|
kwargs["layer_type"] = layer_type
|
|
218
218
|
return self._add_layer(add_method="add_layer_above", base_layer_name=base_layer_name, **kwargs)
|
|
219
219
|
|
|
220
|
-
def add_document_layer(self, name, layer_type="
|
|
220
|
+
def add_document_layer(self, name, layer_type="user", **kwargs):
|
|
221
221
|
"""Add a document layer.
|
|
222
222
|
|
|
223
223
|
Parameters
|
|
@@ -225,7 +225,7 @@ class LayerCollection(object):
|
|
|
225
225
|
name : str
|
|
226
226
|
Name of the layer.
|
|
227
227
|
layer_type: str, optional
|
|
228
|
-
Type of the layer. The default
|
|
228
|
+
Type of the layer. The default is ``"user"``. Options are ``"user"``, ``"outline"``
|
|
229
229
|
kwargs
|
|
230
230
|
|
|
231
231
|
Returns
|
|
@@ -246,7 +246,7 @@ class LayerCollection(object):
|
|
|
246
246
|
|
|
247
247
|
obj = False
|
|
248
248
|
# Add stackup layers
|
|
249
|
-
for _, i in self.
|
|
249
|
+
for _, i in self.layers.items():
|
|
250
250
|
if i.id == layer_clone.id: # replace layer
|
|
251
251
|
add_method(layer_clone._edb_object)
|
|
252
252
|
obj = layer_clone
|
|
@@ -355,7 +355,7 @@ class Stackup(LayerCollection):
|
|
|
355
355
|
layer number.
|
|
356
356
|
|
|
357
357
|
"""
|
|
358
|
-
return len(list(self.
|
|
358
|
+
return len(list(self.layers.keys()))
|
|
359
359
|
|
|
360
360
|
def _int_to_layer_types(self, val):
|
|
361
361
|
if int(val) == 0:
|
|
@@ -513,8 +513,8 @@ class Stackup(LayerCollection):
|
|
|
513
513
|
fillMaterial=dielectric_material,
|
|
514
514
|
method="add_on_bottom",
|
|
515
515
|
)
|
|
516
|
-
self.
|
|
517
|
-
self.
|
|
516
|
+
self.layers["TOP"].dielectric_fill = "SolderMask"
|
|
517
|
+
self.layers["BOT"].dielectric_fill = "SolderMask"
|
|
518
518
|
|
|
519
519
|
for layer_num in np.arange(int(layer_count / 2), 1, -1):
|
|
520
520
|
# Generate upper half
|
|
@@ -843,18 +843,20 @@ class Stackup(LayerCollection):
|
|
|
843
843
|
|
|
844
844
|
materials = self._pedb.materials
|
|
845
845
|
if material not in materials:
|
|
846
|
-
logger.warning(
|
|
847
|
-
f"Material '{material}' does not exist in material library. Intempt to create it from syslib."
|
|
848
|
-
)
|
|
849
846
|
material_properties = self._pedb.materials.read_syslib_material(material)
|
|
850
|
-
|
|
847
|
+
if material_properties:
|
|
848
|
+
logger.info(f"Material {material} found in syslib. Adding it to aedb project.")
|
|
849
|
+
materials.add_material(material, **material_properties)
|
|
850
|
+
else:
|
|
851
|
+
logger.warning(f"Material {material} not found. Check the library and retry.")
|
|
851
852
|
|
|
852
853
|
if layer_type != "dielectric" and fillMaterial not in materials:
|
|
853
|
-
logger.warning(
|
|
854
|
-
f"Material '{fillMaterial}' does not exist in material library. Intempt to create it from syslib."
|
|
855
|
-
)
|
|
856
854
|
material_properties = self._pedb.materials.read_syslib_material(fillMaterial)
|
|
857
|
-
|
|
855
|
+
if material_properties:
|
|
856
|
+
logger.info(f"Material {fillMaterial} found in syslib. Adding it to aedb project.")
|
|
857
|
+
materials.add_material(fillMaterial, **material_properties)
|
|
858
|
+
else:
|
|
859
|
+
logger.warning(f"Material {fillMaterial} not found. Check the library and retry.")
|
|
858
860
|
|
|
859
861
|
if layer_type in ["signal", "dielectric"]:
|
|
860
862
|
new_layer = self._create_stackup_layer(layer_name, thickness, layer_type)
|
|
@@ -977,7 +979,7 @@ class Stackup(LayerCollection):
|
|
|
977
979
|
"Thickness": [],
|
|
978
980
|
}
|
|
979
981
|
idx = []
|
|
980
|
-
for lyr in self.
|
|
982
|
+
for lyr in self.layers.values():
|
|
981
983
|
idx.append(lyr.name)
|
|
982
984
|
data["Type"].append(lyr.type)
|
|
983
985
|
data["Material"].append(lyr.material)
|
|
@@ -1000,7 +1002,7 @@ class Stackup(LayerCollection):
|
|
|
1000
1002
|
for material_name, material in self._pedb.materials.materials.items():
|
|
1001
1003
|
material_out[material_name] = material.to_dict()
|
|
1002
1004
|
layers_out = {}
|
|
1003
|
-
for k, v in self.
|
|
1005
|
+
for k, v in self.layers.items():
|
|
1004
1006
|
data = v._json_format()
|
|
1005
1007
|
# FIXME: Update the API to avoid providing following information to our users
|
|
1006
1008
|
del data["pedb"]
|
|
@@ -1044,16 +1046,16 @@ class Stackup(LayerCollection):
|
|
|
1044
1046
|
else:
|
|
1045
1047
|
self._pedb.materials.update_material(material_name, material)
|
|
1046
1048
|
if k == "layers":
|
|
1047
|
-
if len(list(v.values())) == len(list(self.
|
|
1049
|
+
if len(list(v.values())) == len(list(self.layers.values())):
|
|
1048
1050
|
imported_layers_list = [l_dict["name"] for l_dict in list(v.values())]
|
|
1049
|
-
layout_layer_list = list(self.
|
|
1051
|
+
layout_layer_list = list(self.layers.keys())
|
|
1050
1052
|
for layer_name in imported_layers_list:
|
|
1051
1053
|
layer_index = imported_layers_list.index(layer_name)
|
|
1052
1054
|
if layout_layer_list[layer_index] != layer_name:
|
|
1053
|
-
self.
|
|
1055
|
+
self.layers[layout_layer_list[layer_index]].name = layer_name
|
|
1054
1056
|
prev_layer = None
|
|
1055
1057
|
for layer_name, layer in v.items():
|
|
1056
|
-
if layer["name"] not in self.
|
|
1058
|
+
if layer["name"] not in self.layers:
|
|
1057
1059
|
if not prev_layer:
|
|
1058
1060
|
self.add_layer(
|
|
1059
1061
|
layer_name,
|
|
@@ -1075,8 +1077,8 @@ class Stackup(LayerCollection):
|
|
|
1075
1077
|
thickness=layer["thickness"],
|
|
1076
1078
|
)
|
|
1077
1079
|
prev_layer = layer_name
|
|
1078
|
-
if layer_name in self.
|
|
1079
|
-
self.
|
|
1080
|
+
if layer_name in self.layers:
|
|
1081
|
+
self.layers[layer["name"]]._load_layer(layer)
|
|
1080
1082
|
self.refresh_layer_collection()
|
|
1081
1083
|
return True
|
|
1082
1084
|
|
|
@@ -1205,7 +1207,7 @@ class Stackup(LayerCollection):
|
|
|
1205
1207
|
new_lc.AddLayers(layer_list)
|
|
1206
1208
|
self._pedb.layout.layer_collection = new_lc
|
|
1207
1209
|
|
|
1208
|
-
for pyaedt_cmp in list(self._pedb.components.
|
|
1210
|
+
for pyaedt_cmp in list(self._pedb.components.instances.values()):
|
|
1209
1211
|
cmp = pyaedt_cmp.edbcomponent
|
|
1210
1212
|
cmp_type = cmp.GetComponentType()
|
|
1211
1213
|
cmp_prop = cmp.GetComponentProperty().Clone()
|
|
@@ -1257,7 +1259,7 @@ class Stackup(LayerCollection):
|
|
|
1257
1259
|
float
|
|
1258
1260
|
The thickness value.
|
|
1259
1261
|
"""
|
|
1260
|
-
layers = list(self.
|
|
1262
|
+
layers = list(self.layers.values())
|
|
1261
1263
|
layers.sort(key=lambda lay: lay.lower_elevation)
|
|
1262
1264
|
thickness = 0
|
|
1263
1265
|
if layers:
|
|
@@ -1267,13 +1269,13 @@ class Stackup(LayerCollection):
|
|
|
1267
1269
|
return round(thickness, 7)
|
|
1268
1270
|
|
|
1269
1271
|
def _get_solder_height(self, layer_name):
|
|
1270
|
-
for _, val in self._pedb.components.
|
|
1272
|
+
for _, val in self._pedb.components.instances.items():
|
|
1271
1273
|
if val.solder_ball_height and val.placement_layer == layer_name:
|
|
1272
1274
|
return val.solder_ball_height
|
|
1273
1275
|
return 0
|
|
1274
1276
|
|
|
1275
1277
|
def _remove_solder_pec(self, layer_name):
|
|
1276
|
-
for _, val in self._pedb.components.
|
|
1278
|
+
for _, val in self._pedb.components.instances.items():
|
|
1277
1279
|
if val.solder_ball_height and val.placement_layer == layer_name:
|
|
1278
1280
|
comp_prop = val.component_property
|
|
1279
1281
|
port_property = comp_prop.GetPortProperty().Clone()
|
|
@@ -1291,19 +1293,19 @@ class Stackup(LayerCollection):
|
|
|
1291
1293
|
-------
|
|
1292
1294
|
bool
|
|
1293
1295
|
"""
|
|
1294
|
-
for el, val in self._pedb.components.
|
|
1296
|
+
for el, val in self._pedb.components.instances.items():
|
|
1295
1297
|
if val.solder_ball_height:
|
|
1296
1298
|
layer = val.placement_layer
|
|
1297
|
-
if layer == list(self.
|
|
1299
|
+
if layer == list(self.layers.keys())[0]:
|
|
1298
1300
|
self.add_layer(
|
|
1299
1301
|
"Bottom_air",
|
|
1300
|
-
base_layer=list(self.
|
|
1302
|
+
base_layer=list(self.layers.keys())[-1],
|
|
1301
1303
|
method="insert_below",
|
|
1302
1304
|
material="air",
|
|
1303
1305
|
thickness=val.solder_ball_height,
|
|
1304
1306
|
layer_type="dielectric",
|
|
1305
1307
|
)
|
|
1306
|
-
elif layer == list(self.
|
|
1308
|
+
elif layer == list(self.layers.keys())[-1]:
|
|
1307
1309
|
self.add_layer(
|
|
1308
1310
|
"Top_Air",
|
|
1309
1311
|
base_layer=layer,
|
|
@@ -1312,10 +1314,10 @@ class Stackup(LayerCollection):
|
|
|
1312
1314
|
layer_type="dielectric",
|
|
1313
1315
|
)
|
|
1314
1316
|
elif layer == list(self.signal_layers.keys())[-1]:
|
|
1315
|
-
list(self.
|
|
1317
|
+
list(self.layers.values())[-1].thickness = val.solder_ball_height
|
|
1316
1318
|
|
|
1317
1319
|
elif layer == list(self.signal_layers.keys())[0]:
|
|
1318
|
-
list(self.
|
|
1320
|
+
list(self.layers.values())[0].thickness = val.solder_ball_height
|
|
1319
1321
|
return True
|
|
1320
1322
|
|
|
1321
1323
|
def place_in_layout(
|
|
@@ -1798,7 +1800,7 @@ class Stackup(LayerCollection):
|
|
|
1798
1800
|
temp_data = {name: 0 for name, _ in self.signal_layers.items()}
|
|
1799
1801
|
outline_area = 0
|
|
1800
1802
|
for i in self._pedb.modeler.primitives:
|
|
1801
|
-
layer_name = i.
|
|
1803
|
+
layer_name = i.layer.name
|
|
1802
1804
|
if layer_name.lower() == "outline":
|
|
1803
1805
|
if i.area() > outline_area:
|
|
1804
1806
|
outline_area = i.area()
|
|
@@ -1816,36 +1818,37 @@ class Stackup(LayerCollection):
|
|
|
1816
1818
|
def _import_dict(self, json_dict, rename=False):
|
|
1817
1819
|
"""Import stackup from a dictionary."""
|
|
1818
1820
|
if not "materials" in json_dict:
|
|
1819
|
-
self._logger.
|
|
1820
|
-
self._logger.warning(
|
|
1821
|
-
"Please check your json or xml file, if no material are defined your project will"
|
|
1822
|
-
"likely fail to simulate"
|
|
1823
|
-
)
|
|
1821
|
+
self._logger.info("Configuration file does not have material definition. Using aedb and syslib materials.")
|
|
1824
1822
|
else:
|
|
1825
1823
|
mats = json_dict["materials"]
|
|
1826
|
-
for material in mats.
|
|
1827
|
-
|
|
1828
|
-
|
|
1824
|
+
for name, material in mats.items():
|
|
1825
|
+
try:
|
|
1826
|
+
material_name = material["name"]
|
|
1827
|
+
del material["name"]
|
|
1828
|
+
except KeyError:
|
|
1829
|
+
material_name = name
|
|
1829
1830
|
if material_name not in self._pedb.materials:
|
|
1830
1831
|
self._pedb.materials.add_material(material_name, **material)
|
|
1831
1832
|
else:
|
|
1832
1833
|
self._pedb.materials.update_material(material_name, material)
|
|
1833
|
-
temp =
|
|
1834
|
+
temp = json_dict
|
|
1835
|
+
if "layers" in json_dict:
|
|
1836
|
+
temp = {i: j for i, j in json_dict["layers"].items() if j["type"] in ["signal", "dielectric"]}
|
|
1834
1837
|
config_file_layers = list(temp.keys())
|
|
1835
|
-
layout_layers = list(self.
|
|
1838
|
+
layout_layers = list(self.layers.keys())
|
|
1836
1839
|
renamed_layers = {}
|
|
1837
1840
|
if rename and len(config_file_layers) == len(layout_layers):
|
|
1838
1841
|
for lay_ind in range(len(list(temp.keys()))):
|
|
1839
1842
|
if not config_file_layers[lay_ind] == layout_layers[lay_ind]:
|
|
1840
1843
|
renamed_layers[layout_layers[lay_ind]] = config_file_layers[lay_ind]
|
|
1841
|
-
layers_names = list(self.
|
|
1844
|
+
layers_names = list(self.layers.keys())[::]
|
|
1842
1845
|
for name in layers_names:
|
|
1843
1846
|
layer = None
|
|
1844
1847
|
if name in temp:
|
|
1845
1848
|
layer = temp[name]
|
|
1846
1849
|
elif name in renamed_layers:
|
|
1847
1850
|
layer = temp[renamed_layers[name]]
|
|
1848
|
-
self.
|
|
1851
|
+
self.layers[name].name = renamed_layers[name]
|
|
1849
1852
|
name = renamed_layers[name]
|
|
1850
1853
|
else: # Remove layers not in config file.
|
|
1851
1854
|
self.remove_layer(name)
|
|
@@ -1876,9 +1879,9 @@ class Stackup(LayerCollection):
|
|
|
1876
1879
|
|
|
1877
1880
|
for k, v in layer.items():
|
|
1878
1881
|
default_layer[k] = v
|
|
1879
|
-
self.
|
|
1882
|
+
self.layers[name]._load_layer(default_layer)
|
|
1880
1883
|
for layer_name, layer in temp.items(): # looping over potential new layers to add
|
|
1881
|
-
if layer_name in self.
|
|
1884
|
+
if layer_name in self.layers:
|
|
1882
1885
|
continue # if layer exist, skip
|
|
1883
1886
|
# adding layer
|
|
1884
1887
|
default_layer = {
|
|
@@ -1974,7 +1977,7 @@ class Stackup(LayerCollection):
|
|
|
1974
1977
|
|
|
1975
1978
|
df = pd.read_csv(file_path, index_col=0)
|
|
1976
1979
|
|
|
1977
|
-
for name in self.
|
|
1980
|
+
for name in self.layers.keys(): # pragma: no cover
|
|
1978
1981
|
if not name in df.index:
|
|
1979
1982
|
logger.error("{} doesn't exist in csv".format(name))
|
|
1980
1983
|
return False
|
|
@@ -2028,7 +2031,7 @@ class Stackup(LayerCollection):
|
|
|
2028
2031
|
for name, val in layers.items():
|
|
2029
2032
|
etching_factor = float(val["EtchFactor"]) if "EtchFactor" in val else None
|
|
2030
2033
|
|
|
2031
|
-
if not self.
|
|
2034
|
+
if not self.layers:
|
|
2032
2035
|
self.add_layer(
|
|
2033
2036
|
name,
|
|
2034
2037
|
None,
|
|
@@ -2040,8 +2043,8 @@ class Stackup(LayerCollection):
|
|
|
2040
2043
|
etching_factor,
|
|
2041
2044
|
)
|
|
2042
2045
|
else:
|
|
2043
|
-
if name in self.
|
|
2044
|
-
lyr = self.
|
|
2046
|
+
if name in self.layers.keys():
|
|
2047
|
+
lyr = self.layers[name]
|
|
2045
2048
|
lyr.type = val["Type"]
|
|
2046
2049
|
lyr.material = val["Material"]
|
|
2047
2050
|
lyr.dielectric_fill = val["FillMaterial"] if val["Type"] == "signal" else ""
|
|
@@ -2049,10 +2052,10 @@ class Stackup(LayerCollection):
|
|
|
2049
2052
|
if prev_layer:
|
|
2050
2053
|
self._set_layout_stackup(lyr._edb_layer, "change_position", prev_layer)
|
|
2051
2054
|
else:
|
|
2052
|
-
if prev_layer and prev_layer in self.
|
|
2055
|
+
if prev_layer and prev_layer in self.layers:
|
|
2053
2056
|
layer_name = prev_layer
|
|
2054
2057
|
else:
|
|
2055
|
-
layer_name = list(self.
|
|
2058
|
+
layer_name = list(self.layers.keys())[-1] if self.layers else None
|
|
2056
2059
|
self.add_layer(
|
|
2057
2060
|
name,
|
|
2058
2061
|
layer_name,
|
|
@@ -2064,7 +2067,7 @@ class Stackup(LayerCollection):
|
|
|
2064
2067
|
etching_factor,
|
|
2065
2068
|
)
|
|
2066
2069
|
prev_layer = name
|
|
2067
|
-
for name in self.
|
|
2070
|
+
for name in self.layers:
|
|
2068
2071
|
if name not in layers:
|
|
2069
2072
|
self.remove_layer(name)
|
|
2070
2073
|
|
|
@@ -2141,7 +2144,7 @@ class Stackup(LayerCollection):
|
|
|
2141
2144
|
"""
|
|
2142
2145
|
layers = OrderedDict()
|
|
2143
2146
|
roughness_models = OrderedDict()
|
|
2144
|
-
for name, val in self.
|
|
2147
|
+
for name, val in self.layers.items():
|
|
2145
2148
|
layer = dict()
|
|
2146
2149
|
layer["Material"] = val.material
|
|
2147
2150
|
layer["Name"] = val.name
|
|
@@ -2354,12 +2357,12 @@ class Stackup(LayerCollection):
|
|
|
2354
2357
|
|
|
2355
2358
|
Parameters
|
|
2356
2359
|
----------
|
|
2357
|
-
file_path : str
|
|
2358
|
-
Path to stackup file.
|
|
2360
|
+
file_path : str, dict
|
|
2361
|
+
Path to stackup file or dict with stackup details.
|
|
2359
2362
|
rename : bool
|
|
2360
2363
|
If rename is ``False`` then layer in layout not found in the stackup file are deleted.
|
|
2361
2364
|
Otherwise, if the number of layer in the stackup file equals the number of stackup layer
|
|
2362
|
-
in the layout, layers are renamed according the
|
|
2365
|
+
in the layout, layers are renamed according the file.
|
|
2363
2366
|
Note that layer order matters, and has to be writtent from top to bottom layer in the file.
|
|
2364
2367
|
|
|
2365
2368
|
Returns
|
|
@@ -2385,32 +2388,6 @@ class Stackup(LayerCollection):
|
|
|
2385
2388
|
else:
|
|
2386
2389
|
return False
|
|
2387
2390
|
|
|
2388
|
-
def import_stackup(self, file_path):
|
|
2389
|
-
"""Import stackup from a file. The file format can be XML, CSV, or JSON.
|
|
2390
|
-
|
|
2391
|
-
.. deprecated:: 0.6.61
|
|
2392
|
-
Use :func:`load` instead.
|
|
2393
|
-
|
|
2394
|
-
Parameters
|
|
2395
|
-
----------
|
|
2396
|
-
file_path : str
|
|
2397
|
-
Path to stackup file.
|
|
2398
|
-
|
|
2399
|
-
Returns
|
|
2400
|
-
-------
|
|
2401
|
-
bool
|
|
2402
|
-
``True`` when successful, ``False`` when failed.
|
|
2403
|
-
|
|
2404
|
-
Examples
|
|
2405
|
-
--------
|
|
2406
|
-
>>> from pyedb import Edb
|
|
2407
|
-
>>> edb = Edb()
|
|
2408
|
-
>>> edb.stackup.import_stackup("stackup.xml")
|
|
2409
|
-
"""
|
|
2410
|
-
|
|
2411
|
-
self._logger.warning("Method import_stackup is deprecated. Use .load")
|
|
2412
|
-
return self.load(file_path)
|
|
2413
|
-
|
|
2414
2391
|
def plot(
|
|
2415
2392
|
self,
|
|
2416
2393
|
save_plot=None,
|
|
@@ -2452,7 +2429,7 @@ class Stackup(LayerCollection):
|
|
|
2452
2429
|
from pyedb.generic.constants import CSS4_COLORS
|
|
2453
2430
|
from pyedb.generic.plot import plot_matplotlib
|
|
2454
2431
|
|
|
2455
|
-
layer_names = list(self.
|
|
2432
|
+
layer_names = list(self.layers.keys())
|
|
2456
2433
|
if first_layer is None or first_layer not in layer_names:
|
|
2457
2434
|
bottom_layer = layer_names[-1]
|
|
2458
2435
|
elif isinstance(first_layer, str):
|
|
@@ -2470,14 +2447,14 @@ class Stackup(LayerCollection):
|
|
|
2470
2447
|
else:
|
|
2471
2448
|
raise AttributeError("last_layer must be str or class `dotnet.edb_core.edb_data.layer_data.LayerEdbClass`")
|
|
2472
2449
|
|
|
2473
|
-
stackup_mode = self.
|
|
2450
|
+
stackup_mode = self.mode
|
|
2474
2451
|
if stackup_mode not in ["Laminate", "Overlapping"]:
|
|
2475
2452
|
raise AttributeError("stackup plot supports only 'Laminate' and 'Overlapping' stackup types.")
|
|
2476
2453
|
|
|
2477
2454
|
# build the layers data
|
|
2478
2455
|
layers_data = []
|
|
2479
2456
|
skip_flag = True
|
|
2480
|
-
for layer in self.
|
|
2457
|
+
for layer in self.layers.values(): # start from top
|
|
2481
2458
|
if layer.name != top_layer and skip_flag:
|
|
2482
2459
|
continue
|
|
2483
2460
|
else:
|
|
@@ -113,7 +113,7 @@ class LayerFeature(object):
|
|
|
113
113
|
is_via = False
|
|
114
114
|
if not pin.start_layer == pin.stop_layer:
|
|
115
115
|
is_via = True
|
|
116
|
-
pin_net = pin.GetNet().GetName()
|
|
116
|
+
pin_net = pin._edb_object.GetNet().GetName()
|
|
117
117
|
pos_rot = pin._edb_padstackinstance.GetPositionAndRotationValue()
|
|
118
118
|
pin_rotation = pos_rot[2].ToDouble()
|
|
119
119
|
if pin._edb_padstackinstance.IsLayoutPin():
|
|
@@ -35,7 +35,7 @@ class Polygon(object):
|
|
|
35
35
|
|
|
36
36
|
def add_poly_step(self, polygon=None): # pragma no cover
|
|
37
37
|
if polygon:
|
|
38
|
-
polygon_data = polygon.GetPolygonData()
|
|
38
|
+
polygon_data = polygon._edb_object.GetPolygonData()
|
|
39
39
|
if polygon_data.IsClosed():
|
|
40
40
|
arcs = polygon_data.GetArcData()
|
|
41
41
|
if not arcs:
|
|
@@ -64,7 +64,7 @@ class Polygon(object):
|
|
|
64
64
|
new_poly_step.clock_wise = not arc.IsCCW()
|
|
65
65
|
self.poly_steps.append(new_poly_step)
|
|
66
66
|
for void in polygon.voids:
|
|
67
|
-
void_polygon_data = void.GetPolygonData()
|
|
67
|
+
void_polygon_data = void._edb_object.GetPolygonData()
|
|
68
68
|
if void_polygon_data.IsClosed():
|
|
69
69
|
void_arcs = void_polygon_data.GetArcData()
|
|
70
70
|
if not void_arcs:
|
|
@@ -89,7 +89,7 @@ class Step(object):
|
|
|
89
89
|
net_name = net.name
|
|
90
90
|
logical_net = LogicalNet()
|
|
91
91
|
logical_net.name = net_name
|
|
92
|
-
net_pins = list(net.PadstackInstances)
|
|
92
|
+
net_pins = list(net._edb_object.PadstackInstances)
|
|
93
93
|
for pin in net_pins:
|
|
94
94
|
new_pin_ref = logical_net.get_pin_ref_def()
|
|
95
95
|
new_pin_ref.pin = pin.GetName()
|
|
@@ -250,9 +250,9 @@ class Step(object):
|
|
|
250
250
|
)
|
|
251
251
|
if pdef_name in padstack_defs:
|
|
252
252
|
padstack_def = padstack_defs[pdef_name]
|
|
253
|
-
comp_name = padstack_instance.GetComponent().GetName()
|
|
253
|
+
comp_name = padstack_instance._edb_object.GetComponent().GetName()
|
|
254
254
|
if padstack_instance.is_pin and comp_name:
|
|
255
|
-
component_inst = self._pedb.components.
|
|
255
|
+
component_inst = self._pedb.components.instances[comp_name]
|
|
256
256
|
layers[layer_name].add_component_padstack_instance_feature(
|
|
257
257
|
component_inst, padstack_instance, top_bottom_layers, padstack_def
|
|
258
258
|
)
|
pyedb/ipc2581/ipc2581.py
CHANGED
|
@@ -250,7 +250,7 @@ class Ipc2581(object):
|
|
|
250
250
|
self.layers_name = list(self._pedb.stackup.signal_layers.keys())
|
|
251
251
|
self.top_bottom_layers = [self.layers_name[0], self.layers_name[-1]]
|
|
252
252
|
sequence = 0
|
|
253
|
-
for layer_name in list(self._pedb.stackup.
|
|
253
|
+
for layer_name in list(self._pedb.stackup.layers.keys()):
|
|
254
254
|
sequence += 1
|
|
255
255
|
self.content.add_layer_ref(layer_name)
|
|
256
256
|
layer_color = self._pedb.stackup.layers[layer_name].color
|
|
@@ -316,7 +316,7 @@ class Ipc2581(object):
|
|
|
316
316
|
self.content.dict_colors.add_color("{}".format("Drill"), "255", "255", "255")
|
|
317
317
|
|
|
318
318
|
def add_components(self):
|
|
319
|
-
for item in self._pedb.components.
|
|
319
|
+
for item in self._pedb.components.instances.values():
|
|
320
320
|
self.ecad.cad_data.cad_data_step.add_component(item)
|
|
321
321
|
|
|
322
322
|
def add_logical_nets(self):
|