* TODO src/circuit/inp2dot.c: Refactoring of the function

completed.
This commit is contained in:
arno 2000-06-11 10:10:45 +00:00
parent 0fcbceb82c
commit e563776de8
2 changed files with 323 additions and 256 deletions

19
TODO
View File

@ -47,12 +47,9 @@ Move src/devices/disto into src/maths/partialderiv. Partial
derivatives are math functions and should be classified under that derivatives are math functions and should be classified under that
directory. directory.
Refactor src/circuit/inp2dot.c so that the parser calls subroutines
for each possible dotcard. [PARTIAL]
Testability Testability
=========== -----------
Add tests for all functions in the complex library in Add tests for all functions in the complex library in
src/maths/cmaths. src/maths/cmaths.
@ -64,3 +61,17 @@ Add tests for all functions in the polynomial library in
src/maths/poly. src/maths/poly.
Add more circuit tests into the tests directory. Add more circuit tests into the tests directory.
Documentation
-------------
Update ARCHITECTURE to contain a high level overview of spice.
Convert ngspice.texi further to texinfo format.
Distribute devices documentation into the devices tree. This makes it
easier for developers to update documentation in concert with code.
Update manual pages for spice and nutmeg. Perhaps generate them with
c2man or some other documentation generation utility.

View File

