Skip to content

Create port on component #656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Dec 21, 2021
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
105fef7
create port on component iter #1
svandenb-dev Nov 30, 2021
6ad2f88
auto port creation iter #1
svandenb-dev Dec 1, 2021
1d0868b
auto port creation iter #1
svandenb-dev Dec 1, 2021
80bb682
create port on component iter #2
svandenb-dev Dec 16, 2021
32dc258
create port on component iter #2
svandenb-dev Dec 16, 2021
491de7f
Merge branch 'main' into create_port_on_component
svandenb-dev Dec 16, 2021
f3dcba0
create port on component iter #2
svandenb-dev Dec 16, 2021
53ac3ec
create port on component iter #2
svandenb-dev Dec 16, 2021
5ef245c
create port on component iter #2
svandenb-dev Dec 16, 2021
5539ea1
Merge branch 'main' into create_port_on_component
svandenb-dev Dec 16, 2021
e44ca0e
Merge branch 'main' into create_port_on_component
maxcapodi78 Dec 16, 2021
a61dd8c
Fixed black
maxcapodi78 Dec 16, 2021
828bad5
Update pyaedt/edb_core/components.py
svandenb-dev Dec 16, 2021
70b9af3
create port on component iter #2
svandenb-dev Dec 16, 2021
75cce60
create port on component iter #2
svandenb-dev Dec 16, 2021
82384e7
create port on component iter #2
svandenb-dev Dec 16, 2021
5e061a4
create port on component iter #2
svandenb-dev Dec 16, 2021
9128d2d
create port on component iter #2
svandenb-dev Dec 16, 2021
653223d
try m black fix
svandenb-dev Dec 16, 2021
ce39c35
Update _unittest/test_00_EDB.py
MaxJPRey Dec 17, 2021
d27d822
create ports on component unit test fix
svandenb-dev Dec 17, 2021
9dd14e4
create ports on component unit test fix
svandenb-dev Dec 17, 2021
2047b47
create ports on component unit test fix
svandenb-dev Dec 17, 2021
bd311fc
create ports on component unit test fix
svandenb-dev Dec 17, 2021
7229a74
create ports on component unit test fix
svandenb-dev Dec 17, 2021
7288e89
Update pyaedt/edb_core/components.py
MaxJPRey Dec 17, 2021
8b14d8b
Fixed Bug in get_pin_from_component in Ironpython
maxcapodi78 Dec 20, 2021
b6506a6
Fixed issue
maxcapodi78 Dec 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions _unittest/test_00_EDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from pyaedt import Edb
from pyaedt.edb_core.components import resistor_value_parser
from pyaedt.generic.filesystem import Scratch
from pyaedt.generic.constants import SourceType

test_project_name = "Galileo_edb"
bom_example = "bom_example.csv"
Expand Down Expand Up @@ -532,3 +533,9 @@ def test_68_flip_layer_stackup(self):

def test_69_create_solder_balls_on_component(self):
assert self.edbapp.core_components.set_solder_ball("U2A5")

def test_70_create_ports_on_component(self):
net_list = ["M_DQ<1>", "M_DQ<2>", "M_DQ<3>", "M_DQ<4>", "M_DQ<5>"]
assert self.edbapp.core_components.create_port_on_component(
cmp="U2A5", net_list=net_list, port_type=SourceType.CoaxPort, do_pingroup=False, refnet="GND"
)
253 changes: 234 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,193 @@ 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)

@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.

"""
Comment on lines +538 to +550
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""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.
"""
Comment on lines +569 to +580
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""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 +621,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 +645,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.


"""
Comment on lines +651 to +664
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""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 +849,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 +1177,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)
Comment on lines +1183 to +1190
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# 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 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 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 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