Skip to content

Commit

Permalink
Improved cutout method and fix_disjoint nets method
Browse files Browse the repository at this point in the history
  • Loading branch information
maxcapodi78 authored and maxcapodi78 committed Nov 22, 2023
1 parent f3287dc commit f3c2f17
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 37 deletions.
99 changes: 65 additions & 34 deletions pyaedt/edb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,7 @@ def _create_extent(
smart_cut=False,
reference_list=[],
include_pingroups=True,
pins_to_preserve=None,
):
if extent_type in ["Conforming", self.edb_api.geometry.extent_type.Conforming, 1]:
if use_pyaedt_extent:
Expand All @@ -1423,7 +1424,7 @@ def _create_extent(
expansion_size,
smart_cut,
reference_list,
include_pingroups,
pins_to_preserve,
)
else:
_poly = self.layout.expanded_extent(
Expand All @@ -1448,7 +1449,7 @@ def _create_extent(
expansion_size,
smart_cut,
reference_list,
include_pingroups,
pins_to_preserve,
)
else:
_poly = self.layout.expanded_extent(
Expand All @@ -1473,65 +1474,73 @@ def _create_conformal(
round_extension,
smart_cutout=False,
reference_list=[],
include_pingroups=True,
pins_to_preserve=None,
):
names = []
_polys = []
for net in net_signals:
names.append(net.GetName())
if pins_to_preserve:
insts = self.padstacks.instances
for i in pins_to_preserve:
p = insts[i].position
pos_1 = [i - expansion_size for i in p]
pos_2 = [i + expansion_size for i in p]
plane = self.modeler.Shape("rectangle", pointA=pos_1, pointB=pos_2)
rectangle_data = self.modeler.shape_to_polygon_data(plane)
_polys.append(rectangle_data)

for prim in self.modeler.primitives:
if prim is not None and prim.net_name in names:
obj_data = prim.primitive_object.GetPolygonData().Expand(
expansion_size, tolerance, round_corner, round_extension
)
if obj_data:
_polys.extend(list(obj_data))
_polys.append(prim.primitive_object.GetPolygonData())
if smart_cutout:
_polys.extend(self._smart_cut(net_signals, reference_list, include_pingroups))
_poly_unite = self.edb_api.geometry.polygon_data.unite(_polys)
objs_data = self._smart_cut(reference_list, expansion_size)
_polys.extend(objs_data)
k = 0
delta = expansion_size / 10
while k < 4:
unite_polys = []
for i in _polys:
obj_data = i.Expand(expansion_size, tolerance, round_corner, round_extension)
if obj_data:
unite_polys.extend(list(obj_data))
_poly_unite = self.edb_api.geometry.polygon_data.unite(unite_polys)
if len(_poly_unite) == 1:
self.logger.info("Correctly computed Extension at first iteration.")
return _poly_unite[0]
k += 1
expansion_size += delta
if len(_poly_unite) == 1:
self.logger.info("Correctly computed Extension in {} iterations.".format(k))
return _poly_unite[0]
else:
self.logger.info("Failed to Correctly computed Extension.")
areas = [i.Area() for i in _poly_unite]
return _poly_unite[areas.index(max(areas))]

@pyaedt_function_handler()
def _smart_cut(self, net_signals, reference_list=[], include_pingroups=True):
def _smart_cut(self, reference_list=[], expansion_size=1e-12):
from pyaedt.generic.clr_module import Tuple

_polys = []
terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [0, 3, 4, 7, 8]]
locations = []
for term in terms:
if term.GetTerminalType().ToString() == "PadstackInstanceTerminal":
if term.GetParameters()[1].GetNet().GetName() in reference_list:
locations.append(self.padstacks.instances[term.GetParameters()[1].GetId()].position)
elif term.GetTerminalType().ToString() == "PointTerminal" and term.GetNet().GetName() in reference_list:
if term.GetTerminalType().ToString() == "PointTerminal" and term.GetNet().GetName() in reference_list:
pd = term.GetParameters()[1]
locations.append([pd.X.ToDouble(), pd.Y.ToDouble()])
if include_pingroups:
for reference in reference_list:
for pin in self.nets.nets[reference].padstack_instances:
if pin.pingroups:
locations.append(pin.position)
for point in locations:
pointA = self.edb_api.geometry.point_data(
self.edb_value(point[0] - 1e-12), self.edb_value(point[1] - 1e-12)
self.edb_value(point[0] - expansion_size), self.edb_value(point[1] - expansion_size)
)
pointB = self.edb_api.geometry.point_data(
self.edb_value(point[0] + 1e-12), self.edb_value(point[1] + 1e-12)
self.edb_value(point[0] + expansion_size), self.edb_value(point[1] + expansion_size)
)

points = Tuple[self.edb_api.geometry.geometry.PointData, self.edb_api.geometry.geometry.PointData](
pointA, pointB
)
_polys.append(self.edb_api.geometry.polygon_data.create_from_bbox(points))
for cname, c in self.components.instances.items():
if (
set(net_signals).intersection(c.nets)
and c.is_enabled
and c.model_type in ["SParameterModel", "SpiceModel", "NetlistModel"]
):
for pin in c.pins:
locations.append(pin.position)
return _polys

@pyaedt_function_handler()
Expand All @@ -1544,17 +1553,28 @@ def _create_convex_hull(
round_extension,
smart_cut=False,
reference_list=[],
include_pingroups=True,
pins_to_preserve=None,
):
names = []
_polys = []
for net in net_signals:
names.append(net.GetName())
if pins_to_preserve:
insts = self.padstacks.instances
for i in pins_to_preserve:
p = insts[i].position
pos_1 = [i - 1e-12 for i in p]
pos_2 = [i + 1e-12 for i in p]
plane = self.modeler.Shape("rectangle", pointA=pos_1, pointB=pos_2)
rectangle_data = self.modeler.shape_to_polygon_data(plane)
_polys.append(rectangle_data)
for prim in self.modeler.primitives:
if prim is not None and prim.net_name in names:
_polys.append(prim.primitive_object.GetPolygonData())
if smart_cut:
_polys.extend(self._smart_cut(net_signals, reference_list, include_pingroups))
objs_data = self._smart_cut(reference_list, expansion_size)
_polys.extend(objs_data)

_poly = self.edb_api.geometry.polygon_data.get_convex_hull_of_polygons(convert_py_list_to_net_list(_polys))
_poly = _poly.Expand(expansion_size, tolerance, round_corner, round_extension)[0]
return _poly
Expand Down Expand Up @@ -2027,6 +2047,17 @@ def _create_cutout_multithread(
):
pins_to_preserve.extend([i.id for i in el.pins.values()])
nets_to_preserve.extend(el.nets)
if include_pingroups:
for reference in reference_list:
for pin in self.nets.nets[reference].padstack_instances:
if pin.pingroups:
pins_to_preserve.append(pin.id)
if check_terminals:
terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [0, 3, 4, 7, 8]]
for term in terms:
if term.GetTerminalType().ToString() == "PadstackInstanceTerminal":
if term.GetParameters()[1].GetNet().GetName() in reference_list:
pins_to_preserve.append(term.GetParameters()[1].GetId())