@ -413,28 +413,316 @@ dot_dc(char *line, void *ckt, INPtables *tab, card *current,
} }
/* FIXME: INP2dot(): factor out all analysises. */ static int
dot_tf(char *line, void *ckt, INPtables *tab, card *current,
void *task, void *gnode, void *foo)
{
char *name; /* the resistor's name */
int error; /* error code temporary */
IFvalue ptemp; /* a value structure to package resistance into */
int which; /* which analysis we are performing */
int i; /* generic loop variable */
char *nname1; /* the first node's name */
char *nname2; /* the second node's name */
void *node1; /* the first node's node pointer */
void *node2; /* the second node's node pointer */
/* .tf v( node1, node2 ) src */
/* .tf vsrc2 src */
which = -1;
for (i = 0; i < ft_sim->numAnalyses; i++) {
if (strcmp(ft_sim->analyses[i]->name, "TF") == 0) {
which = i;
break;
}
}
if (which == -1) {
LITERR("Transfer Function analysis unsupported.\n");
return (0);
}
IFC(newAnalysis, (ckt, which, "Transfer Function", &foo, task));
INPgetTok(&line, &name, 0);
/* name is now either V or I or a serious error */
if (*name == 'v' && strlen(name) == 1) {
if (*line != '(' ) {
/* error, bad input format */
}
INPgetTok(&line, &nname1, 0);
INPtermInsert(ckt, &nname1, tab, &node1);
ptemp.nValue = (IFnode) node1;
GCA(INPapName, (ckt, which, foo, "outpos", &ptemp));
if (*line != ')') {
INPgetTok(&line, &nname2, 1);
INPtermInsert(ckt, &nname2, tab, &node2);
ptemp.nValue = (IFnode) node2;
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp));
ptemp.sValue =
(char *) MALLOC(sizeof(char) *
(5 + strlen(nname1) + strlen(nname2)));
(void) sprintf(ptemp.sValue, "V(%s,%s)", nname1, nname2);
GCA(INPapName, (ckt, which, foo, "outname", &ptemp));
} else {
ptemp.nValue = (IFnode) gnode;
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp));
ptemp.sValue =
(char *) MALLOC(sizeof(char) * (4 + strlen(nname1)));
(void) sprintf(ptemp.sValue, "V(%s)", nname1);
GCA(INPapName, (ckt, which, foo, "outname", &ptemp));
}
} else if (*name == 'i' && strlen(name) == 1) {
INPgetTok(&line, &name, 1);
INPinsert(&name, tab);
ptemp.uValue = name;
GCA(INPapName, (ckt, which, foo, "outsrc", &ptemp));
} else {
LITERR("Syntax error: voltage or current expected.\n");
return 0;
}
INPgetTok(&line, &name, 1);
INPinsert(&name, tab);
ptemp.uValue = name;
GCA(INPapName, (ckt, which, foo, "insrc", &ptemp));
return (0);
}
static int
dot_tran(char *line, void *ckt, INPtables *tab, card *current,
void *task, void *gnode, void *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 */
int which; /* which analysis we are performing */
int i; /* generic loop variable */
double dtemp; /* random double precision temporary */
char *word; /* something to stick a word of input into */
/* .tran Tstep Tstop <Tstart <Tmax> > <UIC> */
which = -1;
for (i = 0; i < ft_sim->numAnalyses; i++) {
if (strcmp(ft_sim->analyses[i]->name, "TRAN") == 0) {
which = i;
break;
}
}
if (which == -1) {
LITERR("Transient analysis unsupported.\n");
return (0);
}
IFC(newAnalysis, (ckt, which, "Transient Analysis", &foo, task));
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* Tstep */
GCA(INPapName, (ckt, which, foo, "tstep", parm));
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* Tstop */
GCA(INPapName, (ckt, which, foo, "tstop", parm));
if (*line) {
dtemp = INPevaluate(&line, &error, 1); /* tstart? */
if (error == 0) {
ptemp.rValue = dtemp;
GCA(INPapName, (ckt, which, foo, "tstart", &ptemp));
dtemp = INPevaluate(&line, &error, 1); /* tmax? */
if (error == 0) {
ptemp.rValue = dtemp;
GCA(INPapName, (ckt, which, foo, "tmax", &ptemp));
}
}
}
if (*line) {
INPgetTok(&line, &word, 1); /* uic? */
if (strcmp(word, "uic") == 0) {
ptemp.iValue = 1;
GCA(INPapName, (ckt, which, foo, "uic", &ptemp));
} else {
LITERR(" Error: unknown parameter on .tran - ignored\n");
}
}
return (0);
}
static int
dot_sens(char *line, void *ckt, INPtables *tab, card *current,
void *task, void *gnode, void *foo)
{
char *name; /* the resistor's name */
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 */
int which; /* which analysis we are performing */
int i; /* generic loop variable */
char *nname1; /* the first node's name */
char *nname2; /* the second node's name */
void *node1; /* the first node's node pointer */
void *node2; /* the second node's node pointer */
char *steptype; /* ac analysis, type of stepping function */
which = -1; /* Bug fix from Glao Dezai */
for (i = 0; i < ft_sim->numAnalyses; i++) {
if (strcmp(ft_sim->analyses[i]->name, "SENS") == 0) {
which = i;
break;
}
}
if (which == -1) {
LITERR("Sensitivity unsupported.\n");
return (0);
}
IFC(newAnalysis, (ckt, which, "Sensitivity Analysis", &foo, task));
/* Format is:
* .sens <output>
* + [ac [dec|lin|oct] <pts> <low freq> <high freq> | dc ]
*/
/* Get the output voltage or current */
INPgetTok(&line, &name, 0);
/* name is now either V or I or a serious error */
if (*name == 'v' && strlen(name) == 1) {
if (*line != '(') {
LITERR("Syntax error: '(' expected after 'v'\n");
return 0;
}
INPgetTok(&line, &nname1, 0);
INPtermInsert(ckt, &nname1, tab, &node1);
ptemp.nValue = (IFnode) node1;
GCA(INPapName, (ckt, which, foo, "outpos", &ptemp))
if (*line != ')') {
INPgetTok(&line, &nname2, 1);
INPtermInsert(ckt, &nname2, tab, &node2);
ptemp.nValue = (IFnode) node2;
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp));
ptemp.sValue = (char *)
MALLOC(sizeof(char) *
(5 + strlen(nname1) + strlen(nname2)));
(void) sprintf(ptemp.sValue, "V(%s,%s)", nname1, nname2);
GCA(INPapName, (ckt, which, foo, "outname", &ptemp));
} else {
ptemp.nValue = (IFnode) gnode;
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp));
ptemp.sValue =
(char *) MALLOC(sizeof(char) * (4 + strlen(nname1)));
(void) sprintf(ptemp.sValue, "V(%s)", nname1);
GCA(INPapName, (ckt, which, foo, "outname", &ptemp));
}
} else if (*name == 'i' && strlen(name) == 1) {
INPgetTok(&line, &name, 1);
INPinsert(&name, tab);
ptemp.uValue = name;
GCA(INPapName, (ckt, which, foo, "outsrc", &ptemp));
} else {
LITERR("Syntax error: voltage or current expected.\n");
return 0;
}
INPgetTok(&line, &name, 1);
if (name && !strcmp(name, "pct")) {
ptemp.iValue = 1;
GCA(INPapName, (ckt, which, foo, "pct", &ptemp))
INPgetTok(&line, &name, 1);
}
if (name && !strcmp(name, "ac")) {
INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */
ptemp.iValue = 1;
GCA(INPapName, (ckt, which, foo, steptype, &ptemp));
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));
return (0);
} else if (name && *name && strcmp(name, "dc")) {
/* Bad flag */
LITERR("Syntax error: 'ac' or 'dc' expected.\n");
return 0;
}
return (0);
}
#ifdef WANT_SENSE2
static int
dot_sens2(char *line, void *ckt, INPtables *tab, card *current,
void *task, void *gnode, void *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 */
int which; /* which analysis we are performing */
int i; /* generic loop variable */
char *token; /* a token from the line */
/* .sens {AC} {DC} {TRAN} [dev=nnn parm=nnn]* */
which = -1;
for (i = 0; i < ft_sim->numAnalyses; i++) {
if (strcmp(ft_sim->analyses[i]->name, "SENS2") == 0) {
which = i;
break;
}
}
if (which == -1) {
LITERR("Sensitivity-2 analysis unsupported\n");
return (0);
}
IFC(newAnalysis, (ckt, which, "Sensitivity-2 Analysis", &foo, task));
while (*line) {
/* read the entire line */
INPgetTok(&line, &token, 1);
for (i = 0; i < ft_sim->analyses[which]->numParms; i++) {
/* find the parameter */
if (0 == strcmp(token,
ft_sim->analyses[which]->analysisParms[i].keyword)) {
/* found it, analysis which, parameter i */
if (ft_sim->analyses[which]->analysisParms[i].dataType & IF_FLAG) {
/* one of the keywords! */
ptemp.iValue = 1;
error =
(*(ft_sim->setAnalysisParm)) (ckt, foo,
ft_sim->analyses[which]->analysisParms[i].id,
&ptemp,
(IFvalue *) NULL);
if (error)
current->error =
INPerrCat(current->error, INPerror(error));
} else {
parm =
INPgetValue(ckt, &line,
ft_sim->analyses[which]->analysisParms[i].dataType, tab);
error =
(*(ft_sim->setAnalysisParm)) (ckt, foo,
ft_sim->
analyses
[which]->analysisParms
[i].id, parm,
(IFvalue *)
NULL);
if (error)
current->error =
INPerrCat(current->error, INPerror(error));
}
break;
}
}
if (i == ft_sim->analyses[which]->numParms) {
/* didn't find it! */
LITERR(" Error: unknown parameter on .sens-ignored \n");
}
}
return (0);
}
#endif
int int
INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode) INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode)
{ {
/* .<something> Many possibilities */ /* .<something> Many possibilities */
char *name; /* the resistor's name */
char *nname1; /* the first node's name */
char *nname2; /* the second node's name */
void *node1; /* the first node's node pointer */
void *node2; /* the second node's node pointer */
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 *token; /* a token from the line */ char *token; /* a token from the line */
int which; /* which analysis we are performing */ void *foo = NULL; /* pointer to analysis */
int i; /* generic loop variable */
void *foo; /* pointer to analysis */
char *steptype; /* ac analysis, type of stepping function */
double dtemp; /* random double precision temporary */
char *word; /* something to stick a word of input into */
/* the part of the current line left to parse */ /* the part of the current line left to parse */
char *line = current->line; char *line = current->line;
@ -476,102 +764,9 @@ INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode)
} else if ((strcmp(token, ".dc") == 0)) { } else if ((strcmp(token, ".dc") == 0)) {
return dot_dc(line, ckt, tab, current, task, gnode, foo); return dot_dc(line, ckt, tab, current, task, gnode, foo);
} else if ((strcmp(token, ".tf") == 0)) { } else if ((strcmp(token, ".tf") == 0)) {
/* .tf v( node1, node2 ) src */ return dot_tf(line, ckt, tab, current, task, gnode, foo);
/* .tf vsrc2 src */
which = -1;
for (i = 0; i < ft_sim->numAnalyses; i++) {
if (strcmp(ft_sim->analyses[i]->name, "TF") == 0) {
which = i;
break;
}
}
if (which == -1) {
LITERR("Transfer Function analysis unsupported.\n");
return (0);
}
IFC(newAnalysis, (ckt, which, "Transfer Function", &foo, task))
INPgetTok(&line, &name, 0);
/* name is now either V or I or a serious error */
if (*name == 'v' && strlen(name) == 1) {
if (*line != '(' /* match) */ ) {
/* error, bad input format */
}
INPgetTok(&line, &nname1, 0);
INPtermInsert(ckt, &nname1, tab, &node1);
ptemp.nValue = (IFnode) node1;
GCA(INPapName, (ckt, which, foo, "outpos", &ptemp))
if (*line != /* match ( */ ')') {
INPgetTok(&line, &nname2, 1);
INPtermInsert(ckt, &nname2, tab, &node2);
ptemp.nValue = (IFnode) node2;
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp))
ptemp.sValue = (char *)
MALLOC(sizeof(char) *
(5 + strlen(nname1) + strlen(nname2)));
(void) sprintf(ptemp.sValue, "V(%s,%s)", nname1, nname2);
GCA(INPapName, (ckt, which, foo, "outname", &ptemp))
} else {
ptemp.nValue = (IFnode) gnode;
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp))
ptemp.sValue =
(char *) MALLOC(sizeof(char) * (4 + strlen(nname1)));
(void) sprintf(ptemp.sValue, "V(%s)", nname1);
GCA(INPapName, (ckt, which, foo, "outname", &ptemp))
}
} else if (*name == 'i' && strlen(name) == 1) {
INPgetTok(&line, &name, 1);
INPinsert(&name, tab);
ptemp.uValue = name;
GCA(INPapName, (ckt, which, foo, "outsrc", &ptemp))
} else {
LITERR("Syntax error: voltage or current expected.\n");
return 0;
}
INPgetTok(&line, &name, 1);
INPinsert(&name, tab);
ptemp.uValue = name;
GCA(INPapName, (ckt, which, foo, "insrc", &ptemp))
return (0);
} else if ((strcmp(token, ".tran") == 0)) { } else if ((strcmp(token, ".tran") == 0)) {
/* .tran Tstep Tstop <Tstart <Tmax> > <UIC> */ return dot_tran(line, ckt, tab, current, task, gnode, foo);
which = -1;
for (i = 0; i < ft_sim->numAnalyses; i++) {
if (strcmp(ft_sim->analyses[i]->name, "TRAN") == 0) {
which = i;
break;
}
}
if (which == -1) {
LITERR("Transient analysis unsupported.\n");
return (0);
}
IFC(newAnalysis, (ckt, which, "Transient Analysis", &foo, task))
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* Tstep */
GCA(INPapName, (ckt, which, foo, "tstep", parm))
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* Tstop */
GCA(INPapName, (ckt, which, foo, "tstop", parm))
if (*line) {
dtemp = INPevaluate(&line, &error, 1); /* tstart? */
if (error == 0) {
ptemp.rValue = dtemp;
GCA(INPapName, (ckt, which, foo, "tstart", &ptemp))
dtemp = INPevaluate(&line, &error, 1); /* tmax? */
if (error == 0) {
ptemp.rValue = dtemp;
GCA(INPapName, (ckt, which, foo, "tmax", &ptemp))
}
}
}
if (*line) {
INPgetTok(&line, &word, 1); /* uic? */
if (strcmp(word, "uic") == 0) {
ptemp.iValue = 1;
GCA(INPapName, (ckt, which, foo, "uic", &ptemp))
} else {
LITERR(" Error: unknown parameter on .tran - ignored\n");
}
}
return (0);
} else if ((strcmp(token, ".subckt") == 0) || } else if ((strcmp(token, ".subckt") == 0) ||
(strcmp(token, ".ends") == 0)) { (strcmp(token, ".ends") == 0)) {
/* not yet implemented - warn & ignore */ /* not yet implemented - warn & ignore */
@ -582,150 +777,11 @@ INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode)
/* not allowed to pay attention to additional input - return */ /* not allowed to pay attention to additional input - return */
return (1); return (1);
} else if (strcmp(token, ".sens") == 0) { } else if (strcmp(token, ".sens") == 0) {
which = -1; /* Bug fix from Glao Dezai */ return dot_sens(line, ckt, tab, current, task, gnode, foo);
for (i = 0; i < ft_sim->numAnalyses; i++) {
if (strcmp(ft_sim->analyses[i]->name, "SENS") == 0) {
which = i;
break;
}
}
if (which == -1) {
LITERR("Sensitivity unsupported.\n");
return (0);
}
IFC(newAnalysis, (ckt, which, "Sensitivity Analysis", &foo, task));
/* Format is:
* .sens <output>
* + [ac [dec|lin|oct] <pts> <low freq> <high freq> | dc ]
*/
/* Get the output voltage or current */
INPgetTok(&line, &name, 0);
/* name is now either V or I or a serious error */
if (*name == 'v' && strlen(name) == 1) {
if (*line != '(' /* match) */ ) {
LITERR("Syntax error: '(' expected after 'v'\n");
return 0;
}
INPgetTok(&line, &nname1, 0);
INPtermInsert(ckt, &nname1, tab, &node1);
ptemp.nValue = (IFnode) node1;
GCA(INPapName, (ckt, which, foo, "outpos", &ptemp))
if (*line != /* match ( */ ')') {
INPgetTok(&line, &nname2, 1);
INPtermInsert(ckt, &nname2, tab, &node2);
ptemp.nValue = (IFnode) node2;
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp))
ptemp.sValue = (char *)
MALLOC(sizeof(char) *
(5 + strlen(nname1) + strlen(nname2)));
(void) sprintf(ptemp.sValue, "V(%s,%s)", nname1, nname2);
GCA(INPapName, (ckt, which, foo, "outname", &ptemp))
} else {
ptemp.nValue = (IFnode) gnode;
GCA(INPapName, (ckt, which, foo, "outneg", &ptemp))
ptemp.sValue =
(char *) MALLOC(sizeof(char) * (4 + strlen(nname1)));
(void) sprintf(ptemp.sValue, "V(%s)", nname1);
GCA(INPapName, (ckt, which, foo, "outname", &ptemp))
}
} else if (*name == 'i' && strlen(name) == 1) {
INPgetTok(&line, &name, 1);
INPinsert(&name, tab);
ptemp.uValue = name;
GCA(INPapName, (ckt, which, foo, "outsrc", &ptemp))
} else {
LITERR("Syntax error: voltage or current expected.\n");
return 0;
}
INPgetTok(&line, &name, 1);
if (name && !strcmp(name, "pct")) {
ptemp.iValue = 1;
GCA(INPapName, (ckt, which, foo, "pct", &ptemp))
INPgetTok(&line, &name, 1);
}
if (name && !strcmp(name, "ac")) {
INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */
ptemp.iValue = 1;
GCA(INPapName, (ckt, which, foo, steptype, &ptemp))
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))
return (0);
} else if (name && *name && strcmp(name, "dc")) {
/* Bad flag */
LITERR("Syntax error: 'ac' or 'dc' expected.\n");
return 0;
}
return (0);
} }
#ifdef WANT_SENSE2 #ifdef WANT_SENSE2
else if ((strcmp(token, ".sens2") == 0)) { else if ((strcmp(token, ".sens2") == 0)) {
/* .sens {AC} {DC} {TRAN} [dev=nnn parm=nnn]* */ return dot_sens2(line, ckt, tab, current, task, gnode, foo);
which = -1;
for (i = 0; i < ft_sim->numAnalyses; i++) {
if (strcmp(ft_sim->analyses[i]->name, "SENS2") == 0) {
which = i;
break;
}
}
if (which == -1) {
LITERR("Sensitivity-2 analysis unsupported\n");
return (0);
}
IFC(newAnalysis,
(ckt, which, "Sensitivity-2 Analysis", &foo, task)) while (*line) { /* read the entire line */
INPgetTok(&line, &token, 1);
for (i = 0; i < ft_sim->analyses[which]->numParms; i++) {
/* find the parameter */
if (0 == strcmp(token,
ft_sim->analyses[which]->
analysisParms[i].keyword)) {
/* found it, analysis which, parameter i */
if (ft_sim->analyses[which]->
analysisParms[i].dataType & IF_FLAG) {
/* one of the keywords! */
ptemp.iValue = 1;
error = (*(ft_sim->setAnalysisParm)) (
ckt, foo,
ft_sim->analyses[which]->analysisParms[i].id,
&ptemp, (IFvalue *) NULL);
if (error)
current->error =
INPerrCat(current->error, INPerror(error));
} else {
parm =
INPgetValue(ckt, &line,
ft_sim->analyses[which]->
analysisParms[i].dataType, tab);
error =
(*(ft_sim->setAnalysisParm)) (ckt, foo,
ft_sim->
analyses
[which]->analysisParms
[i].id, parm,
(IFvalue *)
NULL);
if (error)
current->error =
INPerrCat(current->error, INPerror(error));
}
break;
}
}
if (i == ft_sim->analyses[which]->numParms) {
/* didn't find it! */
LITERR(" Error: unknown parameter on .sens-ignored \n");
}
}
return (0);
} }
#endif #endif
else if ((strcmp(token, ".probe") == 0)) { else if ((strcmp(token, ".probe") == 0)) {