Skip to content

Development #395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 88 commits into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
7ae64a1
temporary fix for the spice module import
tapegoji Feb 28, 2025
dbe476b
temp fix
tapegoji Feb 28, 2025
c17b8bc
refactor: only impot ElemetData class at the top
tapegoji Feb 28, 2025
edd0d22
example: skip astable
FabriceSalvaire May 15, 2021
9f6ca3d
readme
Kreijstal Mar 1, 2025
f19faad
readme
Kreijstal Mar 1, 2025
c854d6f
readme
Kreijstal Mar 1, 2025
8b24d4b
Smaller diff with original
Kreijstal Mar 1, 2025
c16688b
Making it work for Mingw for the msys2 project
Kreijstal Nov 23, 2024
0185f53
Sanity test
Kreijstal Mar 1, 2025
e513c8e
Update pyspice-test.yml
Kreijstal Mar 1, 2025
862731b
Add Background simulations
Kreijstal Mar 1, 2025
f261e1b
Bumping NgSpice version
Kreijstal Mar 1, 2025
6155e97
Exception ignored from cffi callback <function NgSpiceShared._backgro…
Kreijstal Nov 24, 2024
5da5b1c
Don't error on halt
Kreijstal Nov 25, 2024
62bb90c
Docs: Spelling error
FlyingStitchman Nov 24, 2024
d410858
Do handle ngspice notes
Kreijstal Feb 26, 2025
3ea4078
oops
Kreijstal Mar 1, 2025
725efd9
Fix background simulation handling in NgSpiceSharedSimulator
tapegoji Mar 3, 2025
c3bbde4
Add SPICE model files for 1N5822 diode and IRF150 MOSFET
tapegoji Mar 3, 2025
7801240
Enhance Pin class: add optional name parameter to add_current_probe a…
tapegoji Mar 3, 2025
c3c2c02
Add background simulation handling and include additional SPICE model…
tapegoji Mar 3, 2025
7b23057
fix: don't error on the colon that appears after params when parsing …
tapegoji Mar 3, 2025
125fcbe
fix: update parser to handle ID followed by a + and - in subckt defin…
tapegoji Mar 3, 2025
90965bd
fix: update ID regex in parser to support '+' and '-' in subckt defin…
tapegoji Mar 3, 2025
18c988c
fix: update .gitignore to exclude YAML files in spice-library examples
tapegoji Mar 3, 2025
c26e197
fix: update .gitignore to include all YAML files in spice-library exa…
tapegoji Mar 4, 2025
6d07a42
fix: enable DEBUG logging level and handle None values in parser expr…
tapegoji Mar 4, 2025
b7d611f
fix: remove obsolete diode and transistor YAML files from spice-library
tapegoji Mar 4, 2025
588f1d2
fix: update .gitignore to include all YAML files in spice-library exa…
tapegoji Mar 4, 2025
eb89537
removed a test case. not needed.
tapegoji Mar 4, 2025
720a151
reverting back the changes to the background simulation. background s…
tapegoji Mar 4, 2025
f7739a9
fix: correct parameter name in semilogx and restore expression handli…
tapegoji Mar 5, 2025
da44827
fix: improve regex pattern for identifier parsing in SpiceParser. Now…
tapegoji Mar 5, 2025
8b2536b
feat: add input clipper example for Xspice control limit test with tr…
tapegoji Mar 5, 2025
8220057
sometimes there is error in stdout which might come form xspice but s…
tapegoji Mar 5, 2025
75a31f4
fix: update regex pattern in SpiceParser to allow '%' as a valid pref…
tapegoji Mar 5, 2025
1707e45
fix: enhance logging for NgSpiceShared to warn on small timestep and …
tapegoji Mar 5, 2025
0daa4bf
fix: add error handling in SpiceLibrary to log warnings for failed li…
tapegoji Mar 6, 2025
ee33324
Create TODO
tapegoji Mar 8, 2025
916fa97
fix: add optional recurse parameter to SpiceLibrary constructor for c…
tapegoji Mar 9, 2025
3c190f0
fix: adjust SpiceLibrary path handling. If a file is given instead of…
tapegoji Mar 9, 2025
1c25eff
fix: add optional section parameter to SpiceLibrary constructor for b…
tapegoji Mar 9, 2025
d4c5093
feat: add buck converter example circuit simulation using ngshared
tapegoji Mar 9, 2025
5946f3b
fix:fix pin issues and saving and loading from yaml file for pins. no…
tapegoji Mar 10, 2025
6556887
feat: fixed a bug when running a simulation in background in backgrou…
tapegoji Mar 10, 2025
f13f136
feat: improved buck converter simulation example with live plotting u…
tapegoji Mar 10, 2025
bd99c25
chore: update GitHub Actions workflows to use 'development' branch an…
tapegoji Mar 10, 2025
8bc043a
chore: update GitHub Actions workflows to comment out unused sections…
tapegoji Mar 10, 2025
8750a15
chore: update GitHub Actions workflows for CodeQL analysis and PySpic…
tapegoji Mar 10, 2025
650e84d
fix: simplify node naming in Pin class by removing redundant element …
tapegoji Mar 11, 2025
9dafb79
reverting back the node name change. it does not generate unique net …
tapegoji Mar 11, 2025
4fa14c2
add hyphen to the parser. sometimes there is a '-' in the t_ID of the…
tapegoji Apr 1, 2025
06eb9d5
fix: rename 'inner_libraries' to 'inner_includes' for consistency in …
tapegoji Apr 4, 2025
009d3ee
fix: convert inner includes to strings in SpiceInclude and update inc…
tapegoji Apr 4, 2025
e729863
fix: uncomment libraries_path and spice_library initialization in sim…
tapegoji Apr 4, 2025
ac607b3
fix: comment out unused code and update library paths in examples for…
tapegoji Apr 5, 2025
e82ec8a
fix: implement Nodes state in SpiceParser to have a more relax regex …
tapegoji Apr 5, 2025
73e0479
fix: update libraries_path in simple_nand.py for correct library refe…
tapegoji Apr 5, 2025
86bc338
fix: added recurseive include resolving in the code
tapegoji Apr 7, 2025
b6efd3a
fix: add recursive processing for inner includes in SpiceInclude
tapegoji Apr 7, 2025
973f40e
fix: enable recursive processing for SpiceLibrary in simple_nand.py
tapegoji Apr 7, 2025
5293875
fix: enhance recursive include processing in SpiceLibrary and SpiceIn…
tapegoji Apr 10, 2025
e098c12
feat: add print_subcircuit_nodes example with recursive subcircuit pr…
tapegoji Apr 10, 2025
502893b
fix: update path handling in SpiceLibrary and SpiceInclude for loadin…
tapegoji Apr 10, 2025
1b11dd9
fix: update library path in print_subcircuit_nodes example for handli…
tapegoji Apr 10, 2025
c1cb050
fix: update regex in t_NODES_ID for improved node ID parsing and comm…
tapegoji Apr 11, 2025
32d7d4f
fix: update libraries_path in print_subcircuit_nodes example and enha…
tapegoji Apr 11, 2025
0fafd6d
fix: add section parameter to SpiceLibrary and SpiceInclude for impro…
tapegoji Apr 11, 2025
b661275
fix: update parser import paths and enhance parser tests for unit test
tapegoji Apr 12, 2025
3cddb50
fix: extend path handling in Circuit class to support Library.Model i…
tapegoji Apr 12, 2025
dbedc97
fix: enhance example runner to support command line arguments and imp…
tapegoji Apr 12, 2025
e94976f
fix: update examples to run with all the new updates
tapegoji Apr 12, 2025
0e0ebfe
fix: add path check for subcircuits in SpiceLibrary when loading a db…
tapegoji Apr 13, 2025
bcb0ef1
fix: update libraries_path to use relative path for better portability
tapegoji Apr 15, 2025
b6b6d4d
feat: add example for ParallelResistor2 subcircuit with logging and v…
tapegoji Apr 16, 2025
6a8a45c
fix: update Builder class to handle spice_code.title correctly and im…
tapegoji Apr 16, 2025
b065bf4
fix: improve handling of subcircuits in Builder and update example fo…
tapegoji Apr 16, 2025
1df99de
fix: add section parameter to read and parse_file methods in SpiceSou…
tapegoji Apr 16, 2025
2381f79
fix: update libraries_path to use a more appropriate relative path fo…
tapegoji Apr 16, 2025
3ca67bf
Merge branch 'fix_build_circuit' into development
tapegoji Apr 16, 2025
a4c2c46
feat: add example for parsing subcircuits with ParallelResistor2 class
tapegoji Apr 16, 2025
6b3409c
fix: enhance Builder class to handle includes and models in translati…
tapegoji Apr 16, 2025
1568de4
refactor: renamed subcircuit2
tapegoji Apr 16, 2025
81dd5ab
fix: prevent appending objects in subcircuit state and streamline obj…
tapegoji Apr 17, 2025
bee8a0b
fix: update handle_Include method to use obj.path for circuit inclusion
tapegoji Apr 17, 2025
392afb0
reverting back some of the changes made in the previous commit
tapegoji Apr 17, 2025
f951d0e
feat: add raw_spice_parser example for translating SPICE code
tapegoji Apr 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions .github/workflows/pyspice-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ name: Pyspice Test
# Trigger the workflow on
on:
push:
branches:
- master
- devel
branches: "*"
pull_request:
branches:
- master
branches: [ "*" ]
# page_build:
# release:
# types: # This configuration does not affect the page_build event above
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,8 @@ examples/p.diff
examples/spice-library-backup/
examples/spice-library/db.pickle
test.cir

