pyedb 0.23.0__py3-none-any.whl → 0.25.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/component_libraries/ansys_components.py +48 -2
- pyedb/configuration/cfg_operations.py +38 -4
- pyedb/configuration/cfg_ports_sources.py +16 -2
- pyedb/configuration/configuration.py +8 -0
- pyedb/dotnet/edb.py +39 -37
- pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py +11 -0
- pyedb/dotnet/edb_core/cell/layout.py +47 -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 +2 -2
- pyedb/dotnet/edb_core/components.py +48 -25
- 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 +10 -24
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +56 -868
- pyedb/dotnet/edb_core/geometry/polygon_data.py +43 -0
- pyedb/dotnet/edb_core/hfss.py +26 -22
- pyedb/dotnet/edb_core/layout_validation.py +3 -3
- pyedb/dotnet/edb_core/modeler.py +64 -81
- pyedb/dotnet/edb_core/nets.py +5 -4
- pyedb/dotnet/edb_core/padstack.py +12 -13
- pyedb/dotnet/edb_core/siwave.py +1 -1
- pyedb/dotnet/edb_core/stackup.py +3 -3
- 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 +2 -2
- pyedb/siwave.py +99 -0
- {pyedb-0.23.0.dist-info → pyedb-0.25.0.dist-info}/METADATA +4 -4
- {pyedb-0.23.0.dist-info → pyedb-0.25.0.dist-info}/RECORD +38 -35
- {pyedb-0.23.0.dist-info → pyedb-0.25.0.dist-info}/LICENSE +0 -0
- {pyedb-0.23.0.dist-info → pyedb-0.25.0.dist-info}/WHEEL +0 -0
pyedb/__init__.py
CHANGED
|
@@ -33,16 +33,62 @@ class ComponentPart:
|
|
|
33
33
|
self.nb_freq = 0
|
|
34
34
|
self.ref_impedance = 50.0
|
|
35
35
|
self._s_parameters = None
|
|
36
|
+
self.type = ""
|
|
36
37
|
|
|
37
38
|
@property
|
|
38
39
|
def s_parameters(self):
|
|
39
|
-
"""Return skrf.network.Network object
|
|
40
|
-
|
|
40
|
+
"""Return a skrf.network.Network object.
|
|
41
|
+
|
|
42
|
+
See `scikit-rf documentation <https://scikit-rf.readthedocs.io/en/latest/api/network.html#network-class>`_.
|
|
41
43
|
"""
|
|
42
44
|
if not self._s_parameters:
|
|
43
45
|
self._extract_impedance()
|
|
44
46
|
return self._s_parameters
|
|
45
47
|
|
|
48
|
+
@property
|
|
49
|
+
def esr(self):
|
|
50
|
+
"""Return the equivalent serial resistor for capacitor only."""
|
|
51
|
+
if self.type == "Capacitor":
|
|
52
|
+
z11 = 1 / self.s_parameters.y[:, 0, 0]
|
|
53
|
+
return np.abs(abs(np.abs(np.real((z11.min()))) - 50))
|
|
54
|
+
else:
|
|
55
|
+
return 0.0
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def f0(self):
|
|
59
|
+
"""Return the capacitor self resonant frequency in Hz."""
|
|
60
|
+
if self.type == "Capacitor":
|
|
61
|
+
z11 = 1 / self.s_parameters.y[:, 0, 0]
|
|
62
|
+
fo_index = np.where(np.abs(z11) == np.min(np.abs(z11)))[0][0]
|
|
63
|
+
return self.s_parameters.f[fo_index]
|
|
64
|
+
else:
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def esl(self):
|
|
69
|
+
"""Return the equivalent serial inductor for capacitor only."""
|
|
70
|
+
if self.type == "Capacitor":
|
|
71
|
+
omega_r = 2 * np.pi * self.f0
|
|
72
|
+
return 1 / (np.power(omega_r, 2) * self.cap_value)
|
|
73
|
+
else:
|
|
74
|
+
return 0.0
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def cap_value(self):
|
|
78
|
+
"""Returns the capacitance value."""
|
|
79
|
+
if self.type == "Capacitor":
|
|
80
|
+
return round(np.imag(self.s_parameters.y[0, 0, 0]) / (2 * np.pi * self._s_parameters.f[0]), 15)
|
|
81
|
+
else:
|
|
82
|
+
return 0.0
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def ind_value(self):
|
|
86
|
+
"""Return the inductance value."""
|
|
87
|
+
if self.type == "Inductor":
|
|
88
|
+
return round(np.imag(1 / self.s_parameters.y[0, 0, 0]) / (2 * np.pi * self._s_parameters.f[0]), 15)
|
|
89
|
+
else:
|
|
90
|
+
return 0.0
|
|
91
|
+
|
|
46
92
|
def _extract_impedance(self):
|
|
47
93
|
with open(self._sbin_file, mode="rb") as file:
|
|
48
94
|
file_content = file.read()
|
|
@@ -24,7 +24,9 @@ from pyedb.configuration.cfg_common import CfgBase
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class CfgCutout(CfgBase):
|
|
27
|
-
def __init__(self, **kwargs):
|
|
27
|
+
def __init__(self, pedb, **kwargs):
|
|
28
|
+
self._pedb = pedb
|
|
29
|
+
|
|
28
30
|
self.signal_list = kwargs.get("signal_list")
|
|
29
31
|
self.reference_list = kwargs.get("reference_list")
|
|
30
32
|
self.extent_type = kwargs.get("extent_type")
|
|
@@ -38,7 +40,7 @@ class CfgCutout(CfgBase):
|
|
|
38
40
|
self.extent_defeature = kwargs.get("extent_defeature")
|
|
39
41
|
self.remove_single_pin_components = kwargs.get("remove_single_pin_components")
|
|
40
42
|
self.custom_extent = kwargs.get("custom_extent")
|
|
41
|
-
self.custom_extent_units = kwargs.get("custom_extent_units")
|
|
43
|
+
self.custom_extent_units = kwargs.get("custom_extent_units", "meter")
|
|
42
44
|
self.include_partial_instances = kwargs.get("include_partial_instances")
|
|
43
45
|
self.keep_voids = kwargs.get("keep_voids")
|
|
44
46
|
self.check_terminals = kwargs.get("check_terminals")
|
|
@@ -49,13 +51,45 @@ class CfgCutout(CfgBase):
|
|
|
49
51
|
self.simple_pad_check = kwargs.get("simple_pad_check")
|
|
50
52
|
self.keep_lines_as_path = kwargs.get("keep_lines_as_path")
|
|
51
53
|
|
|
54
|
+
def get_data_from_db(self):
|
|
55
|
+
if "pyedb_cutout" in self._pedb.stackup.all_layers:
|
|
56
|
+
poly = self._pedb.layout.find_primitive(layer_name="pyedb_cutout")[0]
|
|
57
|
+
self.custom_extent = poly.polygon_data.points
|
|
58
|
+
|
|
59
|
+
net_names = []
|
|
60
|
+
for name, obj in self._pedb.nets.nets.items():
|
|
61
|
+
if obj.primitives[0].layer.name == "pyedb_cutout":
|
|
62
|
+
continue
|
|
63
|
+
if len(obj.primitives) > 0:
|
|
64
|
+
net_names.append(name)
|
|
65
|
+
|
|
66
|
+
self.reference_list = []
|
|
67
|
+
self.signal_list = net_names
|
|
68
|
+
return self.export_properties()
|
|
69
|
+
|
|
70
|
+
def export_properties(self):
|
|
71
|
+
return {
|
|
72
|
+
"signal_list": self.signal_list,
|
|
73
|
+
"reference_list": self.reference_list,
|
|
74
|
+
"custom_extent": self.custom_extent,
|
|
75
|
+
}
|
|
76
|
+
|
|
52
77
|
|
|
53
78
|
class CfgOperations(CfgBase):
|
|
54
79
|
def __init__(self, pedb, data):
|
|
55
80
|
self._pedb = pedb
|
|
56
|
-
self.op_cutout = CfgCutout(**data["cutout"]) if "cutout" in data else None
|
|
81
|
+
self.op_cutout = CfgCutout(pedb, **data["cutout"]) if "cutout" in data else None
|
|
57
82
|
|
|
58
83
|
def apply(self):
|
|
59
84
|
"""Imports operation information from JSON."""
|
|
60
85
|
if self.op_cutout:
|
|
61
|
-
self._pedb.cutout(**self.op_cutout.get_attributes())
|
|
86
|
+
polygon_points = self._pedb.cutout(**self.op_cutout.get_attributes())
|
|
87
|
+
if not "pyedb_cutout" in self._pedb.stackup.all_layers:
|
|
88
|
+
self._pedb.stackup.add_document_layer(name="pyedb_cutout")
|
|
89
|
+
self._pedb.modeler.create_polygon(polygon_points, layer_name="pyedb_cutout", net_name="pyedb_cutout")
|
|
90
|
+
|
|
91
|
+
# create a polygon on pyedb layer
|
|
92
|
+
|
|
93
|
+
def get_data_from_db(self):
|
|
94
|
+
self.op_cutout = CfgCutout(self._pedb)
|
|
95
|
+
return {"cutout": self.op_cutout.get_data_from_db()}
|
|
@@ -45,7 +45,7 @@ class CfgCoordianteTerminalInfo(CfgTerminalInfo):
|
|
|
45
45
|
self.net = self.value["net"]
|
|
46
46
|
|
|
47
47
|
def export_properties(self):
|
|
48
|
-
return {"layer": self.layer, "
|
|
48
|
+
return {"coordinates": {"layer": self.layer, "point": [self.point_x, self.point_y], "net": self.net}}
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
class CfgNearestPinTerminalInfo(CfgTerminalInfo):
|
|
@@ -126,7 +126,10 @@ class CfgPorts:
|
|
|
126
126
|
ports = {name: t for name, t in ports.items() if t.is_port}
|
|
127
127
|
|
|
128
128
|
for _, p in ports.items():
|
|
129
|
-
|
|
129
|
+
if not p.ref_terminal:
|
|
130
|
+
port_type = "coax"
|
|
131
|
+
else:
|
|
132
|
+
port_type = "circuit"
|
|
130
133
|
|
|
131
134
|
if p.terminal_type == "PinGroupTerminal":
|
|
132
135
|
refdes = ""
|
|
@@ -135,6 +138,9 @@ class CfgPorts:
|
|
|
135
138
|
elif p.terminal_type == "PadstackInstanceTerminal":
|
|
136
139
|
refdes = p.component.refdes if p.component else ""
|
|
137
140
|
pos_term_info = {"pin": p.padstack_instance.component_pin}
|
|
141
|
+
elif p.terminal_type == "PointTerminal":
|
|
142
|
+
refdes = ""
|
|
143
|
+
pos_term_info = {"coordinates": {"layer": p.layer.name, "point": p.location, "net": p.net.name}}
|
|
138
144
|
|
|
139
145
|
if port_type == "circuit":
|
|
140
146
|
neg_term = self._pedb.terminals[p.ref_terminal.name]
|
|
@@ -143,6 +149,14 @@ class CfgPorts:
|
|
|
143
149
|
neg_term_info = {"pin_group": pg.name}
|
|
144
150
|
elif neg_term.terminal_type == "PadstackInstanceTerminal":
|
|
145
151
|
neg_term_info = {"pin": neg_term.padstack_instance.component_pin}
|
|
152
|
+
elif neg_term.terminal_type == "PointTerminal":
|
|
153
|
+
neg_term_info = {
|
|
154
|
+
"coordinates": {
|
|
155
|
+
"layer": neg_term.layer.name,
|
|
156
|
+
"point": neg_term.location,
|
|
157
|
+
"net": neg_term.net.name,
|
|
158
|
+
}
|
|
159
|
+
}
|
|
146
160
|
|
|
147
161
|
cfg_port = CfgPort(
|
|
148
162
|
self._pedb,
|
|
@@ -280,6 +280,8 @@ class Configuration:
|
|
|
280
280
|
data["nets"] = self.cfg_data.nets.get_data_from_db()
|
|
281
281
|
if kwargs.get("pin_groups", False):
|
|
282
282
|
data["pin_groups"] = self.cfg_data.pin_groups.get_data_from_db()
|
|
283
|
+
if kwargs.get("operations", False):
|
|
284
|
+
data["operations"] = self.cfg_data.operations.get_data_from_db()
|
|
283
285
|
|
|
284
286
|
return data
|
|
285
287
|
|
|
@@ -293,6 +295,7 @@ class Configuration:
|
|
|
293
295
|
ports=True,
|
|
294
296
|
nets=True,
|
|
295
297
|
pin_groups=True,
|
|
298
|
+
operations=True,
|
|
296
299
|
):
|
|
297
300
|
"""Export the configuration data from layout to a file.
|
|
298
301
|
|
|
@@ -312,6 +315,10 @@ class Configuration:
|
|
|
312
315
|
Whether to export ports or not.
|
|
313
316
|
nets : bool
|
|
314
317
|
Whether to export nets.
|
|
318
|
+
pin_groups : bool
|
|
319
|
+
Whether to export pin groups.
|
|
320
|
+
operations : bool
|
|
321
|
+
Whether to export operations.
|
|
315
322
|
Returns
|
|
316
323
|
-------
|
|
317
324
|
bool
|
|
@@ -326,6 +333,7 @@ class Configuration:
|
|
|
326
333
|
ports=ports,
|
|
327
334
|
nets=nets,
|
|
328
335
|
pin_groups=pin_groups,
|
|
336
|
+
operations=operations,
|
|
329
337
|
)
|
|
330
338
|
with open(file_path, "w") as f:
|
|
331
339
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
pyedb/dotnet/edb.py
CHANGED
|
@@ -454,13 +454,13 @@ class Edb(Database):
|
|
|
454
454
|
@property
|
|
455
455
|
def excitations(self):
|
|
456
456
|
"""Get all layout excitations."""
|
|
457
|
-
terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) == 0]
|
|
457
|
+
terms = [term for term in self.layout.terminals if int(term._edb_object.GetBoundaryType()) == 0]
|
|
458
458
|
temp = {}
|
|
459
459
|
for ter in terms:
|
|
460
|
-
if "BundleTerminal" in ter.GetType().ToString():
|
|
461
|
-
temp[ter.
|
|
460
|
+
if "BundleTerminal" in ter._edb_object.GetType().ToString():
|
|
461
|
+
temp[ter.name] = BundleWavePort(self, ter._edb_object)
|
|
462
462
|
else:
|
|
463
|
-
temp[ter.
|
|
463
|
+
temp[ter.name] = GapPort(self, ter._edb_object)
|
|
464
464
|
return temp
|
|
465
465
|
|
|
466
466
|
@property
|
|
@@ -473,41 +473,41 @@ class Edb(Database):
|
|
|
473
473
|
:class:`pyedb.dotnet.edb_core.edb_data.ports.WavePort`,]]
|
|
474
474
|
|
|
475
475
|
"""
|
|
476
|
-
temp = [term for term in self.layout.terminals if not term.
|
|
476
|
+
temp = [term for term in self.layout.terminals if not term.is_reference_terminal]
|
|
477
477
|
|
|
478
478
|
ports = {}
|
|
479
479
|
for t in temp:
|
|
480
|
-
t2 = Terminal(self, t)
|
|
480
|
+
t2 = Terminal(self, t._edb_object)
|
|
481
481
|
if not t2.boundary_type == "PortBoundary":
|
|
482
482
|
continue
|
|
483
483
|
|
|
484
484
|
if t2.is_circuit_port:
|
|
485
|
-
port = CircuitPort(self, t)
|
|
485
|
+
port = CircuitPort(self, t._edb_object)
|
|
486
486
|
ports[port.name] = port
|
|
487
487
|
elif t2.terminal_type == "BundleTerminal":
|
|
488
|
-
port = BundleWavePort(self, t)
|
|
488
|
+
port = BundleWavePort(self, t._edb_object)
|
|
489
489
|
ports[port.name] = port
|
|
490
490
|
elif t2.hfss_type == "Wave":
|
|
491
|
-
ports[t2.name] = WavePort(self, t)
|
|
491
|
+
ports[t2.name] = WavePort(self, t._edb_object)
|
|
492
492
|
elif t2.terminal_type == "PadstackInstanceTerminal":
|
|
493
|
-
ports[t2.name] = CoaxPort(self, t)
|
|
493
|
+
ports[t2.name] = CoaxPort(self, t._edb_object)
|
|
494
494
|
else:
|
|
495
|
-
ports[t2.name] = GapPort(self, t)
|
|
495
|
+
ports[t2.name] = GapPort(self, t._edb_object)
|
|
496
496
|
return ports
|
|
497
497
|
|
|
498
498
|
@property
|
|
499
499
|
def excitations_nets(self):
|
|
500
500
|
"""Get all excitations net names."""
|
|
501
|
-
names = list(set([i.
|
|
501
|
+
names = list(set([i.net.name for i in self.layout.terminals]))
|
|
502
502
|
names = [i for i in names if i]
|
|
503
503
|
return names
|
|
504
504
|
|
|
505
505
|
@property
|
|
506
506
|
def sources(self):
|
|
507
507
|
"""Get all layout sources."""
|
|
508
|
-
terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [3, 4, 7]]
|
|
509
|
-
terms = [term for term in terms if not term.IsReferenceTerminal()]
|
|
510
|
-
return {ter.
|
|
508
|
+
terms = [term for term in self.layout.terminals if int(term._edb_object.GetBoundaryType()) in [3, 4, 7]]
|
|
509
|
+
terms = [term for term in terms if not term._edb_object.IsReferenceTerminal()]
|
|
510
|
+
return {ter.name: ExcitationSources(self, ter._edb_object) for ter in terms}
|
|
511
511
|
|
|
512
512
|
@property
|
|
513
513
|
def voltage_regulator_modules(self):
|
|
@@ -1167,9 +1167,9 @@ class Edb(Database):
|
|
|
1167
1167
|
elif obj_type == LayoutObjType.Primitive.name:
|
|
1168
1168
|
prim_type = i.GetPrimitiveType().ToString()
|
|
1169
1169
|
if prim_type == Primitives.Path.name:
|
|
1170
|
-
from pyedb.dotnet.edb_core.
|
|
1170
|
+
from pyedb.dotnet.edb_core.cell.primitive.path import Path
|
|
1171
1171
|
|
|
1172
|
-
temp.append(
|
|
1172
|
+
temp.append(Path(self, i))
|
|
1173
1173
|
elif prim_type == Primitives.Rectangle.name:
|
|
1174
1174
|
from pyedb.dotnet.edb_core.edb_data.primitives_data import (
|
|
1175
1175
|
EdbRectangle,
|
|
@@ -1602,7 +1602,7 @@ class Edb(Database):
|
|
|
1602
1602
|
names = []
|
|
1603
1603
|
_polys = []
|
|
1604
1604
|
for net in net_signals:
|
|
1605
|
-
names.append(net.
|
|
1605
|
+
names.append(net.name)
|
|
1606
1606
|
if pins_to_preserve:
|
|
1607
1607
|
insts = self.padstacks.instances
|
|
1608
1608
|
for i in pins_to_preserve:
|
|
@@ -1669,11 +1669,11 @@ class Edb(Database):
|
|
|
1669
1669
|
from pyedb.dotnet.clr_module import Tuple
|
|
1670
1670
|
|
|
1671
1671
|
_polys = []
|
|
1672
|
-
terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [0, 3, 4, 7, 8]]
|
|
1672
|
+
terms = [term for term in self.layout.terminals if int(term._edb_object.GetBoundaryType()) in [0, 3, 4, 7, 8]]
|
|
1673
1673
|
locations = []
|
|
1674
1674
|
for term in terms:
|
|
1675
|
-
if term.GetTerminalType().ToString() == "PointTerminal" and term.
|
|
1676
|
-
pd = term.GetParameters()[1]
|
|
1675
|
+
if term._edb_object.GetTerminalType().ToString() == "PointTerminal" and term.net.name in reference_list:
|
|
1676
|
+
pd = term._edb_object.GetParameters()[1]
|
|
1677
1677
|
locations.append([pd.X.ToDouble(), pd.Y.ToDouble()])
|
|
1678
1678
|
for point in locations:
|
|
1679
1679
|
pointA = self.edb_api.geometry.point_data(
|
|
@@ -1706,7 +1706,7 @@ class Edb(Database):
|
|
|
1706
1706
|
names = []
|
|
1707
1707
|
_polys = []
|
|
1708
1708
|
for net in net_signals:
|
|
1709
|
-
names.append(net.
|
|
1709
|
+
names.append(net.name)
|
|
1710
1710
|
if pins_to_preserve:
|
|
1711
1711
|
insts = self.padstacks.instances
|
|
1712
1712
|
for i in pins_to_preserve:
|
|
@@ -1994,7 +1994,7 @@ class Edb(Database):
|
|
|
1994
1994
|
expansion_size = self.edb_value(expansion_size).ToDouble()
|
|
1995
1995
|
|
|
1996
1996
|
# validate nets in layout
|
|
1997
|
-
net_signals = [net
|
|
1997
|
+
net_signals = [net for net in self.layout.nets if net.name in signal_list]
|
|
1998
1998
|
|
|
1999
1999
|
# validate references in layout
|
|
2000
2000
|
_netsClip = convert_py_list_to_net_list(
|
|
@@ -2214,11 +2214,13 @@ class Edb(Database):
|
|
|
2214
2214
|
if pin.pingroups:
|
|
2215
2215
|
pins_to_preserve.append(pin.id)
|
|
2216
2216
|
if check_terminals:
|
|
2217
|
-
terms = [
|
|
2217
|
+
terms = [
|
|
2218
|
+
term for term in self.layout.terminals if int(term._edb_object.GetBoundaryType()) in [0, 3, 4, 7, 8]
|
|
2219
|
+
]
|
|
2218
2220
|
for term in terms:
|
|
2219
|
-
if term.GetTerminalType().ToString() == "PadstackInstanceTerminal":
|
|
2220
|
-
if term.GetParameters()[1].GetNet().GetName() in reference_list:
|
|
2221
|
-
pins_to_preserve.append(term.GetParameters()[1].GetId())
|
|
2221
|
+
if term._edb_object.GetTerminalType().ToString() == "PadstackInstanceTerminal":
|
|
2222
|
+
if term._edb_object.GetParameters()[1].GetNet().GetName() in reference_list:
|
|
2223
|
+
pins_to_preserve.append(term._edb_object.GetParameters()[1].GetId())
|
|
2222
2224
|
|
|
2223
2225
|
for i in self.nets.nets.values():
|
|
2224
2226
|
name = i.name
|
|
@@ -2262,7 +2264,7 @@ class Edb(Database):
|
|
|
2262
2264
|
elif custom_extent:
|
|
2263
2265
|
_poly = custom_extent
|
|
2264
2266
|
else:
|
|
2265
|
-
net_signals = [net
|
|
2267
|
+
net_signals = [net for net in self.layout.nets if net.name in signal_list]
|
|
2266
2268
|
_poly = self._create_extent(
|
|
2267
2269
|
net_signals,
|
|
2268
2270
|
extent_type,
|
|
@@ -2309,7 +2311,7 @@ class Edb(Database):
|
|
|
2309
2311
|
return poly.Subtract(convert_py_list_to_net_list(poly), convert_py_list_to_net_list(voids))
|
|
2310
2312
|
|
|
2311
2313
|
def clip_path(path):
|
|
2312
|
-
pdata = path.polygon_data.
|
|
2314
|
+
pdata = path.polygon_data._edb_object
|
|
2313
2315
|
int_data = _poly.GetIntersectionType(pdata)
|
|
2314
2316
|
if int_data == 0:
|
|
2315
2317
|
prims_to_delete.append(path)
|
|
@@ -2320,7 +2322,7 @@ class Edb(Database):
|
|
|
2320
2322
|
reference_prims.append(path)
|
|
2321
2323
|
|
|
2322
2324
|
def clean_prim(prim_1): # pragma: no cover
|
|
2323
|
-
pdata = prim_1.polygon_data.
|
|
2325
|
+
pdata = prim_1.polygon_data._edb_object
|
|
2324
2326
|
int_data = _poly.GetIntersectionType(pdata)
|
|
2325
2327
|
if int_data == 2:
|
|
2326
2328
|
if not inlcude_voids_in_extents:
|
|
@@ -2347,7 +2349,7 @@ class Edb(Database):
|
|
|
2347
2349
|
# points = list(p.Points)
|
|
2348
2350
|
list_void = []
|
|
2349
2351
|
if voids:
|
|
2350
|
-
voids_data = [void.polygon_data.
|
|
2352
|
+
voids_data = [void.polygon_data._edb_object for void in voids]
|
|
2351
2353
|
list_prims = subtract(p, voids_data)
|
|
2352
2354
|
for prim in list_prims:
|
|
2353
2355
|
if not prim.IsNull():
|
|
@@ -4445,10 +4447,10 @@ class Edb(Database):
|
|
|
4445
4447
|
for poly in polys:
|
|
4446
4448
|
for void in poly.voids:
|
|
4447
4449
|
void_bbox = (
|
|
4448
|
-
void.polygon_data.
|
|
4449
|
-
void.polygon_data.
|
|
4450
|
-
void.polygon_data.
|
|
4451
|
-
void.polygon_data.
|
|
4450
|
+
void.polygon_data._edb_object.GetBBox().Item1.X.ToDouble(),
|
|
4451
|
+
void.polygon_data._edb_object.GetBBox().Item1.Y.ToDouble(),
|
|
4452
|
+
void.polygon_data._edb_object.GetBBox().Item2.X.ToDouble(),
|
|
4453
|
+
void.polygon_data._edb_object.GetBBox().Item2.Y.ToDouble(),
|
|
4452
4454
|
)
|
|
4453
4455
|
included_instances = list(padstack_instances_index.intersection(void_bbox))
|
|
4454
4456
|
if included_instances:
|
|
@@ -4481,10 +4483,10 @@ class Edb(Database):
|
|
|
4481
4483
|
|
|
4482
4484
|
for void_info in void_padstacks:
|
|
4483
4485
|
port_poly = cloned_edb.modeler.create_polygon(
|
|
4484
|
-
main_shape=void_info[0].polygon_data.
|
|
4486
|
+
main_shape=void_info[0].polygon_data._edb_object, layer_name="ref", net_name="GND"
|
|
4485
4487
|
)
|
|
4486
4488
|
pec_poly = cloned_edb.modeler.create_polygon(
|
|
4487
|
-
main_shape=port_poly.polygon_data.
|
|
4489
|
+
main_shape=port_poly.polygon_data._edb_object, layer_name="port_pec", net_name="GND"
|
|
4488
4490
|
)
|
|
4489
4491
|
pec_poly.scale(1.5)
|
|
4490
4492
|
|
|
@@ -48,3 +48,14 @@ class HierarchyObj(Connectable):
|
|
|
48
48
|
class Group(HierarchyObj):
|
|
49
49
|
def __init__(self, pedb, edb_object):
|
|
50
50
|
super().__init__(pedb, edb_object)
|
|
51
|
+
|
|
52
|
+
def ungroup(self, recursive=False):
|
|
53
|
+
"""Dissolve a group.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
recursive : bool, optional
|
|
58
|
+
If True, all subgroups will also be dissolved.
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
return self._edb_object.Ungroup(recursive)
|
|
@@ -23,8 +23,11 @@
|
|
|
23
23
|
"""
|
|
24
24
|
This module contains these classes: `EdbLayout` and `Shape`.
|
|
25
25
|
"""
|
|
26
|
+
from typing import Union
|
|
27
|
+
|
|
26
28
|
from pyedb.dotnet.edb_core.cell.hierarchy.component import EDBComponent
|
|
27
|
-
from pyedb.dotnet.edb_core.cell.primitive import Bondwire
|
|
29
|
+
from pyedb.dotnet.edb_core.cell.primitive.bondwire import Bondwire
|
|
30
|
+
from pyedb.dotnet.edb_core.cell.primitive.path import Path
|
|
28
31
|
from pyedb.dotnet.edb_core.cell.terminal.bundle_terminal import BundleTerminal
|
|
29
32
|
from pyedb.dotnet.edb_core.cell.terminal.edge_terminal import EdgeTerminal
|
|
30
33
|
from pyedb.dotnet.edb_core.cell.terminal.padstack_instance_terminal import (
|
|
@@ -42,7 +45,6 @@ from pyedb.dotnet.edb_core.edb_data.nets_data import (
|
|
|
42
45
|
from pyedb.dotnet.edb_core.edb_data.padstacks_data import EDBPadstackInstance
|
|
43
46
|
from pyedb.dotnet.edb_core.edb_data.primitives_data import (
|
|
44
47
|
EdbCircle,
|
|
45
|
-
EdbPath,
|
|
46
48
|
EdbPolygon,
|
|
47
49
|
EdbRectangle,
|
|
48
50
|
EdbText,
|
|
@@ -107,6 +109,7 @@ class Layout(ObjBase):
|
|
|
107
109
|
-----
|
|
108
110
|
Method returns the expansion of the contour, so any voids within expanded objects are ignored.
|
|
109
111
|
"""
|
|
112
|
+
nets = [i._edb_object for i in nets]
|
|
110
113
|
return self._edb_object.GetExpandedExtentFromNets(
|
|
111
114
|
convert_py_list_to_net_list(nets),
|
|
112
115
|
extent,
|
|
@@ -206,26 +209,8 @@ class Layout(ObjBase):
|
|
|
206
209
|
"""
|
|
207
210
|
prims = []
|
|
208
211
|
for p in self._edb_object.Primitives:
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
elif p.GetPrimitiveType().ToString() == "Circle":
|
|
212
|
-
prims.append(EdbCircle(p, self._pedb))
|
|
213
|
-
elif p.GetPrimitiveType().ToString() == "Polygon":
|
|
214
|
-
prims.append(EdbPolygon(p, self._pedb))
|
|
215
|
-
elif p.GetPrimitiveType().ToString() == "Path":
|
|
216
|
-
prims.append(EdbPath(p, self._pedb))
|
|
217
|
-
elif p.GetPrimitiveType().ToString() == "Bondwire":
|
|
218
|
-
prims.append(Bondwire(self._pedb, p))
|
|
219
|
-
elif p.GetPrimitiveType().ToString() == "Text":
|
|
220
|
-
prims.append(EdbText(p, self._pedb))
|
|
221
|
-
elif p.GetPrimitiveType().ToString() == "PrimitivePlugin":
|
|
222
|
-
pass
|
|
223
|
-
elif p.GetPrimitiveType().ToString() == "Path3D":
|
|
224
|
-
pass
|
|
225
|
-
elif p.GetPrimitiveType().ToString() == "BoardBendDef":
|
|
226
|
-
pass
|
|
227
|
-
else:
|
|
228
|
-
pass
|
|
212
|
+
obj = self.find_object_by_id(p.GetId())
|
|
213
|
+
prims.append(obj)
|
|
229
214
|
return prims
|
|
230
215
|
|
|
231
216
|
@property
|
|
@@ -293,8 +278,33 @@ class Layout(ObjBase):
|
|
|
293
278
|
ID of the object.
|
|
294
279
|
"""
|
|
295
280
|
obj = self._pedb._edb.Cell.Connectable.FindById(self._edb_object, value)
|
|
281
|
+
if obj is None:
|
|
282
|
+
raise RuntimeError(f"Object Id {value} not found")
|
|
283
|
+
|
|
296
284
|
if obj.GetObjType().ToString() == "PadstackInstance":
|
|
297
|
-
return EDBPadstackInstance(obj, self._pedb)
|
|
285
|
+
return EDBPadstackInstance(obj, self._pedb)
|
|
286
|
+
|
|
287
|
+
if obj.GetObjType().ToString() == "Primitive":
|
|
288
|
+
if obj.GetPrimitiveType().ToString() == "Rectangle":
|
|
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
|
|
298
308
|
|
|
299
309
|
def find_net_by_name(self, value: str):
|
|
300
310
|
"""Find a net object by name
|
|
@@ -324,3 +334,17 @@ class Layout(ObjBase):
|
|
|
324
334
|
"""
|
|
325
335
|
obj = self._pedb._edb.Cell.Hierarchy.Component.FindByName(self._edb_object, value)
|
|
326
336
|
return EDBComponent(self._pedb, obj) if obj is not None else None
|
|
337
|
+
|
|
338
|
+
def find_primitive(self, layer_name: Union[str, list]) -> list:
|
|
339
|
+
"""Find a primitive objects by layer name.
|
|
340
|
+
|
|
341
|
+
Parameters
|
|
342
|
+
----------
|
|
343
|
+
layer_name : str, list
|
|
344
|
+
Name of the layer.
|
|
345
|
+
Returns
|
|
346
|
+
-------
|
|
347
|
+
list
|
|
348
|
+
"""
|
|
349
|
+
layer_name = layer_name if isinstance(layer_name, list) else [layer_name]
|
|
350
|
+
return [i for i in self.primitives if i.layer_name in layer_name]
|
|
@@ -27,15 +27,6 @@ from pyedb.dotnet.edb_core.utilities.obj_base import ObjBase
|
|
|
27
27
|
class LayoutObj(ObjBase):
|
|
28
28
|
"""Manages EDB functionalities for the layout object."""
|
|
29
29
|
|
|
30
|
-
def __getattr__(self, key): # pragma: no cover
|
|
31
|
-
try:
|
|
32
|
-
return super().__getattribute__(key)
|
|
33
|
-
except AttributeError:
|
|
34
|
-
try:
|
|
35
|
-
return getattr(self._edb_object, key)
|
|
36
|
-
except AttributeError:
|
|
37
|
-
raise AttributeError(f"Attribute '{key}' not present")
|
|
38
|
-
|
|
39
30
|
def __init__(self, pedb, edb_object):
|
|
40
31
|
super().__init__(pedb, edb_object)
|
|
41
32
|
|