Skip to content
118 changes: 44 additions & 74 deletions src/pyedb/configuration/cfg_boundaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,97 +20,50 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from enum import Enum
from pyedb.configuration.cfg_common import CfgBase


class CfgBoundaries:
def __init__(self, pdata, boundaries_dict):
self._pedb = pdata._pedb
self._boundaries_dict = boundaries_dict
self.open_region = self._boundaries_dict.get("open_region", None)
self._map_open_region_type()
self.pml_visible = self._boundaries_dict.get("pml_visible", None)
self.pml_operation_frequency = self._boundaries_dict.get("pml_operation_frequency", None)
self.pml_radiation_factor = self._boundaries_dict.get("pml_radiation_factor", None)
self._map_dielectric_extend_type()
self.dielectric_base_polygon = self._boundaries_dict.get("dielectric_base_polygon", None)
self.horizontal_padding = self._boundaries_dict.get("horizontal_padding", None)
self.honor_primitives_on_dielectric_layers = self._boundaries_dict.get(
"honor_primitives_on_dielectric_layers", False
)
self._map_air_box_extend_type()
self.air_box_base_polygon = self._boundaries_dict.get("air_box_base_polygon", None)
self.air_box_truncate_model_ground_layers = self._boundaries_dict.get(
"air_box_truncate_model_ground_layers", None
)
self.air_box_horizontal_padding = self._boundaries_dict.get("air_box_horizontal_padding", None)
self.air_box_positive_vertical_padding = self._boundaries_dict.get("air_box_positive_vertical_padding", None)
self.air_box_negative_vertical_padding = self._boundaries_dict.get("air_box_negative_vertical_padding", None)

def _map_air_box_extend_type(self):
air_box_type = self._boundaries_dict.get("air_box_extents_type", None)
if air_box_type == "bounding_box":
self.air_box_extents_type = self.ExtentType.BOUNDING_BOX
elif air_box_type == "conformal":
self.air_box_extents_type = self.ExtentType.CONFORMAL
elif air_box_type == "convex_hull":
self.air_box_extents_type = self.ExtentType.CONVEX_HULL
elif air_box_type == "polygon":
self.air_box_extents_type = self.ExtentType.POLYGON
else:
self.air_box_extents_type = self.ExtentType.BOUNDING_BOX

def _map_open_region_type(self):
open_region = self._boundaries_dict.get("open_region_type", None)
if open_region == "radiation":
self.open_region_type = self.OpenRegionType.RADIATION
elif open_region == "pec":
self.open_region_type = self.OpenRegionType.PEC
else:
self.open_region_type = self.OpenRegionType.RADIATION

def _map_dielectric_extend_type(self):
extend_type = self._boundaries_dict.get("dielectric_extents_type", None)
if extend_type == "bounding_box":
self.dielectric_extents_type = self.ExtentType.BOUNDING_BOX
elif extend_type == "conformal":
self.dielectric_extents_type = self.ExtentType.CONFORMAL
elif extend_type == "convex_hull":
self.dielectric_extents_type = self.ExtentType.CONVEX_HULL
elif extend_type == "polygon":
self.dielectric_extents_type = self.ExtentType.POLYGON
else:
self.dielectric_extents_type = self.ExtentType.BOUNDING_BOX

class OpenRegionType(Enum):
RADIATION = 0
PEC = 1

class ExtentType(Enum):
BOUNDING_BOX = 0
CONFORMAL = 1
CONVEX_HULL = 2
POLYGON = 3
class CfgBoundaries(CfgBase):
def __init__(self, pedb, boundary_data):
self._pedb = pedb
self.open_region = boundary_data.get("open_region", None)
self.open_region_type = boundary_data.get("map_open_region_type", None)
self.pml_visible = boundary_data.get("pml_visible", None)
self.pml_operation_frequency = boundary_data.get("pml_operation_frequency", None)
self.pml_radiation_factor = boundary_data.get("pml_radiation_factor", None)
self.dielectric_extent_type = boundary_data.get("dielectric_extent_type", None)
# self.dielectric_base_polygon = self.**kwargs.get("dielectric_base_polygon", None)
self.horizontal_padding = boundary_data.get("horizontal_padding", None)
self.honor_primitives_on_dielectric_layers = boundary_data.get("honor_primitives_on_dielectric_layers", False)
self.air_box_extent_type = boundary_data.get("air_box_extent_type", None)
self.air_box_base_polygon = boundary_data.get("air_box_base_polygon", None)
self.air_box_truncate_model_ground_layers = boundary_data.get("air_box_truncate_model_ground_layers", None)
self.air_box_horizontal_padding = boundary_data.get("air_box_horizontal_padding", None)
self.air_box_positive_vertical_padding = boundary_data.get("air_box_positive_vertical_padding", None)
self.air_box_negative_vertical_padding = boundary_data.get("air_box_negative_vertical_padding", None)