.venv/*
*.vscode/*
examples/spice-library/**/**/*.yaml
examples/spice-library/**/*.yaml
2 changes: 1 addition & 1 deletion PySpice/Plot/BodeDiagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

def bode_diagram_gain(axe, frequency, gain, **kwargs):

axe.semilogx(frequency, gain, basex=10, **kwargs)
axe.semilogx(frequency, gain, base=10, **kwargs)
axe.grid(True)
axe.grid(True, which='minor')
axe.set_xlabel("Frequency [Hz]")
Expand Down
27 changes: 24 additions & 3 deletions PySpice/Spice/Element.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def __iadd__(self, obj):

##############################################

def add_current_probe(self, circuit):
def add_current_probe(self, circuit, name=None):
"""Add a current probe between the node and the pin.

The ammeter is named *ElementName_PinName*.
Expand All @@ -221,8 +221,29 @@ def add_current_probe(self, circuit):
# Fixme: add it to a list
if self.connected:
node = self._node
self._node = '_'.join((self._element.name, self._name))
circuit.V(self._node, node, self._node, '0')
self._node = '_'.join((self._element.name, str(node), str(self.position) ))
if name is None:
name = self._node
circuit.V(name, node, self._node, '0')
else:
raise NameError("Dangling pin")

def add_esr(self, circuit, name= None, value=1e-3):

"""Add a series resistance between the node and the pin.

