pyedb 0.55.0__py3-none-any.whl → 0.57.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 +3 -0
- pyedb/configuration/cfg_operations.py +2 -2
- pyedb/configuration/cfg_ports_sources.py +1 -1
- pyedb/configuration/cfg_terminals.py +232 -0
- pyedb/configuration/configuration.py +146 -3
- pyedb/dotnet/clr_module.py +1 -2
- pyedb/dotnet/database/Variables.py +56 -41
- pyedb/dotnet/database/cell/layout.py +5 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +2 -2
- pyedb/dotnet/database/cell/terminal/bundle_terminal.py +12 -0
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +38 -0
- pyedb/dotnet/database/components.py +55 -52
- pyedb/dotnet/database/dotnet/database.py +1 -0
- pyedb/dotnet/database/edb_data/control_file.py +6 -3
- pyedb/dotnet/database/edb_data/nets_data.py +3 -3
- pyedb/dotnet/database/edb_data/padstacks_data.py +5 -2
- pyedb/dotnet/database/edb_data/ports.py +0 -25
- pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
- pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +18 -19
- pyedb/dotnet/database/edb_data/simulation_configuration.py +3 -3
- pyedb/dotnet/database/hfss.py +9 -8
- pyedb/dotnet/database/layout_validation.py +6 -3
- pyedb/dotnet/database/materials.py +1 -3
- pyedb/dotnet/database/modeler.py +7 -3
- pyedb/dotnet/database/nets.py +27 -19
- pyedb/dotnet/database/padstack.py +91 -2
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +1 -1
- pyedb/dotnet/database/siwave.py +4 -3
- pyedb/dotnet/database/stackup.py +50 -26
- pyedb/dotnet/database/utilities/heatsink.py +0 -1
- pyedb/dotnet/database/utilities/simulation_setup.py +7 -5
- pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +1 -0
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +5 -2
- pyedb/dotnet/edb.py +41 -36
- pyedb/exceptions.py +1 -2
- pyedb/extensions/create_cell_array.py +408 -0
- pyedb/generic/data_handlers.py +17 -28
- pyedb/generic/design_types.py +25 -38
- pyedb/generic/filesystem.py +9 -4
- pyedb/generic/general_methods.py +6 -7
- pyedb/generic/plot.py +2 -2
- pyedb/generic/settings.py +4 -0
- pyedb/grpc/database/_typing.py +0 -0
- pyedb/grpc/database/components.py +30 -11
- pyedb/grpc/database/control_file.py +14 -35
- pyedb/grpc/database/definition/materials.py +1 -1
- pyedb/grpc/database/definition/package_def.py +6 -3
- pyedb/grpc/database/definition/padstack_def.py +4 -7
- pyedb/grpc/database/hfss.py +1 -4
- pyedb/grpc/database/hierarchy/component.py +3 -4
- pyedb/grpc/database/hierarchy/pingroup.py +16 -3
- pyedb/grpc/database/layers/layer.py +1 -2
- pyedb/grpc/database/layers/stackup_layer.py +42 -19
- pyedb/grpc/database/layout/layout.py +117 -28
- pyedb/grpc/database/layout/voltage_regulator.py +6 -1
- pyedb/grpc/database/layout_validation.py +7 -4
- pyedb/grpc/database/modeler.py +241 -256
- pyedb/grpc/database/net/differential_pair.py +9 -2
- pyedb/grpc/database/net/extended_net.py +24 -9
- pyedb/grpc/database/net/net.py +14 -5
- pyedb/grpc/database/net/net_class.py +24 -7
- pyedb/grpc/database/nets.py +11 -43
- pyedb/grpc/database/padstacks.py +92 -16
- pyedb/grpc/database/primitive/bondwire.py +3 -67
- pyedb/grpc/database/primitive/circle.py +42 -3
- pyedb/grpc/database/primitive/padstack_instance.py +17 -19
- pyedb/grpc/database/primitive/path.py +154 -5
- pyedb/grpc/database/primitive/polygon.py +75 -9
- pyedb/grpc/database/primitive/primitive.py +2 -2
- pyedb/grpc/database/primitive/rectangle.py +105 -4
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +0 -2
- pyedb/grpc/database/simulation_setup/hfss_settings_options.py +0 -4
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +4 -2
- pyedb/grpc/database/simulation_setup/sweep_data.py +1 -3
- pyedb/grpc/database/siwave.py +6 -13
- pyedb/grpc/database/source_excitations.py +49 -57
- pyedb/grpc/database/stackup.py +50 -27
- pyedb/grpc/database/terminal/bundle_terminal.py +10 -3
- pyedb/grpc/database/terminal/pingroup_terminal.py +8 -1
- pyedb/grpc/database/terminal/terminal.py +19 -8
- pyedb/grpc/database/utility/heat_sink.py +0 -1
- pyedb/grpc/database/utility/hfss_extent_info.py +2 -2
- pyedb/grpc/database/utility/value.py +1 -0
- pyedb/grpc/database/utility/xml_control_file.py +6 -3
- pyedb/grpc/edb.py +33 -24
- pyedb/grpc/edb_init.py +1 -0
- pyedb/grpc/rpc_session.py +4 -3
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +6 -2
- pyedb/ipc2581/ecad/cad_data/step.py +1 -1
- pyedb/ipc2581/ipc2581.py +8 -7
- pyedb/libraries/common.py +3 -4
- pyedb/libraries/rf_libraries/base_functions.py +7 -16
- pyedb/libraries/rf_libraries/planar_antennas.py +3 -21
- pyedb/misc/downloads.py +1 -0
- pyedb/misc/misc.py +5 -2
- pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +1 -1
- pyedb/misc/utilities.py +0 -1
- pyedb/modeler/geometry_operators.py +9 -8
- pyedb/siwave.py +4 -6
- pyedb/siwave_core/__init__.py +0 -0
- pyedb/siwave_core/cpa/__init__.py +0 -0
- {pyedb-0.55.0.dist-info → pyedb-0.57.0.dist-info}/METADATA +3 -3
- {pyedb-0.55.0.dist-info → pyedb-0.57.0.dist-info}/RECORD +107 -102
- {pyedb-0.55.0.dist-info → pyedb-0.57.0.dist-info}/WHEEL +0 -0
- {pyedb-0.55.0.dist-info → pyedb-0.57.0.dist-info}/licenses/LICENSE +0 -0
pyedb/grpc/database/modeler.py
CHANGED
|
@@ -23,20 +23,20 @@
|
|
|
23
23
|
"""
|
|
24
24
|
This module contains these classes: `EdbLayout` and `Shape`.
|
|
25
25
|
"""
|
|
26
|
+
|
|
26
27
|
import math
|
|
27
28
|
from typing import Any, Dict, List, Optional, Union
|
|
28
29
|
|
|
29
30
|
from ansys.edb.core.geometry.arc_data import ArcData as GrpcArcData
|
|
30
31
|
from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
|
|
31
32
|
from ansys.edb.core.geometry.polygon_data import (
|
|
33
|
+
PolygonData as GrpcPolygonData,
|
|
32
34
|
PolygonSenseType as GrpcPolygonSenseType,
|
|
33
35
|
)
|
|
34
|
-
from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
|
|
35
36
|
from ansys.edb.core.hierarchy.pin_group import PinGroup as GrpcPinGroup
|
|
36
37
|
from ansys.edb.core.inner.exceptions import InvalidArgumentException
|
|
37
38
|
from ansys.edb.core.primitive.bondwire import BondwireType as GrpcBondwireType
|
|
38
|
-
from ansys.edb.core.primitive.path import PathCornerType as GrpcPathCornerType
|
|
39
|
-
from ansys.edb.core.primitive.path import PathEndCapType as GrpcPathEndCapType
|
|
39
|
+
from ansys.edb.core.primitive.path import PathCornerType as GrpcPathCornerType, PathEndCapType as GrpcPathEndCapType
|
|
40
40
|
from ansys.edb.core.primitive.rectangle import (
|
|
41
41
|
RectangleRepresentationType as GrpcRectangleRepresentationType,
|
|
42
42
|
)
|
|
@@ -61,7 +61,7 @@ class Modeler(object):
|
|
|
61
61
|
>>> edb_layout = edbapp.modeler
|
|
62
62
|
"""
|
|
63
63
|
|
|
64
|
-
def __getitem__(self, name: Union[str, int]) ->
|
|
64
|
+
def __getitem__(self, name: Union[str, int]) -> Primitive:
|
|
65
65
|
"""Get a primitive by name or ID.
|
|
66
66
|
|
|
67
67
|
Parameters
|
|
@@ -71,7 +71,7 @@ class Modeler(object):
|
|
|
71
71
|
|
|
72
72
|
Returns
|
|
73
73
|
-------
|
|
74
|
-
:class:`pyedb.
|
|
74
|
+
:class:`pyedb.grpc.database.primitive.primitive.Primitive`
|
|
75
75
|
Primitive instance if found, None otherwise.
|
|
76
76
|
|
|
77
77
|
Raises
|
|
@@ -79,21 +79,151 @@ class Modeler(object):
|
|
|
79
79
|
TypeError
|
|
80
80
|
If name is not str or int.
|
|
81
81
|
"""
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
or (isinstance(name, int) and i.id == name)
|
|
87
|
-
):
|
|
88
|
-
return i
|
|
89
|
-
self._pedb.logger.error("Primitive not found.")
|
|
90
|
-
return
|
|
82
|
+
|
|
83
|
+
if isinstance(name, int):
|
|
84
|
+
return self._primitives.get(name)
|
|
85
|
+
return self.primitives_by_name.get(name)
|
|
91
86
|
|
|
92
87
|
def __init__(self, p_edb) -> None:
|
|
93
88
|
"""Initialize Modeler instance."""
|
|
94
89
|
self._pedb = p_edb
|
|
95
|
-
|
|
96
|
-
self.
|
|
90
|
+
# Core cache
|
|
91
|
+
self._primitives: dict[str, Primitive] = {}
|
|
92
|
+
|
|
93
|
+
# Lazy indexes
|
|
94
|
+
self._primitives_by_name: dict[str, Primitive] | None = None
|
|
95
|
+
self._primitives_by_net: dict[str, list[Primitive]] | None = None
|
|
96
|
+
self._primitives_by_layer: dict[str, list[Primitive]] | None = None
|
|
97
|
+
self._primitives_by_layer_and_net: Dict[str, Dict[str, List[Primitive]]] | None = None
|
|
98
|
+
|
|
99
|
+
# ============================================================
|
|
100
|
+
|
|
101
|
+
# Cache management
|
|
102
|
+
# ============================================================
|
|
103
|
+
|
|
104
|
+
def _reload_all(self):
|
|
105
|
+
"""Force reload of all primitives and reset indexes."""
|
|
106
|
+
self._primitives = {p.edb_uid: p for p in self._pedb.layout.primitives}
|
|
107
|
+
self._primitives_by_name = None
|
|
108
|
+
self._primitives_by_net = None
|
|
109
|
+
self._primitives_by_layer = None
|
|
110
|
+
self._primitives_by_layer_and_net = None
|
|
111
|
+
|
|
112
|
+
def _add_primitive(self, prim: Any):
|
|
113
|
+
"""Add primitive wrapper to caches."""
|
|
114
|
+
self._primitives[prim.edb_uid] = prim
|
|
115
|
+
if self._primitives_by_name is not None:
|
|
116
|
+
self._primitives_by_name[prim.aedt_name] = prim
|
|
117
|
+
if self._primitives_by_net is not None and hasattr(prim, "net"):
|
|
118
|
+
self._primitives_by_net.setdefault(prim.net, []).append(prim)
|
|
119
|
+
if hasattr(prim, "layer"):
|
|
120
|
+
if self._primitives_by_layer is not None and prim.layer_name:
|
|
121
|
+
self._primitives_by_layer.setdefault(prim.layer_name, []).append(prim)
|
|
122
|
+
|
|
123
|
+
def _remove_primitive(self, prim: Primitive):
|
|
124
|
+
"""Remove primitive wrapper from all caches efficiently and safely."""
|
|
125
|
+
uid = prim.edb_uid
|
|
126
|
+
|
|
127
|
+
# 1. Remove from primary cache
|
|
128
|
+
self._primitives.pop(uid, None)
|
|
129
|
+
|
|
130
|
+
# 2. Remove from name cache if initialized
|
|
131
|
+
if self._primitives_by_name is not None:
|
|
132
|
+
self._primitives_by_name.pop(prim.aedt_name, None)
|
|
133
|
+
|
|
134
|
+
# 3. Remove from net cache if initialized
|
|
135
|
+
if self._primitives_by_net is not None and hasattr(prim, "net") and not prim.net.is_null:
|
|
136
|
+
net_name = prim.net.name
|
|
137
|
+
net_prims = self._primitives_by_net.get(net_name)
|
|
138
|
+
if net_prims:
|
|
139
|
+
try:
|
|
140
|
+
net_prims.remove(prim)
|
|
141
|
+
except ValueError:
|
|
142
|
+
pass # Not found, skip
|
|
143
|
+
if not net_prims:
|
|
144
|
+
self._primitives_by_net.pop(net_name, None)
|
|
145
|
+
|
|
146
|
+
# 4. Remove from layer cache if initialized
|
|
147
|
+
if self._primitives_by_layer is not None and hasattr(prim, "layer") and prim.layer_name:
|
|
148
|
+
layer_name = prim.layer.name
|
|
149
|
+
layer_prims = self._primitives_by_layer.get(layer_name)
|
|
150
|
+
if layer_prims:
|
|
151
|
+
try:
|
|
152
|
+
layer_prims.remove(prim)
|
|
153
|
+
except ValueError:
|
|
154
|
+
pass
|
|
155
|
+
if not layer_prims:
|
|
156
|
+
self._primitives_by_layer.pop(layer_name, None)
|
|
157
|
+
|
|
158
|
+
# 5. Remove from layer+net cache if initialized
|
|
159
|
+
if self._primitives_by_layer_and_net is not None:
|
|
160
|
+
if hasattr(prim, "layer") and hasattr(prim, "net") and not prim.net.is_null:
|
|
161
|
+
layer_name = prim.layer.name
|
|
162
|
+
net_name = prim.net.name
|
|
163
|
+
layer_dict = self._primitives_by_layer_and_net.get(layer_name)
|
|
164
|
+
if layer_dict:
|
|
165
|
+
net_list = layer_dict.get(net_name)
|
|
166
|
+
if net_list:
|
|
167
|
+
try:
|
|
168
|
+
net_list.remove(prim)
|
|
169
|
+
except ValueError:
|
|
170
|
+
pass
|
|
171
|
+
if not net_list:
|
|
172
|
+
layer_dict.pop(net_name, None)
|
|
173
|
+
if not layer_dict:
|
|
174
|
+
self._primitives_by_layer_and_net.pop(layer_name, None)
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def primitives(self) -> list[Primitive]:
|
|
178
|
+
if not self._primitives:
|
|
179
|
+
self._reload_all()
|
|
180
|
+
return list(self._primitives.values())
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def primitives_by_name(self):
|
|
184
|
+
if self._primitives_by_name is None:
|
|
185
|
+
self._primitives_by_name = {p.aedt_name: p for p in self.primitives}
|
|
186
|
+
return self._primitives_by_name
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def primitives_by_net(self):
|
|
190
|
+
if self._primitives_by_net is None:
|
|
191
|
+
d = {}
|
|
192
|
+
for p in self.primitives:
|
|
193
|
+
if hasattr(p, "net"):
|
|
194
|
+
d.setdefault(p.net.name, []).append(p)
|
|
195
|
+
self._primitives_by_net = d
|
|
196
|
+
return self._primitives_by_net
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def primitives_by_layer(self):
|
|
200
|
+
if self._primitives_by_layer is None:
|
|
201
|
+
d = {}
|
|
202
|
+
for p in self.primitives:
|
|
203
|
+
if p.layer_name:
|
|
204
|
+
d.setdefault(p.layer_name, []).append(p)
|
|
205
|
+
self._primitives_by_layer = d
|
|
206
|
+
return self._primitives_by_layer
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def primitives_by_layer_and_net(self) -> Dict[str, Dict[str, List[Primitive]]]:
|
|
210
|
+
"""Return all primitives indexed first by layer, then by net.
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
dict
|
|
215
|
+
Nested dictionary: layer -> net -> list[Primitive]
|
|
216
|
+
"""
|
|
217
|
+
if self._primitives_by_layer_and_net is None:
|
|
218
|
+
idx: Dict[str, Dict[str, List[Primitive]]] = {}
|
|
219
|
+
for prim in self.primitives:
|
|
220
|
+
if not prim.layer_name or not hasattr(prim, "net") or prim.net.is_null:
|
|
221
|
+
continue
|
|
222
|
+
layer = prim.layer_name
|
|
223
|
+
net = prim.net.name
|
|
224
|
+
idx.setdefault(layer, {}).setdefault(net, []).append(prim)
|
|
225
|
+
self._primitives_by_layer_and_net = idx
|
|
226
|
+
return self._primitives_by_layer_and_net
|
|
97
227
|
|
|
98
228
|
@property
|
|
99
229
|
def _edb(self) -> Any:
|
|
@@ -211,17 +341,6 @@ class Modeler(object):
|
|
|
211
341
|
else:
|
|
212
342
|
return False
|
|
213
343
|
|
|
214
|
-
@property
|
|
215
|
-
def primitives(self) -> List[Primitive]:
|
|
216
|
-
"""All primitives in the layout.
|
|
217
|
-
|
|
218
|
-
Returns
|
|
219
|
-
-------
|
|
220
|
-
list
|
|
221
|
-
List of :class:`pyedb.dotnet.database.edb_data.primitives_data.Primitive` objects.
|
|
222
|
-
"""
|
|
223
|
-
return self._pedb.layout.primitives
|
|
224
|
-
|
|
225
344
|
@property
|
|
226
345
|
def polygons_by_layer(self) -> Dict[str, List[Primitive]]:
|
|
227
346
|
"""Primitives organized by layer names.
|
|
@@ -231,47 +350,13 @@ class Modeler(object):
|
|
|
231
350
|
dict
|
|
232
351
|
Dictionary where keys are layer names and values are lists of polygons.
|
|
233
352
|
"""
|
|
234
|
-
|
|
235
|
-
for lay in self.layers:
|
|
236
|
-
_primitives_by_layer[lay] = self.get_polygons_by_layer(lay)
|
|
237
|
-
return _primitives_by_layer
|
|
238
|
-
|
|
239
|
-
@property
|
|
240
|
-
def primitives_by_net(self) -> Dict[str, List[Primitive]]:
|
|
241
|
-
"""Primitives organized by net names.
|
|
242
|
-
|
|
243
|
-
Returns
|
|
244
|
-
-------
|
|
245
|
-
dict
|
|
246
|
-
Dictionary where keys are net names and values are lists of primitives.
|
|
247
|
-
"""
|
|
248
|
-
_prim_by_net = {}
|
|
249
|
-
for net, net_obj in self._pedb.nets.nets.items():
|
|
250
|
-
_prim_by_net[net] = [i for i in net_obj.primitives]
|
|
251
|
-
return _prim_by_net
|
|
252
|
-
|
|
253
|
-
@property
|
|
254
|
-
def primitives_by_layer(self) -> Dict[str, List[Primitive]]:
|
|
255
|
-
"""Primitives organized by layer names.
|
|
256
|
-
|
|
257
|
-
Returns
|
|
258
|
-
-------
|
|
259
|
-
dict
|
|
260
|
-
Dictionary where keys are layer names and values are lists of primitives.
|
|
261
|
-
"""
|
|
262
|
-
_primitives_by_layer = {}
|
|
353
|
+
polygon_by_layer = {}
|
|
263
354
|
for lay in self.layers:
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
lay = i.layer.name
|
|
270
|
-
if lay in _primitives_by_layer:
|
|
271
|
-
_primitives_by_layer[lay].append(i)
|
|
272
|
-
except (InvalidArgumentException, AttributeError):
|
|
273
|
-
pass
|
|
274
|
-
return _primitives_by_layer
|
|
355
|
+
if lay in self.primitives_by_layer:
|
|
356
|
+
polygon_by_layer[lay] = [prim for prim in self.primitives_by_layer[lay] if prim.type == "polygon"]
|
|
357
|
+
else:
|
|
358
|
+
polygon_by_layer[lay] = []
|
|
359
|
+
return polygon_by_layer
|
|
275
360
|
|
|
276
361
|
@property
|
|
277
362
|
def rectangles(self) -> List[Rectangle]:
|
|
@@ -332,15 +417,10 @@ class Modeler(object):
|
|
|
332
417
|
list
|
|
333
418
|
List of polygon objects.
|
|
334
419
|
"""
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if
|
|
338
|
-
|
|
339
|
-
if net_list and el.net.name in net_list:
|
|
340
|
-
objinst.append(el)
|
|
341
|
-
else:
|
|
342
|
-
objinst.append(el)
|
|
343
|
-
return objinst
|
|
420
|
+
polygons = self.polygons_by_layer.get(layer_name, [])
|
|
421
|
+
if net_list:
|
|
422
|
+
polygons = [p for p in polygons if p.net_name in net_list]
|
|
423
|
+
return polygons
|
|
344
424
|
|
|
345
425
|
def get_primitive_by_layer_and_point(
|
|
346
426
|
self,
|
|
@@ -603,18 +683,21 @@ class Modeler(object):
|
|
|
603
683
|
else:
|
|
604
684
|
corner_style = GrpcPathCornerType.MITER
|
|
605
685
|
_points = []
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
coord
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
686
|
+
if isinstance(points, list):
|
|
687
|
+
for pt in points:
|
|
688
|
+
_pt = []
|
|
689
|
+
for coord in pt:
|
|
690
|
+
coord = Value(coord, self._pedb.active_cell)
|
|
691
|
+
_pt.append(coord)
|
|
692
|
+
_points.append(_pt)
|
|
693
|
+
points = _points
|
|
694
|
+
width = Value(width, self._pedb.active_cell)
|
|
695
|
+
polygon_data = GrpcPolygonData(points)
|
|
696
|
+
elif isinstance(points, GrpcPolygonData):
|
|
697
|
+
polygon_data = points
|
|
698
|
+
else:
|
|
699
|
+
raise TypeError("Points must be a list of points or a PolygonData object.")
|
|
700
|
+
path = Path(self._pedb).create(
|
|
618
701
|
layout=self._active_layout,
|
|
619
702
|
layer=layer_name,
|
|
620
703
|
net=net,
|
|
@@ -631,7 +714,7 @@ class Modeler(object):
|
|
|
631
714
|
|
|
632
715
|
def create_trace(
|
|
633
716
|
self,
|
|
634
|
-
path_list: List[List[float]],
|
|
717
|
+
path_list: Union[List[List[float]], GrpcPolygonData],
|
|
635
718
|
layer_name: str,
|
|
636
719
|
width: float = 1,
|
|
637
720
|
net_name: str = "",
|
|
@@ -673,7 +756,7 @@ class Modeler(object):
|
|
|
673
756
|
end_cap_style=end_cap_style,
|
|
674
757
|
corner_style=corner_style,
|
|
675
758
|
)
|
|
676
|
-
|
|
759
|
+
self._add_primitive(primitive) # update cache
|
|
677
760
|
return primitive
|
|
678
761
|
|
|
679
762
|
def create_polygon(
|
|
@@ -726,10 +809,13 @@ class Modeler(object):
|
|
|
726
809
|
self._logger.error("Failed to create void polygon data")
|
|
727
810
|
return False
|
|
728
811
|
polygon_data.holes.append(void_polygon_data)
|
|
729
|
-
polygon = Polygon
|
|
812
|
+
polygon = Polygon(self._pedb, None).create(
|
|
813
|
+
layout=self._active_layout, layer=layer_name, net=net, polygon_data=polygon_data
|
|
814
|
+
)
|
|
730
815
|
if polygon.is_null or polygon_data is False: # pragma: no cover
|
|
731
816
|
self._logger.error("Null polygon created")
|
|
732
817
|
return False
|
|
818
|
+
self._add_primitive(polygon)
|
|
733
819
|
return Polygon(self._pedb, polygon)
|
|
734
820
|
|
|
735
821
|
def create_rectangle(
|
|
@@ -777,12 +863,11 @@ class Modeler(object):
|
|
|
777
863
|
"""
|
|
778
864
|
edb_net = self._pedb.nets.find_or_create_net(net_name)
|
|
779
865
|
if representation_type == "lower_left_upper_right":
|
|
780
|
-
|
|
781
|
-
rect = Rectangle.create(
|
|
866
|
+
rect = Rectangle(self._pedb).create(
|
|
782
867
|
layout=self._active_layout,
|
|
783
868
|
layer=layer_name,
|
|
784
869
|
net=edb_net,
|
|
785
|
-
rep_type=
|
|
870
|
+
rep_type=representation_type,
|
|
786
871
|
param1=Value(lower_left_point[0]),
|
|
787
872
|
param2=Value(lower_left_point[1]),
|
|
788
873
|
param3=Value(upper_right_point[0]),
|
|
@@ -806,7 +891,7 @@ class Modeler(object):
|
|
|
806
891
|
height = Value(width)
|
|
807
892
|
else:
|
|
808
893
|
height = Value(width)
|
|
809
|
-
rect = Rectangle.create(
|
|
894
|
+
rect = Rectangle(self._pedb).create(
|
|
810
895
|
layout=self._active_layout,
|
|
811
896
|
layer=layer_name,
|
|
812
897
|
net=edb_net,
|
|
@@ -819,7 +904,8 @@ class Modeler(object):
|
|
|
819
904
|
rotation=Value(rotation),
|
|
820
905
|
)
|
|
821
906
|
if not rect.is_null:
|
|
822
|
-
|
|
907
|
+
self._add_primitive(rect)
|
|
908
|
+
return rect
|
|
823
909
|
return False
|
|
824
910
|
|
|
825
911
|
def create_circle(
|
|
@@ -847,7 +933,7 @@ class Modeler(object):
|
|
|
847
933
|
"""
|
|
848
934
|
edb_net = self._pedb.nets.find_or_create_net(net_name)
|
|
849
935
|
|
|
850
|
-
circle = Circle.create(
|
|
936
|
+
circle = Circle(self._pedb).create(
|
|
851
937
|
layout=self._active_layout,
|
|
852
938
|
layer=layer_name,
|
|
853
939
|
net=edb_net,
|
|
@@ -856,7 +942,8 @@ class Modeler(object):
|
|
|
856
942
|
radius=Value(radius),
|
|
857
943
|
)
|
|
858
944
|
if not circle.is_null:
|
|
859
|
-
|
|
945
|
+
self._add_primitive(circle)
|
|
946
|
+
return circle
|
|
860
947
|
return False
|
|
861
948
|
|
|
862
949
|
def delete_primitives(self, net_names: Union[str, List[str]]) -> bool:
|
|
@@ -949,120 +1036,6 @@ class Modeler(object):
|
|
|
949
1036
|
void_circle.delete()
|
|
950
1037
|
return True
|
|
951
1038
|
|
|
952
|
-
@staticmethod
|
|
953
|
-
@staticmethod
|
|
954
|
-
def add_void(shape: "Primitive", void_shape: Union["Primitive", List["Primitive"]]) -> bool:
|
|
955
|
-
"""Add void to shape.
|
|
956
|
-
|
|
957
|
-
Parameters
|
|
958
|
-
----------
|
|
959
|
-
shape : :class:`pyedb.dotnet.database.edb_data.primitives_data.Primitive`
|
|
960
|
-
Main shape.
|
|
961
|
-
void_shape : list or :class:`pyedb.dotnet.database.edb_data.primitives_data.Primitive`
|
|
962
|
-
Void shape(s).
|
|
963
|
-
|
|
964
|
-
Returns
|
|
965
|
-
-------
|
|
966
|
-
bool
|
|
967
|
-
True if successful, False otherwise.
|
|
968
|
-
"""
|
|
969
|
-
if not isinstance(void_shape, list):
|
|
970
|
-
void_shape = [void_shape]
|
|
971
|
-
for void in void_shape:
|
|
972
|
-
if isinstance(void, Primitive):
|
|
973
|
-
shape._edb_object.add_void(void)
|
|
974
|
-
flag = True
|
|
975
|
-
else:
|
|
976
|
-
shape._edb_object.add_void(void)
|
|
977
|
-
flag = True
|
|
978
|
-
if not flag:
|
|
979
|
-
return flag
|
|
980
|
-
return True
|
|
981
|
-
|
|
982
|
-
def _createPolygonDataFromPolygon(self, shape):
|
|
983
|
-
points = shape.points
|
|
984
|
-
if not self._validatePoint(points[0]):
|
|
985
|
-
self._logger.error("Error validating point.")
|
|
986
|
-
return None
|
|
987
|
-
arcs = []
|
|
988
|
-
is_parametric = False
|
|
989
|
-
for i in range(len(points) - 1):
|
|
990
|
-
if i == 0:
|
|
991
|
-
startPoint = points[-1]
|
|
992
|
-
endPoint = points[i]
|
|
993
|
-
else:
|
|
994
|
-
startPoint = points[i - 1]
|
|
995
|
-
endPoint = points[i]
|
|
996
|
-
|
|
997
|
-
if not self._validatePoint(endPoint):
|
|
998
|
-
return None
|
|
999
|
-
startPoint = [Value(i) for i in startPoint]
|
|
1000
|
-
endPoint = [Value(i) for i in endPoint]
|
|
1001
|
-
if len(endPoint) == 2:
|
|
1002
|
-
is_parametric = (
|
|
1003
|
-
is_parametric
|
|
1004
|
-
or startPoint[0].is_parametric
|
|
1005
|
-
or startPoint[1].is_parametric
|
|
1006
|
-
or endPoint[0].is_parametric
|
|
1007
|
-
or endPoint[1].is_parametric
|
|
1008
|
-
)
|
|
1009
|
-
arc = GrpcArcData(
|
|
1010
|
-
GrpcPointData([startPoint[0], startPoint[1]]), GrpcPointData([endPoint[0], endPoint[1]])
|
|
1011
|
-
)
|
|
1012
|
-
arcs.append(arc)
|
|
1013
|
-
elif len(endPoint) == 3:
|
|
1014
|
-
is_parametric = (
|
|
1015
|
-
is_parametric
|
|
1016
|
-
or startPoint[0].is_parametric
|
|
1017
|
-
or startPoint[1].is_parametric
|
|
1018
|
-
or endPoint[0].is_parametric
|
|
1019
|
-
or endPoint[1].is_parametric
|
|
1020
|
-
or endPoint[2].is_parametric
|
|
1021
|
-
)
|
|
1022
|
-
arc = GrpcArcData(
|
|
1023
|
-
GrpcPointData([startPoint[0], startPoint[1]]),
|
|
1024
|
-
GrpcPointData([endPoint[0], endPoint[1]]),
|
|
1025
|
-
kwarg={"height": endPoint[2]},
|
|
1026
|
-
)
|
|
1027
|
-
arcs.append(arc)
|
|
1028
|
-
elif len(endPoint) == 5:
|
|
1029
|
-
is_parametric = (
|
|
1030
|
-
is_parametric
|
|
1031
|
-
or startPoint[0].is_parametric
|
|
1032
|
-
or startPoint[1].is_parametric
|
|
1033
|
-
or endPoint[0].is_parametric
|
|
1034
|
-
or endPoint[1].is_parametric
|
|
1035
|
-
or endPoint[3].is_parametric
|
|
1036
|
-
or endPoint[4].is_parametric
|
|
1037
|
-
)
|
|
1038
|
-
if endPoint[2].is_cw:
|
|
1039
|
-
rotationDirection = GrpcPolygonSenseType.SENSE_CW
|
|
1040
|
-
elif endPoint[2].is_ccw:
|
|
1041
|
-
rotationDirection = GrpcPolygonSenseType.SENSE_CCW
|
|
1042
|
-
else:
|
|
1043
|
-
self._logger.error("Invalid rotation direction %s is specified.", endPoint[2])
|
|
1044
|
-
return None
|
|
1045
|
-
arc = GrpcArcData(
|
|
1046
|
-
GrpcPointData(startPoint),
|
|
1047
|
-
GrpcPointData(endPoint),
|
|
1048
|
-
)
|
|
1049
|
-
# arc.direction = rotationDirection,
|
|
1050
|
-
# arc.center = GrpcPointData([endPoint[3], endPoint[4]]),
|
|
1051
|
-
arcs.append(arc)
|
|
1052
|
-
polygon = GrpcPolygonData(arcs=arcs)
|
|
1053
|
-
if not is_parametric:
|
|
1054
|
-
return polygon
|
|
1055
|
-
else:
|
|
1056
|
-
k = 0
|
|
1057
|
-
for pt in points:
|
|
1058
|
-
point = [Value(i) for i in pt]
|
|
1059
|
-
new_points = GrpcPointData(point)
|
|
1060
|
-
if len(point) > 2:
|
|
1061
|
-
k += 1
|
|
1062
|
-
polygon.set_point(k, new_points)
|
|
1063
|
-
k += 1
|
|
1064
|
-
return polygon
|
|
1065
|
-
|
|
1066
1039
|
def _validatePoint(self, point, allowArcs=True):
|
|
1067
1040
|
if len(point) == 2:
|
|
1068
1041
|
if not isinstance(point[0], (int, float, str)):
|
|
@@ -1110,17 +1083,6 @@ class Modeler(object):
|
|
|
1110
1083
|
self._logger.error("Arc point descriptor has incorrect number of elements (%s)", len(point))
|
|
1111
1084
|
return False
|
|
1112
1085
|
|
|
1113
|
-
def _createPolygonDataFromRectangle(self, shape):
|
|
1114
|
-
# if not self._validatePoint(shape.pointA, False) or not self._validatePoint(shape.pointB, False):
|
|
1115
|
-
# return None
|
|
1116
|
-
# pointA = GrpcPointData(pointA[0]), self._get_edb_value(shape.pointA[1])
|
|
1117
|
-
# )
|
|
1118
|
-
# pointB = self._edb.Geometry.PointData(
|
|
1119
|
-
# self._get_edb_value(shape.pointB[0]), self._get_edb_value(shape.pointB[1])
|
|
1120
|
-
# )
|
|
1121
|
-
# return self._edb.geometry.polygon_data.create_from_bbox((pointA, pointB))
|
|
1122
|
-
pass
|
|
1123
|
-
|
|
1124
1086
|
def parametrize_trace_width(
|
|
1125
1087
|
self,
|
|
1126
1088
|
nets_name: Union[str, List[str]],
|
|
@@ -1204,39 +1166,31 @@ class Modeler(object):
|
|
|
1204
1166
|
all_voids = []
|
|
1205
1167
|
list_polygon_data = []
|
|
1206
1168
|
delete_list = []
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
poly
|
|
1210
|
-
|
|
1211
|
-
if poly.net.name:
|
|
1212
|
-
poly_by_nets[poly.net.name] = [poly]
|
|
1213
|
-
else:
|
|
1214
|
-
if poly.net.name:
|
|
1215
|
-
poly_by_nets[poly.net.name].append(poly)
|
|
1216
|
-
for net in poly_by_nets:
|
|
1169
|
+
for poly in self.polygons_by_layer.get(lay, []):
|
|
1170
|
+
if poly.net_name:
|
|
1171
|
+
poly_by_nets.setdefault(poly.net_name, []).append(poly)
|
|
1172
|
+
for net, polys in poly_by_nets.items():
|
|
1217
1173
|
if net in net_names_list or not net_names_list:
|
|
1218
|
-
for
|
|
1219
|
-
list_polygon_data.append(
|
|
1220
|
-
delete_list.append(
|
|
1221
|
-
all_voids.
|
|
1222
|
-
|
|
1223
|
-
for item in
|
|
1224
|
-
for
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
item.add_hole(void.polygon_data)
|
|
1174
|
+
for p in polys:
|
|
1175
|
+
list_polygon_data.append(p.polygon_data)
|
|
1176
|
+
delete_list.append(p)
|
|
1177
|
+
all_voids.extend(p.voids)
|
|
1178
|
+
united = GrpcPolygonData.unite(list_polygon_data)
|
|
1179
|
+
for item in united:
|
|
1180
|
+
for void in all_voids:
|
|
1181
|
+
if item.intersection_type(void.polygon_data) == 2:
|
|
1182
|
+
item.add_hole(void.polygon_data)
|
|
1228
1183
|
self.create_polygon(item, layer_name=lay, voids=[], net_name=net)
|
|
1229
|
-
for
|
|
1230
|
-
for
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
for poly in delete_list:
|
|
1184
|
+
for void in all_voids:
|
|
1185
|
+
for poly in poly_by_nets[net]: # pragma no cover
|
|
1186
|
+
if void.polygon_data.intersection_type(poly.polygon_data).value >= 2:
|
|
1187
|
+
try:
|
|
1188
|
+
id = delete_list.index(poly)
|
|
1189
|
+
except ValueError:
|
|
1190
|
+
id = -1
|
|
1191
|
+
if id >= 0:
|
|
1192
|
+
delete_list.pop(id)
|
|
1193
|
+
for poly in list(set(delete_list)):
|
|
1240
1194
|
poly.delete()
|
|
1241
1195
|
|
|
1242
1196
|
if delete_padstack_gemometries:
|
|
@@ -1265,7 +1219,7 @@ class Modeler(object):
|
|
|
1265
1219
|
new_poly = poly.polygon_data.defeature(tol=tolerance)
|
|
1266
1220
|
if not new_poly.points:
|
|
1267
1221
|
self._pedb.logger.error(
|
|
1268
|
-
f"Defeaturing on polygon {poly.id} returned empty polygon, tolerance threshold
|
|
1222
|
+
f"Defeaturing on polygon {poly.id} returned empty polygon, tolerance threshold might too large. "
|
|
1269
1223
|
)
|
|
1270
1224
|
return False
|
|
1271
1225
|
poly.polygon_data = new_poly
|
|
@@ -1428,7 +1382,9 @@ class Modeler(object):
|
|
|
1428
1382
|
end_context=end_cell_inst,
|
|
1429
1383
|
start_context=start_cell_inst,
|
|
1430
1384
|
)
|
|
1431
|
-
|
|
1385
|
+
bondwire = Bondwire(self._pedb, bw)
|
|
1386
|
+
self._add_primitive(bondwire)
|
|
1387
|
+
return bondwire
|
|
1432
1388
|
|
|
1433
1389
|
def create_pin_group(
|
|
1434
1390
|
self,
|
|
@@ -1499,3 +1455,32 @@ class Modeler(object):
|
|
|
1499
1455
|
if net_obj:
|
|
1500
1456
|
obj.net = net_obj[0]
|
|
1501
1457
|
return self._pedb.siwave.pin_groups[name]
|
|
1458
|
+
|
|
1459
|
+
@staticmethod
|
|
1460
|
+
def add_void(shape: "Primitive", void_shape: Union["Primitive", List["Primitive"]]) -> bool:
|
|
1461
|
+
"""Add void to shape.
|
|
1462
|
+
|
|
1463
|
+
Parameters
|
|
1464
|
+
----------
|
|
1465
|
+
shape : :class:`pyedb.dotnet.database.edb_data.primitives_data.Primitive`
|
|
1466
|
+
Main shape.
|
|
1467
|
+
void_shape : list or :class:`pyedb.dotnet.database.edb_data.primitives_data.Primitive`
|
|
1468
|
+
Void shape(s).
|
|
1469
|
+
|
|
1470
|
+
Returns
|
|
1471
|
+
-------
|
|
1472
|
+
bool
|
|
1473
|
+
True if successful, False otherwise.
|
|
1474
|
+
"""
|
|
1475
|
+
if not isinstance(void_shape, list):
|
|
1476
|
+
void_shape = [void_shape]
|
|
1477
|
+
for void in void_shape:
|
|
1478
|
+
if isinstance(void, Primitive):
|
|
1479
|
+
shape._edb_object.add_void(void)
|
|
1480
|
+
flag = True
|
|
1481
|
+
else:
|
|
1482
|
+
shape._edb_object.add_void(void)
|
|
1483
|
+
flag = True
|
|
1484
|
+
if not flag:
|
|
1485
|
+
return flag
|
|
1486
|
+
return True
|