Skip to content

Commit

Permalink
Improve h3d layout methods (#4451)
Browse files Browse the repository at this point in the history
Co-authored-by: maxcapodi78 <Shark78>
Co-authored-by: Samuel Lopez <[email protected]>
Co-authored-by: Maxime Rey <[email protected]>
Co-authored-by: Kathy Pippert <[email protected]>
  • Loading branch information
4 people authored Apr 4, 2024
1 parent 36526e7 commit 3012455
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 24 deletions.
14 changes: 13 additions & 1 deletion _unittest/test_01_3dlayout_edb.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ def test_15_3dplacement(self):

def test_16_differential_ports(self):
self.aedtapp.set_active_design(self.design_name)
pins = self.aedtapp.modeler.components["R3"].pins
pins = list(self.aedtapp.modeler.components["R3"].pins.keys())
assert self.aedtapp.create_differential_port(pins[0], pins[1], "test_differential", deembed=True)
assert "test_differential" in self.aedtapp.port_list

Expand Down Expand Up @@ -376,3 +376,15 @@ def test_22_change_design_settings(self):
assert (
self.aedtapp.get_oo_property_value(self.aedtapp.odesign, "Design Settings", "DCExtrapolation") == "Advanced"
)

def test_23_dissolve_element(self):
comp = self.aedtapp.modeler.components["D1"]
pins = {name: pin for name, pin in comp.pins.items() if name in ["D1-1", "D1-2", "D1-7"]}
self.aedtapp.dissolve_component("D1")
comp = self.aedtapp.modeler.create_components_on_pins(list(pins.keys()))
nets = [
list(pins.values())[0].net_name,
list(pins.values())[1].net_name,
]
assert self.aedtapp.create_ports_on_component_by_nets(comp.name, nets)
assert self.aedtapp.create_pec_on_component_by_nets(comp.name, "GND")
55 changes: 54 additions & 1 deletion pyaedt/hfss3dlayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,25 @@ def create_wave_port_from_two_conductors(self, primivitivenames=[""], edgenumber
else:
return False

@pyaedt_function_handler()
def dissolve_component(self, component_name):
"""Dissolve a component and remove it from 3D Layout.
Parameters
----------
component_name : str
Name of the component.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
"""
self.oeditor.DissolveComponents(["NAME:elements", component_name])
return True

@pyaedt_function_handler()
def create_ports_on_component_by_nets(
self,
Expand Down Expand Up @@ -407,9 +426,43 @@ def create_ports_on_component_by_nets(
ports.append(bound)
return ports

@pyaedt_function_handler()
def create_pec_on_component_by_nets(
self,
component_name,
nets,
):
"""Create a PEC connection on a component for a list of nets.
Parameters
----------
component_name : str
Component name.
nets : str, list
Nets to include.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
References
----------
>>> oEditor.CreateEdgePort
"""
if isinstance(nets, list):
pass
else:
nets = [nets]
net_array = ["NAME:Nets"] + nets
self.oeditor.CreatePortsOnComponentsByNet(["NAME:Components", component_name], net_array, "PEC", "0", "0", "0")
return True

@pyaedt_function_handler()
def create_differential_port(self, via_signal, via_reference, port_name, deembed=True):
"""Create a new differential port.
"""Create a differential port.
Parameters
----------
Expand Down
2 changes: 1 addition & 1 deletion pyaedt/modeler/modelerpcb.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ def set_spice_model(self, component_name, model_path, model_name=None, subcircui
pinNames.remove(pinNames[0])
pinNames.remove(pinNames[0])
break
componentPins = self.components[component_name].pins
componentPins = list(self.components[component_name].pins.keys())
componentPins.reverse()
if not pin_map:
pin_map = []
Expand Down
54 changes: 54 additions & 0 deletions pyaedt/modeler/pcb/Primitives3DLayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,60 @@ def place_3d_component(
self.oeditor.CreatePortsOnComponentsByNet(["NAME:Components", comp.name], [], "Port", "0", "0", "0")
return comp #

@pyaedt_function_handler()
def create_components_on_pins(
self,
pins,
definition_name=None,
component_type="Other",
ref_des="U100",
):
"""Create a component based on a pin list.
Parameters
----------
pins : list
Pins to include in the new component.
definition_name : str, optional
Name of the component definition. If no name is provided, a
name is automatically assigned.
component_type : str, optional
Component type. The default is ``"Other"``.
ref_des : str, optional
Reference designator. The default is ``"U100"``.
Returns
-------
:class:`pyaedt.modeler.cad.object3dlayout.Components3DLayout`
"""
if not definition_name:
definition_name = generate_unique_name("COMP")
placement_layer = list(self.layers.signals.keys())[0]
for pin in self.pins.items():
if pin[0] == pins[0]:
placement_layer = pin[1].start_layer
break
comp_name = self.modeler.oeditor.CreateComponent(
[
"NAME:Contents",
"isRCS:=",
True,
"definition_name:=",
definition_name,
"type:=",
component_type,
"ref_des:=",
ref_des,
"placement_layer:=",
placement_layer,
"elements:=",
pins,
]
)
comp = Components3DLayout(self, comp_name.split(";")[-1])
return comp

def create_text(self, text, position, placement_layer="PostProcessing", angle=0, font_size=12):
"""Create a text primitive object.
Expand Down
59 changes: 38 additions & 21 deletions pyaedt/modeler/pcb/object3dlayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ def __init__(self, primitives, name="", edb_object=None):
Objec3DLayout.__init__(self, primitives, "component")
self.name = name
self.edb_object = edb_object
self._pins = {}

@property
def part(self):
Expand Down Expand Up @@ -629,7 +630,13 @@ def set_die_type(

@pyaedt_function_handler()
def set_solderball(
self, solderball_type="Cyl", diameter="0.1mm", mid_diameter="0.1mm", height="0.2mm", material="solder"
self,
solderball_type="Cyl",
diameter="0.1mm",
mid_diameter="0.1mm",
height="0.2mm",
material="solder",
reference_offset=None,
):
"""Set solderball on the active component.
Expand All @@ -648,6 +655,8 @@ def set_solderball(
Ball height. The default is height="0.2mm".
material : str, optional
Ball material. The default is ``"solder"``.
reference_offset : str, optional.
Reference offset for port creation. The default is ``"0mm"``
Returns
-------
Expand All @@ -656,28 +665,30 @@ def set_solderball(
"""
if self._part_type_id not in [0, 4, 5]:
return False
props = self._oeditor.GetComponentInfo(self.name)
model = ""
for p in props:
if "PortProp(" in p:
model = p
break
s = r".+PortProp\(rh='(.+?)', rsa=(.+?), rsx='(.+?)', rsy='(.+?)'\)"
m = re.search(s, model)
rsx = "0"
rsy = "0"
rsa = True
rh = "0"
if m:
rh = m.group(1)
rsx = m.group(3)
rsy = m.group(4)
if m.group(2) == "false":
rsa = False
if reference_offset:
rh = reference_offset
if self._part_type_id == 4:
prop_name = "ICProp:="
if not self.die_enabled:
self.set_die_type()
props = self._oeditor.GetComponentInfo(self.name)
model = ""
for p in props:
if "PortProp(" in p:
model = p
break
s = r".+PortProp\(rh='(.+?)', rsa=(.+?), rsx='(.+?)', rsy='(.+?)'\)"
m = re.search(s, model)
rh = "0"
rsx = "0"
rsy = "0"
rsa = True
if m:
rh = m.group(1)
rsx = m.group(3)
rsy = m.group(4)
if m.group(2) == "false":
rsa = False
s = r".+DieProp\(dt=(.+?), do=(.+?), dh='(.+?)', lid=(.+?)\)"
m = re.search(s, model)
dt = 0
Expand Down Expand Up @@ -739,6 +750,8 @@ def set_solderball(
"sbn:=",
material,
],
"PortProp:=",
["rh:=", rh, "rsa:=", rsa, "rsx:=", rsx, "rsy:=", rsy],
],
],
]
Expand All @@ -750,9 +763,13 @@ def pins(self):
Returns
-------
List of str
dict
Dictionary of pins.
"""
return list(self._oeditor.GetComponentPins(self.name))
if self._pins:
return self._pins
self._pins = {i: Pins3DLayout(self._primitives, i) for i in list(self._oeditor.GetComponentPins(self.name))}
return self._pins

@property
def model(self):
Expand Down

0 comments on commit 3012455

Please sign in to comment.