Skip to content

Commit

Permalink
Create port on component (#656)
Browse files Browse the repository at this point in the history
* create port on component iter #1

* auto port creation iter #1

* auto port creation iter #1

* create port on component iter #2

* create port on component iter #2

* create port on component iter #2

* create port on component iter #2

* create port on component iter #2

* Fixed black

* Update pyaedt/edb_core/components.py

Co-authored-by: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com>

* create port on component iter #2

* create port on component iter #2

* create port on component iter #2

* create port on component iter #2

* create port on component iter #2

* try m black fix

* Update _unittest/test_00_EDB.py

* create ports on component unit test fix

* create ports on component unit test fix

* create ports on component unit test fix

* create ports on component unit test fix

* create ports on component unit test fix

* Update pyaedt/edb_core/components.py

* Fixed Bug in get_pin_from_component in Ironpython

* Fixed issue

Co-authored-by: Massimo Capodiferro <massimo.capodiferro@ansys.com>
Co-authored-by: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 21, 2021
1 parent 0807ad4 commit c538405
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 20 deletions.
254 changes: 235 additions & 19 deletions pyaedt/edb_core/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
from pyaedt import generate_unique_name, _retry_ntimes
from pyaedt.edb_core.general import convert_py_list_to_net_list
from pyaedt.generic.general_methods import aedt_exception_handler, get_filename_without_extension, is_ironpython
from pyaedt.generic.constants import FlipChipOrientation
from pyaedt.generic.constants import SourceType
from pyaedt.edb_core.EDB_Data import EDBComponent
from pyaedt.edb_core.padstack import EdbPadstacks

try:
import clr
Expand Down Expand Up @@ -71,6 +72,7 @@ def __init__(self, p_edb):
self._pins = {}
self._comps_by_part = {}
self._init_parts()
self._padstack = EdbPadstacks(self._pedb)

@property
def _logger(self):
Expand Down Expand Up @@ -400,7 +402,194 @@ def get_solder_ball_height(self, cmp):
return False

@aedt_exception_handler
def set_solder_ball(self, cmp, sball_height=100e-6, sball_diam=150e-6, orientation=FlipChipOrientation.Up):
def create_port_on_component(
self, component, net_list, port_type=SourceType.CoaxPort, do_pingroup=True, reference_net="gnd"
):
"""Create ports on given component.
Parameters
----------
component : str or self._edb.Cell.Hierarchy.Component
EDB component or str component name.
net_list : str or list of string.
The list of nets where ports have to be created on the component.
If net is not part of the component this one will be skipped.
port_type : SourceType enumerator, CoaxPort or CircuitPort
Define the type of port to be created. CoaxPort will auto generate solder balls.
CircuitPort will generate circuit ports on pins belonging to the net list.
do_pingroup : bool
True activate pingroup during port creation (only used with combination of CoaxPort),
False will take the closest reference pin and generate one port per signal pin.
refnet : string or list of string.
list of the reference net.
Returns
-------
double, bool
Salder ball height vale, ``False`` when failed.
Examples
--------
>>> from pyaedt import Edb
>>> edbapp = Edb("myaedbfolder")
>>> net_list = ["M_DQ<1>", "M_DQ<2>", "M_DQ<3>", "M_DQ<4>", "M_DQ<5>"]
>>> edbapp.core_components.create_port_on_component(cmp="U2A5", net_list=net_list,
>>> port_type=SourceType.CoaxPort, do_pingroup=False, refnet="GND")
"""
if isinstance(component, self._edb.Cell.Hierarchy.Component):
cmp = component.GetName()
if not isinstance(net_list, list):
net_list = [net_list]
for net in net_list:
if not isinstance(net, str):
try:
net_name = net.GetName()
if net_name != "":
net_list.append(net_name)
except:
pass
if reference_net in net_list:
net_list.remove(reference_net)
cmp_pins = self.get_pin_from_component(component, net_list)
if len(cmp_pins) == 0:
return False
pin_layers = cmp_pins[0].GetPadstackDef().GetData().GetLayerNames()

if port_type == SourceType.CoaxPort:
pad_params = self._padstack.get_pad_parameters(pin=cmp_pins[0], layername=pin_layers[0], pad_type=0)
sball_diam = min([self._edb_value(val).ToDouble() for val in pad_params[1]])
sb_height = sball_diam
self.set_solder_ball(component, sb_height, sball_diam)
for pin in cmp_pins:
self._padstack.create_coax_port(pin)

elif port_type == SourceType.CircPort:
ref_pins = self.get_pin_from_component(component, reference_net)
if do_pingroup:
pingroups = []
if len(ref_pins) == 1:
ref_pin_group_term = self._create_terminal(ref_pins[0])
else:
ref_pin_group = self.create_pingroup_from_pins(ref_pins)
ref_pin_group_term = self._create_pin_group_terminal(ref_pin_group[1])
if not ref_pin_group[0]:
return False
ref_pin_group_term.SetBoundaryType(self._edb.Cell.Terminal.BoundaryType.PortBoundary)
ref_pin_group_term.SetIsCircuitPort(True)
for net in net_list:
pins = [pin for pin in cmp_pins if pin.GetNet().GetName() == net]
pin_group = self.create_pingroup_from_pins(pins)
if pin_group[0]:
pingroups.append(pin_group[1])
pg_terminal = []
for pg in pingroups:
pg_term = self._create_pin_group_terminal(pg)
pg_terminal.append(pg_term)
for term in pg_terminal:
term.SetBoundaryType(self._edb.Cell.Terminal.BoundaryType.PortBoundary)
term.SetIsCircuitPort(True)
term.SetReferenceTerminal(ref_pin_group_term)
else:
for net in net_list:
pins = [pin for pin in cmp_pins if pin.GetNet().GetName().lower() == net]
for pin in pins:
ref_pin = self._get_closest_pin_from(pin, ref_pins)
ref_pin_term = self._create_terminal(ref_pin)
term = self._create_terminal(pin)
ref_pin_term.SetBoundaryType(self._edb.Cell.Terminal.BoundaryType.PortBoundary)
ref_pin_term.SetIsCircuitPort(True)
term.SetBoundaryType(self._edb.Cell.Terminal.BoundaryType.PortBoundary)
term.SetIsCircuitPort(True)
term.SetReferenceTerminal(ref_pin_term)
return True

@aedt_exception_handler
def _create_terminal(self, pin):
"""Create terminal on component pin.
Parameters
----------
pin : Edb padstack instance.
Returns
-------
Edb terminal.
"""

pin_pos = self._edb.Definition.Geometry.PointData()
pin_rot = 0.0
from_layer = self._edb.Cell.ILayerReadOnly
to_layer = self._edb.Cell.ILayerReadOnly
pin.GetLayerRange(from_layer, to_layer)
term_name = "{]_{}_{}".format(pin.GetComponent().GetName(), pin.GetNet().GetName(), pin.GetName())
term = self._edb.Cell.Terminal.PointTerminal.Create(
pin.GetLayout(), pin.GetNet(), term_name, pin_pos, from_layer
)
return term

@aedt_exception_handler
def _get_closest_pin_from(self, pin, ref_pinlist):
"""Returns the closest pin from given pin among the list of reference pins.
Parameters
----------
pin : Edb padstack instance.
ref_pinlist : list of reference edb pins.
Returns
-------
Edb pin.
"""
pin_position = self._edb.Geometry.PointData()
pin_rot = 0.0
pin.GetPositionAndRotation(pin_position, pin_rot)

distance = 1e3
closest_pin = ref_pinlist[0]
ref_pin_pos = self._edb.Geometry.PointData()
ref_pin_rot = 0.0
for ref_pin in ref_pinlist:
ref_pin.GetPositionAndRotation(ref_pin_pos, ref_pin_rot)
temp_distance = pin_position.Distance(ref_pin_pos)
if temp_distance < distance:
distance = temp_distance
closest_pin = ref_pin
return closest_pin

@aedt_exception_handler
def _create_pin_group_terminal(self, pingroup, isref=False):
"""Creates edb pin group terminal from given edb pin group.
Parameters
----------
pingroup : Edb pin group.
isref : bool
Returns
-------
Edb pin group terminal.
"""

layout = pingroup.GetLayout()
cmp_name = pingroup.GetComponent().GetName()
net_name = pingroup.GetNet().GetName()
term_name = pingroup.GetUniqueName(layout, "Pingroup_{0}_{1}".format(cmp_name, net_name))
pingroup_term = self._edb.Cell.Terminal.PinGroupTerminal.Create(
self._active_layout, pingroup.GetNet(), term_name, pingroup, isref
)
return pingroup_term

@aedt_exception_handler
def set_solder_ball(self, cmp, sball_height=100e-6, sball_diam=150e-6):
"""Define component solder ball ready for port assignment.
Parameters
Expand Down Expand Up @@ -433,14 +622,12 @@ def set_solder_ball(self, cmp, sball_height=100e-6, sball_diam=150e-6, orientati
cmp_type = cmp.GetComponentType()
if cmp_type == self._edb.Definition.ComponentType.IC:
die_prop = cmp_prop.GetDieProperty().Clone()
if orientation == FlipChipOrientation.Up:
if not die_prop.SetOrientation(self._edb.Definition.DieOrientation.ChipUp):
return False
else:
if self._is_top_component(cmp):
die_prop.SetOrientation(self._edb.Definition.DieOrientation.ChipDown)
else:
die_prop.SetOrientation(self._edb.Definition.DieOrientation.ChipUp)
if not cmp_prop.SetDieProperty(die_prop):
return False

solder_prop = cmp_prop.GetSolderBallProperty().Clone()
if not solder_prop.SetDiameter(self._edb_value(sball_diam), self._edb_value(sball_diam)):
return False
Expand All @@ -459,6 +646,28 @@ def set_solder_ball(self, cmp, sball_height=100e-6, sball_diam=150e-6, orientati
else:
return False

@aedt_exception_handler
def _is_top_component(self, cmp):
"""Test the component placment layer.
Parameters
----------
cmp : self._edb.Cell.Hierarchy.Component
Edb component.
Returns
-------
bool
``True`` when component placed on top layer, ``False`` on bottom layer.
"""
signal_layers = cmp.GetLayout().GetLayerCollection().Layers(self._edb.Cell.LayerTypeSet.SignalLayerSet)
if cmp.GetPlacementLayer() == signal_layers[0]:
return True
else:
return False

@aedt_exception_handler
def create_component_from_pins(self, pins, component_name, placement_layer=None):
"""Create a component from pins.
Expand Down Expand Up @@ -641,6 +850,7 @@ def create_pingroup_from_pins(self, pins, group_name=None):
if pingroup.IsNull():
return (False, None)
else:
pingroup.SetNet(pins[0].GetNet())
return (True, pingroup)

@aedt_exception_handler
Expand Down Expand Up @@ -968,27 +1178,33 @@ def get_pin_from_component(self, cmpName, netName=None, pinName=None):

cmp = self._edb.Cell.Hierarchy.Component.FindByName(self._active_layout, cmpName)
if netName:
if not isinstance(netName, list):
netName = [netName]
# pins = []
# cmp_obj = list(cmp.LayoutObjs)
# for p in cmp_obj:
# if p.GetObjType() == 1:
# if p.IsLayoutPin():
# pin_net_name = p.GetNet().GetName()
# if pin_net_name in netName:
# pins.append(p)
pins = [
p
for p in cmp.LayoutObjs
if p.GetObjType() == self._edb.Cell.LayoutObjType.PadstackInstance
and p.IsLayoutPin()
and p.GetNet().GetName() == netName
for p in list(cmp.LayoutObjs)
if int(p.GetObjType()) == 1 and p.IsLayoutPin() and p.GetNet().GetName() in netName
]
elif pinName:
if not isinstance(pinName, list):
pinName = [pinName]
pins = [
p
for p in cmp.LayoutObjs
if p.GetObjType() == self._edb.Cell.LayoutObjType.PadstackInstance
for p in list(cmp.LayoutObjs)
if int(p.GetObjType()) == 1
and p.IsLayoutPin()
and (self.get_aedt_pin_name(p) == str(pinName) or p.GetName() == str(pinName))
and (self.get_aedt_pin_name(p) == str(pinName) or p.GetName() in str(pinName))
]
else:
pins = [
p
for p in cmp.LayoutObjs
if p.GetObjType() == self._edb.Cell.LayoutObjType.PadstackInstance and p.IsLayoutPin()
]
pins = [p for p in list(cmp.LayoutObjs) if int(p.GetObjType()) == 1 and p.IsLayoutPin()]
return pins

@aedt_exception_handler
Expand Down
2 changes: 1 addition & 1 deletion pyaedt/edb_core/padstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def get_pinlist_from_component_and_net(self, refdes=None, netname=None):
return pinlist.Item2

@aedt_exception_handler
def get_pad_parameters(self, pin, layername, pad_type=None):
def get_pad_parameters(self, pin, layername, pad_type=0):
"""Get Padstack Parameters from Pin or Padstack Definition.
Parameters
Expand Down
6 changes: 6 additions & 0 deletions pyaedt/generic/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,12 @@ class FlipChipOrientation(object):
(Up, Down) = range(0, 2)


class SourceType(object):
"""Type of excitation enumerator."""

(CoaxPort, CircPort, LumpedPort, Vsource, Isource, Resistor, Inductor, Capacitor) = range(0, 8)


class SOLUTIONS(object):
"""Provides the names of default solution types."""

Expand Down

0 comments on commit c538405

Please sign in to comment.