def apply(self):
"""Imports boundary information from JSON."""
if self.open_region is not None:
self._pedb.hfss.hfss_extent_info.use_open_region = self.open_region
self._pedb.hfss.hfss_extent_info.open_region_type = self.open_region_type.name.lower()
if self.open_region_type:
self._pedb.hfss.hfss_extent_info.open_region_type = self.open_region_type.lower()
if self.pml_visible is not None:
self._pedb.hfss.hfss_extent_info.is_pml_visible = self.pml_visible
if self.pml_operation_frequency:
self._pedb.hfss.hfss_extent_info.operating_freq = self.pml_operation_frequency
if self.pml_radiation_factor:
self._pedb.hfss.hfss_extent_info.radiation_level = self.pml_radiation_factor
self._pedb.hfss.hfss_extent_info.extent_type = self.dielectric_extents_type.name.lower()
if self.dielectric_base_polygon:
self._pedb.hfss.hfss_extent_info.dielectric_base_polygon = self.dielectric_base_polygon
if self.dielectric_extent_type:
self._pedb.hfss.hfss_extent_info.extent_type = self.dielectric_extent_type.lower()
# if self.dielectric_base_polygon:
# self._pedb.hfss.hfss_extent_info.dielectric_base_polygon = self.dielectric_base_polygon
if self.horizontal_padding:
self._pedb.hfss.hfss_extent_info.dielectric_extent_size = float(self.horizontal_padding)
if self.honor_primitives_on_dielectric_layers is not None:
self._pedb.hfss.hfss_extent_info.honor_user_dielectric = self.honor_primitives_on_dielectric_layers
self._pedb.hfss.hfss_extent_info.extent_type = self.air_box_extents_type.name.lower()
if self.air_box_extent_type:
self._pedb.hfss.hfss_extent_info.extent_type = self.air_box_extent_type.lower()
if self.air_box_truncate_model_ground_layers is not None:
self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground = self.air_box_truncate_model_ground_layers
if self.air_box_horizontal_padding:
Expand All @@ -123,3 +76,20 @@ def apply(self):
self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent = float(
self.air_box_negative_vertical_padding
)

def get_data_from_db(self):
self.open_region = self._pedb.hfss.hfss_extent_info.use_open_region
self.open_region_type = self._pedb.hfss.hfss_extent_info.open_region_type
self.pml_visible = self._pedb.hfss.hfss_extent_info.is_pml_visible
self.pml_operation_frequency = self._pedb.hfss.hfss_extent_info.operating_freq.tostring
self.pml_radiation_factor = self._pedb.hfss.hfss_extent_info.radiation_level.tostring
self.dielectric_extent_type = self._pedb.hfss.hfss_extent_info.extent_type
# self.dielectric_base_polygon = self._pedb.hfss.hfss_extent_info.dielectric_base_polygon
self.horizontal_padding = self._pedb.hfss.hfss_extent_info.dielectric_extent_size
self.honor_primitives_on_dielectric_layers = self._pedb.hfss.hfss_extent_info.honor_user_dielectric
self.air_box_extent_type = self._pedb.hfss.hfss_extent_info.extent_type
self.air_box_truncate_model_ground_layers = self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground
self.air_box_horizontal_padding = self._pedb.hfss.hfss_extent_info.air_box_horizontal_extent
self.air_box_positive_vertical_padding = self._pedb.hfss.hfss_extent_info.air_box_positive_vertical_extent
self.air_box_negative_vertical_padding = self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent
return self.get_attributes()
2 changes: 1 addition & 1 deletion src/pyedb/configuration/cfg_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def get_attributes(self, exclude=None):
exclude = exclude if isinstance(exclude, list) else [exclude]
attrs = {i: j for i, j in attrs.items() if i not in exclude}
attrs = {i: j for i, j in attrs.items() if not i.startswith("_")}
attrs = {i: j for i, j in attrs.items() if j is not None}
attrs = {i: j for i, j in attrs.items() if j not in [None, [], {}]}
return attrs

def set_attributes(self, pedb_object):
Expand Down
104 changes: 29 additions & 75 deletions src/pyedb/configuration/cfg_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,6 @@
from pyedb.configuration.cfg_common import CfgBase


class CfgPortProperties(CfgBase):
def __init__(self, **kwargs):
self.reference_offset = kwargs.pop("reference_offset", 0)
self.reference_size_auto = kwargs.pop("reference_size_auto", 0)
self.reference_size_x = kwargs.pop("reference_size_x", 0)
self.reference_size_y = kwargs.pop("reference_size_y", 0)


class CfgSolderBallsProperties(CfgBase):
def __init__(self, **kwargs):
self.shape = kwargs.pop("shape", None)
self.diameter = kwargs.pop("diameter", None)
self.mid_diameter = kwargs.pop("mid_diameter", None)
self.height = kwargs.pop("height", None)
self.enabled = kwargs.pop("enabled", None)


class CfgRlcModel(CfgBase):
def __init__(self, **kwargs):
self.resistance = kwargs.get("resistance", None)
Expand All @@ -51,42 +34,17 @@ def __init__(self, **kwargs):


class CfgComponent(CfgBase):
protected_attributes = ["reference_designator", "definition", "location", "angle", "placement_layer"]

def __init__(self, **kwargs):
self.enabled = kwargs.get("enabled", None)

self.reference_designator = kwargs.get("reference_designator", None)
self.definition = kwargs.get("definition", None)
self.type = kwargs.get("part_type", None)
self.port_properties = CfgPortProperties(**kwargs["port_properties"]) if "port_properties" in kwargs else None
self.solder_ball_properties = (
CfgSolderBallsProperties(**kwargs["solder_ball_properties"]) if "solder_ball_properties" in kwargs else None
)
self.type = kwargs["part_type"].lower() if kwargs.get("part_type") else None
self.port_properties = kwargs.get("port_properties", {})
self.solder_ball_properties = kwargs.get("solder_ball_properties", {})
self.ic_die_properties = kwargs.get("ic_die_properties", {})
self.pin_pair_model = kwargs.get("pin_pair_model", None)

self.x_location, self.y_location = kwargs.get("location", [None, None])
self.angle = kwargs.get("angle", None)
self.placement_layer = kwargs.get("placement_layer", None)

def export_properties(self):
"""Export component properties.

Returns
-------
Dict
"""
data_comp = {}
data_comp["enabled"] = self.enabled
data_comp["reference_designator"] = self.reference_designator
data_comp["definition"] = self.definition
data_comp["type"] = self.type
data_comp["pin_pair_model"] = self.pin_pair_model
data_comp["x_location"] = self.x_location
data_comp["y_location"] = self.y_location
# data_comp["angle"] = self.angle
data_comp["placement_layer"] = self.placement_layer
return data_comp
self.spice_model = kwargs.get("spice_model", None)
self.s_parameter_model = kwargs.get("s_parameter_model", None)


class CfgComponents:
Expand All @@ -98,31 +56,22 @@ def apply(self):
comps_in_db = self._pedb.components
for comp in self.components:
c_db = comps_in_db[comp.reference_designator]

for attr, value in comp.get_attributes().items(): # All component properties
if attr == "solder_ball_properties":
solder_ball_properties = value
port_properties = comp.port_properties
self._pedb.components.set_solder_ball(
component=comp.reference_designator,
sball_diam=solder_ball_properties.diameter,
sball_mid_diam=solder_ball_properties.mid_diameter,
sball_height=solder_ball_properties.height,
shape=solder_ball_properties.shape,
auto_reference_size=port_properties.reference_size_auto,
reference_height=port_properties.reference_offset,
reference_size_x=port_properties.reference_size_x,
reference_size_y=port_properties.reference_size_y,
)
elif attr == "port_properties":
pass
elif attr == "pin_pair_model":
c_db.set_model_properties(pin_pair_model=comp.pin_pair_model)
else:
if attr in dir(c_db):
setattr(c_db, attr, value)
else:
raise AttributeError(f"'{attr}' is not valid component attribute.")
if comp.definition:
c_db.definition = comp.definition
if comp.type:
c_db.type = comp.type
if comp.solder_ball_properties:
c_db.solder_ball_properties = comp.solder_ball_properties
if comp.port_properties:
c_db.port_properties = comp.port_properties
if comp.ic_die_properties:
c_db.set_ic_die_properties = comp.ic_die_properties
if comp.pin_pair_model:
c_db.model_properties = {"pin_pair_model": comp.pin_pair_model}
if comp.spice_model:
c_db.model_properties = {"spice_model": comp.spice_model}
if comp.s_parameter_model:
c_db.model_properties = {"s_parameter_model": comp.s_parameter_model}

def _load_data_from_db(self):
self.components = []
Expand All @@ -132,16 +81,21 @@ def _load_data_from_db(self):
enabled=comp.enabled,
reference_designator=comp.name,
part_type=comp.type,
pin_pair_model=comp.get_model_properties().get("pin_pair_model"),
pin_pair_model=comp.model_properties.get("pin_pair_model"),
spice_model=comp.model_properties.get("spice_model"),
s_parameter_model=comp.model_properties.get("s_parameter_model"),
definition=comp.component_def,
location=comp.location,
placement_layer=comp.placement_layer,
solder_ball_properties=comp.solder_ball_properties,
ic_die_properties=comp.ic_die_properties,
port_properties=comp.port_properties,
)
self.components.append(cfg_comp)

def get_data_from_db(self):
self._load_data_from_db()
data = []
for comp in self.components:
data.append(comp.export_properties())
data.append(comp.get_attributes())
return data
4 changes: 1 addition & 3 deletions src/pyedb/configuration/cfg_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ def __init__(self, pedb, **kwargs):
self._pedb = pedb
self.general = CfgGeneral(self, kwargs.get("general", None))

self.boundaries = {}
if kwargs.get("boundaries", None):
self.boundaries = CfgBoundaries(self, kwargs.get("boundaries", None))
self.boundaries = CfgBoundaries(self._pedb, kwargs.get("boundaries", {}))

self.nets = CfgNets(
self, kwargs.get("nets", {}).get("signal_nets", []), kwargs.get("nets", {}).get("power_ground_nets", [])
Expand Down
24 changes: 14 additions & 10 deletions src/pyedb/configuration/cfg_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,20 @@ def __init__(self, pedb, **kwargs):

def get_data_from_db(self):
if "pyedb_cutout" in self._pedb.stackup.all_layers:
poly = self._pedb.layout.find_primitive(layer_name="pyedb_cutout")[0]
self.custom_extent = poly.polygon_data.points
polygons = self._pedb.layout.find_primitive(layer_name="pyedb_cutout")
if polygons:
poly = polygons[0]
self.custom_extent = poly.polygon_data.points

net_names = []
for name, obj in self._pedb.nets.nets.items():
if obj.primitives[0].layer.name == "pyedb_cutout":
continue
if len(obj.primitives) > 0:
net_names.append(name)
net_names = []
for name, obj in self._pedb.nets.nets.items():
if obj.primitives[0].layer.name == "pyedb_cutout":
continue
if len(obj.primitives) > 0:
net_names.append(name)

self.reference_list = []
self.signal_list = net_names
self.reference_list = []
self.signal_list = net_names
return self.export_properties()

def export_properties(self):
Expand Down Expand Up @@ -95,3 +97,5 @@ def get_data_from_db(self):
data_from_db = self.op_cutout.get_data_from_db()
if data_from_db:
return {"cutout": data_from_db}
else:
return {}
6 changes: 4 additions & 2 deletions src/pyedb/configuration/cfg_ports_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,15 @@ def create(self):
return circuit_elements

def export_properties(self):
return {
data = {
"name": self.name,
"type": self.type,
"reference_designator": self.reference_designator,
"positive_terminal": self.positive_terminal_info.export_properties(),
"negative_terminal": self.negative_terminal_info.export_properties(),
}
if self.negative_terminal_info:
data.update({"negative_terminal": self.negative_terminal_info.export_properties()})
return data


class CfgSource(CfgCircuitElement):
Expand Down
Loading
Loading