Source code for spice.spice_simcmd

"""
========================
Spice Simulation Command
========================

Class for spice simulation commands.

Initially written by Okko Järvinen, 9.1.2020

"""

import os
import sys
from abc import * 
from thesdk import *
from thesdk.iofile import iofile
import numpy as np
import pandas as pd
import pdb

[docs] class spice_simcmd(thesdk): """ Class to provide simulation command parameters to spice testbench. When instantiated in the parent class, this class automatically attaches spice_simcmd objects to simcmd_bundle -bundle in testbench. Attributes ---------- parent : object The parent object initializing the spice_simcmd instance. Default None. sim : 'tran' or 'dc' Simulation type. plotlist : list(str) List of node names or operating points to be plotted. Node names follow simulator syntax. For Eldo, the voltage/current specifier is expected:: self.plotlist = ['v(OUT)','v(CLK)'] For Spectre, the node name is enough:: self.plotlist = ['OUT','CLK'] .. NOTE:: Below applies only for Spectre! When capturing operating point information with Spectre, adding the instance name to plotlist saves all operating points for the device, e.g:: self.plotlist = [XTB_NAME.XSUBCKT/M0] saves all operating points defined by the model for the device M0 in subckt XSUBCKT. Wildcards are supported, but should be used with caution as the output file can quickly become excessively large. For example to capture the gm of all transistor use:: self.plotlist = [*:gm] It is highly recommended to exclude the devices that are not needed from the output to reduce file size. Examples of such devices are RC-parasitics (include option savefilter='rc' in self.spiceoptions to exclude them) and dummy transistors. See excludelist below. excludelist : list(str) Applies for Spectre only! List of device names NOT to be included in the output report. Wildcards are supported. Exclude list is especially useful for DC simulations when specifiying outputs with wildcards. For example, when capturing gm for all transistors, use exclude list to exclude all dummy transistors with:: self.excludelist = [XTB_NAME*DUMMY_ID*], where DUMMY_ID is extraction tool / runset specific dummy identifier. sweep : List[str] DC & Spectre models only. Name of parameter to be swept in DC analysis. If given as a list, performs a nested sweep of the parameters defined by the list (first element will be the outermost sweep). For example: _spice_simcmd(sim='dc',sweep='temp',swpstart=27,swpstop=87) sweeps the top-level parameter temp (temperature) from 27 to 87 in 10 degree increments. subcktname : List[str] If given, sweeps the parameter defined by property sweep from the subcircuit given by this property. For example:: _=spice_simcmd(sim='dc',sweep='Vb',subcktname='XSUBCKT', swpstart=0.1,swpstop=1.5,step=0.05) sweeps the Vb parameter from subcircuit XSUBCKT from 0.1 volts to 1.5 volts with 0.05 volt increments. devname : List[str] If given, sweeps the parameter defined by property sweep from the device given by this property. For example:: _=spice_simcmd(sim='dc', sweep='w', deviceswp='XSUBCKT.XNMOS', swpstart='10u', swpstop='14u', step='0.1u') sweeps the width of transistor XNMOS of subckt XSUBCKT from 10u to 14u in 0.1u increments. swpstart : int, float or str Starting point of DC sweep. Default 0. swpstop : int, float or str Stop point of DC sweep. Default 0. swpstep : int, float or str Step size of the sweep simulation. Default 10. tprint : float or str Print interval. Default 1e-12 (same as '1p'). tstop : float or str Transient simulation duration. When not defined, the simulation time is the duration of the longest input signal. uic : bool Use initial conditions flag. Default False. noise : bool Noise transient flag. Default False. fmin : float or str Minimum noise frequency. Default 1 (Hz). fmax : float or str Maximum noise frequency. Default 5e9. fscale : 'log' or 'lin' Logarithmic or linear scale for frequency. Default 'log'. fpoints : int Number of points for frequency analysis. Default 0. fstepsize : int Step size for AC analysis, if scale if 'lin'. If fscale is 'log', this parameter gives number of points per decade. Default 0. seed : int Random generator seed for noise transient. Default None (random). method : str Transient integration method. Default None (Spectre takes method from errpreset). cmin : float Spectre cmin parameter: this much cap from each node to ground. Might speed up simulation. Default None (not used). mc : bool Enable Monte Carlo simulation. This flag will enable Monte Carlo modeling for a single simulation. It will NOT execute multiple runs or do any statistical analysis. Intended use case is to generate a group of entities in the testbench with each having mc=True, simulating them in parallel (see run_parallel() of thesdk-class), post-processing results in Python. mc_seed : int Random seed for the Monte Carlo instance. Default None (random seed). model_info : bool For Spectre only! If true, print model parameters to raw-file. maxstep : float Maximum time step Spectre simulator will use during transient analysis step: float According to Spectre: minimum time step used by the simulator solely to maintain the aesthetics of the computed waveforms. strobeperiod: float For Spectre only! Forces simulator to write output data to file at interval defined by this parameter. Note that the simulator still outputs points between the sampling points. skipstart: float For Spectre only! Delay between start of transient simulation and first strobed output, if strobedelay is None. strobedelay: float For Spectre only! Delay between skipstart and the first strobe point. Examples -------- Initiated in parent as:: _=spice_simcmd(self,sim='tran',tprint=1e-12,tstop='10n', uic=True,noise=True,fmin=1,fmax=5e9) For a simple transient with inferred simulation duration:: _=spice_simcmd(self,sim='tran') """ @property def _classfile(self): return os.path.dirname(os.path.realpath(__file__)) + "/"+__name__ def __init__(self,parent,**kwargs): try: self.parent = parent self.sim = kwargs.get('sim','tran') self.plotlist = kwargs.get('plotlist',[]) self.excludelist = kwargs.get('excludelist',[]) self.tprint = kwargs.get('tprint',1e-12) self.tstop = kwargs.get('tstop',None) self.uic = kwargs.get('uic',False) self.noise = kwargs.get('noise',False) self.fmin = kwargs.get('fmin',1) self.fmax = kwargs.get('fmax',5e9) self.fscale = kwargs.get('fscale','log') self.fpoints = kwargs.get('fpoints',0) self.fstepsize = kwargs.get('fstepsize',0) self.seed = kwargs.get('seed',None) self.method = kwargs.get('method',None) self.cmin = kwargs.get('cmin',None) self.mc = kwargs.get('mc',False) self.mc_seed = kwargs.get('mc_seed',None) self.model_info = kwargs.get('model_info', False) self.step = kwargs.get('step', None) self.maxstep = kwargs.get('maxstep', None) self.strobeperiod = kwargs.get('strobeperiod', None) self.strobedelay = kwargs.get('strobedelay', None) self.skipstart = kwargs.get('skipstart', None) # Make list, if they are not already self.sweep = kwargs.get('sweep',[]) if type(kwargs.get('sweep', [])) == list else [kwargs.get('sweep')] self.subcktname = kwargs.get('subcktname',[]) if type(kwargs.get('subcktname', [])) == list else [kwargs.get('subcktname')] self.devname = kwargs.get('devname',[]) if type(kwargs.get('devname', [])) == list else [kwargs.get('devname')] self.swpstart = kwargs.get('swpstart',[]) if type(kwargs.get('swpstart', [])) == list else [kwargs.get('swpstart')] self.swpstop = kwargs.get('swpstop',[]) if type(kwargs.get('swpstop', [])) == list else [kwargs.get('swpstop')] self.swpstep = kwargs.get('swpstep',[]) if type(kwargs.get('swpstep', [])) == list else [kwargs.get('swpstep')] except: self.print_log(type='E',msg=traceback.format_exc()) self.print_log(type='F', msg="Simulation command definition failed.") if hasattr(self.parent,'simcmd_bundle'): # This limits it to 1 of each simulation type. Is this ok? self.parent.simcmd_bundle.new(name=self.sim,val=self) if self.sim == 'dc' and self.parent.model=='spectre': self.print_log(type='I', msg='Saving results in human-readable format (requirement for DC simulation)!') self.parent.spiceoptions.update({'rawfmt': 'psfascii'}) if len(self.subcktname) != 0 and len(self.devname) != 0: self.print_log(type='F', msg='Cannot specify subckt sweep and device sweep in the same simcmd instance!') if self.strobeperiod and self.strobedelay: if self.strobedelay > self.strobeperiod: self.print_log(type='F', msg='Strobedelay cannot be larger than strobeperiod!')