From 13fa540bdc0554913fcc4301c8a7bf93724479fa Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Sat, 19 Oct 2024 09:03:07 +0200 Subject: [PATCH 01/14] REFACTOR: edb padstacks --- src/pyedb/configuration/cfg_padstacks.py | 312 ++++++++++++++---- src/pyedb/configuration/configuration.py | 35 +- .../edb_core/edb_data/padstacks_data.py | 213 +----------- 3 files changed, 279 insertions(+), 281 deletions(-) diff --git a/src/pyedb/configuration/cfg_padstacks.py b/src/pyedb/configuration/cfg_padstacks.py index 3b692b9ccd..b0f49d0d63 100644 --- a/src/pyedb/configuration/cfg_padstacks.py +++ b/src/pyedb/configuration/cfg_padstacks.py @@ -20,7 +20,12 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from pyedb.configuration.cfg_common import CfgBase +from pyedb.dotnet.edb_core.general import ( + PadGeometryTpe, + convert_py_list_to_net_list, + pascal_to_snake, + snake_to_pascal, +) class CfgPadstacks: @@ -30,73 +35,61 @@ def __init__(self, pedb, padstack_dict=None): self._pedb = pedb self.definitions = [] self.instances = [] + + if padstack_dict: + padstack_defs_layout = self._pedb.padstacks.definitions for pdef in padstack_dict.get("definitions", []): - self.definitions.append(Definition(**pdef)) + obj = padstack_defs_layout[pdef["name"]] + self.definitions.append(Definition(self._pedb, obj, **pdef)) + + inst_from_layout = self._pedb.padstacks.instances_by_name for inst in padstack_dict.get("instances", []): - self.instances.append(Instance(**inst)) + obj = inst_from_layout[inst["name"]] + self.instances.append(Instance(self._pedb, obj, **inst)) + + def clean(self): + self.definitions = [] + self.instances = [] def apply(self): """Apply padstack definition and instances on layout.""" if self.definitions: - padstack_defs_layout = self._pedb.padstacks.definitions for pdef in self.definitions: - pdef_layout = padstack_defs_layout[pdef.name] - pdef_layout.set_properties(**pdef.get_attributes()) + pdef.set_parameters_to_edb() if self.instances: - instances_layout = self._pedb.padstacks.instances_by_name for inst in self.instances: - inst_layout = instances_layout[inst.name] - data = dict() - data["backdrill_parameters"] = inst.backdrill_parameters - data["hole_override_enabled"] = inst.hole_override_enabled - data["hole_override_diameter"] = inst.hole_override_diameter - inst_layout.properties = data - - def get_data_from_db(self): - self.definitions = [] - for pdef_name, pdef in self._pedb.padstacks.definitions.items(): - self.definitions.append( - Definition( - name=pdef_name, - hole_plating_thickness=pdef.hole_plating_thickness, - hole_material=pdef.material, - hole_range=pdef.hole_range, - pad_parameters=pdef.pad_parameters, - hole_parameters=pdef.hole_parameters, - ) - ) - data = {} - definitions = [] - for i in self.definitions: - definitions.append(i.get_attributes()) - data["definitions"] = definitions + inst.set_parameters_to_edb() + + def retrieve_parameters_from_edb(self): + self.clean() + for _, obj in self._pedb.padstacks.definitions.items(): + pdef = Definition(self._pedb, obj) + pdef.retrieve_parameters_from_edb() + self.definitions.append(pdef) for obj in self._pedb.layout.padstack_instances: - temp = obj.properties - self.instances.append( - Instance( - name=temp["name"], - definition=temp["definition"], - backdrill_parameters=temp["backdrill_parameters"], - id=temp["id"], - position=temp["position"], - rotation=temp["rotation"], - hole_override_enabled=temp["hole_override_enabled"], - hole_override_diameter=temp["hole_override_diameter"], - ) - ) - instances = [] - for i in self.instances: - instances.append(i.get_attributes("id")) - data["instances"] = instances - return data + inst = Instance(self._pedb, obj) + inst.retrieve_parameters_from_edb() + self.instances.append(inst) -class Definition(CfgBase): +class Definition: """Padstack definition data class.""" + PAD_SHAPE_PARAMETERS = { + "circle": ["diameter"], + "square": ["size"], + "rectangle": ["x_size", "y_size"], + "oval": ["x_size", "y_size", "corner_radius"], + "bullet": ["x_size", "y_size", "corner_radius"], + "round45": ["inner", "channel_width", "isolation_gap"], + "round90": ["inner", "channel_width", "isolation_gap"], + "no_geometry": [], + } - def __init__(self, **kwargs): + def __init__(self, pedb, pyedb_obj, **kwargs): + self._pedb = pedb + self._pyedb_obj = pyedb_obj self.name = kwargs.get("name", None) self.hole_plating_thickness = kwargs.get("hole_plating_thickness", None) self.material = kwargs.get("hole_material", None) @@ -104,16 +97,223 @@ def __init__(self, **kwargs): self.pad_parameters = kwargs.get("pad_parameters", None) self.hole_parameters = kwargs.get("hole_parameters", None) + def set_parameters_to_edb(self): + if self.hole_plating_thickness: + self._pyedb_obj.hole_plating_thickness = self.hole_plating_thickness + if self.material: + self._pyedb_obj.material = self.material + if self.hole_range: + self._pyedb_obj = self.hole_range + if self.pad_parameters: + self._set_pad_parameters_to_edb(self.pad_parameters) + if self.hole_parameters: + self._set_hole_parameters_to_edb(self.hole_parameters) + + def retrieve_parameters_from_edb(self): + self.hole_plating_thickness = self._pyedb_obj.hole_plating_thickness + self.material = self._pyedb_obj.material + self.hole_range = self._pyedb_obj.hole_range + self.pad_parameters = self._get_pad_parameters_from_edb() + self.hole_parameters = self._get_hole_parameters_from_edb() + + def _get_pad_parameters_from_edb(self): + """Pad parameters. + + Returns + ------- + dict + params = { + 'regular_pad': [ + {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0.1mm', 'offset_y': '0', 'rotation': '0', + 'diameter': '0.5mm'} + ], + 'anti_pad': [ + {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', + 'diameter': '1mm'} + ], + 'thermal_pad': [ + {'layer_name': '1_Top', 'shape': 'round90', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', + 'inner': '1mm', 'channel_width': '0.2mm', 'isolation_gap': '0.3mm'}, + ], + 'hole': [ + {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', + 'diameter': '0.1499997mm'}, + ] + } + """ + pdef_data = self._pyedb_obj._padstack_def_data + pad_type_list = [ + self._pedb._edb.Definition.PadType.RegularPad, + self._pedb._edb.Definition.PadType.AntiPad, + self._pedb._edb.Definition.PadType.ThermalPad, + # self._ppadstack._pedb._edb.Definition.PadType.Hole, + # This property doesn't appear in UI. It is unclear what it is used for. Suppressing this property for now. + ] + data = {} + for pad_type in pad_type_list: + pad_type_name = pascal_to_snake(pad_type.ToString()) + temp_list = [] + for lyr_name in list(pdef_data.GetLayerNames()): + result = pdef_data.GetPadParametersValue(lyr_name, pad_type) + _, pad_shape, params, offset_x, offset_y, rotation = result + pad_shape = pascal_to_snake(pad_shape.ToString()) + + pad_params = {} + pad_params["layer_name"] = lyr_name + pad_params["shape"] = pad_shape + pad_params["offset_x"] = offset_x.ToString() + pad_params["offset_y"] = offset_y.ToString() + pad_params["rotation"] = rotation.ToString() + + for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[pad_shape]): + pad_params[i] = params[idx].ToString() + temp_list.append(pad_params) + data[pad_type_name] = temp_list + return data + + def _set_pad_parameters_to_edb(self, param): + pdef_data = self._pyedb_obj._padstack_def_data + + pad_type_list = [ + self._pedb._edb.Definition.PadType.RegularPad, + self._pedb._edb.Definition.PadType.AntiPad, + self._pedb._edb.Definition.PadType.ThermalPad, + self._pedb._edb.Definition.PadType.Hole, + ] + for pad_type in pad_type_list: + pad_type_name = pascal_to_snake(pad_type.ToString()) + rpp = param.get(pad_type_name, []) + for idx, layer_data in enumerate(rpp): + # Get geometry type from kwargs + p = layer_data.get("shape") + temp_param = [] + + # Handle Circle geometry type + if p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Circle.ToString()): + temp_param.append(layer_data["diameter"]) + pad_shape = self._pedb._edb.Definition.PadGeometryType.Circle + + # Handle Square geometry type + elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Square.ToString()): + temp_param.append(layer_data["size"]) + pad_shape = self._pedb._edb.Definition.PadGeometryType.Square + + elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Rectangle.ToString()): + temp_param.append(layer_data["x_size"]) + temp_param.append(layer_data["y_size"]) + pad_shape = self._pedb._edb.Definition.PadGeometryType.Rectangle + + # Handle Oval geometry type + elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Oval.ToString()): + temp_param.append(layer_data["x_size"]) + temp_param.append(layer_data["y_size"]) + temp_param.append(layer_data["corner_radius"]) + pad_shape = self._pedb._edb.Definition.PadGeometryType.Oval + + # Handle Bullet geometry type + elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Bullet.ToString()): + temp_param.append(layer_data["x_size"]) + temp_param.append(layer_data["y_size"]) + temp_param.append(layer_data["corner_radius"]) + pad_shape = self._pedb._edb.Definition.PadGeometryType.Bullet + + # Handle Round45 geometry type + elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Round45.ToString()): + temp_param.append(layer_data["inner"]) + temp_param.append(layer_data["channel_width"]) + temp_param.append(layer_data["isolation_gap"]) + pad_shape = self._pedb._edb.Definition.PadGeometryType.Round45 + + # Handle Round90 geometry type + elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Round90.ToString()): + temp_param.append(layer_data["inner"]) + temp_param.append(layer_data["channel_width"]) + temp_param.append(layer_data["isolation_gap"]) + pad_shape = self._pedb._edb.Definition.PadGeometryType.Round90 + elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.NoGeometry.ToString()): + continue + + # Set pad parameters for the current layer + pdef_data.SetPadParameters( + layer_data["layer_name"], + pad_type, + pad_shape, + convert_py_list_to_net_list([self._pedb.edb_value(i) for i in temp_param]), + self._pedb.edb_value(layer_data.get("offset_x", 0)), + self._pedb.edb_value(layer_data.get("offset_y", 0)), + self._pedb.edb_value(layer_data.get("rotation", 0)), + ) + self._pyedb_obj._padstack_def_data = pdef_data + + def _get_hole_parameters_from_edb(self): + pdef_data = self._pyedb_obj._padstack_def_data + _, hole_shape, params, offset_x, offset_y, rotation = pdef_data.GetHoleParametersValue() + hole_shape = pascal_to_snake(hole_shape.ToString()) + + hole_params = {} + hole_params["shape"] = hole_shape + for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[hole_shape]): + hole_params[i] = params[idx].ToString() + hole_params["offset_x"] = offset_x.ToString() + hole_params["offset_y"] = offset_y.ToString() + hole_params["rotation"] = rotation.ToString() + return hole_params + + def _set_hole_parameters_to_edb(self, params): + original_params = self.hole_parameters + pdef_data = self._pyedb_obj._padstack_def_data + + temp_param = [] + shape = params["shape"] + if shape == "no_geometry": + return # .net api doesn't tell how to set no_geometry shape. + for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[shape]): + temp_param.append(params[i]) + pedb_shape = getattr(self._pedb._edb.Definition.PadGeometryType, snake_to_pascal(shape)) + + pdef_data.SetHoleParameters( + pedb_shape, + convert_py_list_to_net_list([self._pedb.edb_value(i) for i in temp_param]), + self._pedb.edb_value(params.get("offset_x", original_params.get("offset_x", 0))), + self._pedb.edb_value(params.get("offset_y", original_params.get("offset_y", 0))), + self._pedb.edb_value(params.get("rotation", original_params.get("rotation", 0))), + ) + self._pyedb_obj._padstack_def_data = pdef_data + -class Instance(CfgBase): +class Instance: """Instance data class.""" - def __init__(self, **kwargs): - self.name = kwargs["name"] + def __init__(self, pedb, pyedb_obj, **kwargs): + self._pedb = pedb + self._pyedb_obj = pyedb_obj + self.name = kwargs.get("name", None) self.definition = kwargs.get("definition", None) self.backdrill_parameters = kwargs.get("backdrill_parameters", None) - self.id = kwargs.get("id", None) + self._id = kwargs.get("id", None) self.position = kwargs.get("position", []) self.rotation = kwargs.get("rotation", None) self.hole_override_enabled = kwargs.get("hole_override_enabled", None) self.hole_override_diameter = kwargs.get("hole_override_diameter", None) + + def set_parameters_to_edb(self): + if self.name is not None: + self._pyedb_obj.aedt_name = self.name + if self.backdrill_parameters: + self._pyedb_obj.backdrill_parameters = self.backdrill_parameters + + hole_override_enabled, hole_override_diam = self._pyedb_obj._edb_object.GetHoleOverrideValue() + hole_override_enabled = self.hole_override_enabled if self.hole_override_enabled else hole_override_enabled + hole_override_diam = self.hole_override_diameter if self.hole_override_diameter else hole_override_diam + self._pyedb_obj._edb_object.SetHoleOverride(hole_override_enabled, self._pedb.edb_value(hole_override_diam)) + + def retrieve_parameters_from_edb(self): + self.name = self._pyedb_obj.aedt_name + self.definition = self._pyedb_obj.padstack_definition + self.backdrill_parameters = self._pyedb_obj.backdrill_parameters + _, position, rotation = self._pyedb_obj._edb_object.GetPositionAndRotationValue() + self.position = [position.X.ToString(), position.Y.ToString()] + self.rotation = rotation.ToString() + self._id = self._pyedb_obj.id + self.hole_override_enabled, hole_override_diameter = self._pyedb_obj._edb_object.GetHoleOverrideValue() + self.hole_override_diameter = hole_override_diameter.ToString() diff --git a/src/pyedb/configuration/configuration.py b/src/pyedb/configuration/configuration.py index 41a53caaa5..66924e58c9 100644 --- a/src/pyedb/configuration/configuration.py +++ b/src/pyedb/configuration/configuration.py @@ -296,7 +296,10 @@ def get_data_from_db(self, **kwargs): if kwargs.get("operations", False): 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() + self.cfg_data.padstacks.retrieve_parameters_from_edb() + data["padstacks"] = dict() + data["padstacks"]["definitions"] = self.cfg_data.padstacks.definitions + data["padstacks"]["instances"] = self.cfg_data.padstacks.instances if kwargs.get("s_parameters", False): data["s_parameters"] = self.cfg_data.s_parameters.get_data_from_db() if kwargs.get("boundaries", False): @@ -305,21 +308,21 @@ def get_data_from_db(self, **kwargs): return data def export( - self, - file_path, - stackup=True, - package_definitions=True, - setups=True, - sources=True, - ports=True, - nets=True, - pin_groups=True, - operations=True, - components=True, - boundaries=True, - s_parameters=True, - padstacks=True, - general=True, + self, + file_path, + stackup=True, + package_definitions=True, + setups=True, + sources=True, + ports=True, + nets=True, + pin_groups=True, + operations=True, + components=True, + boundaries=True, + s_parameters=True, + padstacks=True, + general=True, ): """Export the configuration data from layout to a file. diff --git a/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py b/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py index 015796c5c6..a5e659f937 100644 --- a/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py +++ b/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py @@ -411,17 +411,6 @@ class EDBPadstack(object): >>> edb_padstack = edb.padstacks.definitions["MyPad"] """ - PAD_SHAPE_PARAMETERS = { - "circle": ["diameter"], - "square": ["size"], - "rectangle": ["x_size", "y_size"], - "oval": ["x_size", "y_size", "corner_radius"], - "bullet": ["x_size", "y_size", "corner_radius"], - "round45": ["inner", "channel_width", "isolation_gap"], - "round90": ["inner", "channel_width", "isolation_gap"], - "no_geometry": [], - } - def __init__(self, edb_padstack, ppadstack): self._edb_object = edb_padstack self.edb_padstack = edb_padstack @@ -468,175 +457,6 @@ def _padstack_def_data(self): def _padstack_def_data(self, value): self._edb_object.SetData(value) - @property - def pad_parameters(self) -> dict: - """Pad parameters. - - Returns - ------- - dict - params = { - 'regular_pad': [ - {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0.1mm', 'offset_y': '0', 'rotation': '0', - 'diameter': '0.5mm'} - ], - 'anti_pad': [ - {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', - 'diameter': '1mm'} - ], - 'thermal_pad': [ - {'layer_name': '1_Top', 'shape': 'round90', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', - 'inner': '1mm', 'channel_width': '0.2mm', 'isolation_gap': '0.3mm'}, - ], - 'hole': [ - {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', - 'diameter': '0.1499997mm'}, - ] - } - """ - pdef_data = self._padstack_def_data - pad_type_list = [ - self._ppadstack._pedb._edb.Definition.PadType.RegularPad, - self._ppadstack._pedb._edb.Definition.PadType.AntiPad, - self._ppadstack._pedb._edb.Definition.PadType.ThermalPad, - # self._ppadstack._pedb._edb.Definition.PadType.Hole, - # This property doesn't appear in UI. It is unclear what it is used for. Suppressing this property for now. - ] - data = {} - for pad_type in pad_type_list: - pad_type_name = pascal_to_snake(pad_type.ToString()) - temp_list = [] - for lyr_name in list(pdef_data.GetLayerNames()): - result = pdef_data.GetPadParametersValue(lyr_name, pad_type) - _, pad_shape, params, offset_x, offset_y, rotation = result - pad_shape = pascal_to_snake(pad_shape.ToString()) - - pad_params = {} - pad_params["layer_name"] = lyr_name - pad_params["shape"] = pad_shape - pad_params["offset_x"] = offset_x.ToString() - pad_params["offset_y"] = offset_y.ToString() - pad_params["rotation"] = rotation.ToString() - - for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[pad_shape]): - pad_params[i] = params[idx].ToString() - temp_list.append(pad_params) - data[pad_type_name] = temp_list - return data - - @pad_parameters.setter - def pad_parameters(self, params: dict): - original_params = self.pad_parameters - pdef_data = self._padstack_def_data - - pad_type_list = [ - self._ppadstack._pedb._edb.Definition.PadType.RegularPad, - self._ppadstack._pedb._edb.Definition.PadType.AntiPad, - self._ppadstack._pedb._edb.Definition.PadType.ThermalPad, - self._ppadstack._pedb._edb.Definition.PadType.Hole, - ] - for pad_type in pad_type_list: - pad_type_name = pascal_to_snake(pad_type.ToString()) - rpp = params.get(pad_type_name, []) - for idx, layer_data in enumerate(rpp): - # Get geometry type from kwargs - p = layer_data.get("shape") - temp_param = [] - - # Handle Circle geometry type - if p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Circle.ToString()): - temp_param.append(layer_data["diameter"]) - pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Circle - - # Handle Square geometry type - elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Square.ToString()): - temp_param.append(layer_data["size"]) - pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Square - - elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Rectangle.ToString()): - temp_param.append(layer_data["x_size"]) - temp_param.append(layer_data["y_size"]) - pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Rectangle - - # Handle Oval geometry type - elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Oval.ToString()): - temp_param.append(layer_data["x_size"]) - temp_param.append(layer_data["y_size"]) - temp_param.append(layer_data["corner_radius"]) - pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Oval - - # Handle Bullet geometry type - elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Bullet.ToString()): - temp_param.append(layer_data["x_size"]) - temp_param.append(layer_data["y_size"]) - temp_param.append(layer_data["corner_radius"]) - pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Bullet - - # Handle Round45 geometry type - elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Round45.ToString()): - temp_param.append(layer_data["inner"]) - temp_param.append(layer_data["channel_width"]) - temp_param.append(layer_data["isolation_gap"]) - pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Round45 - - # Handle Round90 geometry type - elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Round90.ToString()): - temp_param.append(layer_data["inner"]) - temp_param.append(layer_data["channel_width"]) - temp_param.append(layer_data["isolation_gap"]) - pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Round90 - elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.NoGeometry.ToString()): - continue - - # Set pad parameters for the current layer - pdef_data.SetPadParameters( - layer_data["layer_name"], - pad_type, - pad_shape, - convert_py_list_to_net_list([self._ppadstack._pedb.edb_value(i) for i in temp_param]), - self._ppadstack._pedb.edb_value(layer_data.get("offset_x", 0)), - self._ppadstack._pedb.edb_value(layer_data.get("offset_y", 0)), - self._ppadstack._pedb.edb_value(layer_data.get("rotation", 0)), - ) - self._padstack_def_data = pdef_data - - @property - def hole_parameters(self): - pdef_data = self._padstack_def_data - _, hole_shape, params, offset_x, offset_y, rotation = pdef_data.GetHoleParametersValue() - hole_shape = pascal_to_snake(hole_shape.ToString()) - - hole_params = {} - hole_params["shape"] = hole_shape - for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[hole_shape]): - hole_params[i] = params[idx].ToString() - hole_params["offset_x"] = offset_x.ToString() - hole_params["offset_y"] = offset_y.ToString() - hole_params["rotation"] = rotation.ToString() - return hole_params - - @hole_parameters.setter - def hole_parameters(self, params: dict): - original_params = self.hole_parameters - pdef_data = self._padstack_def_data - - temp_param = [] - shape = params["shape"] - if shape == "no_geometry": - return # .net api doesn't tell how to set no_geometry shape. - for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[shape]): - temp_param.append(params[i]) - pedb_shape = getattr(self._ppadstack._pedb._edb.Definition.PadGeometryType, snake_to_pascal(shape)) - - pdef_data.SetHoleParameters( - pedb_shape, - convert_py_list_to_net_list([self._ppadstack._pedb.edb_value(i) for i in temp_param]), - self._ppadstack._pedb.edb_value(params.get("offset_x", original_params.get("offset_x", 0))), - self._ppadstack._pedb.edb_value(params.get("offset_y", original_params.get("offset_y", 0))), - self._ppadstack._pedb.edb_value(params.get("rotation", original_params.get("rotation", 0))), - ) - self._padstack_def_data = pdef_data - @property def instances(self): """Definitions Instances.""" @@ -1975,6 +1795,10 @@ def aedt_name(self): name = str(name).strip("'") return name + @aedt_name.setter + def aedt_name(self, value): + self._edb_object.SetProductProperty(self._pedb.edb_api.ProductId.Designer, 11, value) + def parametrize_position(self, prefix=None): """Parametrize the instance position. @@ -2324,32 +2148,3 @@ def get_reference_pins(self, reference_net="GND", search_radius=5e-3, max_limit= max_limit=max_limit, component_only=component_only, ) - - @property - def properties(self): - data = {} - data["name"] = self.aedt_name - data["definition"] = self.padstack_definition - data["backdrill_parameters"] = self.backdrill_parameters - _, position, rotation = self._edb_object.GetPositionAndRotationValue() - data["position"] = [position.X.ToString(), position.Y.ToString()] - data["rotation"] = [rotation.ToString()] - data["id"] = self.id - hole_override_enabled, hole_override_diam = self._edb_object.GetHoleOverrideValue() - data["hole_override_enabled"] = hole_override_enabled - data["hole_override_diameter"] = hole_override_diam.ToString() - return data - - @properties.setter - def properties(self, params): - name = params.get("name", None) - if name: - self.aedt_name = name - backdrill_parameters = params.get("backdrill_parameters", None) - if backdrill_parameters: - self.backdrill_parameters = backdrill_parameters - h_o_enabled = params.get("hole_override_enabled", None) - h_o_enabled = h_o_enabled if h_o_enabled else self.properties["hole_override_enabled"] - h_o_diameter = params.get("hole_override_diameter") - h_o_diameter = h_o_diameter if h_o_diameter else self.properties["hole_override_diameter"] - self._edb_object.SetHoleOverride(h_o_enabled, self._pedb.edb_value(h_o_diameter)) From 4ecbe8dbedcb8408ab1a7cbbb3306eb420f8dc80 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Sat, 19 Oct 2024 09:10:05 +0200 Subject: [PATCH 02/14] minor --- src/pyedb/configuration/cfg_padstacks.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pyedb/configuration/cfg_padstacks.py b/src/pyedb/configuration/cfg_padstacks.py index b0f49d0d63..5459dd2b3a 100644 --- a/src/pyedb/configuration/cfg_padstacks.py +++ b/src/pyedb/configuration/cfg_padstacks.py @@ -21,7 +21,6 @@ # SOFTWARE. from pyedb.dotnet.edb_core.general import ( - PadGeometryTpe, convert_py_list_to_net_list, pascal_to_snake, snake_to_pascal, From ae217367a0a80ad42b698612a733f92acee42ce0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 19 Oct 2024 07:14:36 +0000 Subject: [PATCH 03/14] MISC: Auto fixes from pre-commit.com hooks For more information, see https://pre-commit.ci --- src/pyedb/configuration/cfg_padstacks.py | 46 ++++++++++++------------ src/pyedb/configuration/configuration.py | 30 ++++++++-------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/pyedb/configuration/cfg_padstacks.py b/src/pyedb/configuration/cfg_padstacks.py index b0f49d0d63..c02d37aab7 100644 --- a/src/pyedb/configuration/cfg_padstacks.py +++ b/src/pyedb/configuration/cfg_padstacks.py @@ -36,7 +36,6 @@ def __init__(self, pedb, padstack_dict=None): self.definitions = [] self.instances = [] - if padstack_dict: padstack_defs_layout = self._pedb.padstacks.definitions for pdef in padstack_dict.get("definitions", []): @@ -76,6 +75,7 @@ def retrieve_parameters_from_edb(self): class Definition: """Padstack definition data class.""" + PAD_SHAPE_PARAMETERS = { "circle": ["diameter"], "square": ["size"], @@ -119,28 +119,28 @@ def retrieve_parameters_from_edb(self): def _get_pad_parameters_from_edb(self): """Pad parameters. - Returns - ------- - dict - params = { - 'regular_pad': [ - {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0.1mm', 'offset_y': '0', 'rotation': '0', - 'diameter': '0.5mm'} - ], - 'anti_pad': [ - {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', - 'diameter': '1mm'} - ], - 'thermal_pad': [ - {'layer_name': '1_Top', 'shape': 'round90', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', - 'inner': '1mm', 'channel_width': '0.2mm', 'isolation_gap': '0.3mm'}, - ], - 'hole': [ - {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', - 'diameter': '0.1499997mm'}, - ] - } - """ + Returns + ------- + dict + params = { + 'regular_pad': [ + {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0.1mm', 'offset_y': '0', 'rotation': '0', + 'diameter': '0.5mm'} + ], + 'anti_pad': [ + {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', + 'diameter': '1mm'} + ], + 'thermal_pad': [ + {'layer_name': '1_Top', 'shape': 'round90', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', + 'inner': '1mm', 'channel_width': '0.2mm', 'isolation_gap': '0.3mm'}, + ], + 'hole': [ + {'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0', + 'diameter': '0.1499997mm'}, + ] + } + """ pdef_data = self._pyedb_obj._padstack_def_data pad_type_list = [ self._pedb._edb.Definition.PadType.RegularPad, diff --git a/src/pyedb/configuration/configuration.py b/src/pyedb/configuration/configuration.py index 66924e58c9..53b42d6c3a 100644 --- a/src/pyedb/configuration/configuration.py +++ b/src/pyedb/configuration/configuration.py @@ -308,21 +308,21 @@ def get_data_from_db(self, **kwargs): return data def export( - self, - file_path, - stackup=True, - package_definitions=True, - setups=True, - sources=True, - ports=True, - nets=True, - pin_groups=True, - operations=True, - components=True, - boundaries=True, - s_parameters=True, - padstacks=True, - general=True, + self, + file_path, + stackup=True, + package_definitions=True, + setups=True, + sources=True, + ports=True, + nets=True, + pin_groups=True, + operations=True, + components=True, + boundaries=True, + s_parameters=True, + padstacks=True, + general=True, ): """Export the configuration data from layout to a file. From 4b7ee5021e2f3b7c9a65390ea71af33648f30c0c Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Fri, 25 Oct 2024 14:41:10 +0200 Subject: [PATCH 04/14] draft --- src/pyedb/configuration/cfg_padstacks.py | 2 +- src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py | 12 ------------ tests/legacy/system/test_edb_configuration_2p0.py | 2 +- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/pyedb/configuration/cfg_padstacks.py b/src/pyedb/configuration/cfg_padstacks.py index 1af94f1d30..409cb71701 100644 --- a/src/pyedb/configuration/cfg_padstacks.py +++ b/src/pyedb/configuration/cfg_padstacks.py @@ -102,7 +102,7 @@ def set_parameters_to_edb(self): if self.material: self._pyedb_obj.material = self.material if self.hole_range: - self._pyedb_obj = self.hole_range + self._pyedb_obj.hole_range = self.hole_range if self.pad_parameters: self._set_pad_parameters_to_edb(self.pad_parameters) if self.hole_parameters: diff --git a/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py b/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py index a5e659f937..c9b20654bb 100644 --- a/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py +++ b/src/pyedb/dotnet/edb_core/edb_data/padstacks_data.py @@ -1142,18 +1142,6 @@ def _update_layer_names(self, old_name, updated_name): self.edb_padstack.SetData(new_padstack_data) return True - def set_properties(self, **kwargs): - for k in ["hole_plating_thickness", "material", "hole_range", "pad_parameters", "hole_parameters"]: - value = kwargs.get(k, False) - if value: - setattr(self, k, value) - - def get_properties(self): - kwargs = {} - for k in ["hole_plating_thickness", "material", "hole_range", "pad_parameters", "hole_parameters"]: - kwargs[k] = getattr(self, k) - return kwargs - class EDBPadstackInstance(Primitive): """Manages EDB functionalities for a padstack. diff --git a/tests/legacy/system/test_edb_configuration_2p0.py b/tests/legacy/system/test_edb_configuration_2p0.py index 7bd24bf858..010c4496a5 100644 --- a/tests/legacy/system/test_edb_configuration_2p0.py +++ b/tests/legacy/system/test_edb_configuration_2p0.py @@ -535,7 +535,7 @@ def test_09_padstack_definition(self, edb_examples): } edbapp = edb_examples.get_si_verse() assert edbapp.configuration.load(data, apply_file=True) - pad_params = edbapp.padstacks.definitions["v35h15"].pad_parameters + pad_params = edbapp.padstacks.definitions["v35h15"] assert pad_params["regular_pad"][0]["diameter"] == "0.5mm" assert pad_params["regular_pad"][0]["offset_x"] == "0.1mm" assert pad_params["anti_pad"][0]["diameter"] == "1mm" From f4c57a2a8ee42b61e44e3fbd92d5c4c6ccb7e551 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Sun, 27 Oct 2024 13:10:37 +0100 Subject: [PATCH 05/14] draft --- tests/legacy/system/test_edb_configuration_2p0.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/legacy/system/test_edb_configuration_2p0.py b/tests/legacy/system/test_edb_configuration_2p0.py index 010c4496a5..ad1e1c9533 100644 --- a/tests/legacy/system/test_edb_configuration_2p0.py +++ b/tests/legacy/system/test_edb_configuration_2p0.py @@ -535,7 +535,9 @@ def test_09_padstack_definition(self, edb_examples): } edbapp = edb_examples.get_si_verse() assert edbapp.configuration.load(data, apply_file=True) - pad_params = edbapp.padstacks.definitions["v35h15"] + data_from_layout = edbapp.configuration.get_data_from_db(padstacks=True) + pad_params = data_from_layout["padstacks"]["definitions"] + assert pad_params["regular_pad"][0]["diameter"] == "0.5mm" assert pad_params["regular_pad"][0]["offset_x"] == "0.1mm" assert pad_params["anti_pad"][0]["diameter"] == "1mm" From 023f6df7765f52af9e6fa536f62187b216792856 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Sun, 27 Oct 2024 16:48:38 +0100 Subject: [PATCH 06/14] REFACTOR: CfgComponents --- src/pyedb/configuration/cfg_components.py | 275 ++++++++++++++---- src/pyedb/configuration/cfg_padstacks.py | 10 +- src/pyedb/configuration/configuration.py | 16 +- .../edb_core/cell/hierarchy/component.py | 201 ------------- tests/legacy/system/test_edb_components.py | 16 - .../system/test_edb_configuration_2p0.py | 27 +- 6 files changed, 245 insertions(+), 300 deletions(-) diff --git a/src/pyedb/configuration/cfg_components.py b/src/pyedb/configuration/cfg_components.py index 8e169e6ad4..0a3e5d6275 100644 --- a/src/pyedb/configuration/cfg_components.py +++ b/src/pyedb/configuration/cfg_components.py @@ -21,20 +21,17 @@ # SOFTWARE. from pyedb.configuration.cfg_common import CfgBase - - -class CfgRlcModel(CfgBase): - def __init__(self, **kwargs): - self.resistance = kwargs.get("resistance", None) - self.inductance = kwargs.get("inductance", None) - self.capacitance = kwargs.get("capacitance", None) - self.type = kwargs.get("type", None) - self.p1 = kwargs.get("p1", None) - self.p2 = kwargs.get("p2", None) +from pyedb.dotnet.edb_core.general import ( + pascal_to_snake, + snake_to_pascal, +) class CfgComponent(CfgBase): - def __init__(self, **kwargs): + def __init__(self, pedb, pedb_object, **kwargs): + self._pedb = pedb + self._pyedb_obj = pedb_object + self.enabled = kwargs.get("enabled", None) self.reference_designator = kwargs.get("reference_designator", None) self.definition = kwargs.get("definition", None) @@ -42,60 +39,228 @@ def __init__(self, **kwargs): 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.pin_pair_model = kwargs.get("pin_pair_model", []) self.spice_model = kwargs.get("spice_model", None) self.s_parameter_model = kwargs.get("s_parameter_model", None) + self.netlist_model = kwargs.get("netlist_model", {}) + + def retrieve_model_properties_from_edb(self): + c_p = self._pyedb_obj.component_property + model = c_p.GetModel().Clone() + + if model.GetModelType().ToString() == "NetlistModel": + self.netlist_model["netlist"] = model.GetNetlist() + elif model.GetModelType().ToString() == "PinPairModel": + temp = {} + for i in model.PinPairs: + temp["first_pin"] = i.FirstPin + temp["second_pin"] = i.SecondPin + rlc = model.GetPinPairRlc(i) + temp["is_parallel"] = rlc.IsParallel + temp["resistance"] = rlc.R.ToString() + temp["resistance_enabled"] = rlc.REnabled + temp["inductance"] = rlc.L.ToString() + temp["inductance_enabled"] = rlc.LEnabled + temp["capacitance"] = rlc.C.ToString() + temp["capacitance_enabled"] = rlc.CEnabled + self.pin_pair_model.append(temp) + elif model.GetModelType().ToString() == "SParameterModel": + self.s_parameter_model["reference_net"] = model.GetReferenceNet() + self.s_parameter_model["model_name"] = model.GetComponentModelName() + elif model.GetModelType().ToString() == "SPICEModel": + self.spice_model["model_name"] = model.GetModelName() + self.spice_model["model_path"] = model.GetModelPath() + self.spice_model["sub_circuit"] = model.GetSubCkt() + self.spice_model["terminal_pairs"] = [[i, j] for i, j in dict(model.GetTerminalPinPairs()).items()] + + def _set_model_properties_to_edb(self): + c_p = self._pyedb_obj.component_property + if self.netlist_model: + m = self._pedb._edb.Cell.Hierarchy.SParameterModel() + m.SetNetlist(self.netlist_model["netlist"]) + c_p.SetModel(m) + self.component_property = c_p + elif self.pin_pair_model: + m = self._pedb._edb.Cell.Hierarchy.PinPairModel() + for i in self.pin_pair_model: + p = self._pedb._edb.Utility.PinPair(str(i["first_pin"]), str(i["second_pin"])) + rlc = self._pedb._edb.Utility.Rlc( + self._pedb.edb_value(i["resistance"]), + i["resistance_enabled"], + self._pedb.edb_value(i["inductance"]), + i["inductance_enabled"], + self._pedb.edb_value(i["capacitance"]), + i["capacitance_enabled"], + i["is_parallel"], + ) + m.SetPinPairRlc(p, rlc) + c_p.SetModel(m) + self._pyedb_obj.component_property = c_p + elif self.s_parameter_model: + m = self._pedb._edb.Cell.Hierarchy.SParameterModel() + m.SetComponentModelName(self.s_parameter_model["model_name"]) + m.SetReferenceNet(self.s_parameter_model["reference_net"]) + c_p.SetModel(m) + self.component_property = c_p + elif self.spice_model: + self._pyedb_obj.assign_spice_model( + self.spice_model["model_path"], + self.spice_model["model_name"], + self.spice_model["sub_circuit"], + self.spice_model["terminal_pairs"], + ) + + def retrieve_ic_die_properties_from_edb(self): + temp = dict() + cp = self._pyedb_obj.component_property + c_type = self.type.lower() + if not c_type == "ic": + return + else: + ic_die_prop = cp.GetDieProperty().Clone() + die_type = pascal_to_snake(ic_die_prop.GetType().ToString()) + self.type = die_type + if not die_type == "no_die": + temp["orientation"] = pascal_to_snake(ic_die_prop.GetOrientation().ToString()) + if die_type == "wire_bond": + temp["height"] = ic_die_prop.GetHeightValue().ToString() + self.ic_die_properties = temp + + def _set_ic_die_properties_to_edb(self): + cp = self._pyedb_obj.component_property + c_type = self._pyedb_obj.type.lower() + if not c_type == "ic": + return + else: + ic_die_prop = cp.GetDieProperty().Clone() + die_type = self.ic_die_properties.get("type") + ic_die_prop.SetType(getattr(self._edb.definition.DieType, snake_to_pascal(die_type))) + if not die_type == "no_die": + orientation = self.ic_die_properties.get("orientation") + if orientation: + ic_die_prop.SetOrientation( + getattr(self._edb.definition.DieOrientation, snake_to_pascal(orientation)) + ) + if die_type == "wire_bond": + height = self.ic_die_properties.get("height") + if height: + ic_die_prop.SetHeight(self._pedb.edb_value(height)) + cp.SetDieProperty(ic_die_prop) + self._pyedb_obj.component_property = cp + + def _retrieve_solder_ball_properties_from_edb(self): + temp = dict() + cp = self._pyedb_obj.component_property + 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 + self.solder_ball_properties = temp + + def _set_solder_ball_properties_to_edb(self): + cp = self._pyedb_obj.component_property + solder_ball_prop = cp.GetSolderBallProperty().Clone() + shape = self.solder_ball_properties.get("shape") + if shape: + solder_ball_prop.SetShape(getattr(self._pedb._edb.Definition.SolderballShape, snake_to_pascal(shape))) + else: + return + + if shape == "cylinder": + diameter = self.solder_ball_properties["diameter"] + solder_ball_prop.SetDiameter(self._pedb.edb_value(diameter), self._pedb.edb_value(diameter)) + elif shape == "spheroid": + diameter = self.solder_ball_properties["diameter"] + mid_diameter = self.solder_ball_properties["mid_diameter"] + solder_ball_prop.SetDiameter(self._pedb.edb_value(diameter), self._pedb.edb_value(mid_diameter)) + else: + raise ValueError("Solderball shape must be either cylinder or spheroid") + solder_ball_prop.SetHeight(self._pedb.edb_value(self.solder_ball_properties["height"])) + cp.SetSolderBallProperty(solder_ball_prop) + self._pyedb_obj.component_property = cp + + def _retrieve_port_properties_from_edb(self): + temp = dict() + cp = self._pyedb_obj.component_property + c_type = self.type.lower() + if c_type not in ["ic", "io", "other"]: + return + 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) + self.port_properties = temp + + def _set_port_properties_to_edb(self): + cp = self._pyedb_obj.component_property + port_prop = cp.GetPortProperty().Clone() + height = self.port_properties.get("reference_height") + if height: + port_prop.SetReferenceHeight(self._pedb.edb_value(height)) + reference_size_auto = self.port_properties.get("reference_size_auto") + if reference_size_auto: + port_prop.SetReferenceSizeAuto(reference_size_auto) + reference_size_x = self.port_properties.get("reference_size_x", 0) + reference_size_y = self.port_properties.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._pyedb_obj.component_property = cp + + def set_parameters_to_edb(self): + if self.enabled: + self._pyedb_obj.enabled = self.enabled + if self.type: + self._pyedb_obj.type = self.type + + self._set_model_properties_to_edb() + if self._pyedb_obj.type.lower() in ["ic", "io", "other"]: + self._set_ic_die_properties_to_edb() + self._set_solder_ball_properties_to_edb() + self._set_port_properties_to_edb() + + def retrieve_parameters_from_edb(self): + self.type = self._pyedb_obj.type + self.definition = self._pyedb_obj.part_name + self.reference_designator = self._pyedb_obj.name + self.retrieve_model_properties_from_edb() + if self._pyedb_obj.type.lower() in ["ic", "io", "other"]: + self.retrieve_ic_die_properties_from_edb() + self._retrieve_solder_ball_properties_from_edb() + self._retrieve_port_properties_from_edb() class CfgComponents: def __init__(self, pedb, components_data): self._pedb = pedb - self.components = [CfgComponent(**comp) for comp in components_data] + self.components = [] + + if components_data: + for comp in components_data: + obj = self._pedb.layout.find_component_by_name(comp["reference_designator"]) + self.components.append(CfgComponent(self._pedb, obj, **comp)) + + def clean(self): + self.components = [] def apply(self): - comps_in_db = self._pedb.components for comp in self.components: - c_db = comps_in_db.instances[comp.reference_designator] - 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.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 = [] + comp.set_parameters_to_edb() + + def retrieve_parameters_from_edb(self): + self.clean() comps_in_db = self._pedb.components for _, comp in comps_in_db.instances.items(): - cfg_comp = CfgComponent( - enabled=comp.enabled, - reference_designator=comp.name, - part_type=comp.type, - 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, - ) + cfg_comp = CfgComponent(self._pedb, comp) + cfg_comp.retrieve_parameters_from_edb() 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.get_attributes()) - return data diff --git a/src/pyedb/configuration/cfg_padstacks.py b/src/pyedb/configuration/cfg_padstacks.py index 409cb71701..910209239b 100644 --- a/src/pyedb/configuration/cfg_padstacks.py +++ b/src/pyedb/configuration/cfg_padstacks.py @@ -20,6 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from pyedb.configuration.cfg_common import CfgBase from pyedb.dotnet.edb_core.general import ( convert_py_list_to_net_list, pascal_to_snake, @@ -72,7 +73,7 @@ def retrieve_parameters_from_edb(self): self.instances.append(inst) -class Definition: +class Definition(CfgBase): """Padstack definition data class.""" PAD_SHAPE_PARAMETERS = { @@ -86,9 +87,9 @@ class Definition: "no_geometry": [], } - def __init__(self, pedb, pyedb_obj, **kwargs): + def __init__(self, pedb, pedb_object, **kwargs): self._pedb = pedb - self._pyedb_obj = pyedb_obj + self._pyedb_obj = pedb_object self.name = kwargs.get("name", None) self.hole_plating_thickness = kwargs.get("hole_plating_thickness", None) self.material = kwargs.get("hole_material", None) @@ -109,6 +110,7 @@ def set_parameters_to_edb(self): self._set_hole_parameters_to_edb(self.hole_parameters) def retrieve_parameters_from_edb(self): + self.name = self._pyedb_obj.name self.hole_plating_thickness = self._pyedb_obj.hole_plating_thickness self.material = self._pyedb_obj.material self.hole_range = self._pyedb_obj.hole_range @@ -280,7 +282,7 @@ def _set_hole_parameters_to_edb(self, params): self._pyedb_obj._padstack_def_data = pdef_data -class Instance: +class Instance(CfgBase): """Instance data class.""" def __init__(self, pedb, pyedb_obj, **kwargs): diff --git a/src/pyedb/configuration/configuration.py b/src/pyedb/configuration/configuration.py index 53b42d6c3a..5f444148a9 100644 --- a/src/pyedb/configuration/configuration.py +++ b/src/pyedb/configuration/configuration.py @@ -288,7 +288,11 @@ def get_data_from_db(self, **kwargs): if kwargs.get("ports", False): data["ports"] = self.cfg_data.ports.get_data_from_db() if kwargs.get("components", False): - data["components"] = self.cfg_data.components.get_data_from_db() + self.cfg_data.components.retrieve_parameters_from_edb() + components = [] + for i in self.cfg_data.components.components: + components.append(i.get_attributes()) + data["components"] = components if kwargs.get("nets", False): data["nets"] = self.cfg_data.nets.get_data_from_db() if kwargs.get("pin_groups", False): @@ -297,9 +301,15 @@ def get_data_from_db(self, **kwargs): data["operations"] = self.cfg_data.operations.get_data_from_db() if kwargs.get("padstacks", False): self.cfg_data.padstacks.retrieve_parameters_from_edb() + definitions = [] + for i in self.cfg_data.padstacks.definitions: + definitions.append(i.get_attributes()) + instances = [] + for i in self.cfg_data.padstacks.instances: + instances.append(i.get_attributes()) data["padstacks"] = dict() - data["padstacks"]["definitions"] = self.cfg_data.padstacks.definitions - data["padstacks"]["instances"] = self.cfg_data.padstacks.instances + data["padstacks"]["definitions"] = definitions + data["padstacks"]["instances"] = instances if kwargs.get("s_parameters", False): data["s_parameters"] = self.cfg_data.s_parameters.get_data_from_db() if kwargs.get("boundaries", False): diff --git a/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py b/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py index 89b4b1b350..f0983a3e54 100644 --- a/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py +++ b/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py @@ -1009,204 +1009,3 @@ def create_clearance_on_component(self, extra_soldermask_clearance=1e-4): ) void.is_negative = True return True - - @property - def model_properties(self): - pp = {} - c_p = self.component_property - model = c_p.GetModel().Clone() - netlist_model = {} - pin_pair_model = [] - s_parameter_model = {} - spice_model = {} - if model.GetModelType().ToString() == "NetlistModel": - netlist_model["netlist"] = model.GetNetlist() - elif model.GetModelType().ToString() == "PinPairModel": - temp = {} - for i in model.PinPairs: - temp["first_pin"] = i.FirstPin - temp["second_pin"] = i.SecondPin - rlc = model.GetPinPairRlc(i) - temp["is_parallel"] = rlc.IsParallel - temp["resistance"] = rlc.R.ToString() - temp["resistance_enabled"] = rlc.REnabled - temp["inductance"] = rlc.L.ToString() - temp["inductance_enabled"] = rlc.LEnabled - temp["capacitance"] = rlc.C.ToString() - 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() - elif model.GetModelType().ToString() == "SPICEModel": - spice_model["model_name"] = model.GetModelName() - spice_model["model_path"] = model.GetModelPath() - spice_model["sub_circuit"] = model.GetSubCkt() - spice_model["terminal_pairs"] = [[i, j] for i, j in dict(model.GetTerminalPinPairs()).items()] - - if netlist_model: - pp["netlist_model"] = netlist_model - if pin_pair_model: - pp["pin_pair_model"] = pin_pair_model - if s_parameter_model: - pp["s_parameter_model"] = s_parameter_model - if spice_model: - pp["spice_model"] = spice_model - return pp - - @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") - spice_model = kwargs.get("spice_model") - - c_p = self.component_property - if netlist_model: - m = self._pedb._edb.Cell.Hierarchy.SParameterModel() - m.SetNetlist(netlist_model["netlist"]) - c_p.SetModel(m) - self.component_property = c_p - elif pin_pair_model: - m = self._pedb._edb.Cell.Hierarchy.PinPairModel() - for i in pin_pair_model: - p = self._pedb._edb.Utility.PinPair(str(i["first_pin"]), str(i["second_pin"])) - rlc = self._pedb._edb.Utility.Rlc( - self._pedb.edb_value(i["resistance"]), - i["resistance_enabled"], - self._pedb.edb_value(i["inductance"]), - i["inductance_enabled"], - self._pedb.edb_value(i["capacitance"]), - i["capacitance_enabled"], - i["is_parallel"], - ) - m.SetPinPairRlc(p, rlc) - c_p.SetModel(m) - self.component_property = c_p - elif s_parameter_model: - m = self._pedb._edb.Cell.Hierarchy.SParameterModel() - m.SetComponentModelName(s_parameter_model["model_name"]) - m.SetReferenceNet(s_parameter_model["reference_net"]) - c_p.SetModel(m) - self.component_property = c_p - elif spice_model: - self.assign_spice_model( - spice_model["model_path"], - spice_model["model_name"], - 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().ToString()) - 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") - ic_die_prop.SetType(getattr(self._edb.definition.DieType, snake_to_pascal(die_type))) - if not die_type == "no_die": - orientation = kwargs.get("orientation") - if orientation: - ic_die_prop.SetOrientation( - getattr(self._edb.definition.DieOrientation, snake_to_pascal(orientation)) - ) - 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/tests/legacy/system/test_edb_components.py b/tests/legacy/system/test_edb_components.py index 9d3865a04a..8fb1d32439 100644 --- a/tests/legacy/system/test_edb_components.py +++ b/tests/legacy/system/test_edb_components.py @@ -627,19 +627,3 @@ def test_properties(self, edb_examples): edbapp.components["C378"].model_properties = pp assert edbapp.components["C378"].model_properties == pp - def test_ic_die_properties(self): - component: EDBComponent = self.edbapp.components["U8"] - _assert_initial_ic_die_properties(component) - component.ic_die_properties = {"type": "flip_chip", "orientation": "chip_down"} - _assert_final_ic_die_properties(component) - - -def _assert_initial_ic_die_properties(component: EDBComponent): - assert component.ic_die_properties["type"] == "no_die" - assert "orientation" not in component.ic_die_properties - assert "height" not in component.ic_die_properties - - -def _assert_final_ic_die_properties(component: EDBComponent): - assert component.ic_die_properties["type"] == "flip_chip" - assert component.ic_die_properties["orientation"] == "chip_down" diff --git a/tests/legacy/system/test_edb_configuration_2p0.py b/tests/legacy/system/test_edb_configuration_2p0.py index ad1e1c9533..c2f610a83b 100644 --- a/tests/legacy/system/test_edb_configuration_2p0.py +++ b/tests/legacy/system/test_edb_configuration_2p0.py @@ -24,12 +24,6 @@ import pytest -from pyedb.dotnet.edb import Edb as EdbType -from tests.legacy.system.test_edb_components import ( - _assert_final_ic_die_properties, - _assert_initial_ic_die_properties, -) - pytestmark = [pytest.mark.unit, pytest.mark.legacy] @@ -536,20 +530,18 @@ def test_09_padstack_definition(self, edb_examples): edbapp = edb_examples.get_si_verse() assert edbapp.configuration.load(data, apply_file=True) data_from_layout = edbapp.configuration.get_data_from_db(padstacks=True) - pad_params = data_from_layout["padstacks"]["definitions"] + pdef = [i for i in data_from_layout["padstacks"]["definitions"] if i["name"]=="v35h15"][0] + pad_params = pdef["pad_parameters"] assert pad_params["regular_pad"][0]["diameter"] == "0.5mm" assert pad_params["regular_pad"][0]["offset_x"] == "0.1mm" assert pad_params["anti_pad"][0]["diameter"] == "1mm" assert pad_params["thermal_pad"][0]["inner"] == "1mm" assert pad_params["thermal_pad"][0]["channel_width"] == "0.2mm" - hole_params = edbapp.padstacks.definitions["v35h15"].hole_parameters + hole_params = pdef["hole_parameters"] assert hole_params["shape"] == "circle" assert hole_params["diameter"] == "0.2mm" - - data_from_db = edbapp.configuration.get_data_from_db(padstacks=True) - assert data_from_db["padstacks"]["definitions"] edbapp.close() def test_09_padstack_instance(self, edb_examples): @@ -952,9 +944,9 @@ 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"].model_properties["pin_pair_model"] == components[0]["pin_pair_model"] - edbapp.configuration.get_data_from_db(components=True) - + data_from_db = edbapp.configuration.get_data_from_db(components=True) + c375 = [i for i in data_from_db["components"] if i["reference_designator"] == "C375"][0] + assert c375["pin_pair_model"] == components[0]["pin_pair_model"] edbapp.close() def test_15b_component_solder_ball(self, edb_examples): @@ -1022,10 +1014,3 @@ def test_16b_export_cutout(self, edb_examples): edbapp = edb_examples.get_si_verse() edbapp.configuration.load(data_from_db, apply_file=True) edbapp.close() - - def test_17_ic_die_properties(self, edb_examples): - db: EdbType = edb_examples.get_si_verse() - component = db.components["U8"] - _assert_initial_ic_die_properties(component) - db.configuration.load(U8_IC_DIE_PROPERTIES, apply_file=True) - _assert_final_ic_die_properties(component) From ecbddb5d1285b0d74b7d1ea169f81d8e3e4dcf21 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 27 Oct 2024 15:50:00 +0000 Subject: [PATCH 07/14] MISC: Auto fixes from pre-commit.com hooks For more information, see https://pre-commit.ci --- src/pyedb/configuration/cfg_components.py | 5 +---- tests/legacy/system/test_edb_components.py | 1 - tests/legacy/system/test_edb_configuration_2p0.py | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/pyedb/configuration/cfg_components.py b/src/pyedb/configuration/cfg_components.py index 0a3e5d6275..59bf497fd2 100644 --- a/src/pyedb/configuration/cfg_components.py +++ b/src/pyedb/configuration/cfg_components.py @@ -21,10 +21,7 @@ # SOFTWARE. from pyedb.configuration.cfg_common import CfgBase -from pyedb.dotnet.edb_core.general import ( - pascal_to_snake, - snake_to_pascal, -) +from pyedb.dotnet.edb_core.general import pascal_to_snake, snake_to_pascal class CfgComponent(CfgBase): diff --git a/tests/legacy/system/test_edb_components.py b/tests/legacy/system/test_edb_components.py index 8fb1d32439..ebdd1c65b0 100644 --- a/tests/legacy/system/test_edb_components.py +++ b/tests/legacy/system/test_edb_components.py @@ -626,4 +626,3 @@ def test_properties(self, edb_examples): } 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 c2f610a83b..82d6aadc97 100644 --- a/tests/legacy/system/test_edb_configuration_2p0.py +++ b/tests/legacy/system/test_edb_configuration_2p0.py @@ -530,7 +530,7 @@ def test_09_padstack_definition(self, edb_examples): edbapp = edb_examples.get_si_verse() assert edbapp.configuration.load(data, apply_file=True) data_from_layout = edbapp.configuration.get_data_from_db(padstacks=True) - pdef = [i for i in data_from_layout["padstacks"]["definitions"] if i["name"]=="v35h15"][0] + pdef = [i for i in data_from_layout["padstacks"]["definitions"] if i["name"] == "v35h15"][0] pad_params = pdef["pad_parameters"] assert pad_params["regular_pad"][0]["diameter"] == "0.5mm" From 0600b8f3355ff41cd9c202454a5b607252890b1e Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Sun, 27 Oct 2024 17:28:38 +0100 Subject: [PATCH 08/14] draft --- src/pyedb/configuration/cfg_components.py | 62 +++++++++---------- .../system/test_edb_configuration_2p0.py | 48 +++++++------- tests/legacy/system/test_edb_padstacks.py | 27 -------- 3 files changed, 52 insertions(+), 85 deletions(-) diff --git a/src/pyedb/configuration/cfg_components.py b/src/pyedb/configuration/cfg_components.py index 0a3e5d6275..2cd4b6e14d 100644 --- a/src/pyedb/configuration/cfg_components.py +++ b/src/pyedb/configuration/cfg_components.py @@ -110,43 +110,35 @@ def _set_model_properties_to_edb(self): self.spice_model["terminal_pairs"], ) - def retrieve_ic_die_properties_from_edb(self): + def _retrieve_ic_die_properties_from_edb(self): temp = dict() cp = self._pyedb_obj.component_property - c_type = self.type.lower() - if not c_type == "ic": - return - else: - ic_die_prop = cp.GetDieProperty().Clone() - die_type = pascal_to_snake(ic_die_prop.GetType().ToString()) - self.type = die_type - if not die_type == "no_die": - temp["orientation"] = pascal_to_snake(ic_die_prop.GetOrientation().ToString()) - if die_type == "wire_bond": - temp["height"] = ic_die_prop.GetHeightValue().ToString() - self.ic_die_properties = temp + 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().ToString()) + if die_type == "wire_bond": + temp["height"] = ic_die_prop.GetHeightValue().ToString() + self.ic_die_properties = temp def _set_ic_die_properties_to_edb(self): cp = self._pyedb_obj.component_property - c_type = self._pyedb_obj.type.lower() - if not c_type == "ic": - return - else: - ic_die_prop = cp.GetDieProperty().Clone() - die_type = self.ic_die_properties.get("type") - ic_die_prop.SetType(getattr(self._edb.definition.DieType, snake_to_pascal(die_type))) - if not die_type == "no_die": - orientation = self.ic_die_properties.get("orientation") - if orientation: - ic_die_prop.SetOrientation( - getattr(self._edb.definition.DieOrientation, snake_to_pascal(orientation)) - ) - if die_type == "wire_bond": - height = self.ic_die_properties.get("height") - if height: - ic_die_prop.SetHeight(self._pedb.edb_value(height)) - cp.SetDieProperty(ic_die_prop) - self._pyedb_obj.component_property = cp + ic_die_prop = cp.GetDieProperty().Clone() + die_type = self.ic_die_properties.get("type") + ic_die_prop.SetType(getattr(self._pedb._edb.Definition.DieType, snake_to_pascal(die_type))) + if not die_type == "no_die": + orientation = self.ic_die_properties.get("orientation") + if orientation: + ic_die_prop.SetOrientation( + getattr(self._pedb._edb.Definition.DieOrientation, snake_to_pascal(orientation)) + ) + if die_type == "wire_bond": + height = self.ic_die_properties.get("height") + if height: + ic_die_prop.SetHeight(self._pedb.edb_value(height)) + cp.SetDieProperty(ic_die_prop) + self._pyedb_obj.component_property = cp def _retrieve_solder_ball_properties_from_edb(self): temp = dict() @@ -234,8 +226,10 @@ def retrieve_parameters_from_edb(self): self.definition = self._pyedb_obj.part_name self.reference_designator = self._pyedb_obj.name self.retrieve_model_properties_from_edb() - if self._pyedb_obj.type.lower() in ["ic", "io", "other"]: - self.retrieve_ic_die_properties_from_edb() + if self._pyedb_obj.type.lower() == "ic": + self._retrieve_ic_die_properties_from_edb() + self._retrieve_port_properties_from_edb() + elif self._pyedb_obj.type.lower() in ["io", "other"]: self._retrieve_solder_ball_properties_from_edb() self._retrieve_port_properties_from_edb() diff --git a/tests/legacy/system/test_edb_configuration_2p0.py b/tests/legacy/system/test_edb_configuration_2p0.py index c2f610a83b..a014aa9579 100644 --- a/tests/legacy/system/test_edb_configuration_2p0.py +++ b/tests/legacy/system/test_edb_configuration_2p0.py @@ -24,6 +24,7 @@ import pytest +from pyedb.dotnet.edb import Edb as EdbType pytestmark = [pytest.mark.unit, pytest.mark.legacy] @@ -949,30 +950,6 @@ def test_16_components_rlc(self, edb_examples): assert c375["pin_pair_model"] == components[0]["pin_pair_model"] edbapp.close() - def test_15b_component_solder_ball(self, edb_examples): - components = [ - { - "reference_designator": "U1", - "part_type": "io", - "solder_ball_properties": {"shape": "cylinder", "diameter": "244um", "height": "406um"}, - "port_properties": { - "reference_offset": "0.1mm", - "reference_size_auto": True, - "reference_size_x": 0, - "reference_size_y": 0, - }, - }, - ] - data = {"components": components} - edbapp = edb_examples.get_si_verse() - assert edbapp.configuration.load(data, apply_file=True) - assert edbapp.components["U1"].type == "IO" - assert edbapp.components["U1"].solder_ball_shape == "Cylinder" - assert edbapp.components["U1"].solder_ball_height == 406e-6 - assert edbapp.components["U1"].solder_ball_diameter == (244e-6, 244e-6) - - edbapp.close() - def test_16_export_to_external_file(self, edb_examples): edbapp = edb_examples.get_si_verse() data_file_path = Path(edb_examples.test_folder) / "test.json" @@ -1014,3 +991,26 @@ def test_16b_export_cutout(self, edb_examples): edbapp = edb_examples.get_si_verse() edbapp.configuration.load(data_from_db, apply_file=True) edbapp.close() + + def test_17_ic_die_properties(self, edb_examples): + db: EdbType = edb_examples.get_si_verse() + + comps_edb = db.configuration.get_data_from_db(components=True)["components"] + component = [i for i in comps_edb if i["reference_designator"] == "U8"][0] + _assert_initial_ic_die_properties(component) + + db.configuration.load(U8_IC_DIE_PROPERTIES, apply_file=True) + comps_edb = db.configuration.get_data_from_db(components=True)["components"] + component = [i for i in comps_edb if i["reference_designator"] == "U8"][0] + _assert_final_ic_die_properties(component) + + +def _assert_initial_ic_die_properties(component: dict): + assert component["ic_die_properties"]["type"] == "no_die" + assert "orientation" not in component["ic_die_properties"] + assert "height" not in component["ic_die_properties"] + + +def _assert_final_ic_die_properties(component: dict): + assert component["ic_die_properties"]["type"] == "flip_chip" + assert component["ic_die_properties"]["orientation"] == "chip_down" diff --git a/tests/legacy/system/test_edb_padstacks.py b/tests/legacy/system/test_edb_padstacks.py index 487a306787..1ec8bcae60 100644 --- a/tests/legacy/system/test_edb_padstacks.py +++ b/tests/legacy/system/test_edb_padstacks.py @@ -456,33 +456,6 @@ def test_via_fence(self): assert "via_central" in edbapp.padstacks.definitions edbapp.close() - def test_pad_parameter(self, edb_examples): - edbapp = edb_examples.get_si_verse() - o_pad_params = edbapp.padstacks.definitions["v35h15"].pad_parameters - assert o_pad_params["regular_pad"][0]["shape"] == "circle" - - i_pad_params = {} - i_pad_params["regular_pad"] = [ - {"layer_name": "1_Top", "shape": "circle", "offset_x": "0.1mm", "rotation": "0", "diameter": "0.5mm"} - ] - i_pad_params["anti_pad"] = [{"layer_name": "1_Top", "shape": "circle", "diameter": "1mm"}] - i_pad_params["thermal_pad"] = [ - { - "layer_name": "1_Top", - "shape": "round90", - "inner": "1mm", - "channel_width": "0.2mm", - "isolation_gap": "0.3mm", - } - ] - edbapp.padstacks.definitions["v35h15"].pad_parameters = i_pad_params - o2_pad_params = edbapp.padstacks.definitions["v35h15"].pad_parameters - assert o2_pad_params["regular_pad"][0]["diameter"] == "0.5mm" - assert o2_pad_params["regular_pad"][0]["offset_x"] == "0.1mm" - assert o2_pad_params["anti_pad"][0]["diameter"] == "1mm" - assert o2_pad_params["thermal_pad"][0]["inner"] == "1mm" - assert o2_pad_params["thermal_pad"][0]["channel_width"] == "0.2mm" - def test_pad_parameter(self, edb_examples): edbapp = edb_examples.get_si_verse() o_hole_params = edbapp.padstacks.definitions["v35h15"].hole_parameters From 3e9af1a04a6a056a774405ad7209dca55befbed9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 27 Oct 2024 16:29:23 +0000 Subject: [PATCH 09/14] MISC: Auto fixes from pre-commit.com hooks For more information, see https://pre-commit.ci --- tests/legacy/system/test_edb_configuration_2p0.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/legacy/system/test_edb_configuration_2p0.py b/tests/legacy/system/test_edb_configuration_2p0.py index c7cec9c00a..27b6ad89cc 100644 --- a/tests/legacy/system/test_edb_configuration_2p0.py +++ b/tests/legacy/system/test_edb_configuration_2p0.py @@ -25,6 +25,7 @@ import pytest from pyedb.dotnet.edb import Edb as EdbType + pytestmark = [pytest.mark.unit, pytest.mark.legacy] From daf677ac74feed782cb7e36bebe9aedb39f1c003 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Mon, 28 Oct 2024 08:18:58 +0100 Subject: [PATCH 10/14] minor fix --- tests/legacy/system/test_edb_padstacks.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/legacy/system/test_edb_padstacks.py b/tests/legacy/system/test_edb_padstacks.py index 1ec8bcae60..cc5728be4c 100644 --- a/tests/legacy/system/test_edb_padstacks.py +++ b/tests/legacy/system/test_edb_padstacks.py @@ -455,10 +455,3 @@ def test_via_fence(self): assert "main_via" in edbapp.padstacks.definitions assert "via_central" in edbapp.padstacks.definitions edbapp.close() - - def test_pad_parameter(self, edb_examples): - edbapp = edb_examples.get_si_verse() - o_hole_params = edbapp.padstacks.definitions["v35h15"].hole_parameters - assert o_hole_params["shape"] == "circle" - edbapp.padstacks.definitions["v35h15"].hole_parameters = {"shape": "circle", "diameter": "0.2mm"} - assert edbapp.padstacks.definitions["v35h15"].hole_parameters["diameter"] == "0.2mm" From 14681b458a42343640e9eec984d81669230275e7 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Mon, 28 Oct 2024 08:21:27 +0100 Subject: [PATCH 11/14] minor fix --- src/pyedb/configuration/cfg_components.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pyedb/configuration/cfg_components.py b/src/pyedb/configuration/cfg_components.py index 48c8782b2d..b85b5f116a 100644 --- a/src/pyedb/configuration/cfg_components.py +++ b/src/pyedb/configuration/cfg_components.py @@ -213,8 +213,10 @@ def set_parameters_to_edb(self): self._pyedb_obj.type = self.type self._set_model_properties_to_edb() - if self._pyedb_obj.type.lower() in ["ic", "io", "other"]: + if self._pyedb_obj.type.lower() == "ic": self._set_ic_die_properties_to_edb() + self._set_port_properties_to_edb() + elif self._pyedb_obj.type.lower() in ["io", "other"]: self._set_solder_ball_properties_to_edb() self._set_port_properties_to_edb() From 36cdb2607674403c2b54dca57bca9e4802fddd65 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Mon, 28 Oct 2024 08:28:23 +0100 Subject: [PATCH 12/14] minor fix --- src/pyedb/dotnet/edb_core/cell/hierarchy/component.py | 1 - tests/legacy/system/test_edb_components.py | 1 - 2 files changed, 2 deletions(-) diff --git a/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py b/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py index f0983a3e54..95517f6f9f 100644 --- a/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py +++ b/src/pyedb/dotnet/edb_core/cell/hierarchy/component.py @@ -33,7 +33,6 @@ 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 diff --git a/tests/legacy/system/test_edb_components.py b/tests/legacy/system/test_edb_components.py index ebdd1c65b0..d06868bdc5 100644 --- a/tests/legacy/system/test_edb_components.py +++ b/tests/legacy/system/test_edb_components.py @@ -29,7 +29,6 @@ # from pyedb import Edb from pyedb.dotnet.edb import Edb -from pyedb.dotnet.edb_core.cell.hierarchy.component import EDBComponent from tests.conftest import desktop_version, local_path from tests.legacy.system.conftest import test_subfolder From 9836338a5f94e3edddb999fab18611547adb1072 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Mon, 28 Oct 2024 09:30:04 +0100 Subject: [PATCH 13/14] fix example --- examples/use_configuration/import_padstack_definitions.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/examples/use_configuration/import_padstack_definitions.py b/examples/use_configuration/import_padstack_definitions.py index 522d1f166b..829c3c6990 100644 --- a/examples/use_configuration/import_padstack_definitions.py +++ b/examples/use_configuration/import_padstack_definitions.py @@ -136,14 +136,6 @@ edbapp.configuration.load(cfg_file_path, apply_file=True) -# Check layout - -pdef = edbapp.padstacks.definitions["v35h15"] - -display(pd.DataFrame(pdef.pad_parameters["regular_pad"])) - -display(pd.DataFrame(pdef.pad_parameters["anti_pad"])) - # ## Save and close Edb # The temporary folder will be deleted once the execution of this script is finished. Replace edbapp.save() with # edbapp.save_as("C:/example.aedb") to keep the example project. From ee13329cabb63460f9e036262f4224281115a110 Mon Sep 17 00:00:00 2001 From: ring630 <@gmail.com> Date: Mon, 28 Oct 2024 16:19:23 +0100 Subject: [PATCH 14/14] minor fix --- examples/use_configuration/import_padstack_definitions.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/use_configuration/import_padstack_definitions.py b/examples/use_configuration/import_padstack_definitions.py index 829c3c6990..3ea55a4e4d 100644 --- a/examples/use_configuration/import_padstack_definitions.py +++ b/examples/use_configuration/import_padstack_definitions.py @@ -71,12 +71,6 @@ edbapp.configuration.load(cfg_file_path, apply_file=True) -# Check layout - -pdef = edbapp.padstacks.definitions["v35h15"] -display(pdef.hole_plating_thickness) -display(pd.DataFrame([pdef.hole_parameters])) - # ## Create a config file with pad information # Keywords