pyedb 0.26.3__py3-none-any.whl → 0.28.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_data.py +1 -1
- pyedb/configuration/cfg_operations.py +5 -3
- pyedb/configuration/cfg_padstacks.py +43 -36
- pyedb/configuration/cfg_pin_groups.py +7 -8
- pyedb/configuration/cfg_spice_models.py +3 -2
- pyedb/configuration/configuration.py +14 -3
- pyedb/dotnet/application/Variables.py +43 -41
- pyedb/dotnet/edb_core/cell/connectable.py +21 -0
- pyedb/dotnet/edb_core/cell/hierarchy/component.py +46 -18
- pyedb/dotnet/edb_core/cell/layout.py +29 -22
- pyedb/dotnet/edb_core/cell/primitive/primitive.py +1 -22
- pyedb/dotnet/edb_core/cell/terminal/pingroup_terminal.py +3 -3
- pyedb/dotnet/edb_core/cell/terminal/terminal.py +0 -10
- pyedb/dotnet/edb_core/components.py +2 -2
- pyedb/dotnet/edb_core/definition/component_def.py +13 -3
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +251 -69
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +2 -2
- pyedb/dotnet/edb_core/general.py +11 -0
- pyedb/dotnet/edb_core/geometry/polygon_data.py +13 -0
- pyedb/dotnet/edb_core/layout_validation.py +1 -1
- pyedb/dotnet/edb_core/modeler.py +5 -2
- pyedb/dotnet/edb_core/padstack.py +1 -1
- pyedb/dotnet/edb_core/utilities/obj_base.py +0 -13
- pyedb/edb_logger.py +1 -1
- pyedb/siwave.py +33 -7
- {pyedb-0.26.3.dist-info → pyedb-0.28.0.dist-info}/METADATA +4 -4
- {pyedb-0.26.3.dist-info → pyedb-0.28.0.dist-info}/RECORD +30 -30
- {pyedb-0.26.3.dist-info → pyedb-0.28.0.dist-info}/LICENSE +0 -0
- {pyedb-0.26.3.dist-info → pyedb-0.28.0.dist-info}/WHEEL +0 -0
pyedb/__init__.py
CHANGED
pyedb/configuration/cfg_data.py
CHANGED
|
@@ -53,7 +53,7 @@ class CfgData(object):
|
|
|
53
53
|
|
|
54
54
|
self.components = CfgComponents(self._pedb, components_data=kwargs.get("components", []))
|
|
55
55
|
|
|
56
|
-
self.padstacks = CfgPadstacks(self, kwargs.get("padstacks", None))
|
|
56
|
+
self.padstacks = CfgPadstacks(self._pedb, kwargs.get("padstacks", None))
|
|
57
57
|
|
|
58
58
|
self.pin_groups = CfgPinGroups(self._pedb, pingroup_data=kwargs.get("pin_groups", []))
|
|
59
59
|
|
|
@@ -65,7 +65,7 @@ class CfgCutout(CfgBase):
|
|
|
65
65
|
|
|
66
66
|
self.reference_list = []
|
|
67
67
|
self.signal_list = net_names
|
|
68
|
-
|
|
68
|
+
return self.export_properties()
|
|
69
69
|
|
|
70
70
|
def export_properties(self):
|
|
71
71
|
return {
|
|
@@ -84,7 +84,7 @@ class CfgOperations(CfgBase):
|
|
|
84
84
|
"""Imports operation information from JSON."""
|
|
85
85
|
if self.op_cutout:
|
|
86
86
|
polygon_points = self._pedb.cutout(**self.op_cutout.get_attributes())
|
|
87
|
-
if
|
|
87
|
+
if "pyedb_cutout" not in self._pedb.stackup.all_layers:
|
|
88
88
|
self._pedb.stackup.add_document_layer(name="pyedb_cutout")
|
|
89
89
|
self._pedb.modeler.create_polygon(polygon_points, layer_name="pyedb_cutout", net_name="pyedb_cutout")
|
|
90
90
|
|
|
@@ -92,4 +92,6 @@ class CfgOperations(CfgBase):
|
|
|
92
92
|
|
|
93
93
|
def get_data_from_db(self):
|
|
94
94
|
self.op_cutout = CfgCutout(self._pedb)
|
|
95
|
-
|
|
95
|
+
data_from_db = self.op_cutout.get_data_from_db()
|
|
96
|
+
if data_from_db:
|
|
97
|
+
return {"cutout": data_from_db}
|
|
@@ -23,62 +23,69 @@
|
|
|
23
23
|
|
|
24
24
|
from enum import Enum
|
|
25
25
|
|
|
26
|
+
from pyedb.configuration.cfg_common import CfgBase
|
|
27
|
+
|
|
26
28
|
|
|
27
29
|
class CfgPadstacks:
|
|
28
30
|
"""Padstack data class."""
|
|
29
31
|
|
|
30
|
-
def __init__(self,
|
|
31
|
-
self._pedb =
|
|
32
|
+
def __init__(self, pedb, padstack_dict=None):
|
|
33
|
+
self._pedb = pedb
|
|
32
34
|
self.definitions = []
|
|
33
35
|
self.instances = []
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
if self._padstack_dict.get("instances", None):
|
|
40
|
-
self._instances_dict = self._padstack_dict.get("instances", "")
|
|
41
|
-
self.instances = [Instance(pdata, inst) for inst in self._instances_dict]
|
|
36
|
+
if padstack_dict:
|
|
37
|
+
for pdef in padstack_dict.get("definitions", []):
|
|
38
|
+
self.definitions.append(Definition(**pdef))
|
|
39
|
+
for inst in padstack_dict.get("instances", []):
|
|
40
|
+
self.instances.append(Instance(self._pedb, inst))
|
|
42
41
|
|
|
43
42
|
def apply(self):
|
|
44
43
|
"""Apply padstack definition and instances on layout."""
|
|
45
|
-
|
|
46
|
-
|
|
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())
|
|
47
48
|
for instance in self.instances:
|
|
48
49
|
instance.apply()
|
|
49
50
|
|
|
51
|
+
def get_data_from_db(self):
|
|
52
|
+
self.definitions = []
|
|
53
|
+
for pdef_name, pdef in self._pedb.padstacks.definitions.items():
|
|
54
|
+
self.definitions.append(
|
|
55
|
+
Definition(
|
|
56
|
+
name=pdef_name,
|
|
57
|
+
hole_plating_thickness=pdef.hole_plating_thickness,
|
|
58
|
+
hole_material=pdef.material,
|
|
59
|
+
hole_range=pdef.hole_range,
|
|
60
|
+
pad_parameters=pdef.pad_parameters,
|
|
61
|
+
hole_parameters=pdef.hole_parameters,
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
data = {}
|
|
65
|
+
definitions = []
|
|
66
|
+
for i in self.definitions:
|
|
67
|
+
definitions.append(i.get_attributes())
|
|
68
|
+
data["definitions"] = definitions
|
|
69
|
+
return data
|
|
70
|
+
|
|
50
71
|
|
|
51
|
-
class Definition:
|
|
72
|
+
class Definition(CfgBase):
|
|
52
73
|
"""Padstack definition data class."""
|
|
53
74
|
|
|
54
|
-
def __init__(self,
|
|
55
|
-
self.
|
|
56
|
-
self.
|
|
57
|
-
self.
|
|
58
|
-
self.
|
|
59
|
-
self.
|
|
60
|
-
self.
|
|
61
|
-
self.hole_range = self._definition_dict.get("hole_range", None)
|
|
62
|
-
|
|
63
|
-
def apply(self):
|
|
64
|
-
"""Apply padstack definition on layout."""
|
|
65
|
-
padstack_defs = self._pedb.padstacks.definitions
|
|
66
|
-
pdef = padstack_defs[self.name]
|
|
67
|
-
if self.hole_diameter:
|
|
68
|
-
pdef.hole_diameter = self.hole_diameter
|
|
69
|
-
if self.hole_plating_thickness:
|
|
70
|
-
pdef.hole_plating_thickness = self.hole_plating_thickness
|
|
71
|
-
if self.hole_material:
|
|
72
|
-
pdef.material = self.hole_material
|
|
73
|
-
if self.hole_range:
|
|
74
|
-
pdef.hole_range = self.hole_range
|
|
75
|
+
def __init__(self, **kwargs):
|
|
76
|
+
self.name = kwargs.get("name", None)
|
|
77
|
+
self.hole_plating_thickness = kwargs.get("hole_plating_thickness", None)
|
|
78
|
+
self.material = kwargs.get("hole_material", None)
|
|
79
|
+
self.hole_range = kwargs.get("hole_range", None)
|
|
80
|
+
self.pad_parameters = kwargs.get("pad_parameters", None)
|
|
81
|
+
self.hole_parameters = kwargs.get("hole_parameters", None)
|
|
75
82
|
|
|
76
83
|
|
|
77
84
|
class Instance:
|
|
78
85
|
"""Instance data class."""
|
|
79
86
|
|
|
80
|
-
def __init__(self,
|
|
81
|
-
self._pedb =
|
|
87
|
+
def __init__(self, pedb, instances_dict):
|
|
88
|
+
self._pedb = pedb
|
|
82
89
|
self._instances_dict = instances_dict
|
|
83
90
|
self.name = self._instances_dict.get("name", "")
|
|
84
91
|
self.backdrill_top = None
|
|
@@ -36,12 +36,14 @@ class CfgPinGroups:
|
|
|
36
36
|
|
|
37
37
|
def get_data_from_db(self):
|
|
38
38
|
self.pin_groups = []
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
layout_pin_groups = self._pedb.siwave.pin_groups
|
|
40
|
+
for pg_name, pg_obj in layout_pin_groups.items():
|
|
41
|
+
pins = list(pg_obj.pins.keys())
|
|
42
|
+
refdes = list(pg_obj.pins.values())[0].component.name
|
|
41
43
|
cfg_pg = CfgPinGroup(
|
|
42
44
|
self._pedb,
|
|
43
|
-
name=
|
|
44
|
-
reference_designator=
|
|
45
|
+
name=pg_name,
|
|
46
|
+
reference_designator=refdes,
|
|
45
47
|
pins=pins,
|
|
46
48
|
)
|
|
47
49
|
self.pin_groups.append(cfg_pg)
|
|
@@ -65,10 +67,7 @@ class CfgPinGroup(CfgBase):
|
|
|
65
67
|
def create(self):
|
|
66
68
|
"""Apply pin group on layout."""
|
|
67
69
|
if self.pins:
|
|
68
|
-
|
|
69
|
-
self._pedb.modeler.create_pin_group(self.name, pins_by_aedt_name=self.pins)
|
|
70
|
-
else:
|
|
71
|
-
self._pedb.siwave.create_pin_group(self.reference_designator, list(self.pins), self.name)
|
|
70
|
+
self._pedb.siwave.create_pin_group(self.reference_designator, list(self.pins), self.name)
|
|
72
71
|
elif self.net:
|
|
73
72
|
if self.reference_designator in self._pedb.components.instances:
|
|
74
73
|
comp = self._pedb.components.instances[self.reference_designator]
|
|
@@ -34,6 +34,7 @@ class CfgSpiceModel:
|
|
|
34
34
|
self.sub_circuit_name = self._spice_dict.get("sub_circuit_name", "")
|
|
35
35
|
self.apply_to_all = self._spice_dict.get("apply_to_all", True)
|
|
36
36
|
self.components = list(self._spice_dict.get("components", []))
|
|
37
|
+
self.terminal_pairs = self._spice_dict.get("terminal_pairs", None)
|
|
37
38
|
|
|
38
39
|
def apply(self):
|
|
39
40
|
"""Apply Spice model on layout."""
|
|
@@ -45,8 +46,8 @@ class CfgSpiceModel:
|
|
|
45
46
|
comps = self._pedb.components.definitions[self.component_definition].components
|
|
46
47
|
if self.apply_to_all:
|
|
47
48
|
for ref_des, comp in comps.items():
|
|
48
|
-
comp.assign_spice_model(fpath, self.name, self.sub_circuit_name)
|
|
49
|
+
comp.assign_spice_model(fpath, self.name, self.sub_circuit_name, self.terminal_pairs)
|
|
49
50
|
else:
|
|
50
51
|
for ref_des, comp in comps.items():
|
|
51
52
|
if ref_des in self.components:
|
|
52
|
-
comp.assign_spice_model(fpath, self.name, self.sub_circuit_name)
|
|
53
|
+
comp.assign_spice_model(fpath, self.name, self.sub_circuit_name, self.terminal_pairs)
|
|
@@ -74,7 +74,7 @@ class Configuration:
|
|
|
74
74
|
elif config_file.endswith(".toml"):
|
|
75
75
|
data = toml.load(f)
|
|
76
76
|
else: # pragma: no cover
|
|
77
|
-
|
|
77
|
+
raise RuntimeError(f"File {config_file} does not exist.")
|
|
78
78
|
|
|
79
79
|
if not append: # pragma: no cover
|
|
80
80
|
self.data = {}
|
|
@@ -103,7 +103,7 @@ class Configuration:
|
|
|
103
103
|
self._pedb.open_edb()
|
|
104
104
|
return self.cfg_data
|
|
105
105
|
|
|
106
|
-
def run(self):
|
|
106
|
+
def run(self, **kwargs):
|
|
107
107
|
"""Apply configuration settings to the current design"""
|
|
108
108
|
|
|
109
109
|
# Configure boundary settings
|
|
@@ -134,7 +134,16 @@ class Configuration:
|
|
|
134
134
|
self.cfg_data.setups.apply()
|
|
135
135
|
|
|
136
136
|
# Configure stackup
|
|
137
|
-
|
|
137
|
+
if kwargs.get("fix_padstack_def"):
|
|
138
|
+
pedb_defs = self._pedb.padstacks.definitions
|
|
139
|
+
temp = {}
|
|
140
|
+
for name, pdef in pedb_defs.items():
|
|
141
|
+
temp[name] = pdef.get_properties()
|
|
142
|
+
self.cfg_data.stackup.apply()
|
|
143
|
+
for name, pdef_p in temp.items():
|
|
144
|
+
pedb_defs[name].set_properties(**pdef_p)
|
|
145
|
+
else:
|
|
146
|
+
self.cfg_data.stackup.apply()
|
|
138
147
|
|
|
139
148
|
# Configure S-parameter
|
|
140
149
|
for s_parameter_model in self.cfg_data.s_parameters:
|
|
@@ -282,6 +291,8 @@ class Configuration:
|
|
|
282
291
|
data["pin_groups"] = self.cfg_data.pin_groups.get_data_from_db()
|
|
283
292
|
if kwargs.get("operations", False):
|
|
284
293
|
data["operations"] = self.cfg_data.operations.get_data_from_db()
|
|
294
|
+
if kwargs.get("padstacks", False):
|
|
295
|
+
data["padstacks"] = self.cfg_data.padstacks.get_data_from_db()
|
|
285
296
|
|
|
286
297
|
return data
|
|
287
298
|
|
|
@@ -27,7 +27,7 @@ This module is used to create and edit design and project variables in the 3D to
|
|
|
27
27
|
|
|
28
28
|
Examples
|
|
29
29
|
--------
|
|
30
|
-
>>> from
|
|
30
|
+
>>> from ansys.aedt.core import Hfss
|
|
31
31
|
>>> hfss = Hfss()
|
|
32
32
|
>>> hfss["$d"] = "5mm"
|
|
33
33
|
>>> hfss["d"] = "5mm"
|
|
@@ -415,8 +415,8 @@ class VariableManager(object):
|
|
|
415
415
|
Examples
|
|
416
416
|
--------
|
|
417
417
|
|
|
418
|
-
>>> from
|
|
419
|
-
>>> from
|
|
418
|
+
>>> from ansys.aedt.core.maxwell import Maxwell3d
|
|
419
|
+
>>> from ansys.aedt.core.desktop import Desktop
|
|
420
420
|
>>> d = Desktop()
|
|
421
421
|
>>> aedtapp = Maxwell3d()
|
|
422
422
|
|
|
@@ -1765,40 +1765,42 @@ class Variable(object):
|
|
|
1765
1765
|
def __mul__(self, other): # pragma: no cover
|
|
1766
1766
|
"""Multiply the variable with a number or another variable and return a new object.
|
|
1767
1767
|
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
import
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1768
|
+
Parameters
|
|
1769
|
+
----------
|
|
1770
|
+
other : numbers.Number or variable
|
|
1771
|
+
Object to be multiplied.
|
|
1772
|
+
|
|
1773
|
+
Returns
|
|
1774
|
+
-------
|
|
1775
|
+
type
|
|
1776
|
+
Variable.
|
|
1777
|
+
|
|
1778
|
+
Examples
|
|
1779
|
+
--------
|
|
1780
|
+
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1781
|
+
|
|
1782
|
+
Multiply ``'Length1'`` by unitless ``'None'``` to obtain ``'Length'``.
|
|
1783
|
+
A numerical value is also considered to be unitless.
|
|
1784
|
+
|
|
1785
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1786
|
+
>>> v1 = Variable("10mm")
|
|
1787
|
+
>>> v2 = Variable(3)
|
|
1788
|
+
>>> result_1 = v1 * v2
|
|
1789
|
+
>>> result_2 = v1 * 3
|
|
1790
|
+
>>> assert result_1.numeric_value == 30.0
|
|
1791
|
+
>>> assert result_1.unit_system == "Length"
|
|
1792
|
+
>>> assert result_2.numeric_value == result_1.numeric_value
|
|
1793
|
+
>>> assert result_2.unit_system == "Length"
|
|
1794
|
+
|
|
1795
|
+
Multiply voltage times current to obtain power.
|
|
1796
|
+
|
|
1797
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1798
|
+
>>> v3 = Variable("3mA")
|
|
1799
|
+
>>> v4 = Variable("40V")
|
|
1800
|
+
>>> result_3 = v3 * v4
|
|
1801
|
+
>>> assert result_3.numeric_value == 0.12
|
|
1802
|
+
>>> assert result_3.units == "W"
|
|
1803
|
+
>>> assert result_3.unit_system == "Power"
|
|
1802
1804
|
|
|
1803
1805
|
"""
|
|
1804
1806
|
assert is_number(other) or isinstance(other, Variable), "Multiplier must be a scalar quantity or a variable."
|
|
@@ -1836,7 +1838,7 @@ class Variable(object):
|
|
|
1836
1838
|
Examples
|
|
1837
1839
|
--------
|
|
1838
1840
|
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1839
|
-
>>> import
|
|
1841
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1840
1842
|
>>> v1 = Variable("3mA")
|
|
1841
1843
|
>>> v2 = Variable("10A")
|
|
1842
1844
|
>>> result = v1 + v2
|
|
@@ -1876,7 +1878,7 @@ class Variable(object):
|
|
|
1876
1878
|
Examples
|
|
1877
1879
|
--------
|
|
1878
1880
|
|
|
1879
|
-
>>> import
|
|
1881
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1880
1882
|
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1881
1883
|
>>> v3 = Variable("3mA")
|
|
1882
1884
|
>>> v4 = Variable("10A")
|
|
@@ -1922,7 +1924,7 @@ class Variable(object):
|
|
|
1922
1924
|
resolve the new units to ``"A"``.
|
|
1923
1925
|
|
|
1924
1926
|
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1925
|
-
>>> import
|
|
1927
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1926
1928
|
>>> v1 = Variable("10W")
|
|
1927
1929
|
>>> v2 = Variable("40V")
|
|
1928
1930
|
>>> result = v1 / v2
|
|
@@ -1964,7 +1966,7 @@ class Variable(object):
|
|
|
1964
1966
|
Divide a number by a variable with units ``"s"`` and automatically determine that
|
|
1965
1967
|
the result is in ``"Hz"``.
|
|
1966
1968
|
|
|
1967
|
-
>>> import
|
|
1969
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1968
1970
|
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1969
1971
|
>>> v = Variable("1s")
|
|
1970
1972
|
>>> result = 3.0 / v
|
|
@@ -47,6 +47,27 @@ class Connectable(LayoutObj):
|
|
|
47
47
|
net = self._pedb.nets[value]
|
|
48
48
|
self._edb_object.SetNet(net.net_object)
|
|
49
49
|
|
|
50
|
+
@property
|
|
51
|
+
def net_name(self):
|
|
52
|
+
"""Get the primitive layer name.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
str
|
|
57
|
+
"""
|
|
58
|
+
try:
|
|
59
|
+
return self._edb_object.GetNet().GetName()
|
|
60
|
+
except (KeyError, AttributeError): # pragma: no cover
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
@net_name.setter
|
|
64
|
+
def net_name(self, name):
|
|
65
|
+
if name in self._pedb.nets.netlist:
|
|
66
|
+
obj = self._pedb.nets.nets[name].net_object
|
|
67
|
+
self._edb_object.SetNet(obj)
|
|
68
|
+
else:
|
|
69
|
+
raise ValueError(f"Net {name} not found.")
|
|
70
|
+
|
|
50
71
|
@property
|
|
51
72
|
def component(self):
|
|
52
73
|
"""Component connected to this object.
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
import logging
|
|
24
24
|
import re
|
|
25
|
+
from typing import Optional
|
|
25
26
|
import warnings
|
|
26
27
|
|
|
27
28
|
from pyedb.dotnet.edb_core.cell.hierarchy.hierarchy_obj import Group
|
|
@@ -61,6 +62,15 @@ class EDBComponent(Group):
|
|
|
61
62
|
self._layout_instance = None
|
|
62
63
|
self._comp_instance = None
|
|
63
64
|
|
|
65
|
+
@property
|
|
66
|
+
def name(self):
|
|
67
|
+
"""Name of the definition."""
|
|
68
|
+
return self._edb_object.GetName()
|
|
69
|
+
|
|
70
|
+
@name.setter
|
|
71
|
+
def name(self, value):
|
|
72
|
+
self._edb_object.SetName(value)
|
|
73
|
+
|
|
64
74
|
@property
|
|
65
75
|
def group_type(self):
|
|
66
76
|
return self._edb_object.ToString().split(".")[-1].lower()
|
|
@@ -808,7 +818,13 @@ class EDBComponent(Group):
|
|
|
808
818
|
return False
|
|
809
819
|
return True
|
|
810
820
|
|
|
811
|
-
def assign_spice_model(
|
|
821
|
+
def assign_spice_model(
|
|
822
|
+
self,
|
|
823
|
+
file_path: str,
|
|
824
|
+
name: Optional[str] = None,
|
|
825
|
+
sub_circuit_name: Optional[str] = None,
|
|
826
|
+
terminal_pairs: Optional[list] = None,
|
|
827
|
+
):
|
|
812
828
|
"""Assign Spice model to this component.
|
|
813
829
|
|
|
814
830
|
Parameters
|
|
@@ -817,6 +833,10 @@ class EDBComponent(Group):
|
|
|
817
833
|
File path of the Spice model.
|
|
818
834
|
name : str, optional
|
|
819
835
|
Name of the Spice model.
|
|
836
|
+
sub_circuit_name : str, optional
|
|
837
|
+
Name of the sub circuit.
|
|
838
|
+
terminal_pairs : list, optional
|
|
839
|
+
list of terminal pairs.
|
|
820
840
|
|
|
821
841
|
Returns
|
|
822
842
|
-------
|
|
@@ -828,23 +848,30 @@ class EDBComponent(Group):
|
|
|
828
848
|
with open(file_path, "r") as f:
|
|
829
849
|
for line in f:
|
|
830
850
|
if "subckt" in line.lower():
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
851
|
+
pin_names_sp = [i.strip() for i in re.split(" |\t", line) if i]
|
|
852
|
+
pin_names_sp.remove(pin_names_sp[0])
|
|
853
|
+
pin_names_sp.remove(pin_names_sp[0])
|
|
834
854
|
break
|
|
835
|
-
if len(
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
855
|
+
if not len(pin_names_sp) == self.numpins: # pragma: no cover
|
|
856
|
+
raise ValueError(f"Pin counts doesn't match component {self.name}.")
|
|
857
|
+
|
|
858
|
+
model = self._edb.cell.hierarchy._hierarchy.SPICEModel()
|
|
859
|
+
model.SetModelPath(file_path)
|
|
860
|
+
model.SetModelName(name)
|
|
861
|
+
if sub_circuit_name:
|
|
862
|
+
model.SetSubCkt(sub_circuit_name)
|
|
863
|
+
|
|
864
|
+
if terminal_pairs:
|
|
865
|
+
terminal_pairs = terminal_pairs if isinstance(terminal_pairs[0], list) else [terminal_pairs]
|
|
866
|
+
for pair in terminal_pairs:
|
|
867
|
+
pname, pnumber = pair
|
|
868
|
+
if pname not in pin_names_sp: # pragma: no cover
|
|
869
|
+
raise ValueError(f"Pin name {pname} doesn't exist in {file_path}.")
|
|
870
|
+
model.AddTerminalPinPair(pname, str(pnumber))
|
|
871
|
+
else:
|
|
872
|
+
for idx, pname in enumerate(pin_names_sp):
|
|
873
|
+
model.AddTerminalPinPair(pname, str(idx + 1))
|
|
874
|
+
|
|
848
875
|
return self._set_model(model)
|
|
849
876
|
|
|
850
877
|
def assign_s_param_model(self, file_path, name=None, reference_net=None):
|
|
@@ -856,7 +883,8 @@ class EDBComponent(Group):
|
|
|
856
883
|
File path of the S-parameter model.
|
|
857
884
|
name : str, optional
|
|
858
885
|
Name of the S-parameter model.
|
|
859
|
-
|
|
886
|
+
reference_net : str, optional
|
|
887
|
+
Name of the reference net.
|
|
860
888
|
Returns
|
|
861
889
|
-------
|
|
862
890
|
|
|
@@ -54,6 +54,29 @@ from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
|
|
|
54
54
|
from pyedb.dotnet.edb_core.utilities.obj_base import ObjBase
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
def primitive_cast(pedb, edb_object):
|
|
58
|
+
if edb_object.GetPrimitiveType().ToString() == "Rectangle":
|
|
59
|
+
return EdbRectangle(edb_object, pedb)
|
|
60
|
+
elif edb_object.GetPrimitiveType().ToString() == "Circle":
|
|
61
|
+
return EdbCircle(edb_object, pedb)
|
|
62
|
+
elif edb_object.GetPrimitiveType().ToString() == "Polygon":
|
|
63
|
+
return EdbPolygon(edb_object, pedb)
|
|
64
|
+
elif edb_object.GetPrimitiveType().ToString() == "Path":
|
|
65
|
+
return Path(pedb, edb_object)
|
|
66
|
+
elif edb_object.GetPrimitiveType().ToString() == "Bondwire":
|
|
67
|
+
return Bondwire(pedb, edb_object)
|
|
68
|
+
elif edb_object.GetPrimitiveType().ToString() == "Text":
|
|
69
|
+
return EdbText(edb_object, pedb)
|
|
70
|
+
elif edb_object.GetPrimitiveType().ToString() == "PrimitivePlugin":
|
|
71
|
+
return
|
|
72
|
+
elif edb_object.GetPrimitiveType().ToString() == "Path3D":
|
|
73
|
+
return
|
|
74
|
+
elif edb_object.GetPrimitiveType().ToString() == "BoardBendDef":
|
|
75
|
+
return
|
|
76
|
+
else:
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
|
|
57
80
|
class Layout(ObjBase):
|
|
58
81
|
def __init__(self, pedb, edb_object):
|
|
59
82
|
super().__init__(pedb, edb_object)
|
|
@@ -209,7 +232,7 @@ class Layout(ObjBase):
|
|
|
209
232
|
"""
|
|
210
233
|
prims = []
|
|
211
234
|
for p in self._edb_object.Primitives:
|
|
212
|
-
obj = self.
|
|
235
|
+
obj = primitive_cast(self._pedb, p)
|
|
213
236
|
prims.append(obj)
|
|
214
237
|
return prims
|
|
215
238
|
|
|
@@ -285,26 +308,7 @@ class Layout(ObjBase):
|
|
|
285
308
|
return EDBPadstackInstance(obj, self._pedb)
|
|
286
309
|
|
|
287
310
|
if obj.GetObjType().ToString() == "Primitive":
|
|
288
|
-
|
|
289
|
-
return EdbRectangle(obj, self._pedb)
|
|
290
|
-
elif obj.GetPrimitiveType().ToString() == "Circle":
|
|
291
|
-
return EdbCircle(obj, self._pedb)
|
|
292
|
-
elif obj.GetPrimitiveType().ToString() == "Polygon":
|
|
293
|
-
return EdbPolygon(obj, self._pedb)
|
|
294
|
-
elif obj.GetPrimitiveType().ToString() == "Path":
|
|
295
|
-
return Path(self._pedb, obj)
|
|
296
|
-
elif obj.GetPrimitiveType().ToString() == "Bondwire":
|
|
297
|
-
return Bondwire(self._pedb, obj)
|
|
298
|
-
elif obj.GetPrimitiveType().ToString() == "Text":
|
|
299
|
-
return EdbText(obj, self._pedb)
|
|
300
|
-
elif obj.GetPrimitiveType().ToString() == "PrimitivePlugin":
|
|
301
|
-
pass
|
|
302
|
-
elif obj.GetPrimitiveType().ToString() == "Path3D":
|
|
303
|
-
pass
|
|
304
|
-
elif obj.GetPrimitiveType().ToString() == "BoardBendDef":
|
|
305
|
-
pass
|
|
306
|
-
else:
|
|
307
|
-
pass
|
|
311
|
+
return primitive_cast(self._pedb, obj)
|
|
308
312
|
|
|
309
313
|
def find_net_by_name(self, value: str):
|
|
310
314
|
"""Find a net object by name
|
|
@@ -319,7 +323,10 @@ class Layout(ObjBase):
|
|
|
319
323
|
|
|
320
324
|
"""
|
|
321
325
|
obj = self._pedb._edb.Cell.Net.FindByName(self._edb_object, value)
|
|
322
|
-
|
|
326
|
+
if obj.IsNull():
|
|
327
|
+
raise ValueError(f"Net {value} doesn't exist")
|
|
328
|
+
else:
|
|
329
|
+
return EDBNetsData(obj, self._pedb)
|
|
323
330
|
|
|
324
331
|
def find_component_by_name(self, value: str):
|
|
325
332
|
"""Find a component object by name. Component name is the reference designator in layout.
|
|
@@ -89,27 +89,6 @@ class Primitive(Connectable):
|
|
|
89
89
|
"""
|
|
90
90
|
return self._edb_object.GetPrimitiveType().ToString().lower()
|
|
91
91
|
|
|
92
|
-
@property
|
|
93
|
-
def net_name(self):
|
|
94
|
-
"""Get the primitive net name.
|
|
95
|
-
|
|
96
|
-
Returns
|
|
97
|
-
-------
|
|
98
|
-
str
|
|
99
|
-
"""
|
|
100
|
-
return self.net.name
|
|
101
|
-
|
|
102
|
-
@net_name.setter
|
|
103
|
-
def net_name(self, name):
|
|
104
|
-
if isinstance(name, str):
|
|
105
|
-
net = self._app.nets.nets[name].net_object
|
|
106
|
-
self.primitive_object.SetNet(net)
|
|
107
|
-
else:
|
|
108
|
-
try:
|
|
109
|
-
self.net = name.name
|
|
110
|
-
except: # pragma: no cover
|
|
111
|
-
self._app.logger.error("Failed to set net name.")
|
|
112
|
-
|
|
113
92
|
@property
|
|
114
93
|
def layer(self):
|
|
115
94
|
"""Get the primitive edb layer object."""
|
|
@@ -128,7 +107,7 @@ class Primitive(Connectable):
|
|
|
128
107
|
str
|
|
129
108
|
"""
|
|
130
109
|
try:
|
|
131
|
-
return self.
|
|
110
|
+
return self._edb_object.GetLayer().GetName()
|
|
132
111
|
except (KeyError, AttributeError): # pragma: no cover
|
|
133
112
|
return None
|
|
134
113
|
|
|
@@ -47,10 +47,10 @@ class PinGroupTerminal(Terminal):
|
|
|
47
47
|
-------
|
|
48
48
|
:class:`pyedb.dotnet.edb_core.edb_data.terminals.PinGroupTerminal`
|
|
49
49
|
"""
|
|
50
|
-
net_obj = self._pedb.
|
|
50
|
+
net_obj = self._pedb.layout.find_net_by_name(net_name)
|
|
51
51
|
term = self._pedb.edb_api.cell.terminal.PinGroupTerminal.Create(
|
|
52
52
|
self._pedb.active_layout,
|
|
53
|
-
net_obj.
|
|
53
|
+
net_obj._edb_object,
|
|
54
54
|
name,
|
|
55
55
|
self._pedb.siwave.pin_groups[pin_group_name]._edb_object,
|
|
56
56
|
is_ref,
|
|
@@ -60,7 +60,7 @@ class PinGroupTerminal(Terminal):
|
|
|
60
60
|
msg = f"Failed to create terminal. "
|
|
61
61
|
if name in self._pedb.terminals:
|
|
62
62
|
msg += f"Terminal {name} already exists."
|
|
63
|
-
raise
|
|
63
|
+
raise ValueError(msg)
|
|
64
64
|
else:
|
|
65
65
|
return term
|
|
66
66
|
|