initial loop analysis code
This commit is contained in:
parent
a0389bb547
commit
4f076ed210
11
configure.ac
11
configure.ac
|
|
@ -70,6 +70,10 @@ AC_ARG_ENABLE([adms],
|
|||
AC_ARG_ENABLE([pss],
|
||||
[AS_HELP_STRING([--enable-pss], [Enable PSS Analysis, (experimental)])])
|
||||
|
||||
# --enable-loopana: enable Loop Analysis
|
||||
AC_ARG_ENABLE([loopana],
|
||||
[AS_HELP_STRING([--enable-loopana], [Enable Loop Analysis])])
|
||||
|
||||
# --enable-relpath: Relative path for binary and data. Default is "no".
|
||||
# ngspice shared may want relative paths for spinit etc.
|
||||
AC_ARG_ENABLE([relpath],
|
||||
|
|
@ -967,6 +971,11 @@ if test "x$enable_pss" = xyes; then
|
|||
AC_DEFINE([WITH_PSS], [], [Define if you want PSS analysis])
|
||||
AC_MSG_RESULT([WARNING: PSS analysis enabled])
|
||||
fi
|
||||
if test "x$enable_loopana" = xyes; then
|
||||
AC_DEFINE([WITH_LOOPANA], [], [Define if you want LOOP analysis])
|
||||
AC_MSG_RESULT([WARNING: LOOP analysis enabled])
|
||||
fi
|
||||
|
||||
if test "x$enable_blktmsdebug" = xyes; then
|
||||
AC_DEFINE([D_DBG_BLOCKTIMES], [], [Define if we want debug distortion analysis (BLOCKTIMES)])
|
||||
AC_MSG_RESULT([WARNING: Distortion analysis debug *D_DBG_BLOCKTIMES* is enabled])
|
||||
|
|
@ -1059,6 +1068,8 @@ AM_CONDITIONAL([NUMDEV_WANTED], [test "x$enable_cider" = xyes])
|
|||
|
||||
AM_CONDITIONAL([PSS_WANTED], [test "x$enable_pss" = xyes])
|
||||
|
||||
AM_CONDITIONAL([LOOPANA_WANTED], [test "x$enable_loopana" = xyes])
|
||||
|
||||
AM_CONDITIONAL([SENSE2_WANTED], [test "x$enable_sense2" = xyes])
|
||||
|
||||
# adms option
|
||||
|
|
|
|||
|
|
@ -220,6 +220,9 @@ if_run(CKTcircuit *ckt, char *what, wordlist *args, INPtables *tab)
|
|||
/* SP: Steady State Analysis */
|
||||
|| eq(what, "pss")
|
||||
/* SP */
|
||||
#endif
|
||||
#ifdef WITH_LOOPANA
|
||||
|| eq(what, "loop")
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
|
@ -335,6 +338,9 @@ if_run(CKTcircuit *ckt, char *what, wordlist *args, INPtables *tab)
|
|||
/* SP: Steady State Analysis */
|
||||
(eq(what, "pss")) ||
|
||||
/* SP */
|
||||
#endif
|
||||
#ifdef WITH_LOOPANA
|
||||
(eq(what, "loop")) ||
|
||||
#endif
|
||||
(eq(what, "run")))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,7 +86,9 @@ static struct plotab plotabs[NUMPLOTTYPES] = {
|
|||
{ "sp", "sp", FALSE, FALSE },
|
||||
{ "harm", "harm", FALSE, FALSE },
|
||||
{ "spect", "spect", FALSE, FALSE },
|
||||
{ "pss", "periodic", FALSE, FALSE }
|
||||
{ "pss", "periodic", FALSE, FALSE },
|
||||
{ "loop", "loop", FALSE, FALSE },
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,12 @@ libckt_la_SOURCES += \
|
|||
psssetp.c
|
||||
endif
|
||||
|
||||
if LOOPANA_WANTED
|
||||
libckt_la_SOURCES += \
|
||||
loopan.c \
|
||||
loopsetp.c \
|
||||
loopaskq.c
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices
|
||||
AM_CFLAGS = $(STATIC)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ extern SPICEanalysis SENSinfo;
|
|||
extern SPICEanalysis PSSinfo;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LOOPANA
|
||||
extern SPICEanalysis LOOPinfo;
|
||||
#endif
|
||||
|
||||
#ifdef WANT_SENSE2
|
||||
extern SPICEanalysis SEN2info;
|
||||
#endif
|
||||
|
|
@ -38,6 +42,9 @@ SPICEanalysis *analInfo[] = {
|
|||
#ifdef WITH_PSS
|
||||
&PSSinfo,
|
||||
#endif
|
||||
#ifdef WITH_LOOPANA
|
||||
&LOOPinfo,
|
||||
#endif
|
||||
#ifdef WANT_SENSE2
|
||||
&SEN2info,
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ struct SPICEanalysis {
|
|||
int (*askQuest)(CKTcircuit *ckt, JOB *anal, int which, IFvalue *value);
|
||||
int (*an_init)(CKTcircuit *ckt, JOB *job);
|
||||
int (*an_func)(CKTcircuit *ckt, int restart);
|
||||
#ifdef WITH_LOOPANA
|
||||
int (*an_preset)(CKTcircuit *ckt, JOB *job);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -156,6 +156,20 @@ CKTdoJob(CKTcircuit *ckt, int reset, TSKtask *task)
|
|||
/* gtri - end - 12/12/90 */
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LOOPANA
|
||||
/* add opportunity to modify the circuit before CKTsetup */
|
||||
/* Note that it must be done in a benign way in order not to */
|
||||
/* affect others analysis */
|
||||
for (i = 0; i < ANALmaxnum; i++)
|
||||
for (job = task->jobs; job; job = job->JOBnextJob)
|
||||
if (job->JOBtype == i)
|
||||
if (!error)
|
||||
{
|
||||
if (analInfo[i]->an_preset)
|
||||
error = analInfo[i]->an_preset (ckt, job);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!error)
|
||||
error = CKTsetup(ckt);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,21 @@ Modified: 2000 AlansFixes
|
|||
#include "ngspice/cpdefs.h"
|
||||
#include "ngspice/tskdefs.h"
|
||||
|
||||
/* F.B. 2020
|
||||
parse additionnal parameters in the form key=val.
|
||||
Use analysis INFO IFparm list to check if key is recognized and
|
||||
the type of val.
|
||||
*/
|
||||
static int
|
||||
dot_params(char *line, CKTcircuit *ckt, int ana, JOB* job)
|
||||
{
|
||||
char *name; /* the resistor's name */
|
||||
while(*line)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dot_noise(char *line, CKTcircuit *ckt, INPtables *tab, struct card *current,
|
||||
TSKtask *task, CKTnode *gnode, JOB *foo)
|
||||
|
|
@ -553,6 +568,137 @@ dot_sens2(char *line, CKTcircuit *ckt, INPtables *tab, struct card *current,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LOOPANA
|
||||
int
|
||||
dot_loop(char *line, void *ckt, INPtables *tab, struct card *current,
|
||||
void *task, void *gnode, JOB *foo)
|
||||
{
|
||||
int error; /* error code temporary */
|
||||
IFvalue ptemp; /* a value structure to package resistance into */
|
||||
IFvalue *parm; /* a pointer to a value struct for function returns */
|
||||
char *nname; /* the oscNode name */
|
||||
CKTnode *nnode; /* the oscNode node */
|
||||
int which; /* which analysis we are performing */
|
||||
char *word; /* something to stick a word of input into */
|
||||
char *steptype; /* type of stepping function */
|
||||
char *name; /* a name */
|
||||
|
||||
static char* probesparams[2]={"probe","probe-"};
|
||||
static char* probenumparams[2]={"portnum","portnum-"};
|
||||
static char* probenameparams[2]={"portname","portname-"};
|
||||
static char* dirparams[2]={"dir","dir-"};
|
||||
|
||||
NG_IGNORE(gnode);
|
||||
|
||||
/* .loop probe {DEC OCT LIN} NP FSTART FSTOP */
|
||||
/* @M2(#2) @M2:gate:into
|
||||
|
||||
|
||||
*/
|
||||
which = ft_find_analysis("LOOP");
|
||||
if (which == -1) {
|
||||
LITERR("Loop analysis unsupported.\n");
|
||||
return (0);
|
||||
}
|
||||
IFC(newAnalysis, (ckt, which, "Loop gain analysis", &foo, task));
|
||||
|
||||
for(int diff=0;diff<2;diff++)
|
||||
{
|
||||
INPgetTok(&line, &name, 1);
|
||||
INPinsert(&name, tab);
|
||||
if(0) printf("loop probe element is %s\n", name);
|
||||
ptemp.uValue = name;
|
||||
GCA(INPapName, (ckt, which, foo, probesparams[diff], &ptemp));
|
||||
|
||||
if(*line=='/')
|
||||
{
|
||||
INPgetTok(&line, &name, 1); /* eat / */
|
||||
tfree(name);
|
||||
INPgetTok(&line, &name, 1);
|
||||
if(*name== '#') {
|
||||
if(0) printf("port number %d\n",atoi(&name[1]));
|
||||
ptemp.iValue = atoi(&name[1]);
|
||||
tfree(name);
|
||||
GCA(INPapName, (ckt, which, foo, probenumparams[diff], &ptemp));
|
||||
} else {
|
||||
if(0) printf("port name %s\n",name);
|
||||
ptemp.uValue = name;
|
||||
GCA(INPapName, (ckt, which, foo, probenameparams[diff], &ptemp));
|
||||
}
|
||||
}
|
||||
if(*line=='/')
|
||||
{
|
||||
INPgetTok(&line, &name, 1); /* eat / */
|
||||
tfree(name);
|
||||
INPgetTok(&line, &name, 1);
|
||||
if(strcmp(name, "in")==0 || strcmp(name, "into")==0
|
||||
|| strcmp(name, "to")==0 ) {
|
||||
if(0) printf("into\n");
|
||||
ptemp.iValue = 1;
|
||||
GCA(INPapName, (ckt, which, foo, dirparams[diff], &ptemp));
|
||||
} else if(strcmp(name, "out")==0 || strcmp(name, "from")==0
|
||||
|| strcmp(name, "outfrom")==0) {
|
||||
if(0) printf("out\n");
|
||||
ptemp.iValue = 2;
|
||||
GCA(INPapName, (ckt, which, foo, dirparams[diff], &ptemp));
|
||||
} else
|
||||
printf("syntax error for .loop, expect direction, got %s\n", name);
|
||||
tfree(name);
|
||||
}
|
||||
if(*line != '+') break;
|
||||
INPgetTok(&line, &name, 1); tfree(name); /* eat the + and start again*/
|
||||
}
|
||||
|
||||
INPgetTok(&line, &steptype, 1);
|
||||
ptemp.iValue = 1;
|
||||
GCA(INPapName, (ckt, which, foo, steptype, &ptemp));
|
||||
tfree(steptype);
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* number of points */
|
||||
GCA(INPapName, (ckt, which, foo, "numsteps", parm));
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstart */
|
||||
GCA(INPapName, (ckt, which, foo, "start", parm));
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstop */
|
||||
GCA(INPapName, (ckt, which, foo, "stop", parm));
|
||||
|
||||
if(*line)
|
||||
{
|
||||
/* input & output follows for transfert function calculations */
|
||||
INPgetTok(&line, &name, 1);
|
||||
INPinsert(&name, tab);
|
||||
ptemp.uValue = name;
|
||||
GCA(INPapName, (ckt, which, foo, "insrc", &ptemp));
|
||||
|
||||
INPgetTok(&line, &name, 1);
|
||||
if(strcmp(name,"v")==0 && *line=='(')
|
||||
{
|
||||
/* v(pos,neg) format */
|
||||
tfree(name);
|
||||
INPgetNetTok(&line, &name, 0);
|
||||
INPtermInsert(ckt, &name, tab, &ptemp.nValue);
|
||||
GCA(INPapName, (ckt, which, foo, "outpos", &ptemp));
|
||||
if(*line==',') {
|
||||
INPgetNetTok(&line, &name, 1);
|
||||
INPtermInsert(ckt, &name, tab, &ptemp.nValue);
|
||||
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp));
|
||||
} else {
|
||||
ptemp.nValue = gnode;
|
||||
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INPinsert(&name, tab);
|
||||
ptemp.uValue = name;
|
||||
GCA(INPapName, (ckt, which, foo, "outsrc", &ptemp));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PSS
|
||||
/*SP: Steady State Analyis */
|
||||
static int
|
||||
|
|
@ -699,6 +845,11 @@ INP2dot(CKTcircuit *ckt, INPtables *tab, struct card *current, TSKtask *task, CK
|
|||
rtn = dot_pss(line, ckt, tab, current, task, gnode, foo);
|
||||
goto quit;
|
||||
/* SP */
|
||||
#endif
|
||||
#ifdef WITH_LOOPANA
|
||||
} else if ((strcmp(token, ".loop") == 0)) {
|
||||
rtn = dot_loop(line, ckt, tab, current, task, gnode, foo);
|
||||
goto quit;
|
||||
#endif
|
||||
} else if ((strcmp(token, ".subckt") == 0) ||
|
||||
(strcmp(token, ".ends") == 0)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue