diff --git a/src/pyedb/configuration/cfg_boundaries.py b/src/pyedb/configuration/cfg_boundaries.py index d0b62363c2..c2ee3b1100 100644 --- a/src/pyedb/configuration/cfg_boundaries.py +++ b/src/pyedb/configuration/cfg_boundaries.py @@ -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: @@ -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() diff --git a/src/pyedb/configuration/cfg_common.py b/src/pyedb/configuration/cfg_common.py index ef57624878..bc08ccac42 100644 --- a/src/pyedb/configuration/cfg_common.py +++ b/src/pyedb/configuration/cfg_common.py @@ -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): diff --git a/src/pyedb/configuration/cfg_components.py b/src/pyedb/configuration/cfg_components.py index 35aa6fca75..a97ce3f8ed 100644 --- a/src/pyedb/configuration/cfg_components.py +++ b/src/pyedb/configuration/cfg_components.py @@ -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) @@ -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: @@ -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 = [] @@ -132,10 +81,15 @@ 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) @@ -143,5 +97,5 @@ 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 diff --git a/src/pyedb/configuration/cfg_data.py b/src/pyedb/configuration/cfg_data.py index 53d9a04091..5365e39f08 100644 --- a/src/pyedb/configuration/cfg_data.py +++ b/src/pyedb/configuration/cfg_data.py @@ -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", []) diff --git a/src/pyedb/configuration/cfg_operations.py b/src/pyedb/configuration/cfg_operations.py index ed31cbac5f..19e7c0f12e 100644 --- a/src/pyedb/configuration/cfg_operations.py +++ b/src/pyedb/configuration/cfg_operations.py @@ -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): @@ -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 {} diff --git a/src/pyedb/configuration/cfg_ports_sources.py b/src/pyedb/configuration/cfg_ports_sources.py index 5d4eac9301..feb549a94c 100644 --- a/src/pyedb/configuration/cfg_ports_sources.py +++ b/src/pyedb/configuration/cfg_ports_sources.py @@ -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): diff --git a/src/pyedb/configuration/configuration.py b/src/pyedb/configuration/configuration.py index 22747d747c..a48b90af2e 100644 --- a/src/pyedb/configuration/configuration.py +++ b/src/pyedb/configuration/configuration.py @@ -293,6 +293,8 @@ def get_data_from_db(self, **kwargs): data["operations"] = self.cfg_data.operations.get_data_from_db() if kwargs.get("padstacks", False): data["padstacks"] = self.cfg_data.padstacks.get_data_from_db() + if kwargs.get("boundaries", False): + data["boundaries"] = self.cfg_data.boundaries.get_data_from_db() return data @@ -307,6 +309,8 @@ def export( nets=True, pin_groups=True, operations=True, + components=True, + boundaries=True, ): """Export the configuration data from layout to a file. @@ -330,12 +334,14 @@ def export( Whether to export pin groups. operations : bool Whether to export operations. + components : bool + Whether to export component. + boundaries : bool + Whether to export boundaries. Returns ------- bool """ - file_path = file_path if isinstance(file_path, Path) else Path(file_path) - file_path = file_path if file_path.suffix == ".json" else file_path.with_suffix(".json") data = self.get_data_from_db( stackup=stackup, package_definitions=package_definitions, @@ -345,7 +351,16 @@ def export( nets=nets, pin_groups=pin_groups, operations=operations, + components=components, + boundaries=boundaries, ) + + file_path = file_path if isinstance(file_path, Path) else Path(file_path) + file_path = file_path.with_suffix(".json") if file_path.suffix == "" else file_path + with open(file_path, "w") as f: - json.dump(data, f, ensure_ascii=False, indent=4) + if file_path.suffix == ".json": + json.dump(data, f, ensure_ascii=False, indent=4) + else: + toml.dump(data, f) return True if os.path.isfile(file_path) else False diff --git a/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py b/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py index 7505a52ee4..cfd5e45ab0 100644 --- a/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py +++ b/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py @@ -33,6 +33,7 @@ from pyedb.dotnet.edb_core.cell.hierarchy.spice_model import SpiceModel from pyedb.dotnet.edb_core.definition.package_def import PackageDef from pyedb.dotnet.edb_core.edb_data.padstacks_data import EDBPadstackInstance +from pyedb.dotnet.edb_core.general import pascal_to_snake, snake_to_pascal try: import numpy as np @@ -1009,7 +1010,8 @@ def create_clearance_on_component(self, extra_soldermask_clearance=1e-4): void.is_negative = True return True - def get_model_properties(self): + @property + def model_properties(self): pp = {} c_p = self.component_property model = c_p.GetModel().Clone() @@ -1034,8 +1036,10 @@ def get_model_properties(self): temp["capacitance_enabled"] = rlc.CEnabled pin_pair_model.append(temp) elif model.GetModelType().ToString() == "SParameterModel": - s_parameter_model["reference_net"] = model.GetReferenceNet() - s_parameter_model["model_name"] = model.GetComponentModelName() + temp = dict() + temp["reference_net"] = model.GetReferenceNet() + temp["model_name"] = model.GetComponentModelName() + s_parameter_model.append(temp) elif model.GetModelType().ToString() == "SPICEModel": spice_model["model_name"] = model.GetModelName() spice_model["model_path"] = model.GetModelPath() @@ -1052,7 +1056,8 @@ def get_model_properties(self): pp["spice_model"] = spice_model return pp - def set_model_properties(self, **kwargs): + @model_properties.setter + def model_properties(self, kwargs): netlist_model = kwargs.get("netlist_model") pin_pair_model = kwargs.get("pin_pair_model") s_parameter_model = kwargs.get("s_parameter_model") @@ -1093,3 +1098,114 @@ def set_model_properties(self, **kwargs): spice_model["sub_circuit"], spice_model["terminal_pairs"], ) + + @property + def ic_die_properties(self): + temp = dict() + cp = self.component_property + c_type = self.type.lower() + if not c_type == "ic": + return temp + else: + ic_die_prop = cp.GetDieProperty().Clone() + die_type = pascal_to_snake(ic_die_prop.GetType().ToString()) + temp["type"] = die_type + if not die_type == "no_die": + temp["orientation"] = pascal_to_snake(ic_die_prop.GetOrientation()) + if die_type == "wire_bond": + temp["height"] = ic_die_prop.GetHeightValue().ToString() + return temp + + @ic_die_properties.setter + def ic_die_properties(self, kwargs): + cp = self.component_property + c_type = self.type.lower() + if not c_type == "ic": + return + else: + ic_die_prop = cp.GetDieProperty().Clone() + die_type = kwargs.get("type") + if not die_type == "no_die": + orientation = kwargs.get("orientation") + if orientation: + ic_die_prop.SetOrientation(getattr(self._edb.definition.DieType, snake_to_pascal(die_type))) + if die_type == "wire_bond": + height = kwargs.get("height") + if height: + ic_die_prop.SetHeight(self._pedb.edb_value(height)) + cp.SetDieProperty(ic_die_prop) + self.component_property = cp + + @property + def solder_ball_properties(self): + temp = dict() + cp = self.component_property + c_type = self.type.lower() + if c_type not in ["io", "other"]: + return temp + else: + solder_ball_prop = cp.GetSolderBallProperty().Clone() + _, diam, mid_diam = solder_ball_prop.GetDiameterValue() + height = solder_ball_prop.GetHeightValue().ToString() + shape = solder_ball_prop.GetShape().ToString() + uses_solder_ball = solder_ball_prop.UsesSolderball() + temp["uses_solder_ball"] = uses_solder_ball + temp["shape"] = pascal_to_snake(shape) + temp["diameter"] = diam.ToString() + temp["mid_diameter"] = mid_diam.ToString() + temp["height"] = height + return temp + + @solder_ball_properties.setter + def solder_ball_properties(self, kwargs): + cp = self.component_property + solder_ball_prop = cp.GetSolderBallProperty().Clone() + shape = kwargs.get("shape") + if shape: + solder_ball_prop.SetShape(getattr(self._edb.definition.SolderballShape, snake_to_pascal(shape))) + if shape == "cylinder": + diameter = kwargs["diameter"] + solder_ball_prop.SetDiameter(self._pedb.edb_value(diameter), self._pedb.edb_value(diameter)) + elif shape == "spheroid": + diameter = kwargs["diameter"] + mid_diameter = kwargs["mid_diameter"] + solder_ball_prop.SetDiameter(self._pedb.edb_value(diameter), self._pedb.edb_value(mid_diameter)) + else: + return + solder_ball_prop.SetHeight(self._get_edb_value(kwargs["height"])) + cp.SetSolderBallProperty(solder_ball_prop) + self.component_property = cp + + @property + def port_properties(self): + temp = dict() + cp = self.component_property + c_type = self.type.lower() + if c_type not in ["ic", "io", "other"]: + return temp + else: + port_prop = cp.GetPortProperty().Clone() + reference_height = port_prop.GetReferenceHeightValue().ToString() + reference_size_auto = port_prop.GetReferenceSizeAuto() + _, reference_size_x, reference_size_y = port_prop.GetReferenceSize() + temp["reference_height"] = reference_height + temp["reference_size_auto"] = reference_size_auto + temp["reference_size_x"] = str(reference_size_x) + temp["reference_size_y"] = str(reference_size_y) + return temp + + @port_properties.setter + def port_properties(self, kwargs): + cp = self.component_property + port_prop = cp.GetPortProperty().Clone() + height = kwargs.get("reference_height") + if height: + port_prop.SetReferenceHeight(self._pedb.edb_value(height)) + reference_size_auto = kwargs.get("reference_size_auto") + if reference_size_auto: + port_prop.SetReferenceSizeAuto(reference_size_auto) + reference_size_x = kwargs.get("reference_size_x", 0) + reference_size_y = kwargs.get("reference_size_y", 0) + port_prop.SetReferenceSize(self._pedb.edb_value(reference_size_x), self._pedb.edb_value(reference_size_y)) + cp.SetPortProperty(port_prop) + self.component_property = cp diff --git a/src/pyedb/dotnet/edb_core/cell/terminal/terminal.py b/src/pyedb/dotnet/edb_core/cell/terminal/terminal.py index 672deeec8f..854e1ba9c8 100644 --- a/src/pyedb/dotnet/edb_core/cell/terminal/terminal.py +++ b/src/pyedb/dotnet/edb_core/cell/terminal/terminal.py @@ -223,9 +223,10 @@ def ref_terminal(self): """Get reference terminal.""" edb_terminal = self._edb_object.GetReferenceTerminal() - terminal = self._pedb.terminals[edb_terminal.GetName()] - if not terminal.is_null: - return terminal + if not edb_terminal.IsNull(): + return self._pedb.terminals[edb_terminal.GetName()] + else: + return None @ref_terminal.setter def ref_terminal(self, value): diff --git a/src/pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py b/src/pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py index 548b92080d..c33a01243f 100644 --- a/src/pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +++ b/src/pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py @@ -22,7 +22,7 @@ from pyedb.dotnet.edb_core.edb_data.edbvalue import EdbValue from pyedb.dotnet.edb_core.edb_data.primitives_data import cast -from pyedb.dotnet.edb_core.general import convert_pytuple_to_nettuple +from pyedb.dotnet.edb_core.general import convert_pytuple_to_nettuple, pascal_to_snake class HfssExtentInfo: @@ -192,7 +192,7 @@ def dielectric_extent_size(self, value): @property def dielectric_extent_type(self): """Dielectric extent type.""" - return self._edb_hfss_extent_info.DielectricExtentType.ToString().lower() + return pascal_to_snake(self._edb_hfss_extent_info.DielectricExtentType.ToString()) @dielectric_extent_type.setter def dielectric_extent_type(self, value): @@ -204,7 +204,7 @@ def dielectric_extent_type(self, value): @property def extent_type(self): """Extent type.""" - return self._edb_hfss_extent_info.ExtentType.ToString().lower() + return pascal_to_snake(self._edb_hfss_extent_info.ExtentType.ToString()) @extent_type.setter def extent_type(self, value): diff --git a/tests/legacy/system/test_edb_components.py b/tests/legacy/system/test_edb_components.py index b3d5d35e4e..d06868bdc5 100644 --- a/tests/legacy/system/test_edb_components.py +++ b/tests/legacy/system/test_edb_components.py @@ -623,5 +623,5 @@ def test_properties(self, edb_examples): } ] } - edbapp.components["C378"].set_model_properties(**pp) - assert edbapp.components["C378"].get_model_properties() == pp + edbapp.components["C378"].model_properties = pp + assert edbapp.components["C378"].model_properties == pp diff --git a/tests/legacy/system/test_edb_configuration_2p0.py b/tests/legacy/system/test_edb_configuration_2p0.py index eab1001029..5fb3de92b3 100644 --- a/tests/legacy/system/test_edb_configuration_2p0.py +++ b/tests/legacy/system/test_edb_configuration_2p0.py @@ -417,11 +417,29 @@ def test_06_s_parameters(self, edb_examples): edbapp.close() def test_07_boundaries(self, edb_examples): - with open(self.local_input_folder / "boundaries.json") as f: - data = json.load(f) - + data = { + "boundaries": { + "open_region": True, + "open_region_type": "radiation", + "pml_visible": False, + "pml_operation_frequency": "5GHz", + "pml_radiation_factor": "10", + "dielectric_extent_type": "bounding_box", + # "dielectric_base_polygon": "", + "horizontal_padding": 0.0, + "honor_primitives_on_dielectric_layers": True, + "air_box_extent_type": "bounding_box", + # "air_box_base_polygon": "", + "air_box_truncate_model_ground_layers": False, + "air_box_horizontal_padding": 0.15, + "air_box_positive_vertical_padding": 1.0, + "air_box_negative_vertical_padding": 1.0, + } + } edbapp = edb_examples.get_si_verse() assert edbapp.configuration.load(data, apply_file=True) + data_from_db = edbapp.configuration.get_data_from_db(boundaries=True) + assert data == data_from_db edbapp.close() def test_08a_operations_cutout(self, edb_examples): @@ -920,7 +938,7 @@ def test_16_components_rlc(self, edb_examples): data = {"components": components} edbapp = edb_examples.get_si_verse() assert edbapp.configuration.load(data, apply_file=True) - assert edbapp.components["C375"].get_model_properties()["pin_pair_model"] == components[0]["pin_pair_model"] + assert edbapp.components["C375"].model_properties["pin_pair_model"] == components[0]["pin_pair_model"] edbapp.configuration.get_data_from_db(components=True) edbapp.close()