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
|
@@ -159,16 +159,6 @@ class Terminal(Connectable):
|
|
|
159
159
|
ppp.DoRenormalize = value
|
|
160
160
|
self._port_post_processing_prop = ppp
|
|
161
161
|
|
|
162
|
-
@property
|
|
163
|
-
def net_name(self):
|
|
164
|
-
"""Net name.
|
|
165
|
-
|
|
166
|
-
Returns
|
|
167
|
-
-------
|
|
168
|
-
str
|
|
169
|
-
"""
|
|
170
|
-
return self.net.name
|
|
171
|
-
|
|
172
162
|
@property
|
|
173
163
|
def terminal_type(self):
|
|
174
164
|
"""Terminal Type.
|
|
@@ -1807,8 +1807,8 @@ class Components(object):
|
|
|
1807
1807
|
|
|
1808
1808
|
sParameterMod = self._edb.cell.hierarchy._hierarchy.SParameterModel()
|
|
1809
1809
|
sParameterMod.SetComponentModelName(nPortModelName)
|
|
1810
|
-
gndnets = filter(lambda x: "gnd" in x.lower(), componentNets)
|
|
1811
|
-
if len(
|
|
1810
|
+
gndnets = list(filter(lambda x: "gnd" in x.lower(), componentNets))
|
|
1811
|
+
if len(gndnets) > 0: # pragma: no cover
|
|
1812
1812
|
net = gndnets[0]
|
|
1813
1813
|
else: # pragma: no cover
|
|
1814
1814
|
net = componentNets[len(componentNets) - 1]
|
|
@@ -130,22 +130,32 @@ class EDBComponentDef(ObjBase):
|
|
|
130
130
|
comp.assign_s_param_model(file_path, model_name, reference_net)
|
|
131
131
|
return True
|
|
132
132
|
|
|
133
|
-
def assign_spice_model(
|
|
133
|
+
def assign_spice_model(
|
|
134
|
+
self,
|
|
135
|
+
file_path,
|
|
136
|
+
model_name=None,
|
|
137
|
+
sub_circuit_name=None,
|
|
138
|
+
terminal_pairs=None,
|
|
139
|
+
):
|
|
134
140
|
"""Assign Spice model to all components under this part name.
|
|
135
141
|
|
|
136
142
|
Parameters
|
|
137
143
|
----------
|
|
138
144
|
file_path : str
|
|
139
145
|
File path of the Spice model.
|
|
140
|
-
|
|
146
|
+
model_name : str, optional
|
|
141
147
|
Name of the Spice model.
|
|
148
|
+
sub_circuit_name : str, optional
|
|
149
|
+
Name of the sub circuit.
|
|
150
|
+
terminal_pairs : list, optional
|
|
151
|
+
list of terminal pairs.
|
|
142
152
|
|
|
143
153
|
Returns
|
|
144
154
|
-------
|
|
145
155
|
|
|
146
156
|
"""
|
|
147
157
|
for comp in list(self.components.values()):
|
|
148
|
-
comp.assign_spice_model(file_path, model_name)
|
|
158
|
+
comp.assign_spice_model(file_path, model_name, sub_circuit_name, terminal_pairs)
|
|
149
159
|
return True
|
|
150
160
|
|
|
151
161
|
@property
|
|
@@ -29,7 +29,12 @@ from pyedb.dotnet.clr_module import String
|
|
|
29
29
|
from pyedb.dotnet.edb_core.cell.primitive.primitive import Primitive
|
|
30
30
|
from pyedb.dotnet.edb_core.dotnet.database import PolygonDataDotNet
|
|
31
31
|
from pyedb.dotnet.edb_core.edb_data.edbvalue import EdbValue
|
|
32
|
-
from pyedb.dotnet.edb_core.general import
|
|
32
|
+
from pyedb.dotnet.edb_core.general import (
|
|
33
|
+
PadGeometryTpe,
|
|
34
|
+
convert_py_list_to_net_list,
|
|
35
|
+
pascal_to_snake,
|
|
36
|
+
snake_to_pascal,
|
|
37
|
+
)
|
|
33
38
|
from pyedb.generic.general_methods import generate_unique_name
|
|
34
39
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
35
40
|
|
|
@@ -406,19 +411,231 @@ class EDBPadstack(object):
|
|
|
406
411
|
>>> edb_padstack = edb.padstacks.definitions["MyPad"]
|
|
407
412
|
"""
|
|
408
413
|
|
|
414
|
+
PAD_SHAPE_PARAMETERS = {
|
|
415
|
+
"circle": ["diameter"],
|
|
416
|
+
"square": ["size"],
|
|
417
|
+
"rectangle": ["x_size", "y_size"],
|
|
418
|
+
"oval": ["x_size", "y_size", "corner_radius"],
|
|
419
|
+
"bullet": ["x_size", "y_size", "corner_radius"],
|
|
420
|
+
"round45": ["inner", "channel_width", "isolation_gap"],
|
|
421
|
+
"round90": ["inner", "channel_width", "isolation_gap"],
|
|
422
|
+
"no_geometry": [],
|
|
423
|
+
}
|
|
424
|
+
|
|
409
425
|
def __init__(self, edb_padstack, ppadstack):
|
|
426
|
+
self._edb_object = edb_padstack
|
|
410
427
|
self.edb_padstack = edb_padstack
|
|
411
428
|
self._ppadstack = ppadstack
|
|
412
|
-
self.pad_by_layer = {}
|
|
413
|
-
self.antipad_by_layer = {}
|
|
414
|
-
self.thermalpad_by_layer = {}
|
|
415
429
|
self._bounding_box = []
|
|
416
430
|
self._hole_params = None
|
|
431
|
+
|
|
432
|
+
@property
|
|
433
|
+
def pad_by_layer(self):
|
|
434
|
+
"""Regular pad property."""
|
|
435
|
+
temp = {}
|
|
436
|
+
for layer in self.via_layers:
|
|
437
|
+
temp[layer] = EDBPadProperties(self._edb_object, layer, 0, self)
|
|
438
|
+
return temp
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def antipad_by_layer(self):
|
|
442
|
+
"""Anti pad property."""
|
|
443
|
+
temp = {}
|
|
417
444
|
for layer in self.via_layers:
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
445
|
+
temp[layer] = EDBPadProperties(self._edb_object, layer, 1, self)
|
|
446
|
+
return temp
|
|
447
|
+
|
|
448
|
+
@property
|
|
449
|
+
def thermalpad_by_layer(self):
|
|
450
|
+
"""Thermal pad property."""
|
|
451
|
+
temp = {}
|
|
452
|
+
for layer in self.via_layers:
|
|
453
|
+
temp[layer] = EDBPadProperties(self._edb_object, layer, 2, self)
|
|
454
|
+
return temp
|
|
455
|
+
|
|
456
|
+
@property
|
|
457
|
+
def _padstack_def_data(self):
|
|
458
|
+
"""Get padstack definition data.
|
|
459
|
+
|
|
460
|
+
Returns
|
|
461
|
+
-------
|
|
462
|
+
|
|
463
|
+
"""
|
|
464
|
+
pstack_data = self._edb_object.GetData()
|
|
465
|
+
return self._edb.definition.PadstackDefData(pstack_data)
|
|
466
|
+
|
|
467
|
+
@_padstack_def_data.setter
|
|
468
|
+
def _padstack_def_data(self, value):
|
|
469
|
+
self._edb_object.SetData(value)
|
|
470
|
+
|
|
471
|
+
@property
|
|
472
|
+
def pad_parameters(self) -> dict:
|
|
473
|
+
"""Pad parameters.
|
|
474
|
+
|
|
475
|
+
Returns
|
|
476
|
+
-------
|
|
477
|
+
dict
|
|
478
|
+
params = {
|
|
479
|
+
'regular_pad': [
|
|
480
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0.1mm', 'offset_y': '0', 'rotation': '0',
|
|
481
|
+
'diameter': '0.5mm'}
|
|
482
|
+
],
|
|
483
|
+
'anti_pad': [
|
|
484
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
485
|
+
'diameter': '1mm'}
|
|
486
|
+
],
|
|
487
|
+
'thermal_pad': [
|
|
488
|
+
{'layer_name': '1_Top', 'shape': 'round90', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
489
|
+
'inner': '1mm', 'channel_width': '0.2mm', 'isolation_gap': '0.3mm'},
|
|
490
|
+
],
|
|
491
|
+
'hole': [
|
|
492
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
493
|
+
'diameter': '0.1499997mm'},
|
|
494
|
+
]
|
|
495
|
+
}
|
|
496
|
+
"""
|
|
497
|
+
pdef_data = self._padstack_def_data
|
|
498
|
+
pad_type_list = [
|
|
499
|
+
self._ppadstack._pedb._edb.Definition.PadType.RegularPad,
|
|
500
|
+
self._ppadstack._pedb._edb.Definition.PadType.AntiPad,
|
|
501
|
+
self._ppadstack._pedb._edb.Definition.PadType.ThermalPad,
|
|
502
|
+
self._ppadstack._pedb._edb.Definition.PadType.Hole,
|
|
503
|
+
]
|
|
504
|
+
data = {}
|
|
505
|
+
for pad_type in pad_type_list:
|
|
506
|
+
pad_type_name = pascal_to_snake(pad_type.ToString())
|
|
507
|
+
temp_list = []
|
|
508
|
+
for lyr_name in list(pdef_data.GetLayerNames()):
|
|
509
|
+
result = pdef_data.GetPadParametersValue(lyr_name, pad_type)
|
|
510
|
+
_, pad_shape, params, offset_x, offset_y, rotation = result
|
|
511
|
+
pad_shape = pascal_to_snake(pad_shape.ToString())
|
|
512
|
+
|
|
513
|
+
pad_params = {}
|
|
514
|
+
pad_params["layer_name"] = lyr_name
|
|
515
|
+
pad_params["shape"] = pad_shape
|
|
516
|
+
pad_params["offset_x"] = offset_x.ToString()
|
|
517
|
+
pad_params["offset_y"] = offset_y.ToString()
|
|
518
|
+
pad_params["rotation"] = rotation.ToString()
|
|
519
|
+
|
|
520
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[pad_shape]):
|
|
521
|
+
pad_params[i] = params[idx].ToString()
|
|
522
|
+
temp_list.append(pad_params)
|
|
523
|
+
data[pad_type_name] = temp_list
|
|
524
|
+
return data
|
|
525
|
+
|
|
526
|
+
@pad_parameters.setter
|
|
527
|
+
def pad_parameters(self, params: dict):
|
|
528
|
+
original_params = self.pad_parameters
|
|
529
|
+
pdef_data = self._padstack_def_data
|
|
530
|
+
|
|
531
|
+
pad_type_list = [
|
|
532
|
+
self._ppadstack._pedb._edb.Definition.PadType.RegularPad,
|
|
533
|
+
self._ppadstack._pedb._edb.Definition.PadType.AntiPad,
|
|
534
|
+
self._ppadstack._pedb._edb.Definition.PadType.ThermalPad,
|
|
535
|
+
self._ppadstack._pedb._edb.Definition.PadType.Hole,
|
|
536
|
+
]
|
|
537
|
+
for pad_type in pad_type_list:
|
|
538
|
+
pad_type_name = pascal_to_snake(pad_type.ToString())
|
|
539
|
+
rpp = params.get(pad_type_name, [])
|
|
540
|
+
for idx, layer_data in enumerate(rpp):
|
|
541
|
+
# Get geometry type from kwargs
|
|
542
|
+
p = layer_data.get("shape")
|
|
543
|
+
temp_param = []
|
|
544
|
+
|
|
545
|
+
# Handle Circle geometry type
|
|
546
|
+
if p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Circle.ToString()):
|
|
547
|
+
temp_param.append(layer_data["diameter"])
|
|
548
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Circle
|
|
549
|
+
|
|
550
|
+
# Handle Square geometry type
|
|
551
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Square.ToString()):
|
|
552
|
+
temp_param.append(layer_data["size"])
|
|
553
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Square
|
|
554
|
+
|
|
555
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Rectangle.ToString()):
|
|
556
|
+
temp_param.append(layer_data["x_size"])
|
|
557
|
+
temp_param.append(layer_data["y_size"])
|
|
558
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Rectangle
|
|
559
|
+
|
|
560
|
+
# Handle Oval geometry type
|
|
561
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Oval.ToString()):
|
|
562
|
+
temp_param.append(layer_data["x_size"])
|
|
563
|
+
temp_param.append(layer_data["y_size"])
|
|
564
|
+
temp_param.append(layer_data["corner_radius"])
|
|
565
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Oval
|
|
566
|
+
|
|
567
|
+
# Handle Bullet geometry type
|
|
568
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Bullet.ToString()):
|
|
569
|
+
temp_param.append(layer_data["x_size"])
|
|
570
|
+
temp_param.append(layer_data["y_size"])
|
|
571
|
+
temp_param.append(layer_data["corner_radius"])
|
|
572
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Bullet
|
|
573
|
+
|
|
574
|
+
# Handle Round45 geometry type
|
|
575
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Round45.ToString()):
|
|
576
|
+
temp_param.append(layer_data["inner"])
|
|
577
|
+
temp_param.append(layer_data["channel_width"])
|
|
578
|
+
temp_param.append(layer_data["isolation_gap"])
|
|
579
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Round45
|
|
580
|
+
|
|
581
|
+
# Handle Round90 geometry type
|
|
582
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Round90.ToString()):
|
|
583
|
+
temp_param.append(layer_data["inner"])
|
|
584
|
+
temp_param.append(layer_data["channel_width"])
|
|
585
|
+
temp_param.append(layer_data["isolation_gap"])
|
|
586
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Round90
|
|
587
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.NoGeometry.ToString()):
|
|
588
|
+
continue
|
|
589
|
+
|
|
590
|
+
# Set pad parameters for the current layer
|
|
591
|
+
default = original_params[pad_type_name]
|
|
592
|
+
pdef_data.SetPadParameters(
|
|
593
|
+
layer_data["layer_name"],
|
|
594
|
+
pad_type,
|
|
595
|
+
pad_shape,
|
|
596
|
+
convert_py_list_to_net_list([self._ppadstack._pedb.edb_value(i) for i in temp_param]),
|
|
597
|
+
self._ppadstack._pedb.edb_value(layer_data.get("offset_x", default[idx].get("offset_x", 0))),
|
|
598
|
+
self._ppadstack._pedb.edb_value(layer_data.get("offset_y", default[idx].get("offset_y", 0))),
|
|
599
|
+
self._ppadstack._pedb.edb_value(layer_data.get("rotation", default[idx].get("rotation", 0))),
|
|
600
|
+
)
|
|
601
|
+
self._padstack_def_data = pdef_data
|
|
602
|
+
|
|
603
|
+
@property
|
|
604
|
+
def hole_parameters(self):
|
|
605
|
+
pdef_data = self._padstack_def_data
|
|
606
|
+
_, hole_shape, params, offset_x, offset_y, rotation = pdef_data.GetHoleParametersValue()
|
|
607
|
+
hole_shape = pascal_to_snake(hole_shape.ToString())
|
|
608
|
+
|
|
609
|
+
hole_params = {}
|
|
610
|
+
hole_params["shape"] = hole_shape
|
|
611
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[hole_shape]):
|
|
612
|
+
hole_params[i] = params[idx].ToString()
|
|
613
|
+
hole_params["offset_x"] = offset_x.ToString()
|
|
614
|
+
hole_params["offset_y"] = offset_y.ToString()
|
|
615
|
+
hole_params["rotation"] = rotation.ToString()
|
|
616
|
+
return hole_params
|
|
617
|
+
|
|
618
|
+
@hole_parameters.setter
|
|
619
|
+
def hole_parameters(self, params: dict):
|
|
620
|
+
original_params = self.hole_parameters
|
|
621
|
+
pdef_data = self._padstack_def_data
|
|
622
|
+
|
|
623
|
+
temp_param = []
|
|
624
|
+
shape = params["shape"]
|
|
625
|
+
if shape == "no_geometry":
|
|
626
|
+
return # .net api doesn't tell how to set no_geometry shape.
|
|
627
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[shape]):
|
|
628
|
+
temp_param.append(params[i])
|
|
629
|
+
pedb_shape = getattr(self._ppadstack._pedb._edb.Definition.PadGeometryType, snake_to_pascal(shape))
|
|
630
|
+
|
|
631
|
+
pdef_data.SetHoleParameters(
|
|
632
|
+
pedb_shape,
|
|
633
|
+
convert_py_list_to_net_list([self._ppadstack._pedb.edb_value(i) for i in temp_param]),
|
|
634
|
+
self._ppadstack._pedb.edb_value(params.get("offset_x", original_params.get("offset_x", 0))),
|
|
635
|
+
self._ppadstack._pedb.edb_value(params.get("offset_y", original_params.get("offset_y", 0))),
|
|
636
|
+
self._ppadstack._pedb.edb_value(params.get("rotation", original_params.get("rotation", 0))),
|
|
637
|
+
)
|
|
638
|
+
self._padstack_def_data = pdef_data
|
|
422
639
|
|
|
423
640
|
@property
|
|
424
641
|
def instances(self):
|
|
@@ -455,7 +672,7 @@ class EDBPadstack(object):
|
|
|
455
672
|
list
|
|
456
673
|
List of layers.
|
|
457
674
|
"""
|
|
458
|
-
return self.
|
|
675
|
+
return self._padstack_def_data.GetLayerNames()
|
|
459
676
|
|
|
460
677
|
@property
|
|
461
678
|
def via_start_layer(self):
|
|
@@ -488,7 +705,7 @@ class EDBPadstack(object):
|
|
|
488
705
|
return self._hole_params
|
|
489
706
|
|
|
490
707
|
@property
|
|
491
|
-
def
|
|
708
|
+
def _hole_parameters(self):
|
|
492
709
|
"""Hole parameters.
|
|
493
710
|
|
|
494
711
|
Returns
|
|
@@ -496,8 +713,7 @@ class EDBPadstack(object):
|
|
|
496
713
|
list
|
|
497
714
|
List of the hole parameters.
|
|
498
715
|
"""
|
|
499
|
-
|
|
500
|
-
return self._hole_parameters
|
|
716
|
+
return self.hole_params[2]
|
|
501
717
|
|
|
502
718
|
@property
|
|
503
719
|
def hole_diameter(self):
|
|
@@ -540,7 +756,7 @@ class EDBPadstack(object):
|
|
|
540
756
|
if not hole_type:
|
|
541
757
|
hole_type = self.hole_type
|
|
542
758
|
if not params:
|
|
543
|
-
params = self.
|
|
759
|
+
params = self._hole_parameters
|
|
544
760
|
if isinstance(params, list):
|
|
545
761
|
params = convert_py_list_to_net_list(params)
|
|
546
762
|
if not offsetx:
|
|
@@ -709,14 +925,13 @@ class EDBPadstack(object):
|
|
|
709
925
|
str
|
|
710
926
|
Material of the hole.
|
|
711
927
|
"""
|
|
712
|
-
return self.
|
|
928
|
+
return self._padstack_def_data.GetMaterial()
|
|
713
929
|
|
|
714
930
|
@material.setter
|
|
715
931
|
def material(self, materialname):
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
self.edb_padstack.SetData(newPadstackDefinitionData)
|
|
932
|
+
pdef_data = self._padstack_def_data
|
|
933
|
+
pdef_data.SetMaterial(materialname)
|
|
934
|
+
self._padstack_def_data = pdef_data
|
|
720
935
|
|
|
721
936
|
@property
|
|
722
937
|
def padstack_instances(self):
|
|
@@ -736,36 +951,15 @@ class EDBPadstack(object):
|
|
|
736
951
|
-------
|
|
737
952
|
str
|
|
738
953
|
Possible returned values are ``"through"``, ``"begin_on_upper_pad"``,
|
|
739
|
-
``"end_on_lower_pad"``, ``"upper_pad_to_lower_pad"``, and ``"
|
|
954
|
+
``"end_on_lower_pad"``, ``"upper_pad_to_lower_pad"``, and ``"unknown_range"``.
|
|
740
955
|
"""
|
|
741
|
-
|
|
742
|
-
hole_ange_type = int(cloned_padstackdef_data.GetHoleRange())
|
|
743
|
-
if hole_ange_type == 0: # pragma no cover
|
|
744
|
-
return "through"
|
|
745
|
-
elif hole_ange_type == 1: # pragma no cover
|
|
746
|
-
return "begin_on_upper_pad"
|
|
747
|
-
elif hole_ange_type == 2: # pragma no cover
|
|
748
|
-
return "end_on_lower_pad"
|
|
749
|
-
elif hole_ange_type == 3: # pragma no cover
|
|
750
|
-
return "upper_pad_to_lower_pad"
|
|
751
|
-
else: # pragma no cover
|
|
752
|
-
return "undefined"
|
|
956
|
+
return pascal_to_snake(self._padstack_def_data.GetHoleRange().ToString())
|
|
753
957
|
|
|
754
958
|
@hole_range.setter
|
|
755
959
|
def hole_range(self, value):
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.Through)
|
|
760
|
-
elif value == "begin_on_upper_pad": # pragma no cover
|
|
761
|
-
cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.BeginOnUpperPad)
|
|
762
|
-
elif value == "end_on_lower_pad": # pragma no cover
|
|
763
|
-
cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.EndOnLowerPad)
|
|
764
|
-
elif value == "upper_pad_to_lower_pad": # pragma no cover
|
|
765
|
-
cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.UpperPadToLowerPad)
|
|
766
|
-
else: # pragma no cover
|
|
767
|
-
return
|
|
768
|
-
self.edb_padstack.SetData(cloned_padstackdef_data)
|
|
960
|
+
pdef_data = self._padstack_def_data
|
|
961
|
+
pdef_data.SetHoleRange(getattr(self._edb.definition.PadstackHoleRange, snake_to_pascal(value)))
|
|
962
|
+
self._padstack_def_data = pdef_data
|
|
769
963
|
|
|
770
964
|
def convert_to_3d_microvias(self, convert_only_signal_vias=True, hole_wall_angle=15, delete_padstack_def=True):
|
|
771
965
|
"""Convert actual padstack instance to microvias 3D Objects with a given aspect ratio.
|
|
@@ -984,7 +1178,7 @@ class EDBPadstack(object):
|
|
|
984
1178
|
)
|
|
985
1179
|
new_padstack_definition_data.SetHoleParameters(
|
|
986
1180
|
self.hole_type,
|
|
987
|
-
self.
|
|
1181
|
+
self._hole_parameters,
|
|
988
1182
|
self._get_edb_value(self.hole_offset_x),
|
|
989
1183
|
self._get_edb_value(self.hole_offset_y),
|
|
990
1184
|
self._get_edb_value(self.hole_rotation),
|
|
@@ -1128,6 +1322,18 @@ class EDBPadstack(object):
|
|
|
1128
1322
|
self.edb_padstack.SetData(new_padstack_data)
|
|
1129
1323
|
return True
|
|
1130
1324
|
|
|
1325
|
+
def set_properties(self, **kwargs):
|
|
1326
|
+
for k in ["hole_plating_thickness", "material", "hole_range", "pad_parameters", "hole_parameters"]:
|
|
1327
|
+
value = kwargs.get(k, False)
|
|
1328
|
+
if value:
|
|
1329
|
+
setattr(self, k, value)
|
|
1330
|
+
|
|
1331
|
+
def get_properties(self):
|
|
1332
|
+
kwargs = {}
|
|
1333
|
+
for k in ["hole_plating_thickness", "material", "hole_range", "pad_parameters", "hole_parameters"]:
|
|
1334
|
+
kwargs[k] = getattr(self, k)
|
|
1335
|
+
return kwargs
|
|
1336
|
+
|
|
1131
1337
|
|
|
1132
1338
|
class EDBPadstackInstance(Primitive):
|
|
1133
1339
|
"""Manages EDB functionalities for a padstack.
|
|
@@ -1562,30 +1768,6 @@ class EDBPadstackInstance(Primitive):
|
|
|
1562
1768
|
break
|
|
1563
1769
|
return layer_list
|
|
1564
1770
|
|
|
1565
|
-
@property
|
|
1566
|
-
def net_name(self):
|
|
1567
|
-
"""Net name.
|
|
1568
|
-
|
|
1569
|
-
Returns
|
|
1570
|
-
-------
|
|
1571
|
-
str
|
|
1572
|
-
Name of the net.
|
|
1573
|
-
"""
|
|
1574
|
-
return self._edb_padstackinstance.GetNet().GetName()
|
|
1575
|
-
|
|
1576
|
-
@net_name.setter
|
|
1577
|
-
def net_name(self, val):
|
|
1578
|
-
if not isinstance(val, str):
|
|
1579
|
-
try:
|
|
1580
|
-
self._edb_padstackinstance.SetNet(val.net_obj)
|
|
1581
|
-
except:
|
|
1582
|
-
raise AttributeError("Value inserted not found. Input has to be net name or net object.")
|
|
1583
|
-
elif val in self._pedb.nets.netlist:
|
|
1584
|
-
net = self._pedb.nets.nets[val].net_object
|
|
1585
|
-
self._edb_padstackinstance.SetNet(net)
|
|
1586
|
-
else:
|
|
1587
|
-
raise AttributeError("Value inserted not found. Input has to be net name or net object.")
|
|
1588
|
-
|
|
1589
1771
|
@property
|
|
1590
1772
|
def is_pin(self):
|
|
1591
1773
|
"""Determines whether this padstack instance is a layout pin.
|
|
@@ -158,7 +158,7 @@ class EdbPolygon(Primitive):
|
|
|
158
158
|
|
|
159
159
|
Examples
|
|
160
160
|
--------
|
|
161
|
-
>>> edbapp =
|
|
161
|
+
>>> edbapp = ansys.aedt.core.Edb("myproject.aedb")
|
|
162
162
|
>>> top_layer_polygon = [poly for poly in edbapp.modeler.polygons if poly.layer_name == "Top Layer"]
|
|
163
163
|
>>> for polygon in top_layer_polygon:
|
|
164
164
|
>>> polygon.move(vector=["2mm", "100um"])
|
|
@@ -191,7 +191,7 @@ class EdbPolygon(Primitive):
|
|
|
191
191
|
|
|
192
192
|
Examples
|
|
193
193
|
--------
|
|
194
|
-
>>> edbapp =
|
|
194
|
+
>>> edbapp = ansys.aedt.core.Edb("myproject.aedb")
|
|
195
195
|
>>> top_layer_polygon = [poly for poly in edbapp.modeler.polygons if poly.layer_name == "Top Layer"]
|
|
196
196
|
>>> for polygon in top_layer_polygon:
|
|
197
197
|
>>> polygon.rotate(angle=45)
|
pyedb/dotnet/edb_core/general.py
CHANGED
|
@@ -28,6 +28,7 @@ This module contains EDB general methods and related methods.
|
|
|
28
28
|
from __future__ import absolute_import # noreorder
|
|
29
29
|
|
|
30
30
|
import logging
|
|
31
|
+
import re
|
|
31
32
|
|
|
32
33
|
from pyedb.dotnet.clr_module import Dictionary, List, Tuple
|
|
33
34
|
|
|
@@ -140,6 +141,16 @@ def convert_net_list_to_py_list(netlist):
|
|
|
140
141
|
return pylist
|
|
141
142
|
|
|
142
143
|
|
|
144
|
+
def pascal_to_snake(s):
|
|
145
|
+
# Convert PascalCase to snake_case
|
|
146
|
+
return re.sub(r"(?<!^)(?=[A-Z])", "_", s).lower()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def snake_to_pascal(s):
|
|
150
|
+
# Split the string at underscores and capitalize the first letter of each part
|
|
151
|
+
return "".join(word.capitalize() for word in s.split("_"))
|
|
152
|
+
|
|
153
|
+
|
|
143
154
|
class PadGeometryTpe(Enum): # pragma: no cover
|
|
144
155
|
Circle = 1
|
|
145
156
|
Square = 2
|
|
@@ -51,6 +51,19 @@ class PolygonData:
|
|
|
51
51
|
else: # pragma: no cover
|
|
52
52
|
self._edb_object = edb_object
|
|
53
53
|
|
|
54
|
+
@property
|
|
55
|
+
def bounding_box(self):
|
|
56
|
+
"""Bounding box.
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
List[float]
|
|
61
|
+
List of coordinates for the component's bounding box, with the list of
|
|
62
|
+
coordinates in this order: [X lower left corner, Y lower left corner,
|
|
63
|
+
X upper right corner, Y upper right corner].
|
|
64
|
+
"""
|
|
65
|
+
return BBox(self._pedb, self._edb_object.GetBBox()).corner_points
|
|
66
|
+
|
|
54
67
|
@property
|
|
55
68
|
def arcs(self):
|
|
56
69
|
"""Get the Primitive Arc Data."""
|
pyedb/dotnet/edb_core/modeler.py
CHANGED
|
@@ -1460,6 +1460,9 @@ class Modeler(object):
|
|
|
1460
1460
|
self._pedb.active_layout, name, convert_py_list_to_net_list(pins)
|
|
1461
1461
|
)
|
|
1462
1462
|
if obj.IsNull():
|
|
1463
|
-
|
|
1464
|
-
|
|
1463
|
+
raise RuntimeError(f"Failed to create pin group {name}.")
|
|
1464
|
+
else:
|
|
1465
|
+
net_obj = [i.GetNet() for i in pins if not i.GetNet().IsNull()]
|
|
1466
|
+
if net_obj:
|
|
1467
|
+
obj.SetNet(net_obj[0])
|
|
1465
1468
|
return self._pedb.siwave.pin_groups[name]
|
|
@@ -79,16 +79,3 @@ class ObjBase(object):
|
|
|
79
79
|
@name.setter
|
|
80
80
|
def name(self, value):
|
|
81
81
|
self._edb_object.SetName(value)
|
|
82
|
-
|
|
83
|
-
@property
|
|
84
|
-
def bounding_box(self):
|
|
85
|
-
"""Bounding box.
|
|
86
|
-
|
|
87
|
-
Returns
|
|
88
|
-
-------
|
|
89
|
-
List[float]
|
|
90
|
-
List of coordinates for the component's bounding box, with the list of
|
|
91
|
-
coordinates in this order: [X lower left corner, Y lower left corner,
|
|
92
|
-
X upper right corner, Y upper right corner].
|
|
93
|
-
"""
|
|
94
|
-
return BBox(self._pedb, self._edb_object.GetBBox()).corner_points
|
pyedb/edb_logger.py
CHANGED
|
@@ -417,7 +417,7 @@ class EdbLogger(object):
|
|
|
417
417
|
|
|
418
418
|
logger = logging.getLogger("Global")
|
|
419
419
|
if any("aedt_logger" in str(i) for i in logger.filters):
|
|
420
|
-
from
|
|
420
|
+
from ansys.aedt.core.generic.settings import settings as pyaedt_settings
|
|
421
421
|
|
|
422
422
|
from pyedb.generic.settings import settings as pyaedb_settings
|
|
423
423
|
|