for i in self.nets.nets.values():
name = i.name
Expand Down Expand Up @@ -2067,8 +2098,7 @@ def _create_cutout_multithread(
elif custom_extent:
_poly = custom_extent
else:
nets_cutout = [i for i in nets_to_preserve if i not in reference_list]
net_signals = [net.api_object for net in self.layout.nets if net.name in signal_list + nets_cutout]
net_signals = [net.api_object for net in self.layout.nets if net.name in signal_list]
_poly = self._create_extent(
net_signals,
extent_type,
Expand All @@ -2078,6 +2108,7 @@ def _create_cutout_multithread(
smart_cut=check_terminals,
reference_list=reference_list,
include_pingroups=include_pingroups,
pins_to_preserve=pins_to_preserve,
)
if extent_type in ["Conforming", self.edb_api.geometry.extent_type.Conforming, 1] and extent_defeature > 0:
_poly = _poly.Defeature(extent_defeature)
Expand Down
23 changes: 20 additions & 3 deletions pyaedt/edb_core/layout_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ def dc_shorts(self, net_list=None, fix=False):

@pyaedt_function_handler()
def disjoint_nets(
self, net_list=None, keep_only_main_net=False, clean_disjoints_less_than=0.0, order_by_area=False
self,
net_list=None,
keep_only_main_net=False,
clean_disjoints_less_than=0.0,
order_by_area=False,
keep_disjoint_pins=False,
):
"""Find and fix disjoint nets from a given netlist.
Expand All @@ -110,6 +115,8 @@ def disjoint_nets(
order_by_area : bool, optional
Whether if the naming order has to be by number of objects (fastest) or area (slowest but more accurate).
Default is ``False``.
keep_disjoint_pins : bool, optional
Whether if delete disjoints pins not connected to any other primitive or not. Default is ``False``.
Returns
-------
List
Expand Down Expand Up @@ -190,14 +197,24 @@ def area_calc(elem):
except KeyError:
pass
elif len(disjoints) == 1 and (
isinstance(obj_dict[disjoints[0]], EDBPadstackInstance)
or clean_disjoints_less_than
clean_disjoints_less_than
and "area" in dir(obj_dict[disjoints[0]])
and obj_dict[disjoints[0]].area() < clean_disjoints_less_than
):
try:
obj_dict[disjoints[0]].delete()
except KeyError:
pass
elif (
len(disjoints) == 1
and not keep_disjoint_pins
and isinstance(obj_dict[disjoints[0]], EDBPadstackInstance)
):
try:
obj_dict[disjoints[0]].delete()
except KeyError:
pass

else:
new_net_name = generate_unique_name(net, n=6)
net_obj = self._pedb.nets.find_or_create_net(new_net_name)
Expand Down

0 comments on commit f3c2f17

Please sign in to comment.