Skip to content

Commit

Permalink
Merge pull request #160 from nunobrum/xyce-and-ngspice-path-corrections
Browse files Browse the repository at this point in the history
xyce path corrections, simulator switch standardisation
  • Loading branch information
nunobrum authored Feb 23, 2025
2 parents 3c63510 + a6d0f26 commit 2ff5fc3
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 149 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,8 @@ For support and improvement requests please open an Issue in [GitHub spicelib is

## History

* Version TBD
* Version 1.4.1
* Fixed Issue #158 - improve xyce path detection, improve runner switch parameter help texts
* Fixed Issue #154 - support embedded subcircuits in Qspice
* Fixed Issue #139 - support xyce raw files
* Added `get_all_parameter_names()` function to all editors (#159)
Expand Down
116 changes: 61 additions & 55 deletions spicelib/simulators/ltspice_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,34 +136,36 @@ class LTspice(Simulator):
_logger.debug(f"Found LTspice installed in: '{spice_exe}' ")

ltspice_args = {
'alt' : ['-alt'], # Set solver to Alternate.
'ascii' : ['-ascii'], # Use ASCII.raw files. Seriously degrades program performance.
'-alt' : ['-alt'], # Set solver to Alternate.
'-ascii' : ['-ascii'], # Use ASCII.raw files. Seriously degrades program performance.
# 'batch' : ['-b <path>'], # Used by run command: Run in batch mode.E.g. "ltspice.exe-b deck.cir" will leave the data infile deck.raw
'big' : ['-big'], # Start as a maximized window.
'encrypt' : ['-encrypt'],
'-big' : ['-big'], # Start as a maximized window.
'-encrypt' : ['-encrypt'],
# Encrypt a model library.For 3rd parties wishing to allow people to use libraries without
# revealing implementation details. Not used by AnalogDevices models.
'fastaccess' : ['-FastAccess'], # Batch conversion of a binary.rawfile to Fast Access format.
'FixUpSchematicFonts': ['-FixUpSchematicFonts'],
'-fastaccess' : ['-FastAccess'], # Batch conversion of a binary.rawfile to Fast Access format.
'-FixUpSchematicFonts': ['-FixUpSchematicFonts'],
# Convert the font size field of very old user - authored schematic text to the modern default.
'FixUpSymbolFonts' : ['-FixUpSymbolFonts'],
'-FixUpSymbolFonts' : ['-FixUpSymbolFonts'],
# Convert the font size field of very old user - authored symbols to the modern default.
# See Changelog.txt for application hints.
'ini' : ['- ini', '<path>'], # Specify an .ini file to use other than %APPDATA%\LTspice.ini
'I' : ['-I<path>'], # Specify a path to insert in the symbol and file search paths.
'-ini' : ['- ini', '<path>'], # Specify an .ini file to use other than %APPDATA%\LTspice.ini
'-I' : ['-I<path>'], # Specify a path to insert in the symbol and file search paths.
# Must be the last specified option.
# No space between "-I" and < path > is allowed.
'max' : ['-max'], # Synonym for -big
'netlist' : ['-netlist'], # Batch conversion of a schematic to a netlist.
'norm' : ['-norm'], # Set solver to Normal.
'PCBnetlist': ['-PCBnetlist'], # Batch conversion of a schematic to a PCB format netlist.
'-max' : ['-max'], # Synonym for -big
'-netlist' : ['-netlist'], # Batch conversion of a schematic to a netlist.
'-norm' : ['-norm'], # Set solver to Normal.
'-PCBnetlist': ['-PCBnetlist'], # Batch conversion of a schematic to a PCB format netlist.
# 'run' : ['-Run', '-b', '{path}'], # Start simulating the schematic opened on the command line without
# pressing the Run button.
'SOI' : ['-SOI'], # Allow MOSFET's to have up to 7 nodes even in subcircuit expansion.
'sync' : ['-sync'], # Update component libraries
'uninstall' : ['-uninstall'], # Please don't. Executes one step of the uninstallation process.
'-SOI' : ['-SOI'], # Allow MOSFET's to have up to 7 nodes even in subcircuit expansion.
'-sync' : ['-sync'], # Update component libraries
# '-uninstall' : ['-uninstall'], # Please don't. Executes one step of the uninstallation process. >> Not used in this implementation.
}
""":meta private:"""

_default_run_switches = ['-Run', '-b']

@classmethod
def using_macos_native_sim(cls) -> bool:
Expand All @@ -175,47 +177,32 @@ def using_macos_native_sim(cls) -> bool:
return sys.platform == "darwin" and cls.spice_exe and "wine" not in cls.spice_exe[0].lower()

@classmethod
def valid_switch(cls, switch, path='') -> list:
def valid_switch(cls, switch: str, path: str = '') -> list:
"""
Validates a command line switch. The following options are available for Windows/wine LTspice:
* 'alt' : Set solver to Alternate.
* 'ascii' : Use ASCII.raw files. Seriously degrades program performance.
* 'encrypt' : Encrypt a model library.For 3rd parties wishing to allow people to use libraries without
revealing implementation details. Not used by AnalogDevices models.
* 'fastaccess': Batch conversion of a binary.rawfile to Fast Access format.
* 'FixUpSchematicFonts' : Convert the font size field of very old user - authored schematic text to the
modern default.
* 'FixUpSymbolFonts' : Convert the font size field of very old user - authored symbols to the modern
default. See Changelog.txt for application hints.
* 'ini <path>' : Specify an .ini file to use other than %APPDATA%\\LTspice.ini
* 'I<path>' : Specify a path to insert in the symbol and file search paths. Must be the last specified
option.
* 'netlist' : Batch conversion of a schematic to a netlist.
* 'normal' : Set solver to Normal.
* 'PCBnetlist': Batch conversion of a schematic to a PCB format netlist.
* 'SOI' : Allow MOSFET's to have up to 7 nodes even in subcircuit expansion.
* 'sync' : Update component libraries
* 'uninstall' : Executes one step of the uninstallation process. Please don't.
* `-alt`: Set solver to Alternate.
* `-ascii`: Use ASCII.raw files. Seriously degrades program performance.
* `-encrypt`: Encrypt a model library.For 3rd parties wishing to allow people to use libraries without revealing implementation details. Not used by AnalogDevices models.
* `-fastaccess`: Batch conversion of a binary.rawfile to Fast Access format.
* `-FixUpSchematicFonts`: Convert the font size field of very old user - authored schematic text to the modern default.
* `-FixUpSymbolFonts`: Convert the font size field of very old user - authored symbols to the modern default. See Changelog.txt for application hints.
* `-ini <path>`: Specify an .ini file to use other than %APPDATA%\\LTspice.ini
* `-I<path>`: Specify a path to insert in the symbol and file search paths. Must be the last specified option.
* `-netlist`: Batch conversion of a schematic to a netlist.
* `-normal`: Set solver to Normal.
* `-PCBnetlistBatch`: Conversion of a schematic to a PCB format netlist.
* `-SOI`: Allow MOSFET's to have up to 7 nodes even in subcircuit expansion.
* `-sync`: Update component libraries
MacOS native LTspice accepts no command line switches (yet).
The following parameters will already be filled in by spicelib, and cannot be set:
* `-Run`: Start simulating the schematic opened on the command line without pressing the Run button.
* `-b`: Run in batch mode.
MacOS native LTspice accepts no command line switches (yet), use it under wine for full support.
:param switch: switch to be added. If the switch is not on the list above, it should be correctly formatted with
the preceding '-' switch
:param switch: switch to be added.
:type switch: str
:param path: path to the file related to the switch being given.
:type path: str, optional
Expand All @@ -227,18 +214,35 @@ def valid_switch(cls, switch, path='') -> list:
# this is the native LTspice. It has no useful command line switches (except '-b').
raise ValueError("MacOS native LTspice does not support command line switches. Use it under wine for full support.")

# format check
if switch is None:
return []
switch = switch.strip()
if len(switch) == 0:
return []
if switch[0] != '-':
switch = '-' + switch

# will be set anyway?
if switch in cls._default_run_switches:
_logger.info(f"Switch {switch} is already in the default switches")
return []

if switch in cls.ltspice_args:
switches = cls.ltspice_args[switch]
switches = [switch.replace('<path>', path) for switch in switches]
return switches
else:
raise ValueError("Invalid switch for class ")
raise ValueError(f"Invalid Switch '{switch}'")

@classmethod
def run(cls, netlist_file: Union[str, Path], cmd_line_switches: list = None, timeout: float = None,
stdout=None, stderr=None,
exe_log: bool = False) -> int:
"""Executes a LTspice simulation run.
A raw file and a log file will be generated, with the same name as the netlist file,
but with `.raw` and `.log` extension.
:param netlist_file: path to the netlist file
:type netlist_file: Union[str, Path]
Expand All @@ -260,7 +264,7 @@ def run(cls, netlist_file: Union[str, Path], cmd_line_switches: list = None, tim
:return: return code from the process
:rtype: int
"""
if not cls.spice_exe:
if not cls.is_available():
_logger.error("================== ALERT! ====================")
_logger.error("Unable to find a LTspice executable.")
_logger.error("A specific location of the LTSPICE can be set")
Expand All @@ -272,7 +276,9 @@ def run(cls, netlist_file: Union[str, Path], cmd_line_switches: list = None, tim
cmd_line_switches = []
elif isinstance(cmd_line_switches, str):
cmd_line_switches = [cmd_line_switches]
netlist_file = Path(netlist_file)
netlist_file = Path(netlist_file)

# cannot set raw and log file names or extensions. They are always '<netlist_file>.raw' and '<netlist_file>.log'

if sys.platform == "linux" or sys.platform == "darwin":
if cls.using_macos_native_sim():
Expand Down
110 changes: 65 additions & 45 deletions spicelib/simulators/ngspice_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ class NGspiceSimulator(Simulator):
_logger.debug(f"Found ngspice installed in: '{spice_exe}' ")

ngspice_args = {
'-a' : ['-a'],
'--autorun' : ['--autorun'], # run the loaded netlist
'-b' : ['-b'],
'--batch' : ['--batch'], # process FILE in batch mode
# '-a' : ['-a'],
# '--autorun' : ['--autorun'], # run the loaded netlist
# '-b' : ['-b'],
# '--batch' : ['--batch'], # process FILE in batch mode
'-c' : ['-c', '<FILE>'], #
'--circuitfile' : ['--circuitfile', '<FILE>'], # set the circuitfile
'-D' : ['-D', 'var_value'], #
Expand All @@ -84,36 +84,50 @@ class NGspiceSimulator(Simulator):
'--interactive' : ['--interactive'], # run in interactive mode
'-n' : ['-n'], #
'--no-spiceinit': ['--no-spiceinit'], # don't load the local or user's config file
'-o' : ['-o', '<FILE>'], #
'--output' : ['--output', '<FILE>'], # set the outputfile
'-p' : ['-p'], #
'--pipe' : ['--pipe'], # run in I/O pipe mode
# '-o' : ['-o', '<FILE>'], #
# '--output' : ['--output', '<FILE>'], # set the outputfile
# '-p' : ['-p'], #
# '--pipe' : ['--pipe'], # run in I/O pipe mode
'-q' : ['-q'], #
'--completion' : ['--completion'], # activate command completion
'-r' : ['-r'], #
'--rawfile' : ['--rawfile', '<FILE>'], # set the rawfile output
# '-r' : ['-r'], #
# '--rawfile' : ['--rawfile', '<FILE>'], # set the rawfile output
'--soa-log' : ['--soa-log', '<FILE>'], # set the outputfile for SOA warnings
'-s' : ['-s'], #
'--server' : ['--server'], # run spice as a server process
'-t' : ['-t', '<TERM>'], #
'--term' : ['--term', '<TERM>'], # set the terminal type
'-h' : ['-h'], #
'--help' : ['--help'], # display this help and exit
'-v' : ['-v'], #
'--version' : ['--version'], # output version information and exit
# '-h' : ['-h'], #
# '--help' : ['--help'], # display this help and exit
# '-v' : ['-v'], #
# '--version' : ['--version'], # output version information and exit
}
""":meta private:"""

_default_run_switches = ['-b', '-o', '-r', '-a']
_compatibility_mode = 'kiltpsa'

@classmethod
def valid_switch(cls, switch, parameter='') -> list:
def valid_switch(cls, switch: str, parameter: str = '') -> list:
"""
Validates a command line switch. The following options are available for NGSpice:
* `-c, --circuitfile=FILE`: set the circuitfile
* `-D, --define=variable[=value]`: define variable to true/[value]
* `-n, --no-spiceinit`: don't load the local or user's config file
* `-q, --completion`: activate command completion
* `--soa-log=FILE`: set the outputfile for SOA warnings
* `-s, --server`: run spice as a server process
* `-t, --term=TERM`: set the terminal type
The following parameters will already be filled in by spicelib, and cannot be set:
* `-a --autorun`: run the loaded netlist
* `-b, --batch`: process FILE in batch mode
* `-o, --output=FILE`: set the outputfile
* `-r, --rawfile=FILE`: set the rawfile output
:param switch: switch to be added. If the switch is not on the list above, it should be correctly formatted with
the preceding '-' switch
:param switch: switch to be added.
:type switch: str
:param parameter: parameter for the switch
:type parameter: str, optional
Expand All @@ -122,10 +136,22 @@ def valid_switch(cls, switch, parameter='') -> list:
"""
ret = [] # This is an empty switch
parameter = parameter.strip()

# format check
if switch is None:
return []
switch = switch.strip()
if len(switch) == 0:
return []
if switch[0] != '-':
switch = '-' + switch

# will be set anyway?
if switch in cls._default_run_switches:
_logger.info(f"Switch {switch} is already in the default switches")
return []

if switch in cls.ngspice_args:
if switch in cls._default_run_switches:
_logger.info(f"Switch {switch} is already in the default switches")
return ret
if cls.set_compatibility_mode and (switch == '-D' or switch == '--define') and parameter.lower().startswith("ngbehavior"):
_logger.info(f"Switch {switch} {parameter} is already in the default switches, use 'set_compatibility_mode' instead")
return ret
Expand All @@ -139,14 +165,17 @@ def valid_switch(cls, switch, parameter='') -> list:
else:
ret = switch_list
else:
_logger.warning(f"Invalid Switch {switch}")
raise ValueError(f"Invalid Switch '{switch}'")
return ret

@classmethod
def run(cls, netlist_file: Union[str, Path], cmd_line_switches: list = None, timeout: float = None,
stdout=None, stderr=None,
exe_log: bool = False) -> int:
"""Executes a NGspice simulation run.
A raw file and a log file will be generated, with the same name as the netlist file,
but with `.raw` and `.log` extension.
:param netlist_file: path to the netlist file
:type netlist_file: Union[str, Path]
Expand All @@ -168,7 +197,7 @@ def run(cls, netlist_file: Union[str, Path], cmd_line_switches: list = None, tim
:return: return code from the process
:rtype: int
"""
if not cls.spice_exe:
if not cls.is_available():
_logger.error("================== ALERT! ====================")
_logger.error("Unable to find the NGSPICE executable.")
_logger.error("A specific location of the NGSPICE can be set")
Expand All @@ -190,7 +219,7 @@ def run(cls, netlist_file: Union[str, Path], cmd_line_switches: list = None, tim
if cls._compatibility_mode:
extra_switches = ['-D', f"ngbehavior={cls._compatibility_mode}"]
# TODO: -a seems useless with -b, however it is still defined in the default switches. Need to check if it is really needed.
cmd_run = cls.spice_exe + cmd_line_switches + extra_switches + ['-b'] + ['-o'] + [logfile] + ['-r'] + [rawfile] + [netlist_file]
cmd_run = cls.spice_exe + cmd_line_switches + extra_switches + ['-b'] + ['-o'] + [logfile] + ['-r'] + [rawfile] + [netlist_file.as_posix()]
# start execution
if exe_log:
log_exe_file = netlist_file.with_suffix('.exe.log')
Expand All @@ -201,33 +230,24 @@ def run(cls, netlist_file: Union[str, Path], cmd_line_switches: list = None, tim
return error

@classmethod
def set_compatibility_mode(cls, mode: str):
def set_compatibility_mode(cls, mode: str = _compatibility_mode):
"""
Set the compatibility mode. It has become mandatory in recent ngspice versions, as the default 'all' is no longer valid.
A good default seems to be "kiltpsa" (KiCad, LTspice, PSPICE, netlists)
The following compatibility modes are available (as of mid 2024, ngspice v43):
* a : complete netlist transformed
* ps : PSPICE compatibility
* hs : HSPICE compatibility
* spe : Spectre compatibility
* lt : LTSPICE compatibility
* s3 : Spice3 compatibility
* ll : all (currently not used)
* ki : KiCad compatibility
A good default seems to be "kiltpsa" (KiCad, LTspice, PSPICE, netlists).
* eg : EAGLE compatibility
The following compatibility modes are available (as of end 2024, ngspice v44):
* mc : for ’make check’
* `a : complete netlist transformed`
* `ps : PSPICE compatibility`
* `hs : HSPICE compatibility`
* `spe : Spectre compatibility`
* `lt : LTSPICE compatibility`
* `s3 : Spice3 compatibility`
* `ll : all (currently not used)`
* `ki : KiCad compatibility`
* `eg : EAGLE compatibility`
* `mc : for ’make check’`
:param mode: the compatibility mode to be set. Set to None to remove the compatibility setting.
:type mode: str
Expand Down
Loading

0 comments on commit 2ff5fc3

Please sign in to comment.