2000-04-27 22:03:57 +02:00
|
|
|
/* Copyright 1990
|
|
|
|
|
Regents of the University of California.
|
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
|
|
Author: 1985 Wayne A. Christopher
|
|
|
|
|
|
2005-05-29 03:44:20 +02:00
|
|
|
The main routine for ngspice
|
|
|
|
|
$Id$
|
|
|
|
|
*/
|
2004-01-10 22:39:36 +01:00
|
|
|
|
2007-11-28 18:38:00 +01:00
|
|
|
#include "ngspice.h"
|
2000-06-18 00:54:26 +02:00
|
|
|
|
2010-09-10 17:06:04 +02:00
|
|
|
#ifdef HAVE_ASPRINTF
|
2011-07-02 17:32:55 +02:00
|
|
|
# ifdef HAVE_LIBIBERTY_H /* asprintf */
|
|
|
|
|
# include <libiberty.h>
|
|
|
|
|
# elif defined(__MINGW32__) || defined(__SUNPRO_C) /* we have asprintf, but not libiberty.h */
|
|
|
|
|
# include <stdarg.h>
|
|
|
|
|
extern int asprintf(char **out, const char *fmt, ...);
|
|
|
|
|
extern int vasprintf(char **out, const char *fmt, va_list ap);
|
|
|
|
|
# endif
|
2007-11-28 18:38:00 +01:00
|
|
|
#endif
|
2005-05-31 18:47:48 +02:00
|
|
|
|
2010-10-06 22:06:05 +02:00
|
|
|
#include <setjmp.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
2008-11-26 21:33:20 +01:00
|
|
|
/* MINGW: random, srandom in libiberty.a, but not in libiberty.h */
|
|
|
|
|
#if defined(__MINGW32__) && defined(HAVE_RANDOM)
|
2011-07-02 17:32:55 +02:00
|
|
|
extern long int random (void);
|
|
|
|
|
extern void srandom (unsigned int seed);
|
2008-11-26 21:33:20 +01:00
|
|
|
#endif
|
|
|
|
|
|
2003-08-14 21:21:10 +02:00
|
|
|
/* Added GNU Readline Support 11/3/97 -- Andrew Veliath <veliaa@rpi.edu> */
|
|
|
|
|
/* from spice3f4 patch to ng-spice. jmr */
|
2011-07-02 17:32:55 +02:00
|
|
|
#ifdef HAVE_GNUREADLINE
|
|
|
|
|
# include <readline/readline.h>
|
|
|
|
|
# include <readline/history.h>
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2004-01-10 22:39:36 +01:00
|
|
|
|
2005-05-07 01:42:56 +02:00
|
|
|
/* SJB added editline support 2005-05-05 */
|
2011-07-02 17:32:55 +02:00
|
|
|
#ifdef HAVE_BSDEDITLINE
|
|
|
|
|
# include <editline/readline.h>
|
|
|
|
|
extern VFunction *rl_event_hook; /* missing from editline/readline.h */
|
|
|
|
|
extern int rl_catch_signals; /* missing from editline/readline.h */
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2005-05-07 01:42:56 +02:00
|
|
|
|
2005-05-31 18:47:48 +02:00
|
|
|
#include "iferrmsg.h"
|
|
|
|
|
#include "ftedefs.h"
|
|
|
|
|
#include "devdefs.h"
|
|
|
|
|
#include "spicelib/devices/dev.h"
|
|
|
|
|
#include "spicelib/analysis/analysis.h"
|
|
|
|
|
#include "misc/ivars.h"
|
2010-10-15 20:32:57 +02:00
|
|
|
#include "misc/misc_time.h"
|
2011-07-02 17:32:55 +02:00
|
|
|
|
2010-10-17 18:04:34 +02:00
|
|
|
#if defined(HAS_WINDOWS) || defined(_MSC_VER) || defined(__MINGW32__)
|
2011-07-02 17:32:55 +02:00
|
|
|
# include "misc/mktemp.h"
|
2010-10-17 18:04:34 +02:00
|
|
|
#endif
|
2011-07-02 17:32:55 +02:00
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
#if defined(HAVE_GETOPT_LONG) && defined(HAVE_GETOPT_H)
|
2011-07-02 17:32:55 +02:00
|
|
|
# include <getopt.h>
|
2009-04-12 23:08:18 +02:00
|
|
|
#else
|
2011-07-02 17:32:55 +02:00
|
|
|
# include "misc/getopt_bsd.h"
|
2009-04-12 23:08:18 +02:00
|
|
|
#endif
|
2011-07-02 17:32:55 +02:00
|
|
|
|
2010-10-16 17:50:32 +02:00
|
|
|
#include "frontend/spiceif.h"
|
2005-05-31 18:47:48 +02:00
|
|
|
#include "frontend/resource.h"
|
|
|
|
|
#include "frontend/variable.h"
|
2009-10-24 08:28:09 +02:00
|
|
|
#include "frontend/display.h" /* added by SDB to pick up Input() fcn */
|
2005-05-31 18:47:48 +02:00
|
|
|
#include "frontend/signal_handler.h"
|
2010-10-16 19:09:46 +02:00
|
|
|
#include "frontend/misccoms.h"
|
2009-11-15 22:22:04 +01:00
|
|
|
#include "compatmode.h"
|
2005-05-31 18:47:48 +02:00
|
|
|
|
|
|
|
|
/* saj xspice headers */
|
|
|
|
|
#ifdef XSPICE
|
2011-07-02 17:32:55 +02:00
|
|
|
# include "ipctiein.h"
|
|
|
|
|
# include "mif.h"
|
|
|
|
|
# include "enh.h"
|
|
|
|
|
# include "mifproto.h"
|
|
|
|
|
# include "evtproto.h"
|
2005-05-31 18:47:48 +02:00
|
|
|
#endif
|
|
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
#ifdef CIDER
|
2011-07-02 17:32:55 +02:00
|
|
|
# include "numenum.h"
|
|
|
|
|
# include "maths/misc/accuracy.h"
|
2009-10-24 08:28:09 +02:00
|
|
|
#endif
|
2003-08-11 22:53:33 +02:00
|
|
|
|
2005-05-31 18:47:48 +02:00
|
|
|
#if defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE)
|
2011-07-02 17:32:55 +02:00
|
|
|
char history_file[512] = {'\0'};
|
|
|
|
|
static char *application_name;
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2005-05-31 18:47:48 +02:00
|
|
|
|
2009-10-24 08:28:09 +02:00
|
|
|
/* Undefine this next line for debug tracing */
|
2005-04-26 21:42:41 +02:00
|
|
|
/* #define TRACE */
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Main options */
|
|
|
|
|
static bool ft_servermode = FALSE;
|
2009-10-18 12:32:11 +02:00
|
|
|
bool ft_batchmode = FALSE;
|
2009-12-19 17:04:22 +01:00
|
|
|
bool rflag = FALSE; /* has rawfile */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* Frontend options */
|
2004-01-10 22:39:36 +01:00
|
|
|
bool ft_intrpt = FALSE; /* Set by the (void) signal handlers. TRUE = we've been interrupted. */
|
|
|
|
|
bool ft_setflag = FALSE; /* TRUE = Don't abort simulation after an interrupt. */
|
2000-04-27 22:03:57 +02:00
|
|
|
char *ft_rawfile = "rawspice.raw";
|
|
|
|
|
|
2005-05-31 18:47:48 +02:00
|
|
|
#ifdef HAS_WINDOWS
|
2011-07-02 17:32:55 +02:00
|
|
|
extern void winmessage(char *new_msg); /* display a message box (defined in winmain.c)*/
|
|
|
|
|
extern void SetSource( char *Name); /* display the source file name in the source window */
|
2011-07-02 17:33:24 +02:00
|
|
|
extern int xmain(int argc, char **argv);
|
2011-07-02 17:32:55 +02:00
|
|
|
FILE *flogp = NULL; /* log file ('-o logfile' command line option) */
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2002-01-03 23:44:21 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Frontend and circuit options */
|
|
|
|
|
IFsimulator *ft_sim = NULL;
|
|
|
|
|
|
|
|
|
|
/* (Virtual) Machine architecture parameters */
|
|
|
|
|
int ARCHme;
|
|
|
|
|
int ARCHsize;
|
|
|
|
|
|
2009-08-15 11:27:08 +02:00
|
|
|
char *errRtn; /* name of the routine declaring error */
|
|
|
|
|
char *errMsg; /* descriptive message about what went wrong */
|
|
|
|
|
char *cp_program; /* program name 'ngspice' */
|
2005-05-31 18:47:48 +02:00
|
|
|
|
2008-08-24 19:03:26 +02:00
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
/* Globals definitions for Machine Accuracy Limits
|
|
|
|
|
* (needed by CIDER)
|
2009-10-24 08:28:09 +02:00
|
|
|
*/
|
2003-08-11 22:53:33 +02:00
|
|
|
double BMin; /* lower limit for B(x) */
|
|
|
|
|
double BMax; /* upper limit for B(x) */
|
|
|
|
|
double ExpLim; /* limit for exponential */
|
|
|
|
|
double Accuracy; /* accuracy of the machine */
|
2010-10-15 21:24:52 +02:00
|
|
|
double MuLim, MutLim;
|
2003-08-11 22:53:33 +02:00
|
|
|
|
2008-08-24 19:03:26 +02:00
|
|
|
#ifdef CIDER
|
2003-08-11 22:53:33 +02:00
|
|
|
/* Global debug flags from CIDER, soon they will become
|
|
|
|
|
* spice variables :)
|
2009-10-24 08:28:09 +02:00
|
|
|
*/
|
2003-08-11 22:53:33 +02:00
|
|
|
BOOLEAN ONEacDebug = FALSE;
|
|
|
|
|
BOOLEAN ONEdcDebug = TRUE;
|
|
|
|
|
BOOLEAN ONEtranDebug = TRUE;
|
|
|
|
|
BOOLEAN ONEjacDebug = FALSE;
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
BOOLEAN TWOacDebug = FALSE;
|
|
|
|
|
BOOLEAN TWOdcDebug = TRUE;
|
|
|
|
|
BOOLEAN TWOtranDebug = TRUE;
|
2009-10-24 08:28:09 +02:00
|
|
|
BOOLEAN TWOjacDebug = FALSE;
|
|
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
/* CIDER Global Variable Declarations */
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
int BandGapNarrowing;
|
|
|
|
|
int TempDepMobility, ConcDepMobility, FieldDepMobility, TransDepMobility;
|
|
|
|
|
int SurfaceMobility, MatchingMobility, MobDeriv;
|
|
|
|
|
int CCScattering;
|
|
|
|
|
int Srh, Auger, ConcDepLifetime, AvalancheGen;
|
|
|
|
|
int FreezeOut = FALSE;
|
|
|
|
|
int OneCarrier;
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
int MaxIterations = 100;
|
|
|
|
|
int AcAnalysisMethod = DIRECT;
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
double Temp, RelTemp, Vt;
|
|
|
|
|
double RefPsi;/* potential at Infinity */
|
|
|
|
|
double EpsNorm, VNorm, NNorm, LNorm, TNorm, JNorm, GNorm, ENorm;
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
/* end cider globals */
|
|
|
|
|
#endif /* CIDER */
|
|
|
|
|
|
2011-07-02 17:32:07 +02:00
|
|
|
struct variable *(*if_getparam)(CKTcircuit *ckt, char **name, char *param, int ind, int do_model);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2005-04-26 21:42:41 +02:00
|
|
|
/* static functions */
|
2008-08-27 15:39:05 +02:00
|
|
|
int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator);
|
2008-01-20 18:36:02 +01:00
|
|
|
static int sp_shutdown(int exitval);
|
2005-05-04 03:30:09 +02:00
|
|
|
static void app_rl_readlines(void);
|
2005-05-07 01:42:56 +02:00
|
|
|
|
|
|
|
|
#if defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE)
|
2011-07-02 17:32:55 +02:00
|
|
|
static char *prompt(void);
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2005-05-07 01:42:56 +02:00
|
|
|
|
2010-08-09 20:36:57 +02:00
|
|
|
#ifndef X_DISPLAY_MISSING
|
2011-07-02 17:32:55 +02:00
|
|
|
# include "frontend/plotting/x11.h"
|
|
|
|
|
# ifdef HAVE_GNUREADLINE
|
|
|
|
|
static int app_event_func(void);
|
2011-07-02 17:34:17 +02:00
|
|
|
# endif
|
2011-07-02 17:32:55 +02:00
|
|
|
# ifdef HAVE_BSDEDITLINE
|
|
|
|
|
static void app_event_func(void);
|
2011-07-02 17:34:17 +02:00
|
|
|
# endif
|
2010-08-09 20:36:57 +02:00
|
|
|
#endif
|
2005-05-07 01:42:56 +02:00
|
|
|
|
2005-04-26 21:42:41 +02:00
|
|
|
static void show_help(void);
|
|
|
|
|
static void show_version(void);
|
2011-07-02 17:32:07 +02:00
|
|
|
static bool read_initialisation_file(char *dir, char *name);
|
|
|
|
|
|
2005-04-26 21:42:41 +02:00
|
|
|
#ifdef SIMULATOR
|
|
|
|
|
static void append_to_stream(FILE *dest, FILE *source);
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
extern IFsimulator SIMinfo;
|
|
|
|
|
|
|
|
|
|
#ifdef SIMULATOR
|
|
|
|
|
|
|
|
|
|
bool ft_nutmeg = FALSE;
|
|
|
|
|
extern struct comm spcp_coms[ ];
|
|
|
|
|
struct comm *cp_coms = spcp_coms;
|
|
|
|
|
|
2011-07-02 17:34:54 +02:00
|
|
|
extern int OUTpBeginPlot(CKTcircuit *,JOB *,IFuid,IFuid,int,int,IFuid *,int,void **);
|
|
|
|
|
extern int OUTpData(void *,IFvalue *,IFvalue *);
|
|
|
|
|
extern int OUTwBeginPlot(CKTcircuit *,JOB *,IFuid,IFuid,int,int,IFuid *,int,void **);
|
2009-11-15 22:22:04 +01:00
|
|
|
extern int OUTwReference(void *,IFvalue *,void **);
|
2011-07-02 17:34:54 +02:00
|
|
|
extern int OUTwData(void *,int,IFvalue *,void *), OUTwEnd(void *), OUTendPlot(void *);
|
2009-11-15 22:22:04 +01:00
|
|
|
extern int OUTbeginDomain(void *,IFuid,int,IFvalue *);
|
2011-07-02 17:34:54 +02:00
|
|
|
extern int OUTendDomain(void *), OUTstopnow(void), OUTerror(int,char *,IFuid *);
|
2010-01-17 17:40:22 +01:00
|
|
|
extern int OUTattributes(void *,IFuid,int,IFvalue *);
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2010-11-27 17:36:03 +01:00
|
|
|
extern void initw(void);
|
|
|
|
|
|
2008-08-27 15:39:05 +02:00
|
|
|
IFfrontEnd nutmeginfo = {
|
2009-04-12 23:08:18 +02:00
|
|
|
IFnewUid,
|
|
|
|
|
IFdelUid,
|
|
|
|
|
OUTstopnow,
|
|
|
|
|
seconds,
|
|
|
|
|
OUTerror,
|
|
|
|
|
OUTpBeginPlot,
|
|
|
|
|
OUTpData,
|
|
|
|
|
OUTwBeginPlot,
|
|
|
|
|
OUTwReference,
|
|
|
|
|
OUTwData,
|
|
|
|
|
OUTwEnd,
|
|
|
|
|
OUTendPlot,
|
|
|
|
|
OUTbeginDomain,
|
|
|
|
|
OUTendDomain,
|
|
|
|
|
OUTattributes
|
2008-12-07 11:07:35 +01:00
|
|
|
};
|
2008-08-27 15:39:05 +02:00
|
|
|
|
2005-05-31 18:47:48 +02:00
|
|
|
#else /* SIMULATOR */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
bool ft_nutmeg = TRUE;
|
|
|
|
|
extern struct comm nutcp_coms[ ];
|
|
|
|
|
struct comm *cp_coms = nutcp_coms;
|
2008-08-27 15:39:05 +02:00
|
|
|
IFfrontEnd nutmeginfo;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
int
|
2010-07-06 21:03:40 +02:00
|
|
|
if_run(CKTcircuit *t, char *w, wordlist *s, INPtables *b)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(b);
|
|
|
|
|
NG_IGNORE(s);
|
|
|
|
|
NG_IGNORE(w);
|
|
|
|
|
NG_IGNORE(t);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
int
|
2010-07-06 21:03:40 +02:00
|
|
|
if_sens_run(CKTcircuit *t, wordlist *args, INPtables *tab)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(tab);
|
|
|
|
|
NG_IGNORE(args);
|
|
|
|
|
NG_IGNORE(t);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
void
|
2010-07-06 21:03:40 +02:00
|
|
|
if_dump(CKTcircuit *ckt, FILE *fp)
|
2010-11-16 20:11:32 +01:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(fp);
|
|
|
|
|
NG_IGNORE(ckt);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2010-07-06 21:03:40 +02:00
|
|
|
CKTcircuit *
|
|
|
|
|
if_inpdeck(struct line *deck, INPtables **tab)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(tab);
|
|
|
|
|
NG_IGNORE(deck);
|
2010-07-06 21:03:40 +02:00
|
|
|
return NULL;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
int
|
2010-07-18 00:11:51 +02:00
|
|
|
if_option(CKTcircuit *ckt, char *name, enum cp_types type, void *value)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(value);
|
|
|
|
|
NG_IGNORE(type);
|
|
|
|
|
NG_IGNORE(name);
|
|
|
|
|
NG_IGNORE(ckt);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2010-07-06 21:03:40 +02:00
|
|
|
void if_cktfree(CKTcircuit *ckt, INPtables *tab)
|
2010-11-16 20:11:32 +01:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(tab);
|
|
|
|
|
NG_IGNORE(ckt);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
void if_setndnames(char *line)
|
2010-11-16 20:11:32 +01:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(line);
|
2010-11-16 20:11:32 +01:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
char *
|
|
|
|
|
if_errstring(int code)
|
|
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(code);
|
2000-04-27 22:03:57 +02:00
|
|
|
return ("spice error");
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2007-10-08 23:45:00 +02:00
|
|
|
void
|
2010-07-06 21:03:40 +02:00
|
|
|
if_setparam_model(CKTcircuit *ckt, char **name, char *val)
|
2010-11-16 20:11:32 +01:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(val);
|
|
|
|
|
NG_IGNORE(name);
|
|
|
|
|
NG_IGNORE(ckt);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-10-08 23:45:00 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
void
|
2010-07-06 21:03:40 +02:00
|
|
|
if_setparam(CKTcircuit *ckt, char **name, char *param, struct dvec *val, int do_model)
|
2010-11-16 20:11:32 +01:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(do_model);
|
|
|
|
|
NG_IGNORE(val);
|
|
|
|
|
NG_IGNORE(param);
|
|
|
|
|
NG_IGNORE(name);
|
|
|
|
|
NG_IGNORE(ckt);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
bool
|
|
|
|
|
if_tranparams(struct circ *ckt, double *start, double *stop, double *step)
|
|
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(step);
|
|
|
|
|
NG_IGNORE(stop);
|
|
|
|
|
NG_IGNORE(start);
|
|
|
|
|
NG_IGNORE(ckt);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
2009-10-24 08:28:09 +02:00
|
|
|
return (FALSE);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
struct variable *
|
2010-07-06 21:03:40 +02:00
|
|
|
if_getstat(CKTcircuit *ckt, char *name)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(name);
|
|
|
|
|
NG_IGNORE(ckt);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-23 21:36:39 +02:00
|
|
|
#ifdef EXPERIMENTAL_CODE
|
|
|
|
|
void com_loadsnap(wordlist *wl) { return; }
|
|
|
|
|
void com_savesnap(wordlist *wl) { return; }
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-07-25 21:57:34 +02:00
|
|
|
#endif /* SIMULATOR */
|
|
|
|
|
|
|
|
|
|
#ifndef SIMULATOR
|
2003-07-23 21:36:39 +02:00
|
|
|
|
|
|
|
|
#ifdef XSPICE
|
2004-01-10 22:39:36 +01:00
|
|
|
/* saj to get nutmeg to compile, not nice but necessary */
|
2003-07-23 21:36:39 +02:00
|
|
|
Ipc_Tiein_t g_ipc;
|
|
|
|
|
Ipc_Status_t ipc_send_errchk(void ) {
|
2010-06-24 21:00:15 +02:00
|
|
|
Ipc_Status_t x = IPC_STATUS_OK;
|
2003-07-23 21:36:39 +02:00
|
|
|
return(x);
|
|
|
|
|
}
|
|
|
|
|
Ipc_Status_t ipc_get_line(char *str , int *len , Ipc_Wait_t wait ){
|
2010-06-24 21:00:15 +02:00
|
|
|
Ipc_Status_t x = IPC_STATUS_OK;
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(str);
|
|
|
|
|
NG_IGNORE(len);
|
|
|
|
|
NG_IGNORE(wait);
|
2010-11-16 20:11:32 +01:00
|
|
|
|
2003-07-23 21:36:39 +02:00
|
|
|
return(x);
|
|
|
|
|
}
|
|
|
|
|
struct line *ENHtranslate_poly(struct line *deck){
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(deck);
|
2003-07-23 21:36:39 +02:00
|
|
|
return(NULL);
|
|
|
|
|
}
|
|
|
|
|
int load_opus(char *name){
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(name);
|
2003-07-23 21:36:39 +02:00
|
|
|
return(1);
|
|
|
|
|
}
|
|
|
|
|
char *MIFgettok(char **s){
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(s);
|
2003-07-23 21:36:39 +02:00
|
|
|
return(NULL);
|
|
|
|
|
}
|
|
|
|
|
void EVTprint(wordlist *wl){
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(wl);
|
2003-07-23 21:36:39 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
struct dvec *EVTfindvec(char *node){
|
2010-11-16 21:38:24 +01:00
|
|
|
NG_IGNORE(node);
|
2003-07-23 21:36:39 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2005-05-31 18:47:48 +02:00
|
|
|
#endif /* XSPICE */
|
2003-07-23 21:36:39 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
#endif /* SIMULATOR */
|
|
|
|
|
|
|
|
|
|
char *hlp_filelist[] = { "ngspice", 0 };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* allocate space for global constants in 'CONST.h' */
|
|
|
|
|
|
|
|
|
|
double CONSTroot2;
|
|
|
|
|
double CONSTvt0;
|
|
|
|
|
double CONSTKoverQ;
|
|
|
|
|
double CONSTe;
|
|
|
|
|
IFfrontEnd *SPfrontEnd = NULL;
|
2000-05-06 16:12:51 +02:00
|
|
|
int DEVmaxnum = 0;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2009-11-15 22:22:04 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
/* Set a compatibility flag.
|
|
|
|
|
Currently available are flags for:
|
2011-05-29 12:07:10 +02:00
|
|
|
- ngspice (standard)
|
|
|
|
|
- a commercial simulator
|
|
|
|
|
- Spice3
|
2011-05-29 13:13:04 +02:00
|
|
|
- all compatibility stuff
|
2009-11-15 22:22:04 +01:00
|
|
|
*/
|
|
|
|
|
COMPATMODE_T ngspice_compat_mode(void)
|
|
|
|
|
{
|
|
|
|
|
char behaviour[80] ;
|
|
|
|
|
|
2010-07-17 22:48:20 +02:00
|
|
|
if( cp_getvar("ngbehavior", CP_STRING, behaviour)){
|
2011-07-02 17:34:54 +02:00
|
|
|
if (strcasecmp(behaviour, "all")==0)
|
2010-04-24 00:00:40 +02:00
|
|
|
return( COMPATMODE_ALL ) ;
|
2011-07-02 17:34:54 +02:00
|
|
|
if (strcasecmp(behaviour, "hs")==0)
|
2011-05-29 12:07:10 +02:00
|
|
|
return( COMPATMODE_HS ) ;
|
2011-07-02 17:34:54 +02:00
|
|
|
if (strcasecmp(behaviour, "spice3")==0)
|
|
|
|
|
return( COMPATMODE_SPICE3 ) ;
|
2009-11-15 22:22:04 +01:00
|
|
|
}
|
|
|
|
|
return(COMPATMODE_NATIVE) ;
|
|
|
|
|
} /* end ngspice_compat_mode() */
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2008-08-27 15:39:05 +02:00
|
|
|
int
|
2005-04-26 21:42:41 +02:00
|
|
|
SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2000-05-01 19:43:38 +02:00
|
|
|
#ifdef SIMULATOR
|
2000-07-18 20:07:16 +02:00
|
|
|
spice_init_devices();
|
2000-05-06 16:12:51 +02:00
|
|
|
SIMinfo.numDevices = DEVmaxnum = num_devices();
|
2000-05-01 19:43:38 +02:00
|
|
|
SIMinfo.devices = devices_ptr();
|
2000-09-05 21:48:22 +02:00
|
|
|
SIMinfo.numAnalyses = spice_num_analysis();
|
2009-10-24 08:28:09 +02:00
|
|
|
SIMinfo.analyses = (IFanalysis **)spice_analysis_ptr(); /* va: we recast, because we use
|
|
|
|
|
* only the public part
|
2009-04-12 23:08:18 +02:00
|
|
|
*/
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2003-08-11 22:53:33 +02:00
|
|
|
#ifdef CIDER
|
|
|
|
|
/* Evaluates limits of machine accuracy for CIDER */
|
|
|
|
|
evalAccLimits();
|
2009-10-24 08:28:09 +02:00
|
|
|
#endif /* CIDER */
|
|
|
|
|
|
2000-05-01 19:43:38 +02:00
|
|
|
#endif /* SIMULATOR */
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
SPfrontEnd = frontEnd;
|
|
|
|
|
*simulator = &SIMinfo;
|
|
|
|
|
CONSTroot2 = sqrt(2.);
|
|
|
|
|
CONSTvt0 = CONSTboltz * (27 /* deg c */ + CONSTCtoK ) / CHARGE;
|
|
|
|
|
CONSTKoverQ = CONSTboltz / CHARGE;
|
|
|
|
|
CONSTe = exp((double)1.0);
|
|
|
|
|
return(OK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Shutdown gracefully. */
|
2005-04-26 21:42:41 +02:00
|
|
|
static int
|
2008-01-20 18:36:02 +01:00
|
|
|
sp_shutdown(int exitval)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
|
|
|
|
cleanvars();
|
|
|
|
|
#ifdef PARALLEL_ARCH
|
2009-04-12 23:08:18 +02:00
|
|
|
{
|
|
|
|
|
Error("Fatal error in SPICE", -1);
|
2000-04-27 22:03:57 +02:00
|
|
|
} else {
|
2009-04-12 23:08:18 +02:00
|
|
|
PEND_();
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
#endif /* PARALLEL_ARCH */
|
2009-04-12 23:08:18 +02:00
|
|
|
#ifdef HAS_WINDOWS
|
|
|
|
|
if (exitval == EXIT_BAD)
|
|
|
|
|
winmessage("Fatal error in SPICE");
|
2011-06-25 12:18:40 +02:00
|
|
|
else if (exitval == EXIT_INFO)
|
|
|
|
|
winmessage("Information during setup, see main window!");
|
2009-04-12 23:08:18 +02:00
|
|
|
#endif
|
2011-06-25 12:18:40 +02:00
|
|
|
if (exitval == EXIT_INFO) exitval = EXIT_NORMAL;
|
2000-04-27 22:03:57 +02:00
|
|
|
exit (exitval);
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
2005-05-07 01:42:56 +02:00
|
|
|
#if defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE)
|
2003-08-14 21:21:10 +02:00
|
|
|
/* Adapted ../lib/cp/lexical.c:prompt() for GNU Readline -- Andrew Veliath <veliaa@rpi.edu> */
|
|
|
|
|
static char *
|
2005-05-04 03:30:09 +02:00
|
|
|
prompt(void)
|
2003-08-14 21:21:10 +02:00
|
|
|
{
|
|
|
|
|
static char pbuf[128];
|
|
|
|
|
char *p = pbuf, *s;
|
|
|
|
|
|
|
|
|
|
if (cp_interactive == FALSE)
|
2009-04-12 23:08:18 +02:00
|
|
|
return NULL; /* NULL means no prompt */
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-05-04 03:30:09 +02:00
|
|
|
s = get_alt_prompt();
|
|
|
|
|
if(s==NULL)
|
2009-04-12 23:08:18 +02:00
|
|
|
s = cp_promptstring;
|
2005-05-04 03:30:09 +02:00
|
|
|
if(s==NULL)
|
2009-04-12 23:08:18 +02:00
|
|
|
s = "->";
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2003-08-14 21:21:10 +02:00
|
|
|
while (*s) {
|
2009-10-24 08:28:09 +02:00
|
|
|
switch (strip(*s)) {
|
2009-04-12 23:08:18 +02:00
|
|
|
case '!':
|
2010-08-07 12:24:58 +02:00
|
|
|
#if defined(HAVE_BSDEDITLINE) && 0
|
2009-10-24 08:28:09 +02:00
|
|
|
{
|
2009-04-12 23:08:18 +02:00
|
|
|
/* SJB In the present version of editline (v2.9)
|
|
|
|
|
it seems that where_history() is broken.
|
|
|
|
|
This is a hack that works round this problem.
|
|
|
|
|
WARNING: It may fail to work in the future
|
|
|
|
|
as it relies on undocumented structure */
|
2010-08-07 12:24:58 +02:00
|
|
|
/* some years later, it fails indeed, (v2.11 on debian) */
|
2009-04-12 23:08:18 +02:00
|
|
|
int where = 0;
|
2011-07-02 17:32:07 +02:00
|
|
|
HIST_ENTRY *he = current_history();
|
2009-04-12 23:08:18 +02:00
|
|
|
if(he!=NULL) where = *(int*)(he->data);
|
|
|
|
|
p += sprintf(p, "%d", where + 1);
|
2009-10-24 08:28:09 +02:00
|
|
|
}
|
2005-05-07 01:42:56 +02:00
|
|
|
#else
|
2009-10-24 08:28:09 +02:00
|
|
|
p += sprintf(p, "%d", where_history() + 1);
|
2009-04-12 23:08:18 +02:00
|
|
|
#endif /* HAVE_BSDEDITLINE*/
|
2009-10-24 08:28:09 +02:00
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
case '\\':
|
2009-10-24 08:28:09 +02:00
|
|
|
if (*(s + 1))
|
|
|
|
|
p += sprintf(p, "%c", strip(*++s));
|
|
|
|
|
default:
|
2010-11-02 18:31:19 +01:00
|
|
|
*p = (char) strip(*s); ++p;
|
2009-10-24 08:28:09 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s++;
|
2003-08-14 21:21:10 +02:00
|
|
|
}
|
|
|
|
|
*p = 0;
|
|
|
|
|
return pbuf;
|
|
|
|
|
}
|
2005-05-07 01:42:56 +02:00
|
|
|
#endif /* HAVE_GNUREADLINE || HAVE_BSDEDITLINE */
|
2003-08-14 21:21:10 +02:00
|
|
|
|
2010-08-09 20:36:57 +02:00
|
|
|
#ifndef X_DISPLAY_MISSING
|
2005-05-07 01:42:56 +02:00
|
|
|
#ifdef HAVE_GNUREADLINE
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2003-08-14 21:21:10 +02:00
|
|
|
/* Process device events in Readline's hook since there is no where
|
|
|
|
|
else to do it now - AV */
|
2005-04-26 21:42:41 +02:00
|
|
|
static int
|
2010-08-09 20:36:57 +02:00
|
|
|
app_event_func(void)
|
2004-01-10 22:39:36 +01:00
|
|
|
/* called by GNU readline periodically to know what to do about keypresses */
|
2003-08-14 21:21:10 +02:00
|
|
|
{
|
2010-08-09 20:36:57 +02:00
|
|
|
static REQUEST reqst = { char_option, 0 };
|
|
|
|
|
reqst.fp = rl_instream;
|
|
|
|
|
X11_Input(&reqst, NULL);
|
2003-08-14 21:21:10 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
2005-05-04 03:30:09 +02:00
|
|
|
#endif /* HAVE_GNUREADLINE */
|
2003-08-14 21:21:10 +02:00
|
|
|
|
2005-05-07 01:42:56 +02:00
|
|
|
#ifdef HAVE_BSDEDITLINE
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
/* Process device events in Editline's hook.
|
|
|
|
|
similar to the readline function above but returns void */
|
|
|
|
|
static void
|
2010-08-09 20:36:57 +02:00
|
|
|
app_event_func(void)
|
2005-05-07 01:42:56 +02:00
|
|
|
/* called by GNU readline periodically to know what to do about keypresses */
|
|
|
|
|
{
|
2010-08-09 20:36:57 +02:00
|
|
|
static REQUEST reqst = { char_option, 0 };
|
|
|
|
|
reqst.fp = rl_instream;
|
|
|
|
|
X11_Input(&reqst, NULL);
|
2005-05-07 01:42:56 +02:00
|
|
|
}
|
|
|
|
|
#endif /* HAVE_BSDEDITLINE */
|
2010-08-09 20:36:57 +02:00
|
|
|
#endif
|
2005-05-07 01:42:56 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2005-05-04 03:30:09 +02:00
|
|
|
/* This is the command processing loop for spice and nutmeg.
|
|
|
|
|
The function is called even when GNU readline is unavailable, in which
|
|
|
|
|
case it falls back to repeatable calling cp_evloop()
|
|
|
|
|
SJB 26th April 2005 */
|
2005-04-26 21:42:41 +02:00
|
|
|
static void
|
2010-06-23 20:57:13 +02:00
|
|
|
app_rl_readlines(void)
|
2003-08-14 21:21:10 +02:00
|
|
|
{
|
2005-05-07 01:42:56 +02:00
|
|
|
#if defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE)
|
2005-05-04 03:30:09 +02:00
|
|
|
/* GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */
|
2003-08-14 21:21:10 +02:00
|
|
|
char *line, *expanded_line;
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-05-04 03:30:09 +02:00
|
|
|
/* --- set up readline params --- */
|
2005-05-07 01:42:56 +02:00
|
|
|
strcpy(history_file, getenv("HOME"));
|
|
|
|
|
strcat(history_file, "/.");
|
|
|
|
|
strcat(history_file, application_name);
|
|
|
|
|
strcat(history_file, "_history");
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-05-04 03:30:09 +02:00
|
|
|
using_history();
|
2005-05-07 01:42:56 +02:00
|
|
|
read_history(history_file);
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-05-04 03:30:09 +02:00
|
|
|
rl_readline_name = application_name;
|
|
|
|
|
rl_instream = cp_in;
|
|
|
|
|
rl_outstream = cp_out;
|
2010-08-09 20:36:57 +02:00
|
|
|
#ifndef X_DISPLAY_MISSING
|
|
|
|
|
if(dispdev->Input == X11_Input)
|
|
|
|
|
rl_event_hook = app_event_func;
|
|
|
|
|
#endif
|
2005-05-07 01:42:56 +02:00
|
|
|
rl_catch_signals = 0; /* disable signal handling */
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-05-07 01:42:56 +02:00
|
|
|
/* sjb - what to do for editline?
|
2009-10-24 08:28:09 +02:00
|
|
|
This variable is not supported by editline. */
|
|
|
|
|
#if defined(HAVE_GNUREADLINE)
|
2005-05-04 03:30:09 +02:00
|
|
|
rl_catch_sigwinch = 1; /* allow readline to respond to resized windows */
|
2009-10-24 08:28:09 +02:00
|
|
|
#endif
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* note that we want some mechanism to detect ctrl-D and expand it to exit */
|
2010-09-07 22:07:57 +02:00
|
|
|
for (;;) {
|
2004-01-10 22:39:36 +01:00
|
|
|
history_set_pos(history_length);
|
|
|
|
|
|
2005-05-17 23:43:31 +02:00
|
|
|
SETJMP(jbuf, 1); /* Set location to jump to after handling SIGINT (ctrl-C) */
|
2004-01-10 22:39:36 +01:00
|
|
|
|
|
|
|
|
line = readline(prompt());
|
|
|
|
|
if (line && *line) {
|
|
|
|
|
int s = history_expand(line, &expanded_line);
|
|
|
|
|
|
|
|
|
|
if (s == 2) {
|
|
|
|
|
fprintf(stderr, "-> %s\n", expanded_line);
|
|
|
|
|
} else if (s == -1) {
|
|
|
|
|
fprintf(stderr, "readline: %s\n", expanded_line);
|
|
|
|
|
} else {
|
|
|
|
|
cp_evloop(expanded_line);
|
|
|
|
|
add_history(expanded_line);
|
|
|
|
|
}
|
|
|
|
|
free(expanded_line);
|
|
|
|
|
}
|
|
|
|
|
if (line) free(line);
|
2003-08-14 21:21:10 +02:00
|
|
|
}
|
|
|
|
|
/* History gets written in ../fte/misccoms.c com_quit */
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-05-04 03:30:09 +02:00
|
|
|
#else
|
2011-04-28 17:59:36 +02:00
|
|
|
while (cp_evloop(NULL) == 1) ;
|
2005-05-07 01:42:56 +02:00
|
|
|
#endif /* defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE) */
|
2003-08-14 21:21:10 +02:00
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
2005-04-26 21:42:41 +02:00
|
|
|
static void
|
2000-04-27 22:03:57 +02:00
|
|
|
show_help(void)
|
|
|
|
|
{
|
|
|
|
|
printf("Usage: %s [OPTION]... [FILE]...\n"
|
2009-04-12 23:08:18 +02:00
|
|
|
"Simulate the electical circuits in FILE.\n"
|
|
|
|
|
"\n"
|
2009-01-15 17:46:31 +01:00
|
|
|
" -a --autorun run the loaded netlist\n"
|
2009-04-12 23:08:18 +02:00
|
|
|
" -b, --batch process FILE in batch mode\n"
|
|
|
|
|
" -c, --circuitfile=FILE set the circuitfile\n"
|
|
|
|
|
" -i, --interactive run in interactive mode\n"
|
|
|
|
|
" -n, --no-spiceinit don't load the local or user's config file\n"
|
|
|
|
|
" -o, --output=FILE set the outputfile\n"
|
2011-06-25 12:18:40 +02:00
|
|
|
" -p, --pipe run in I/O pipe mode\n"
|
2009-04-12 23:08:18 +02:00
|
|
|
" -q, --completion activate command completion\n"
|
2009-10-24 08:28:09 +02:00
|
|
|
" -r, --rawfile=FILE set the rawfile output\n"
|
2009-04-12 23:08:18 +02:00
|
|
|
" -s, --server run spice as a server process\n"
|
|
|
|
|
" -t, --term=TERM set the terminal type\n"
|
|
|
|
|
" -h, --help display this help and exit\n"
|
|
|
|
|
" -v, --version output version information and exit\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Report bugs to %s.\n", cp_program, Bug_Addr);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2005-04-26 21:42:41 +02:00
|
|
|
static void
|
2000-04-27 22:03:57 +02:00
|
|
|
show_version(void)
|
|
|
|
|
{
|
|
|
|
|
printf("%s compiled from %s revision %s\n"
|
2009-04-12 23:08:18 +02:00
|
|
|
"Written originally by Berkeley University\n"
|
|
|
|
|
"Currently maintained by the NGSpice Project\n\n"
|
|
|
|
|
"Copyright (C) 1985-1996,"
|
|
|
|
|
" The Regents of the University of California\n"
|
2011-06-25 12:18:40 +02:00
|
|
|
"Copyright (C) 1999-2011,"
|
2009-04-12 23:08:18 +02:00
|
|
|
" The NGSpice Project\n", cp_program, PACKAGE, VERSION);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2005-04-26 21:42:41 +02:00
|
|
|
#ifdef SIMULATOR
|
2004-01-10 22:39:36 +01:00
|
|
|
/* -------------------------------------------------------------------------- */
|
2005-04-26 21:42:41 +02:00
|
|
|
static void
|
2000-04-27 22:03:57 +02:00
|
|
|
append_to_stream(FILE *dest, FILE *source)
|
|
|
|
|
{
|
2010-09-12 19:29:43 +02:00
|
|
|
char buf[BSIZE_SP];
|
2010-11-04 20:15:41 +01:00
|
|
|
size_t n;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2010-11-04 20:15:41 +01:00
|
|
|
while ((n = fread(buf, 1, BSIZE_SP, source)) > 0)
|
|
|
|
|
fwrite(buf, n, 1, dest);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2005-04-26 21:42:41 +02:00
|
|
|
#endif /* SIMULATOR */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
/* Read an initialisation file.
|
|
|
|
|
dir is the directory (use NULL or "" for current directory)
|
|
|
|
|
name is the initialisation file's name
|
|
|
|
|
Return true on success
|
|
|
|
|
SJB 25th April 2005 */
|
|
|
|
|
static bool
|
2011-07-02 17:32:07 +02:00
|
|
|
read_initialisation_file(char *dir, char *name)
|
2005-04-26 21:42:41 +02:00
|
|
|
{
|
2009-04-12 23:08:18 +02:00
|
|
|
#ifndef HAVE_UNISTD_H
|
2011-07-02 17:32:07 +02:00
|
|
|
FILE *fp = NULL;
|
2010-10-06 22:06:05 +02:00
|
|
|
#endif /* not HAVE_UNISTD_H */
|
2011-07-02 17:32:07 +02:00
|
|
|
char *path;
|
2005-04-26 21:42:41 +02:00
|
|
|
bool result = FALSE;
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-04-26 21:42:41 +02:00
|
|
|
/* check name */
|
|
|
|
|
if(name==NULL || name[0]=='\0')
|
2009-04-12 23:08:18 +02:00
|
|
|
return FALSE; /* Fail; name needed */
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-04-26 21:42:41 +02:00
|
|
|
/* contruct the full path */
|
|
|
|
|
if(dir == NULL || dir[0]=='\0') {
|
2009-10-24 08:28:09 +02:00
|
|
|
path = name;
|
2005-04-26 21:42:41 +02:00
|
|
|
} else {
|
|
|
|
|
#ifdef HAVE_ASPRINTF
|
2011-07-02 17:34:54 +02:00
|
|
|
asprintf(&path, "%s" DIR_PATHSEP "%s", dir, name);
|
2009-10-24 08:28:09 +02:00
|
|
|
if(path==NULL) return FALSE; /* memory allocation error */
|
2005-04-26 21:42:41 +02:00
|
|
|
#else /* ~ HAVE_ASPRINTF */
|
2010-10-28 21:32:34 +02:00
|
|
|
path = TMALLOC(char, 2 + strlen(dir) + strlen(name));
|
2009-10-24 08:28:09 +02:00
|
|
|
if(path==NULL) return FALSE; /* memory allocation error */
|
2011-07-02 17:34:54 +02:00
|
|
|
sprintf(path, "%s" DIR_PATHSEP "%s", dir, name);
|
2005-04-26 21:42:41 +02:00
|
|
|
#endif /* HAVE_ASPRINTF */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* now access the file */
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
2009-10-24 08:28:09 +02:00
|
|
|
if (access(path, R_OK) == 0) {
|
2005-04-26 21:42:41 +02:00
|
|
|
#else
|
|
|
|
|
if ((fp = fopen(path, "r")) != NULL) {
|
2009-04-12 23:08:18 +02:00
|
|
|
(void) fclose(fp);
|
2005-04-26 21:42:41 +02:00
|
|
|
#endif /* HAVE_UNISTD_H */
|
2009-04-12 23:08:18 +02:00
|
|
|
inp_source(path);
|
2005-04-26 21:42:41 +02:00
|
|
|
#ifdef TRACE
|
2011-07-02 17:34:54 +02:00
|
|
|
printf("Init file: '%s'\n", path);
|
2009-10-24 08:28:09 +02:00
|
|
|
#endif /* TRACE */
|
2009-04-12 23:08:18 +02:00
|
|
|
result = TRUE; /* loaded okay */
|
2005-04-26 21:42:41 +02:00
|
|
|
}
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-04-26 21:42:41 +02:00
|
|
|
/* if dir was not NULL and not empty then we allocated memory above */
|
|
|
|
|
if(dir!=NULL && dir[0] !='\0')
|
|
|
|
|
#ifdef HAVE_ASPRINTF
|
2009-04-12 23:08:18 +02:00
|
|
|
free(path);
|
2005-04-26 21:42:41 +02:00
|
|
|
#else
|
2009-04-12 23:08:18 +02:00
|
|
|
tfree(path);
|
2005-04-26 21:42:41 +02:00
|
|
|
#endif /* HAVE_ASPRINTF */
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2005-04-26 21:42:41 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-02 12:17:04 +02:00
|
|
|
static void
|
|
|
|
|
print_news(void)
|
|
|
|
|
{
|
|
|
|
|
if (News_File && *News_File) {
|
|
|
|
|
char* fname = cp_tildexpand(News_File); /*DG Memory leak */
|
|
|
|
|
FILE *fp = fopen(fname, "r");
|
|
|
|
|
tfree(fname);
|
|
|
|
|
if (fp) {
|
|
|
|
|
char buf[BSIZE_SP];
|
|
|
|
|
while (fgets(buf, BSIZE_SP, fp))
|
|
|
|
|
fputs(buf, stdout);
|
|
|
|
|
(void) fclose(fp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-25 21:57:34 +02:00
|
|
|
|
2002-01-03 23:44:21 +01:00
|
|
|
#ifdef HAS_WINDOWS
|
2011-07-02 17:17:20 +02:00
|
|
|
#define main xmain
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int
|
2000-04-27 22:03:57 +02:00
|
|
|
main(int argc, char **argv)
|
|
|
|
|
{
|
2011-07-02 17:34:54 +02:00
|
|
|
int err;
|
2007-10-11 13:14:06 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
#ifdef SIMULATOR
|
2011-07-02 17:34:54 +02:00
|
|
|
bool gotone = FALSE;
|
2011-07-02 17:34:17 +02:00
|
|
|
#else
|
2000-04-27 22:03:57 +02:00
|
|
|
bool gdata = TRUE;
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
char buf[BSIZE_SP];
|
|
|
|
|
bool readinit = TRUE;
|
|
|
|
|
bool istty = TRUE;
|
|
|
|
|
bool iflag = FALSE;
|
|
|
|
|
bool qflag = FALSE;
|
2009-12-19 17:04:22 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
FILE *circuit_file;
|
2009-04-12 23:08:18 +02:00
|
|
|
bool orflag = FALSE;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2003-07-23 21:36:39 +02:00
|
|
|
#ifdef TRACE
|
|
|
|
|
/* this is used to detect memory leaks during debugging */
|
|
|
|
|
/* added by SDB during debug . . . . */
|
2011-07-02 17:34:54 +02:00
|
|
|
/* mtrace(); */
|
2003-07-23 21:36:39 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef TRACE
|
|
|
|
|
/* this is also used for memory leak plugging . . . */
|
|
|
|
|
/* added by SDB during debug . . . . */
|
2011-07-02 17:34:54 +02:00
|
|
|
/* mwDoFlush(1); */
|
2003-07-23 21:36:39 +02:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* MFB tends to jump to 0 on errors. This tends to catch it. */
|
2011-07-02 17:19:15 +02:00
|
|
|
{
|
|
|
|
|
static int started = 0;
|
|
|
|
|
if (started++) {
|
|
|
|
|
fprintf(cp_err, "main: Internal Error: jump to zero\n");
|
|
|
|
|
sp_shutdown(EXIT_BAD);
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2005-05-07 01:42:56 +02:00
|
|
|
#if defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE)
|
2011-07-02 17:28:22 +02:00
|
|
|
application_name = strrchr(argv[0], '/');
|
|
|
|
|
if (application_name)
|
|
|
|
|
application_name ++;
|
2003-08-14 21:21:10 +02:00
|
|
|
else
|
2011-07-02 17:28:22 +02:00
|
|
|
application_name = argv[0];
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2004-01-10 22:39:36 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
#ifdef PARALLEL_ARCH
|
|
|
|
|
PBEGIN_(argc, argv);
|
|
|
|
|
ARCHme = NODEID_();
|
|
|
|
|
ARCHsize = NNODES_();
|
|
|
|
|
SETDBG_(&debug_flag);
|
|
|
|
|
fprintf( stderr, "On-line: process %d of %d total.\n", ARCHme, ARCHsize );
|
|
|
|
|
evlog(EVKEY_ENABLE, EVKEY_EVENT, "On-line", EVKEY_DUMP, EVKEY_DISABLE,
|
2009-04-12 23:08:18 +02:00
|
|
|
EVKEY_LAST_ARG);
|
2000-04-27 22:03:57 +02:00
|
|
|
#else
|
|
|
|
|
ARCHme = 0;
|
|
|
|
|
ARCHsize = 1;
|
2011-07-02 17:34:17 +02:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-06-25 18:03:05 +02:00
|
|
|
ivars(argv[0]);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-02 17:34:54 +02:00
|
|
|
cp_in = stdin;
|
2000-04-27 22:03:57 +02:00
|
|
|
cp_out = stdout;
|
|
|
|
|
cp_err = stderr;
|
|
|
|
|
|
|
|
|
|
circuit_file = stdin;
|
|
|
|
|
|
|
|
|
|
#ifdef MALLOCTRACE
|
|
|
|
|
mallocTraceInit("malloc.out");
|
|
|
|
|
#endif
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
#if defined(HAVE_ISATTY) && !defined(HAS_WINDOWS)
|
2000-04-27 22:03:57 +02:00
|
|
|
istty = (bool) isatty(fileno(stdin));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
init_time( );
|
|
|
|
|
|
2011-07-02 17:30:40 +02:00
|
|
|
{
|
|
|
|
|
int rv = SIMinit(&nutmeginfo, &ft_sim);
|
|
|
|
|
if(rv != OK) {
|
|
|
|
|
ft_sperror(rv, "SIMinit");
|
|
|
|
|
sp_shutdown(EXIT_BAD);
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2011-07-02 17:30:40 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
cp_program = ft_sim->simulator;
|
|
|
|
|
|
2011-06-24 17:26:52 +02:00
|
|
|
srand((unsigned int) getpid());
|
2010-08-28 20:13:08 +02:00
|
|
|
TausSeed();
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
/* --- Process command line options --- */
|
2010-09-07 22:07:57 +02:00
|
|
|
for(;;) {
|
2011-07-02 17:20:35 +02:00
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
static struct option long_options[] = {
|
|
|
|
|
{"help", 0, 0, 'h'},
|
|
|
|
|
{"version", 0, 0, 'v'},
|
|
|
|
|
{"batch", 0, 0, 'b'},
|
|
|
|
|
{"autorun", 0, 0, 'a'},
|
|
|
|
|
{"circuitfile", 1, 0, 'c'},
|
|
|
|
|
{"interactive", 0, 0, 'i'},
|
|
|
|
|
{"no-spiceinit", 0, 0, 'n'},
|
|
|
|
|
{"output", 1, 0, 'o'},
|
2009-12-07 22:42:09 +01:00
|
|
|
{"pipe", 0, 0, 'p'},
|
2009-04-12 23:08:18 +02:00
|
|
|
{"completion", 0, 0, 'q'},
|
|
|
|
|
{"rawfile", 1, 0, 'r'},
|
|
|
|
|
{"server", 0, 0, 's'},
|
|
|
|
|
{"terminal", 1, 0, 't'},
|
|
|
|
|
{0, 0, 0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
2011-07-02 17:20:35 +02:00
|
|
|
int option_index = 0;
|
|
|
|
|
|
|
|
|
|
int c = getopt_long (argc, argv, "hvbac:ino:pqr:st:",
|
|
|
|
|
long_options, &option_index);
|
|
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
if (c == -1)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
case 'h': /* Help */
|
2009-10-24 08:28:09 +02:00
|
|
|
show_help();
|
2011-06-25 12:18:40 +02:00
|
|
|
sp_shutdown (EXIT_INFO);
|
2009-10-24 08:28:09 +02:00
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case 'v': /* Version info */
|
2009-10-24 08:28:09 +02:00
|
|
|
show_version();
|
2011-06-25 12:18:40 +02:00
|
|
|
sp_shutdown (EXIT_INFO);
|
2009-10-24 08:28:09 +02:00
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case 'b': /* Batch mode */
|
2011-07-02 17:27:19 +02:00
|
|
|
{
|
|
|
|
|
bool x_false = FALSE;
|
|
|
|
|
cp_vset("addcontrol", CP_BOOL, &x_false);
|
|
|
|
|
|
|
|
|
|
ft_batchmode = TRUE;
|
|
|
|
|
}
|
2009-10-24 08:28:09 +02:00
|
|
|
break;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-02 17:34:54 +02:00
|
|
|
case 'a': /* Add control section for autorun */
|
2009-10-24 08:28:09 +02:00
|
|
|
if (!ft_batchmode) {
|
2011-07-02 17:27:19 +02:00
|
|
|
bool x_true = TRUE;
|
|
|
|
|
cp_vset("addcontrol", CP_BOOL, &x_true);
|
2009-10-24 08:28:09 +02:00
|
|
|
}
|
|
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case 'c': /* Circuit file */
|
2009-10-24 08:28:09 +02:00
|
|
|
if (optarg) {
|
2010-11-19 19:54:40 +01:00
|
|
|
if ((circuit_file = fopen(optarg, "r")) == NULL) {
|
2009-10-24 08:28:09 +02:00
|
|
|
perror(optarg);
|
|
|
|
|
sp_shutdown(EXIT_BAD);
|
|
|
|
|
}
|
|
|
|
|
istty = FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case 'i': /* Interactive mode */
|
2009-10-24 08:28:09 +02:00
|
|
|
iflag = TRUE;
|
|
|
|
|
break;
|
2007-10-11 13:14:06 +02:00
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
case 'n': /* Don't read initialisation file */
|
2009-10-24 08:28:09 +02:00
|
|
|
readinit = FALSE;
|
|
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case 'o': /* Output file */
|
2009-10-24 08:28:09 +02:00
|
|
|
if (optarg) {
|
|
|
|
|
/* turn off buffering for stdout */
|
|
|
|
|
setbuf(stdout, NULL);
|
2000-04-27 22:03:57 +02:00
|
|
|
#ifdef PARALLEL_ARCH
|
2011-07-02 17:34:54 +02:00
|
|
|
sprintf (buf, "%s%03d", optarg, ARCHme);
|
2005-05-31 18:47:48 +02:00
|
|
|
#else
|
2011-07-02 17:34:54 +02:00
|
|
|
sprintf (buf, "%s", optarg);
|
2005-05-31 18:47:48 +02:00
|
|
|
#endif
|
2011-07-02 17:34:54 +02:00
|
|
|
orflag = TRUE;
|
2009-10-24 08:28:09 +02:00
|
|
|
}
|
|
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
2009-12-07 22:42:09 +01:00
|
|
|
case 'p': /* Run in pipe mode */
|
|
|
|
|
iflag = TRUE;
|
|
|
|
|
istty = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
case 'q': /* Command completion */
|
2009-10-24 08:28:09 +02:00
|
|
|
qflag = TRUE;
|
|
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case 'r': /* The raw file */
|
2011-07-02 17:35:54 +02:00
|
|
|
if (optarg)
|
2010-07-17 22:48:20 +02:00
|
|
|
cp_vset("rawfile", CP_STRING, optarg);
|
2009-10-24 08:28:09 +02:00
|
|
|
rflag = TRUE;
|
|
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case 's': /* Server mode */
|
2009-10-24 08:28:09 +02:00
|
|
|
ft_servermode = TRUE;
|
|
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case 't':
|
2011-07-02 17:35:54 +02:00
|
|
|
if (optarg)
|
2010-07-17 22:48:20 +02:00
|
|
|
cp_vset("term", CP_STRING, optarg);
|
2009-10-24 08:28:09 +02:00
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
case '?':
|
2009-10-24 08:28:09 +02:00
|
|
|
break;
|
2009-04-12 23:08:18 +02:00
|
|
|
|
|
|
|
|
default:
|
2009-10-24 08:28:09 +02:00
|
|
|
printf ("?? getopt returned character code 0%o ??\n", c);
|
2009-04-12 23:08:18 +02:00
|
|
|
}
|
|
|
|
|
} /* --- End of command line option processing (While(1)-loop) --- */
|
|
|
|
|
|
2011-07-02 17:24:05 +02:00
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
if (orflag) { /* -o option has been set */
|
2011-07-02 17:24:05 +02:00
|
|
|
|
2008-04-13 16:29:16 +02:00
|
|
|
com_version(NULL);
|
2011-07-02 17:24:05 +02:00
|
|
|
|
|
|
|
|
if (ft_servermode)
|
|
|
|
|
fprintf(stdout, "\nServer mode\n\n");
|
|
|
|
|
else if (ft_batchmode)
|
|
|
|
|
fprintf(stdout, "\nBatch mode\n\n");
|
|
|
|
|
else
|
|
|
|
|
fprintf(stdout, "\nInteractive mode, better used without -o option\n\n");
|
|
|
|
|
|
|
|
|
|
if (rflag)
|
|
|
|
|
fprintf(stdout, "Simulation output goes to rawfile: %s\n", ft_rawfile);
|
|
|
|
|
|
2008-04-13 16:29:16 +02:00
|
|
|
fprintf(stdout, "Comments and warnings go to log-file: %s\n\n", buf);
|
2011-07-02 17:24:05 +02:00
|
|
|
|
2008-04-13 16:29:16 +02:00
|
|
|
/* Open the log file */
|
|
|
|
|
#ifdef HAS_WINDOWS
|
2009-08-15 11:27:08 +02:00
|
|
|
/* flogp used by winmain's putc which writes to file 'buf' */
|
2011-07-02 17:31:19 +02:00
|
|
|
flogp = fopen(buf, "w");
|
|
|
|
|
if (!flogp) {
|
|
|
|
|
perror (buf);
|
|
|
|
|
sp_shutdown (EXIT_BAD);
|
|
|
|
|
}
|
|
|
|
|
oflag = TRUE; /* All further output to -o log file */
|
2008-04-13 16:29:16 +02:00
|
|
|
#else
|
2009-04-12 23:08:18 +02:00
|
|
|
/* Connect stdout to file buf and log stdout */
|
2011-07-02 17:31:19 +02:00
|
|
|
if (!freopen (buf, "w", stdout)) {
|
2008-04-13 16:29:16 +02:00
|
|
|
perror (buf);
|
|
|
|
|
sp_shutdown (EXIT_BAD);
|
|
|
|
|
}
|
2011-07-02 17:31:19 +02:00
|
|
|
#endif
|
2008-04-13 16:29:16 +02:00
|
|
|
} /* orflag */
|
2011-07-02 17:31:19 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
#ifdef SIMULATOR
|
2009-01-15 17:46:31 +01:00
|
|
|
if_getparam = spif_getparam_special;
|
2000-04-27 22:03:57 +02:00
|
|
|
#else
|
|
|
|
|
if_getparam = nutif_getparam;
|
|
|
|
|
|
2011-07-02 17:35:54 +02:00
|
|
|
if (optind == argc) /* No raw file */
|
|
|
|
|
gdata = FALSE;
|
2000-04-27 22:03:57 +02:00
|
|
|
#endif
|
|
|
|
|
|
2009-10-24 08:28:09 +02:00
|
|
|
if ((!iflag && !istty) || ft_servermode) /* (batch and file) or server operation */
|
2000-04-27 22:03:57 +02:00
|
|
|
ft_batchmode = TRUE;
|
2009-10-24 08:28:09 +02:00
|
|
|
|
|
|
|
|
if ((iflag && !istty) || qflag) /* (interactive and file) or command completion */
|
|
|
|
|
cp_nocc = TRUE; /* set command completion */
|
2009-08-15 13:47:05 +02:00
|
|
|
else
|
2009-10-24 08:28:09 +02:00
|
|
|
cp_nocc = FALSE;
|
|
|
|
|
|
|
|
|
|
if (ft_servermode) /* in server no init file */
|
2000-04-27 22:03:57 +02:00
|
|
|
readinit = FALSE;
|
2009-10-24 08:28:09 +02:00
|
|
|
|
|
|
|
|
if (!istty || ft_batchmode) /* file or batch - no more output */
|
2000-04-27 22:03:57 +02:00
|
|
|
out_moremode = FALSE;
|
|
|
|
|
|
2009-08-15 13:47:05 +02:00
|
|
|
/* Get information on memory status upon startup.
|
|
|
|
|
Would like to do this later, but cpinit evals commands.
|
|
|
|
|
fcn is in resource.c */
|
2000-04-27 22:03:57 +02:00
|
|
|
init_rlimits( );
|
|
|
|
|
|
2009-10-24 08:28:09 +02:00
|
|
|
/* Have to initialize cp now.
|
2009-08-15 13:47:05 +02:00
|
|
|
fcn is in cpitf.c*/
|
2000-04-27 22:03:57 +02:00
|
|
|
ft_cpinit();
|
|
|
|
|
|
|
|
|
|
/* To catch interrupts during .spiceinit... */
|
2011-07-02 22:10:30 +02:00
|
|
|
if (SETJMP(jbuf, 1)) {
|
2011-07-02 22:14:17 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_err, "Warning: error executing .spiceinit.\n");
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2011-07-02 22:14:17 +02:00
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* Set up signal handling */
|
|
|
|
|
if (!ft_batchmode) {
|
|
|
|
|
/* Set up interrupt handler */
|
|
|
|
|
(void) signal(SIGINT, (SIGNAL_FUNCTION) ft_sigintr);
|
2003-08-14 21:21:10 +02:00
|
|
|
|
2011-07-02 22:14:17 +02:00
|
|
|
/* floating point exception */
|
|
|
|
|
(void) signal(SIGFPE, (SIGNAL_FUNCTION) sigfloat);
|
2003-08-14 21:21:10 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
#ifdef SIGTSTP
|
2011-07-02 22:14:17 +02:00
|
|
|
signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop);
|
2000-04-27 22:03:57 +02:00
|
|
|
#endif
|
2011-07-02 22:14:17 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-02 22:14:17 +02:00
|
|
|
/* Set up signal handling for fatal errors. */
|
|
|
|
|
signal(SIGILL, (SIGNAL_FUNCTION) sigill);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
#ifdef SIGBUS
|
2011-07-02 22:14:17 +02:00
|
|
|
signal(SIGBUS, (SIGNAL_FUNCTION) sigbus);
|
2000-04-27 22:03:57 +02:00
|
|
|
#endif
|
2009-05-02 11:40:33 +02:00
|
|
|
#if defined(SIGSEGV) && !defined(NGDEBUG) && defined(HAS_WINDOWS)
|
|
|
|
|
/* Allow a comment and graceful shutdown after seg fault */
|
2011-07-02 22:14:17 +02:00
|
|
|
signal(SIGSEGV, (SIGNAL_FUNCTION) sigsegv);
|
2000-04-27 22:03:57 +02:00
|
|
|
#endif
|
|
|
|
|
#ifdef SIGSYS
|
2011-07-02 22:14:17 +02:00
|
|
|
signal(SIGSYS, (SIGNAL_FUNCTION) sig_sys);
|
2000-04-27 22:03:57 +02:00
|
|
|
#endif
|
|
|
|
|
|
2011-07-02 22:14:17 +02:00
|
|
|
if (readinit) {
|
|
|
|
|
/* load user's initialisation file
|
|
|
|
|
try accessing the initialisation file in the current directory
|
|
|
|
|
if that fails try the alternate name */
|
|
|
|
|
if(FALSE == read_initialisation_file("", INITSTR) &&
|
|
|
|
|
FALSE == read_initialisation_file("", ALT_INITSTR)) {
|
|
|
|
|
/* if that failed try in the user's home directory
|
|
|
|
|
if their HOME environment variable is set */
|
|
|
|
|
char *homedir = getenv("HOME");
|
|
|
|
|
if(homedir != NULL)
|
|
|
|
|
if(FALSE == read_initialisation_file(homedir, INITSTR) &&
|
|
|
|
|
FALSE == read_initialisation_file(homedir, ALT_INITSTR)) {
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-04-12 23:08:18 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-02 22:14:17 +02:00
|
|
|
if (!ft_batchmode) {
|
|
|
|
|
com_version(NULL);
|
|
|
|
|
DevInit( );
|
|
|
|
|
print_news();
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-02 22:14:17 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* Pass 2 -- get the filenames. If we are spice, then this means
|
|
|
|
|
* build a circuit for this file. If this is in server mode, don't
|
|
|
|
|
* process any of these args. */
|
|
|
|
|
|
2011-07-02 22:10:30 +02:00
|
|
|
if (SETJMP(jbuf, 1))
|
2000-04-27 22:03:57 +02:00
|
|
|
goto evl;
|
|
|
|
|
|
|
|
|
|
cp_interactive = FALSE;
|
|
|
|
|
err = 0;
|
|
|
|
|
|
|
|
|
|
#ifdef SIMULATOR
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2010-11-27 17:36:03 +01:00
|
|
|
#ifdef FastRand
|
|
|
|
|
// initialization and seed for FastNorm Gaussian random generator
|
2011-04-28 19:05:22 +02:00
|
|
|
{
|
|
|
|
|
unsigned int rseed = 66;
|
|
|
|
|
initnorm (0, 0);
|
|
|
|
|
if (!cp_getvar("rndseed", CP_NUM, &rseed)) {
|
|
|
|
|
time_t acttime = time(NULL);
|
2011-06-24 17:26:52 +02:00
|
|
|
rseed = (unsigned int) acttime;
|
2011-04-28 19:05:22 +02:00
|
|
|
}
|
|
|
|
|
initnorm (rseed, 2);
|
|
|
|
|
fprintf (cp_out, "SoS %f, seed value: %ld\n", renormalize(), rseed);
|
2010-11-27 17:36:03 +01:00
|
|
|
}
|
|
|
|
|
#elif defined (WaGauss)
|
2011-04-28 19:05:22 +02:00
|
|
|
{
|
|
|
|
|
unsigned int rseed = 66;
|
|
|
|
|
if (!cp_getvar("rndseed", CP_NUM, &rseed)) {
|
|
|
|
|
time_t acttime = time(NULL);
|
2011-06-24 17:26:52 +02:00
|
|
|
rseed = (unsigned int) acttime;
|
2011-04-28 19:05:22 +02:00
|
|
|
}
|
|
|
|
|
srand(rseed);
|
|
|
|
|
initw();
|
2010-11-27 17:36:03 +01:00
|
|
|
}
|
|
|
|
|
#endif
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!ft_servermode && !ft_nutmeg) {
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
/* Concatenate all non-option arguments into a temporary file
|
|
|
|
|
and load that file into the spice core.
|
2009-10-24 08:28:09 +02:00
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
The original routine took a special path if there was only
|
|
|
|
|
one non-option argument. In that case, it didn't create
|
|
|
|
|
the temporary file but used the original file instead. The
|
|
|
|
|
current algorithm is uniform at the expense of a little
|
|
|
|
|
startup time. */
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2011-07-02 17:29:35 +02:00
|
|
|
FILE *tempfile = tmpfile();
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2008-10-05 00:44:52 +02:00
|
|
|
#if defined(HAS_WINDOWS) || defined(_MSC_VER) || defined(__MINGW32__)
|
2011-07-02 17:34:54 +02:00
|
|
|
char *tpf = NULL; /* temporary file */
|
|
|
|
|
char *dname = NULL; /* input file*/
|
|
|
|
|
|
|
|
|
|
/* tmpfile() returns NULL, if in MS Windows as non admin user
|
|
|
|
|
then we add a tempfile in the local directory */
|
|
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
if (tempfile == NULL) {
|
|
|
|
|
tpf = smktemp("sp");
|
|
|
|
|
tempfile = fopen(tpf, "w+b");
|
|
|
|
|
if (tempfile == NULL) {
|
|
|
|
|
fprintf(stderr, "Could not open a temporary file to save and use optional arguments.");
|
|
|
|
|
sp_shutdown(EXIT_BAD);
|
2009-10-24 08:28:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2009-04-12 23:08:18 +02:00
|
|
|
|
2010-09-12 19:29:43 +02:00
|
|
|
if(!tempfile) {
|
|
|
|
|
perror("tmpfile()");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-02 17:35:54 +02:00
|
|
|
if (optind == argc && !istty)
|
2009-04-12 23:08:18 +02:00
|
|
|
append_to_stream(tempfile, stdin);
|
|
|
|
|
|
|
|
|
|
while (optind < argc) {
|
2011-07-02 17:25:32 +02:00
|
|
|
char *arg = argv[optind++];
|
2009-04-12 23:08:18 +02:00
|
|
|
FILE *tp;
|
|
|
|
|
|
|
|
|
|
/* Copy all the arguments into the temporary file */
|
|
|
|
|
tp = fopen(arg, "r");
|
|
|
|
|
if (!tp) {
|
2011-07-02 17:25:32 +02:00
|
|
|
char *lbuffer = getenv("NGSPICE_INPUT");
|
2011-06-25 18:03:05 +02:00
|
|
|
if (lbuffer && *lbuffer) {
|
2011-07-02 17:25:32 +02:00
|
|
|
char *p =
|
|
|
|
|
TMALLOC(char, strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(arg) + 1);
|
2011-06-25 18:03:05 +02:00
|
|
|
sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, arg);
|
|
|
|
|
tp = fopen(p, "r");
|
|
|
|
|
tfree(p);
|
|
|
|
|
}
|
|
|
|
|
if (!tp) {
|
|
|
|
|
perror(arg);
|
|
|
|
|
err = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2009-04-12 23:08:18 +02:00
|
|
|
}
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2008-10-05 00:44:52 +02:00
|
|
|
#if defined(HAS_WINDOWS) || defined(_MSC_VER) || defined(__MINGW32__)
|
2008-09-24 00:13:46 +02:00
|
|
|
/* Copy the input file name which otherwise will be lost due to the
|
|
|
|
|
temporary file */
|
|
|
|
|
dname = copy(arg);
|
2009-10-18 12:32:11 +02:00
|
|
|
#endif
|
|
|
|
|
#if defined(HAS_WINDOWS)
|
|
|
|
|
/* write source file name into source window */
|
|
|
|
|
SetSource(dname);
|
2009-12-19 10:18:03 +01:00
|
|
|
/* write source file name into a variable */
|
2010-07-17 22:48:20 +02:00
|
|
|
cp_vset("sourcefile", CP_STRING, dname);
|
2009-10-18 12:32:11 +02:00
|
|
|
#endif
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2009-04-12 23:08:18 +02:00
|
|
|
append_to_stream(tempfile, tp);
|
|
|
|
|
fclose(tp);
|
|
|
|
|
}
|
2011-07-02 17:21:14 +02:00
|
|
|
|
|
|
|
|
fseek(tempfile, 0L, SEEK_SET);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
if (tempfile && (!err || !ft_batchmode)) {
|
2008-10-05 00:44:52 +02:00
|
|
|
#if defined(HAS_WINDOWS) || defined(_MSC_VER) || defined(__MINGW32__)
|
2008-09-24 00:13:46 +02:00
|
|
|
/* Copy the input file name for adding another file search path */
|
|
|
|
|
inp_spsource(tempfile, FALSE, dname);
|
|
|
|
|
tfree(dname);
|
2009-10-24 08:28:09 +02:00
|
|
|
#else
|
2000-04-27 22:03:57 +02:00
|
|
|
inp_spsource(tempfile, FALSE, NULL);
|
2008-09-24 00:13:46 +02:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
gotone = TRUE;
|
|
|
|
|
}
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2008-10-05 00:44:52 +02:00
|
|
|
#if defined(HAS_WINDOWS) || defined(_MSC_VER) || defined(__MINGW32__)
|
2011-07-02 12:23:54 +02:00
|
|
|
if (tempfile && tpf && remove(tpf))
|
|
|
|
|
perror("Could not delete temp file");
|
2009-10-24 08:28:09 +02:00
|
|
|
#endif
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2011-07-02 17:35:54 +02:00
|
|
|
if (ft_batchmode && err)
|
2009-04-12 23:08:18 +02:00
|
|
|
sp_shutdown(EXIT_BAD);
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2004-01-10 22:39:36 +01:00
|
|
|
} /* --- if (!ft_servermode && !ft_nutmeg) --- */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
if (!gotone && ft_batchmode && !ft_nutmeg)
|
2011-04-28 17:59:36 +02:00
|
|
|
inp_spsource(circuit_file, FALSE, NULL);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-02 17:34:54 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
evl:
|
|
|
|
|
if (ft_batchmode) {
|
2009-12-19 17:04:22 +01:00
|
|
|
|
|
|
|
|
/* If we get back here in batch mode then something is wrong,
|
|
|
|
|
* so exit. */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-02 22:12:25 +02:00
|
|
|
if (SETJMP(jbuf, 1))
|
2008-01-20 18:36:02 +01:00
|
|
|
sp_shutdown(EXIT_BAD);
|
2011-07-02 17:34:54 +02:00
|
|
|
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (ft_servermode) {
|
|
|
|
|
if (ft_curckt == NULL) {
|
|
|
|
|
fprintf(cp_err, "Error: no circuit loaded!\n");
|
2008-01-20 18:36:02 +01:00
|
|
|
sp_shutdown(EXIT_BAD);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
if (ft_dorun(""))
|
2009-04-12 23:08:18 +02:00
|
|
|
sp_shutdown(EXIT_BAD);
|
2008-01-20 18:36:02 +01:00
|
|
|
sp_shutdown(EXIT_NORMAL);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2009-12-19 17:04:22 +01:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
cp_interactive = FALSE;
|
2011-07-02 17:24:54 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (rflag) {
|
2011-07-02 17:24:54 +02:00
|
|
|
/* If -r is specified, then dot cards (.width, .plot, .print, .op, .meas, .tf)
|
|
|
|
|
are ignored, except .save, which has been handled by ft_dotsaves()
|
|
|
|
|
from within inp_spsource (), data are put into linked list dbs.
|
|
|
|
|
*/
|
|
|
|
|
int error2 = ft_dorun(ft_rawfile);
|
2009-12-19 17:04:22 +01:00
|
|
|
/* Execute the .whatever lines found in the deck, after we are done running. */
|
2009-04-12 23:08:18 +02:00
|
|
|
if (ft_cktcoms(TRUE) || error2)
|
|
|
|
|
sp_shutdown(EXIT_BAD);
|
2000-04-27 22:03:57 +02:00
|
|
|
} else if (ft_savedotargs()) {
|
2011-07-02 17:24:54 +02:00
|
|
|
/* all dot card data to be put into dbs */
|
|
|
|
|
int error2 = ft_dorun(NULL);
|
2009-12-19 17:04:22 +01:00
|
|
|
/* Execute the .whatever lines found in the deck, after we are done running. */
|
2009-04-12 23:08:18 +02:00
|
|
|
if (ft_cktcoms(FALSE) || error2)
|
|
|
|
|
sp_shutdown(EXIT_BAD);
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
2011-07-02 17:24:54 +02:00
|
|
|
"Note: No \".plot\", \".print\", or \".fourier\" lines; "
|
|
|
|
|
"no simulations run\n");
|
2009-04-12 23:08:18 +02:00
|
|
|
sp_shutdown(EXIT_BAD);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2011-07-02 17:24:54 +02:00
|
|
|
|
2009-10-24 08:28:09 +02:00
|
|
|
} /* --- if (ft_batchmode) --- */
|
2004-01-10 22:39:36 +01:00
|
|
|
else {
|
2000-04-27 22:03:57 +02:00
|
|
|
cp_interactive = TRUE;
|
2005-05-04 03:30:09 +02:00
|
|
|
app_rl_readlines(); /* enter the command processing loop */
|
2004-01-10 22:39:36 +01:00
|
|
|
} /* --- else (if (ft_batchmode)) --- */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
#else /* ~ SIMULATOR */
|
|
|
|
|
|
|
|
|
|
if (ft_nutmeg && gdata) {
|
2011-07-02 17:22:16 +02:00
|
|
|
if (optind < argc)
|
|
|
|
|
while (optind < argc)
|
|
|
|
|
ft_loadfile(argv[optind++]);
|
|
|
|
|
else
|
|
|
|
|
ft_loadfile(ft_rawfile);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
evl:
|
|
|
|
|
/* Nutmeg "main" */
|
2011-07-02 22:11:31 +02:00
|
|
|
for(;;)
|
|
|
|
|
if(!SETJMP(jbuf, 1)) {
|
|
|
|
|
/* enter the command processing loop */
|
|
|
|
|
cp_interactive = TRUE;
|
|
|
|
|
app_rl_readlines();
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
#endif /* ~ SIMULATOR */
|
|
|
|
|
|
2008-01-20 18:36:02 +01:00
|
|
|
return sp_shutdown(EXIT_NORMAL);
|
2008-10-14 21:59:23 +02:00
|
|
|
}
|