pyedb 0.28.0__py3-none-any.whl → 0.29.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.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_boundaries.py +44 -74
- pyedb/configuration/cfg_common.py +1 -1
- pyedb/configuration/cfg_components.py +31 -105
- pyedb/configuration/cfg_data.py +3 -8
- pyedb/configuration/cfg_operations.py +14 -10
- pyedb/configuration/cfg_padstacks.py +31 -61
- pyedb/configuration/cfg_ports_sources.py +4 -2
- pyedb/configuration/cfg_s_parameter_models.py +85 -29
- pyedb/configuration/configuration.py +34 -10
- pyedb/dotnet/edb.py +12 -4
- pyedb/dotnet/edb_core/cell/hierarchy/component.py +199 -0
- pyedb/dotnet/edb_core/cell/primitive/primitive.py +2 -0
- pyedb/dotnet/edb_core/cell/terminal/terminal.py +4 -3
- pyedb/dotnet/edb_core/definition/component_def.py +17 -1
- pyedb/dotnet/edb_core/definition/component_model.py +0 -4
- pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +3 -3
- pyedb/dotnet/edb_core/edb_data/nets_data.py +10 -7
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +50 -0
- pyedb/dotnet/edb_core/layout_validation.py +3 -3
- pyedb/dotnet/edb_core/nets.py +162 -181
- {pyedb-0.28.0.dist-info → pyedb-0.29.0.dist-info}/METADATA +2 -2
- {pyedb-0.28.0.dist-info → pyedb-0.29.0.dist-info}/RECORD +25 -25
- {pyedb-0.28.0.dist-info → pyedb-0.29.0.dist-info}/LICENSE +0 -0
- {pyedb-0.28.0.dist-info → pyedb-0.29.0.dist-info}/WHEEL +0 -0
|
@@ -24,37 +24,93 @@ from pathlib import Path
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class CfgSParameterModel:
|
|
27
|
-
def __init__(self,
|
|
28
|
-
self.
|
|
27
|
+
def __init__(self, **kwargs):
|
|
28
|
+
self.name = kwargs.get("name", "")
|
|
29
|
+
self.component_definition = kwargs.get("component_definition", "")
|
|
30
|
+
self.file_path = kwargs.get("file_path", "")
|
|
31
|
+
self.apply_to_all = kwargs.get("apply_to_all", False)
|
|
32
|
+
self.components = kwargs.get("components", [])
|
|
33
|
+
self.reference_net = kwargs.get("reference_net", "")
|
|
34
|
+
self.reference_net_per_component = kwargs.get("reference_net_per_component", {})
|
|
35
|
+
self.pin_order = kwargs.get("pin_order", None)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class CfgSParameters:
|
|
39
|
+
def __init__(self, pedb, data, path_lib=None):
|
|
40
|
+
self._pedb = pedb
|
|
29
41
|
self.path_libraries = path_lib
|
|
30
|
-
self.
|
|
31
|
-
self.name = self._sparam_dict.get("name", "")
|
|
32
|
-
self.component_definition = self._sparam_dict.get("component_definition", "")
|
|
33
|
-
self.file_path = self._sparam_dict.get("file_path", "")
|
|
34
|
-
self.apply_to_all = self._sparam_dict.get("apply_to_all", False)
|
|
35
|
-
self.components = self._sparam_dict.get("components", [])
|
|
36
|
-
self.reference_net = self._sparam_dict.get("reference_net", "")
|
|
37
|
-
self.reference_net_per_component = self._sparam_dict.get("reference_net_per_component", {})
|
|
42
|
+
self.s_parameters_models = [CfgSParameterModel(**i) for i in data]
|
|
38
43
|
|
|
39
44
|
def apply(self):
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
for s_param in self.s_parameters_models:
|
|
46
|
+
fpath = s_param.file_path
|
|
47
|
+
if not Path(fpath).anchor:
|
|
48
|
+
fpath = str(Path(self.path_libraries) / fpath)
|
|
49
|
+
comp_def = self._pedb.definitions.component[s_param.component_definition]
|
|
50
|
+
if s_param.pin_order:
|
|
51
|
+
comp_def.set_properties(pin_order=s_param.pin_order)
|
|
52
|
+
comp_def.add_n_port_model(fpath, s_param.name)
|
|
53
|
+
comp_list = dict()
|
|
54
|
+
if s_param.apply_to_all:
|
|
55
|
+
comp_list.update(
|
|
56
|
+
{refdes: comp for refdes, comp in comp_def.components.items() if refdes not in s_param.components}
|
|
57
|
+
)
|
|
58
|
+
else:
|
|
59
|
+
comp_list.update(
|
|
60
|
+
{refdes: comp for refdes, comp in comp_def.components.items() if refdes in s_param.components}
|
|
61
|
+
)
|
|
54
62
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
for refdes, comp in comp_list.items():
|
|
64
|
+
if refdes in s_param.reference_net_per_component:
|
|
65
|
+
ref_net = s_param.reference_net_per_component[refdes]
|
|
66
|
+
else:
|
|
67
|
+
ref_net = s_param.reference_net
|
|
68
|
+
comp.use_s_parameter_model(s_param.name, reference_net=ref_net)
|
|
69
|
+
|
|
70
|
+
def get_data_from_db(self):
|
|
71
|
+
db_comp_def = self._pedb.definitions.component
|
|
72
|
+
for name, compdef_obj in db_comp_def.items():
|
|
73
|
+
nport_models = compdef_obj.component_models
|
|
74
|
+
if not nport_models:
|
|
75
|
+
continue
|
|
58
76
|
else:
|
|
59
|
-
|
|
60
|
-
|
|
77
|
+
pin_order = compdef_obj.get_properties()["pin_order"]
|
|
78
|
+
temp_comps = compdef_obj.components
|
|
79
|
+
for model_name, model_obj in nport_models.items():
|
|
80
|
+
temp_comp_list = []
|
|
81
|
+
reference_net_per_component = {}
|
|
82
|
+
for i in temp_comps.values():
|
|
83
|
+
s_param_model = i.model_properties.get("s_parameter_model")
|
|
84
|
+
if s_param_model:
|
|
85
|
+
if s_param_model["model_name"] == model_name:
|
|
86
|
+
temp_comp_list.append(i.refdes)
|
|
87
|
+
reference_net_per_component[i.refdes] = s_param_model["reference_net"]
|
|
88
|
+
else:
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
self.s_parameters_models.append(
|
|
92
|
+
CfgSParameterModel(
|
|
93
|
+
name=model_name,
|
|
94
|
+
component_definition=name,
|
|
95
|
+
file_path=model_obj.reference_file,
|
|
96
|
+
apply_to_all=False,
|
|
97
|
+
components=temp_comp_list,
|
|
98
|
+
reference_net_per_component=reference_net_per_component,
|
|
99
|
+
pin_order=pin_order,
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
data = []
|
|
104
|
+
for i in self.s_parameters_models:
|
|
105
|
+
data.append(
|
|
106
|
+
{
|
|
107
|
+
"name": i.name,
|
|
108
|
+
"component_definition": i.component_definition,
|
|
109
|
+
"file_path": i.file_path,
|
|
110
|
+
"apply_to_all": i.apply_to_all,
|
|
111
|
+
"components": i.components,
|
|
112
|
+
"reference_net_per_component": i.reference_net_per_component,
|
|
113
|
+
"pin_order": i.pin_order,
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
return data
|
|
@@ -117,10 +117,6 @@ class Configuration:
|
|
|
117
117
|
# Configure components
|
|
118
118
|
self.cfg_data.components.apply()
|
|
119
119
|
|
|
120
|
-
# Configure padstacks
|
|
121
|
-
if self.cfg_data.padstacks:
|
|
122
|
-
self.cfg_data.padstacks.apply()
|
|
123
|
-
|
|
124
120
|
# Configure pin groups
|
|
125
121
|
self.cfg_data.pin_groups.apply()
|
|
126
122
|
|
|
@@ -145,9 +141,12 @@ class Configuration:
|
|
|
145
141
|
else:
|
|
146
142
|
self.cfg_data.stackup.apply()
|
|
147
143
|
|
|
144
|
+
# Configure padstacks
|
|
145
|
+
if self.cfg_data.padstacks:
|
|
146
|
+
self.cfg_data.padstacks.apply()
|
|
147
|
+
|
|
148
148
|
# Configure S-parameter
|
|
149
|
-
|
|
150
|
-
s_parameter_model.apply()
|
|
149
|
+
self.cfg_data.s_parameters.apply()
|
|
151
150
|
|
|
152
151
|
# Configure SPICE models
|
|
153
152
|
for spice_model in self.cfg_data.spice_models:
|
|
@@ -293,6 +292,10 @@ class Configuration:
|
|
|
293
292
|
data["operations"] = self.cfg_data.operations.get_data_from_db()
|
|
294
293
|
if kwargs.get("padstacks", False):
|
|
295
294
|
data["padstacks"] = self.cfg_data.padstacks.get_data_from_db()
|
|
295
|
+
if kwargs.get("s_parameters", False):
|
|
296
|
+
data["s_parameters"] = self.cfg_data.s_parameters.get_data_from_db()
|
|
297
|
+
if kwargs.get("boundaries", False):
|
|
298
|
+
data["boundaries"] = self.cfg_data.boundaries.get_data_from_db()
|
|
296
299
|
|
|
297
300
|
return data
|
|
298
301
|
|
|
@@ -307,6 +310,10 @@ class Configuration:
|
|
|
307
310
|
nets=True,
|
|
308
311
|
pin_groups=True,
|
|
309
312
|
operations=True,
|
|
313
|
+
components=True,
|
|
314
|
+
boundaries=True,
|
|
315
|
+
s_parameters=True,
|
|
316
|
+
padstacks=True,
|
|
310
317
|
):
|
|
311
318
|
"""Export the configuration data from layout to a file.
|
|
312
319
|
|
|
@@ -330,22 +337,39 @@ class Configuration:
|
|
|
330
337
|
Whether to export pin groups.
|
|
331
338
|
operations : bool
|
|
332
339
|
Whether to export operations.
|
|
340
|
+
components : bool
|
|
341
|
+
Whether to export component.
|
|
342
|
+
boundaries : bool
|
|
343
|
+
Whether to export boundaries.
|
|
344
|
+
s_parameters : bool
|
|
345
|
+
Whether to export s_parameters.
|
|
346
|
+
padstacks : bool
|
|
347
|
+
Whether to export padstacks.
|
|
333
348
|
Returns
|
|
334
349
|
-------
|
|
335
350
|
bool
|
|
336
351
|
"""
|
|
337
|
-
file_path = file_path if isinstance(file_path, Path) else Path(file_path)
|
|
338
|
-
file_path = file_path if file_path.suffix == ".json" else file_path.with_suffix(".json")
|
|
339
352
|
data = self.get_data_from_db(
|
|
340
353
|
stackup=stackup,
|
|
341
354
|
package_definitions=package_definitions,
|
|
342
|
-
setups=
|
|
355
|
+
setups=False,
|
|
343
356
|
sources=sources,
|
|
344
357
|
ports=ports,
|
|
345
358
|
nets=nets,
|
|
346
359
|
pin_groups=pin_groups,
|
|
347
360
|
operations=operations,
|
|
361
|
+
components=components,
|
|
362
|
+
boundaries=boundaries,
|
|
363
|
+
s_parameters=s_parameters,
|
|
364
|
+
padstacks=padstacks,
|
|
348
365
|
)
|
|
366
|
+
|
|
367
|
+
file_path = file_path if isinstance(file_path, Path) else Path(file_path)
|
|
368
|
+
file_path = file_path.with_suffix(".json") if file_path.suffix == "" else file_path
|
|
369
|
+
|
|
349
370
|
with open(file_path, "w") as f:
|
|
350
|
-
|
|
371
|
+
if file_path.suffix == ".json":
|
|
372
|
+
json.dump(data, f, ensure_ascii=False, indent=4)
|
|
373
|
+
else:
|
|
374
|
+
toml.dump(data, f)
|
|
351
375
|
return True if os.path.isfile(file_path) else False
|
pyedb/dotnet/edb.py
CHANGED
|
@@ -1630,6 +1630,14 @@ class Edb(Database):
|
|
|
1630
1630
|
)
|
|
1631
1631
|
else:
|
|
1632
1632
|
obj_data = i.Expand(expansion_size, tolerance, round_corner, round_extension)
|
|
1633
|
+
if inlcude_voids_in_extents and "PolygonData" not in str(i) and i.has_voids and obj_data:
|
|
1634
|
+
for void in i.voids:
|
|
1635
|
+
void_data = void.primitive_object.GetPolygonData().Expand(
|
|
1636
|
+
-1 * expansion_size, tolerance, round_corner, round_extension
|
|
1637
|
+
)
|
|
1638
|
+
if void_data:
|
|
1639
|
+
for v in list(void_data):
|
|
1640
|
+
obj_data[0].AddHole(v)
|
|
1633
1641
|
if obj_data:
|
|
1634
1642
|
if not inlcude_voids_in_extents:
|
|
1635
1643
|
unite_polys.extend(list(obj_data))
|
|
@@ -2209,9 +2217,9 @@ class Edb(Database):
|
|
|
2209
2217
|
pins_to_preserve.extend([i.id for i in el.pins.values()])
|
|
2210
2218
|
nets_to_preserve.extend(el.nets)
|
|
2211
2219
|
if include_pingroups:
|
|
2212
|
-
for
|
|
2213
|
-
for pin in
|
|
2214
|
-
if pin.
|
|
2220
|
+
for pingroup in self.padstacks.pingroups:
|
|
2221
|
+
for pin in pingroup.pins.values():
|
|
2222
|
+
if pin.net_name in reference_list:
|
|
2215
2223
|
pins_to_preserve.append(pin.id)
|
|
2216
2224
|
if check_terminals:
|
|
2217
2225
|
terms = [
|
|
@@ -2280,12 +2288,12 @@ class Edb(Database):
|
|
|
2280
2288
|
if extent_type in ["Conforming", self.edb_api.geometry.extent_type.Conforming, 1]:
|
|
2281
2289
|
if extent_defeature > 0:
|
|
2282
2290
|
_poly = _poly.Defeature(extent_defeature)
|
|
2283
|
-
|
|
2284
2291
|
_poly1 = _poly.CreateFromArcs(_poly.GetArcData(), True)
|
|
2285
2292
|
if inlcude_voids_in_extents:
|
|
2286
2293
|
for hole in list(_poly.Holes):
|
|
2287
2294
|
if hole.Area() >= 0.05 * _poly1.Area():
|
|
2288
2295
|
_poly1.AddHole(hole)
|
|
2296
|
+
self.logger.info(f"Number of voids included:{len(list(_poly1.Holes))}")
|
|
2289
2297
|
_poly = _poly1
|
|
2290
2298
|
if not _poly or _poly.IsNull():
|
|
2291
2299
|
self._logger.error("Failed to create Extent.")
|
|
@@ -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,201 @@ 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())
|
|
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
|
+
if not die_type == "no_die":
|
|
1127
|
+
orientation = kwargs.get("orientation")
|
|
1128
|
+
if orientation:
|
|
1129
|
+
ic_die_prop.SetOrientation(getattr(self._edb.definition.DieType, snake_to_pascal(die_type)))
|
|
1130
|
+
if die_type == "wire_bond":
|
|
1131
|
+
height = kwargs.get("height")
|
|
1132
|
+
if height:
|
|
1133
|
+
ic_die_prop.SetHeight(self._pedb.edb_value(height))
|
|
1134
|
+
cp.SetDieProperty(ic_die_prop)
|
|
1135
|
+
self.component_property = cp
|
|
1136
|
+
|
|
1137
|
+
@property
|
|
1138
|
+
def solder_ball_properties(self):
|
|
1139
|
+
temp = dict()
|
|
1140
|
+
cp = self.component_property
|
|
1141
|
+
c_type = self.type.lower()
|
|
1142
|
+
if c_type not in ["io", "other"]:
|
|
1143
|
+
return temp
|
|
1144
|
+
else:
|
|
1145
|
+
solder_ball_prop = cp.GetSolderBallProperty().Clone()
|
|
1146
|
+
_, diam, mid_diam = solder_ball_prop.GetDiameterValue()
|
|
1147
|
+
height = solder_ball_prop.GetHeightValue().ToString()
|
|
1148
|
+
shape = solder_ball_prop.GetShape().ToString()
|
|
1149
|
+
uses_solder_ball = solder_ball_prop.UsesSolderball()
|
|
1150
|
+
temp["uses_solder_ball"] = uses_solder_ball
|
|
1151
|
+
temp["shape"] = pascal_to_snake(shape)
|
|
1152
|
+
temp["diameter"] = diam.ToString()
|
|
1153
|
+
temp["mid_diameter"] = mid_diam.ToString()
|
|
1154
|
+
temp["height"] = height
|
|
1155
|
+
return temp
|
|
1156
|
+
|
|
1157
|
+
@solder_ball_properties.setter
|
|
1158
|
+
def solder_ball_properties(self, kwargs):
|
|
1159
|
+
cp = self.component_property
|
|
1160
|
+
solder_ball_prop = cp.GetSolderBallProperty().Clone()
|
|
1161
|
+
shape = kwargs.get("shape")
|
|
1162
|
+
if shape:
|
|
1163
|
+
solder_ball_prop.SetShape(getattr(self._edb.definition.SolderballShape, snake_to_pascal(shape)))
|
|
1164
|
+
if shape == "cylinder":
|
|
1165
|
+
diameter = kwargs["diameter"]
|
|
1166
|
+
solder_ball_prop.SetDiameter(self._pedb.edb_value(diameter), self._pedb.edb_value(diameter))
|
|
1167
|
+
elif shape == "spheroid":
|
|
1168
|
+
diameter = kwargs["diameter"]
|
|
1169
|
+
mid_diameter = kwargs["mid_diameter"]
|
|
1170
|
+
solder_ball_prop.SetDiameter(self._pedb.edb_value(diameter), self._pedb.edb_value(mid_diameter))
|
|
1171
|
+
else:
|
|
1172
|
+
return
|
|
1173
|
+
solder_ball_prop.SetHeight(self._get_edb_value(kwargs["height"]))
|
|
1174
|
+
cp.SetSolderBallProperty(solder_ball_prop)
|
|
1175
|
+
self.component_property = cp
|
|
1176
|
+
|
|
1177
|
+
@property
|
|
1178
|
+
def port_properties(self):
|
|
1179
|
+
temp = dict()
|
|
1180
|
+
cp = self.component_property
|
|
1181
|
+
c_type = self.type.lower()
|
|
1182
|
+
if c_type not in ["ic", "io", "other"]:
|
|
1183
|
+
return temp
|
|
1184
|
+
else:
|
|
1185
|
+
port_prop = cp.GetPortProperty().Clone()
|
|
1186
|
+
reference_height = port_prop.GetReferenceHeightValue().ToString()
|
|
1187
|
+
reference_size_auto = port_prop.GetReferenceSizeAuto()
|
|
1188
|
+
_, reference_size_x, reference_size_y = port_prop.GetReferenceSize()
|
|
1189
|
+
temp["reference_height"] = reference_height
|
|
1190
|
+
temp["reference_size_auto"] = reference_size_auto
|
|
1191
|
+
temp["reference_size_x"] = str(reference_size_x)
|
|
1192
|
+
temp["reference_size_y"] = str(reference_size_y)
|
|
1193
|
+
return temp
|
|
1194
|
+
|
|
1195
|
+
@port_properties.setter
|
|
1196
|
+
def port_properties(self, kwargs):
|
|
1197
|
+
cp = self.component_property
|
|
1198
|
+
port_prop = cp.GetPortProperty().Clone()
|
|
1199
|
+
height = kwargs.get("reference_height")
|
|
1200
|
+
if height:
|
|
1201
|
+
port_prop.SetReferenceHeight(self._pedb.edb_value(height))
|
|
1202
|
+
reference_size_auto = kwargs.get("reference_size_auto")
|
|
1203
|
+
if reference_size_auto:
|
|
1204
|
+
port_prop.SetReferenceSizeAuto(reference_size_auto)
|
|
1205
|
+
reference_size_x = kwargs.get("reference_size_x", 0)
|
|
1206
|
+
reference_size_y = kwargs.get("reference_size_y", 0)
|
|
1207
|
+
port_prop.SetReferenceSize(self._pedb.edb_value(reference_size_x), self._pedb.edb_value(reference_size_y))
|
|
1208
|
+
cp.SetPortProperty(port_prop)
|
|
1209
|
+
self.component_property = cp
|
|
@@ -223,9 +223,10 @@ class Terminal(Connectable):
|
|
|
223
223
|
"""Get reference terminal."""
|
|
224
224
|
|
|
225
225
|
edb_terminal = self._edb_object.GetReferenceTerminal()
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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):
|
|
@@ -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(".")[
|
|
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()
|
|
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()
|
|
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):
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|
|
@@ -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
|
|