Skip to content

Commit ca56eb7

Browse files
Create port on trace (#784)
* temp * create edge port issue with .Net class * added edblib new dll * boolean for returning points only * temp * temp * create group fixed * create port on edge completed * create port on traces completed * black fix * doc string and export points only added * black style fixed * Update pyaedt/edb_core/hfss.py Co-authored-by: Maxime Rey <[email protected]> * Update pyaedt/edb_core/hfss.py Co-authored-by: Maxime Rey <[email protected]> * Update pyaedt/edb_core/hfss.py Co-authored-by: Maxime Rey <[email protected]> * Update pyaedt/edb_core/hfss.py Co-authored-by: Maxime Rey <[email protected]> * Update pyaedt/edb_core/hfss.py Co-authored-by: Maxime Rey <[email protected]> * Update pyaedt/edb_core/hfss.py Co-authored-by: Maxime Rey <[email protected]> * Update pyaedt/edb_core/hfss.py Co-authored-by: Maxime Rey <[email protected]> * Update pyaedt/edb_core/hfss.py Co-authored-by: Maxime Rey <[email protected]> * create component fix with ironpython * black fix Co-authored-by: Maxime Rey <[email protected]>
1 parent bd1b871 commit ca56eb7

File tree

3 files changed

+213
-21
lines changed

3 files changed

+213
-21
lines changed

pyaedt/dlls/EDBLib/DataModel.dll

-1 KB
Binary file not shown.

pyaedt/edb_core/components.py

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -737,28 +737,32 @@ def create_component_from_pins(self, pins, component_name, placement_layer=None)
737737
>>> edbapp.core_components.create_component_from_pins(pins, "A1New")
738738
739739
"""
740-
try:
741-
new_cmp = self._edb.Cell.Hierarchy.Component.Create(self._active_layout, component_name, component_name)
742-
new_group = self._edb.Cell.Hierarchy.Group.Create(self._active_layout, component_name)
743-
new_cmp.SetGroup(new_group)
744-
for pin in pins:
745-
pin.SetIsLayoutPin(True)
746-
conv_pin = self._components_methods.PinToConnectable(pin)
747-
add_result = new_group.AddMember(conv_pin)
748-
# new_cmp.SetGroup(new_group)
749-
if not placement_layer:
750-
new_cmp_layer_name = pins[0].GetPadstackDef().GetData().GetLayerNames()[0]
740+
# try:
741+
new_cmp = self._edb.Cell.Hierarchy.Component.Create(self._active_layout, component_name, component_name)
742+
new_group = self._edb.Cell.Hierarchy.Group.Create(self._active_layout, component_name)
743+
new_cmp.SetGroup(new_group)
744+
for pin in pins:
745+
pin.SetIsLayoutPin(True)
746+
if is_ironpython:
747+
test = new_group.AddMember(pin)
751748
else:
752-
new_cmp_layer_name = placement_layer
753-
new_cmp_placement_layer = self._edb.Cell.Layer.FindByName(
754-
self._active_layout.GetLayerCollection(), new_cmp_layer_name
755-
)
756-
new_cmp.SetPlacementLayer(new_cmp_placement_layer)
757-
# cmp_transform = System.Activator.CreateInstance(self._edb.Utility.)
758-
# new_cmp.SetTransform(cmp_transform)
759-
return (True, new_cmp)
760-
except:
761-
return (False, None)
749+
if not self._components_methods.AddPinToGroup(new_group, pin):
750+
aedt_exception_handler(
751+
"Failed to add pin {} to the group {}".format(pin.GetName(), new_group.GetName())
752+
)
753+
if not placement_layer:
754+
new_cmp_layer_name = pins[0].GetPadstackDef().GetData().GetLayerNames()[0]
755+
else:
756+
new_cmp_layer_name = placement_layer
757+
new_cmp_placement_layer = self._edb.Cell.Layer.FindByName(
758+
self._active_layout.GetLayerCollection(), new_cmp_layer_name
759+
)
760+
new_cmp.SetPlacementLayer(new_cmp_placement_layer)
761+
# cmp_transform = System.Activator.CreateInstance(self._edb.Utility.)
762+
# new_cmp.SetTransform(cmp_transform)
763+
return (True, new_cmp)
764+
# except:
765+
# return (False, None)
762766

763767
@aedt_exception_handler
764768
def set_component_model(self, componentname, model_type="Spice", modelpath=None, modelname=None):

pyaedt/edb_core/hfss.py

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
This module contains the `EdbHfss` class.
33
"""
44
from pyaedt.edb_core.general import convert_netdict_to_pydict
5+
from pyaedt.edb_core.general import convert_py_list_to_net_list
56
from pyaedt.generic.general_methods import aedt_exception_handler, generate_unique_name, is_ironpython
67

78

@@ -478,3 +479,190 @@ def create_hfss_ports_on_padstack(self, pinpos, portname=None):
478479
return True
479480
else:
480481
return False
482+
483+
@aedt_exception_handler
484+
def create_lumped_port_on_trace(
485+
self,
486+
nets=None,
487+
reference_layer=None,
488+
return_points_only=False,
489+
polygon_trace_threshhold=300e-6,
490+
digit_resolution=6,
491+
):
492+
"""Create an edge port on traces.
493+
494+
Parameters
495+
----------
496+
nets : list, optional
497+
List of nets, str or Edb net.
498+
499+
reference_layer : str, Edb layer.
500+
Name or Edb layer object.
501+
502+
return_points_only : bool, optional
503+
Use this boolean when you want to return only the points from the edges and not creating ports. Default
504+
value is ``False``.
505+
506+
polygon_trace_threshhold : float, optional
507+
Used only when selected nets are routed as polygon. The value gives the algorithm the threshold
508+
of the polygon width at the design border for considering placing an edge port. The default value is
509+
``300-e6``.
510+
511+
digit_resolution : int, optional
512+
The number of digits carried for the edges location accuracy. The default value is ``6``.
513+
514+
Returns
515+
-------
516+
bool
517+
``True`` when successful, ``False`` when failed.
518+
"""
519+
if not isinstance(nets, list):
520+
if isinstance(nets, str):
521+
nets = [self._edb.Cell.Net.FindByName(self._active_layout, nets)]
522+
elif isinstance(nets, self._edb.Cell.Net):
523+
nets = [nets]
524+
else:
525+
temp_nets = []
526+
for nn in nets:
527+
if isinstance(nn, str):
528+
temp_nets.append(self._edb.Cell.Net.FindByName(self._active_layout, nn))
529+
elif isinstance(nn, self._edb.Cell.Net):
530+
temp_nets.append(nn)
531+
nets = temp_nets
532+
edges_pts = []
533+
if nets:
534+
if isinstance(reference_layer, str):
535+
reference_layer = self._pedb.core_stackup.signal_layers[reference_layer]._layer
536+
if not isinstance(reference_layer, self._edb.Cell.ILayerReadOnly):
537+
return False
538+
layout = nets[0].GetLayout()
539+
layout_bbox = self.get_layout_bounding_box(layout, digit_resolution)
540+
for net in nets:
541+
net_primitives = list(net.Primitives)
542+
net_paths = [
543+
pp for pp in net_primitives if pp.GetPrimitiveType() == self._edb.Cell.Primitive.PrimitiveType.Path
544+
]
545+
net_poly = [
546+
pp
547+
for pp in net_primitives
548+
if pp.GetPrimitiveType() == self._edb.Cell.Primitive.PrimitiveType.Polygon
549+
]
550+
for path in net_paths:
551+
trace_path_pts = list(path.GetCenterLine().Points)
552+
for pt in trace_path_pts:
553+
_pt = [round(pt.X.ToDouble(), digit_resolution), round(pt.Y.ToDouble(), digit_resolution)]
554+
if bool(set(_pt) & set(layout_bbox)):
555+
if return_points_only:
556+
edges_pts.append(_pt)
557+
else:
558+
port_name = generate_unique_name("port")
559+
if not self._hfss_terminals.CreateEdgePort(path, pt, reference_layer, port_name):
560+
aedt_exception_handler(
561+
"edge port creation failed on point {}, {}".format(str(pt[0]), str(_pt[1]))
562+
)
563+
for poly in net_poly:
564+
pt_list = list(poly.GetPolygonData().Points)
565+
points_at_border = [
566+
pt
567+
for pt in pt_list
568+
if round(pt.X.ToDouble(), digit_resolution) in layout_bbox
569+
or round(pt.Y.ToDouble(), digit_resolution) in layout_bbox
570+
]
571+
pt_at_left = [
572+
pt for pt in points_at_border if round(pt.X.ToDouble(), digit_resolution) == layout_bbox[0]
573+
]
574+
pt_at_left_values = [pt.Y.ToDouble() for pt in pt_at_left]
575+
if pt_at_left_values:
576+
left_edge_length = abs(max(pt_at_left_values) - min(pt_at_left_values))
577+
if polygon_trace_threshhold >= left_edge_length > 0:
578+
if return_points_only:
579+
edges_pts.append(pt_at_left)
580+
else:
581+
port_name = generate_unique_name("port")
582+
if not self._hfss_terminals.CreateEdgePortOnPolygon(
583+
poly, convert_py_list_to_net_list(pt_at_left), reference_layer, port_name
584+
):
585+
aedt_exception_handler("Failed to create port on polygon {}".format(poly.GetName()))
586+
587+
pt_at_bottom = [
588+
pt for pt in points_at_border if round(pt.Y.ToDouble(), digit_resolution) == layout_bbox[1]
589+
]
590+
pt_at_bottom_values = [pt.X.ToDouble() for pt in pt_at_bottom]
591+
if pt_at_bottom_values:
592+
bot_edge_length = abs(max(pt_at_bottom_values) - min(pt_at_bottom_values))
593+
if polygon_trace_threshhold >= bot_edge_length > 0:
594+
if return_points_only:
595+
edges_pts.append(pt_at_bottom)
596+
else:
597+
port_name = generate_unique_name("port")
598+
if not self._hfss_terminals.CreateEdgePortOnPolygon(
599+
poly, convert_py_list_to_net_list(pt_at_bottom), reference_layer, port_name
600+
):
601+
aedt_exception_handler("Failed to create port on polygon {}".format(poly.GetName()))
602+
603+
pt_at_right = [
604+
pt for pt in points_at_border if round(pt.X.ToDouble(), digit_resolution) == layout_bbox[2]
605+
]
606+
pt_at_right_values = [pt.Y.ToDouble() for pt in pt_at_right]
607+
if pt_at_right_values:
608+
right_edge_length = abs(max(pt_at_right_values) - min(pt_at_right_values))
609+
if polygon_trace_threshhold >= right_edge_length > 0:
610+
if return_points_only:
611+
edges_pts.append(pt_at_right)
612+
else:
613+
port_name = generate_unique_name("port")
614+
if not self._hfss_terminals.CreateEdgePortOnPolygon(
615+
poly, convert_py_list_to_net_list(pt_at_right), reference_layer, port_name
616+
):
617+
aedt_exception_handler("Failed to create port on polygon {}".format(poly.GetName()))
618+
619+
pt_at_top = [
620+
pt for pt in points_at_border if round(pt.Y.ToDouble(), digit_resolution) == layout_bbox[3]
621+
]
622+
pt_at_top_values = [pt.X.ToDouble() for pt in pt_at_top]
623+
if pt_at_top_values:
624+
top_edge_length = abs(max(pt_at_top_values) - min(pt_at_top_values))
625+
if polygon_trace_threshhold >= top_edge_length > 0:
626+
if return_points_only:
627+
edges_pts.append(pt - pt_at_top)
628+
else:
629+
port_name = generate_unique_name("port")
630+
if not self._hfss_terminals.CreateEdgePortOnPolygon(
631+
poly, convert_py_list_to_net_list(pt_at_top), reference_layer, port_name
632+
):
633+
aedt_exception_handler("Failed to create port on polygon {}".format(poly.GetName()))
634+
if return_points_only:
635+
return edges_pts
636+
return True
637+
638+
@aedt_exception_handler
639+
def get_layout_bounding_box(self, layout=None, digit_resolution=6):
640+
"""Evaluate the layout bounding box.
641+
642+
Parameters
643+
----------
644+
layout :
645+
Edb layout.
646+
647+
digit_resolution : int, optional
648+
Digit Resolution. The default value is ``6``.
649+
Returns
650+
-------
651+
list
652+
[lower left corner X, lower left corner, upper right corner X, upper right corner Y]
653+
"""
654+
if layout == None:
655+
return False
656+
layout_obj_instances = layout.GetLayoutInstance().GetAllLayoutObjInstances()
657+
tuple_list = []
658+
for lobj in layout_obj_instances.Items:
659+
lobj_bbox = lobj.GetLayoutInstanceContext().GetBBox(False)
660+
tuple_list.append(lobj_bbox)
661+
_bbox = self._edb.Geometry.PolygonData.GetBBoxOfBoxes(convert_py_list_to_net_list(tuple_list))
662+
layout_bbox = [
663+
round(_bbox.Item1.X.ToDouble(), digit_resolution),
664+
round(_bbox.Item1.Y.ToDouble(), digit_resolution),
665+
round(_bbox.Item2.X.ToDouble(), digit_resolution),
666+
round(_bbox.Item2.Y.ToDouble(), digit_resolution),
667+
]
668+
return layout_bbox

0 commit comments

Comments
 (0)