Skip to content

Commit

Permalink
FEAT: Siwave locked lib exporter (#687)
Browse files Browse the repository at this point in the history
* hfsspi SimsetupInfo bug fixed

* temp

* component lib
  • Loading branch information
svandenb-dev authored Jul 24, 2024
1 parent e2a49a0 commit a69b72b
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 0 deletions.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ dependencies = [
"pydantic>=2.6.4,<2.9",
"Rtree >= 1.2.0",
"toml == 0.10.2",
"scikit-rf"
]

[project.optional-dependencies]
Expand All @@ -43,6 +44,7 @@ tests = [
"pytest>=7.4.0,<8.3",
"pytest-cov>=4.0.0,<5.1",
"pytest-xdist>=3.5.0,<3.7",
"scikit-rf"
]
doc = [
"ansys-sphinx-theme>=0.10.0,<0.17",
Expand Down
85 changes: 85 additions & 0 deletions src/pyedb/component_libraries/ansys_components.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import struct

import numpy as np
import skrf as rf


class ComponentLib:
"""Handle component libraries."""

def __init__(self):
self.capacitors = {}
self.inductors = {}
self.path = ""
self.series = {}


class Series:
"""Handle component series."""

def __init__(self):
self._index_file = ""
self._sbin_file = ""


class ComponentPart:
"""Handle component part definition."""

def __init__(self, name, index, sbin_file):
self.name = name
self._index = index
self._sbin_file = sbin_file
self.nb_ports = 2
self.nb_freq = 0
self.ref_impedance = 50.0
self._s_parameters = None

@property
def s_parameters(self):
"""Return skrf.network.Network object
See `scikit-rf documentation <https://scikit-rf.readthedocs.io/en/latest/api/network.html#network-class>`
"""
if not self._s_parameters:
self._extract_impedance()
return self._s_parameters

def _extract_impedance(self):
with open(self._sbin_file, mode="rb") as file:
file_content = file.read()
file.seek(self._index)
self.nb_ports = struct.unpack("i", file_content[self._index : self._index + 4])[0]
self._index += 4
self.nb_freq = struct.unpack("i", file_content[self._index : self._index + 4])[0]
self._index += 4
self.ref_impedance = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s_matrix = np.zeros((self.nb_freq, 2, 2), dtype=complex)
frequencies = []
for f in range(self.nb_freq):
freq = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s11_re_imp = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s11_im_imp = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s12_re_imp = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s12_im_imp = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s21_re_imp = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s21_im_imp = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s22_re_imp = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s22_im_imp = struct.unpack("f", file_content[self._index : self._index + 4])[0]
self._index += 4
s_matrix[f, 0, 0] = s11_re_imp + s11_im_imp * 1j
s_matrix[f, 0, 1] = s12_re_imp + s12_im_imp * 1j
s_matrix[f, 1, 0] = s21_re_imp + s21_im_imp * 1j
s_matrix[f, 1, 1] = s22_re_imp + s22_im_imp * 1j
frequencies.append(freq)
self._s_parameters = rf.Network()
self._s_parameters.frequency = tuple(frequencies)
self._s_parameters.s = s_matrix
file.close()
50 changes: 50 additions & 0 deletions src/pyedb/dotnet/edb_core/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,15 @@
import codecs
import json
import math
import os
import re
import warnings

from pyedb.component_libraries.ansys_components import (
ComponentLib,
ComponentPart,
Series,
)
from pyedb.dotnet.clr_module import String
from pyedb.dotnet.edb_core.cell.hierarchy.component import EDBComponent
from pyedb.dotnet.edb_core.definition.component_def import EDBComponentDef
Expand Down Expand Up @@ -640,6 +646,50 @@ def get_solder_ball_height(self, cmp):
return cmp_prop.GetSolderBallProperty().GetHeight()
return False

def get_vendor_libraries(self):
"""Retrieve all capacitors and inductors libraries from ANSYS installation (used by Siwave).
Returns
-------
pyedb.component_libraries.ansys_components import ComponentLib object. ComponentLib object contains nested
dictionaries to navigate through [component tpe][vendors][series]
[class: `pyedb.component_libraries.ansys_components.ComponentPart`]
Examples
--------
>>> edbapp = Edb()
>>> comp_lib = edbapp.components.get_vendor_libraries()
>>> network = comp_lib.capacitors["AVX"]["AccuP01005"]["C005YJ0R1ABSTR"].s_parameters
>>> network.write_touchstone(os.path.join(edbapp.directory, "test_export.s2p"))
"""
comp_lib_path = os.path.join(self._pedb.base_path, "complib", "Locked")
comp_types = ["Capacitors", "Inductors"]
comp_lib = ComponentLib()
comp_lib.path = comp_lib_path
for cmp_type in comp_types:
folder = os.path.join(comp_lib_path, cmp_type)
vendors = {f.name: "" for f in os.scandir(folder) if f.is_dir()}
for vendor in list(vendors.keys()):
series = {f.name: Series() for f in os.scandir(os.path.join(folder, vendor)) if f.is_dir()}
for serie_name, _ in series.items():
_serie = {}
index_file = os.path.join(folder, vendor, serie_name, "index.txt")
sbin_file = os.path.join(folder, vendor, serie_name, "sdata.bin")
if os.path.isfile(index_file):
with open(index_file, "r") as f:
for line in f.readlines():
part_name, index = line.split()
_serie[part_name] = ComponentPart(part_name, int(index), sbin_file)
f.close()
series[serie_name] = _serie
vendors[vendor] = series
if cmp_type == "Capacitors":
comp_lib.capacitors = vendors
elif cmp_type == "Inductors":
comp_lib.inductors = vendors
return comp_lib

def create_source_on_component(self, sources=None):
"""Create voltage, current source, or resistor on component.
Expand Down
11 changes: 11 additions & 0 deletions tests/legacy/system/test_edb_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,14 @@ def test_create_pingroup_from_pins_types(self, edb_examples):
assert edbapp.components.create_pingroup_from_pins([*edbapp.components.components["Q1"].pins.values()])
assert edbapp.components._create_pin_group_terminal(edbapp.padstacks.pingroups[0], term_type="circuit")
edbapp.close()

def test_component_lib(self):
edbapp = Edb()
comp_lib = edbapp.components.get_vendor_libraries()
assert len(comp_lib.capacitors) == 13
assert len(comp_lib.inductors) == 7
network = comp_lib.capacitors["AVX"]["AccuP01005"]["C005YJ0R1ABSTR"].s_parameters
assert network
assert network.frequency.npoints == 400
network.write_touchstone(os.path.join(edbapp.directory, "test_export.s2p"))
assert os.path.isfile(os.path.join(edbapp.directory, "test_export.s2p"))

0 comments on commit a69b72b

Please sign in to comment.