The ammeter is named *ElementName_PinName*.

"""

# Fixme: require a reference to circuit
# Fixme: add it to a list
if self.connected:
node = self._node
self._node = '_'.join((self._element.name, str(self._node), str(self.position)))
if name is None:
name = self._node
return circuit.R(name, node, self._node, value)
else:
raise NameError("Dangling pin")

Expand Down
96 changes: 87 additions & 9 deletions PySpice/Spice/Library/Library.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,27 @@ class SpiceLibrary:

##############################################

def __init__(self, root_path: str | Path, scan: bool = False) -> None:
def __init__(self, root_path: str | Path, scan: bool = False, recurse: bool = False, section: bool = False) -> None:
# recurse will be removed in the future maybe. it's here because skidl uses it
# if recurse:
# scan = recurse
self._path = PathTools.expand_path(root_path)
if not self._path.exists():
self._path.mkdir(parents=True)
self._logger.info(f"Created {self._path}")
# elif self._path.is_file():
# self._path = self._path.parent
self._subcircuits = {}
self._models = {}
self._recurse = recurse
self._section = section
if not scan:
if self.has_db_path:
self.load()
'''Check if the library has the our path in the subcircuits.'''
paths = {Path(sub_path) for sub_path in self._subcircuits.values()}
if self._path not in paths:
scan = True
else:
self._logger.info("Initialize library...")
scan = True
Expand All @@ -91,6 +102,9 @@ def __init__(self, root_path: str | Path, scan: bool = False) -> None:

@property
def db_path(self) -> Path:
if self._path.is_file():
# If the db path is for a file, use the file's parent directory
return self._path.parent.joinpath('db.pickle')
return self._path.joinpath('db.pickle')

@property
Expand Down Expand Up @@ -165,19 +179,36 @@ def list_categories(self) -> str:
##############################################

def scan(self) -> None:

self._logger.info(f"Scan {self._path}...")

# Handle the case where self._path is a file, not a directory
if self._path.is_file():
# Check if the file has a valid extension
_ = self._path.suffix.lower()
if _ in self.EXTENSIONS:
try:
self._handle_library(self._path)
except Exception as e:
self._logger.warning(f"Failed to parse {self._path}: {e}")
return

# Handle the case where self._path is a directory
for path in PathTools.walk(self._path):
_ = path.suffix.lower()
if _ in self.EXTENSIONS:
self._handle_library(path)
try:
self._handle_library(path)
except Exception as e:
self._logger.warning(f"Failed to parse {path}: {e}")

##############################################

def _handle_library(self, path: Path) -> None:
spice_include = SpiceInclude(path)
spice_include = SpiceInclude(path, recurse=self._recurse, section=self._section)
# Fixme: check overwrite
self._models.update({_.name: path for _ in spice_include.models})
self._subcircuits.update({_.name: path for _ in spice_include.subcircuits})
self._models.update({_.name: str(_.path) for _ in spice_include.models})
self._subcircuits.update({_.name: str(_.path) for _ in spice_include.subcircuits})

##############################################

Expand All @@ -192,16 +223,63 @@ def delete_yaml(self) -> None:
def __getitem__(self, name: str) -> Subcircuit | Model:
if not self:
self._logger.warning("Empty library")

# First, check if the requested item exists directly
path = None
if name in self._subcircuits:
path = self._subcircuits[name]
elif name in self._models:
path = self._models[name]
else:
# print('Library {} not found in {}'.format(name, self._path))
# self._logger.warn('Library {} not found in {}'.format(name, self._path))
# Item not found directly - warn and raise KeyError
available = list(self._subcircuits.keys()) + list(self._models.keys())
available_str = ", ".join(available[:10])
if len(available) > 10:
available_str += f", ... ({len(available)-10} more)"
self._logger.warning(f"Library item '{name}' not found in {self._path}. Available: {available_str}")
raise KeyError(name)
# Fixme: lazy ???
return SpiceInclude(path)[name]

# Create SpiceInclude with recursion enabled if requested
spice_include = SpiceInclude(path, recurse=self._recurse)

try:
# Try to get the item directly from this SpiceInclude
return spice_include[name]
except KeyError:
# Item exists in index but not in the file - search in parent directory
self._logger.info(f"Item '{name}' referenced in {path} but not found there. Searching in sibling files...")

# Try to find the component in sibling library files
original_path = Path(path)
parent_dir = original_path.parent

# Try looking for the item in other library files in the same directory
for lib_ext in self.EXTENSIONS:
for sibling_file in parent_dir.glob(f"*{lib_ext}"):
if sibling_file == original_path:
continue # Skip the original file

try:
self._logger.info(f"Checking {sibling_file} for {name}")
sibling_include = SpiceInclude(sibling_file, recurse=self._recurse)
# Check if this file contains our item
for subckt in sibling_include.subcircuits:
if subckt.name == name:
return subckt
for model in sibling_include.models:
if model.name == name:
return model
except Exception as e:
self._logger.warning(f"Error checking {sibling_file}: {e}")

# If we still can't find it, try one last method - force reparse everything
try:
self._logger.info(f"Attempting one last search with forced reparse for {name}")
reparse_include = SpiceInclude(path, rewrite_yaml=True, recurse=True)
return reparse_include[name]
except KeyError:
# Detailed error message when all recovery attempts fail
raise KeyError(f"'{name}' referenced in library index but not found in any source file. Check your include hierarchy.")

##############################################

Expand Down
Loading