191 lines
4.2 KiB
C
191 lines
4.2 KiB
C
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|
**********/
|
|
|
|
/*
|
|
* Code to deal with breakpoints and tracing.
|
|
*/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/cpdefs.h"
|
|
#include "ngspice/ftedefs.h"
|
|
#include "ngspice/dvec.h"
|
|
#include "ngspice/ftedebug.h"
|
|
#include "breakp2.h"
|
|
|
|
|
|
/* global linked list to store .save data and breakpoint data */
|
|
struct dbcomm *dbs = NULL; /* export for iplot */
|
|
|
|
/* used in breakp.c and breakp2.c */
|
|
int debugnumber = 1;
|
|
|
|
static char *copynode(char* s);
|
|
|
|
|
|
/* Analyse the data given by the .save card or 'save' command.
|
|
Store the data in the global dbs struct.
|
|
*/
|
|
|
|
/* Save a vector. */
|
|
|
|
void
|
|
com_save(wordlist *wl)
|
|
{
|
|
settrace(wl, VF_ACCUM, NULL);
|
|
}
|
|
|
|
|
|
/* Save a vector with the analysis type given (name). */
|
|
void
|
|
com_save2(wordlist *wl, char *name)
|
|
{
|
|
settrace(wl, VF_ACCUM, name);
|
|
}
|
|
|
|
|
|
void
|
|
settrace(wordlist *wl, int what, char *name)
|
|
{
|
|
struct dbcomm *d, *last, *dbcheck;
|
|
|
|
if (!ft_curckt) {
|
|
fprintf(cp_err, "Error: no circuit loaded\n");
|
|
return;
|
|
}
|
|
|
|
if (dbs)
|
|
for (last = dbs; last->db_next; last = last->db_next)
|
|
;
|
|
else
|
|
last = NULL;
|
|
|
|
for (;wl ;wl = wl->wl_next) {
|
|
char *s = cp_unquote(wl->wl_word);
|
|
char *db_nodename1 = NULL;
|
|
char db_type = 0;
|
|
if (eq(s, "all") || eq(s, "nosub")) {
|
|
switch (what) {
|
|
case VF_PRINT:
|
|
db_type = DB_TRACEALL;
|
|
break;
|
|
case VF_ACCUM:
|
|
db_nodename1 = copy(s);
|
|
db_type = DB_SAVE;
|
|
break;
|
|
}
|
|
tfree(s);
|
|
} else {
|
|
switch (what) {
|
|
case VF_PRINT:
|
|
db_type = DB_TRACENODE;
|
|
break;
|
|
case VF_ACCUM:
|
|
db_type = DB_SAVE;
|
|
break;
|
|
}
|
|
/* v(2) --> 2, i(vds) --> vds#branch */
|
|
db_nodename1 = copynode(s);
|
|
tfree(s);
|
|
if (!db_nodename1) /* skip on error */
|
|
continue;
|
|
}
|
|
|
|
/* Don't save a nodename more than once, except for token 'all' */
|
|
if (db_type == DB_SAVE) {
|
|
for (dbcheck = dbs; dbcheck; dbcheck = dbcheck->db_next) {
|
|
if (dbcheck->db_type == DB_SAVE && eq(dbcheck->db_nodename1, db_nodename1) &&
|
|
!eq("all", db_nodename1)) {
|
|
tfree(db_nodename1);
|
|
goto loopend;
|
|
}
|
|
}
|
|
}
|
|
|
|
d = TMALLOC(struct dbcomm, 1);
|
|
d->db_analysis = name;
|
|
d->db_type = db_type;
|
|
d->db_nodename1 = db_nodename1;
|
|
d->db_number = debugnumber++;
|
|
|
|
if (last)
|
|
last->db_next = d;
|
|
else
|
|
ft_curckt->ci_dbs = dbs = d;
|
|
|
|
last = d;
|
|
|
|
loopend:;
|
|
}
|
|
}
|
|
|
|
|
|
/* retrieve the save nodes from dbs into an array */
|
|
int
|
|
ft_getSaves(struct save_info **savesp)
|
|
/* global variable: dbs */
|
|
{
|
|
struct dbcomm *d;
|
|
int count = 0, i = 0;
|
|
struct save_info *array;
|
|
|
|
for (d = dbs; d; d = d->db_next)
|
|
if (d->db_type == DB_SAVE)
|
|
count++;
|
|
|
|
if (!count)
|
|
return (0);
|
|
|
|
*savesp = array = TMALLOC(struct save_info, count);
|
|
|
|
for (d = dbs; d; d = d->db_next)
|
|
if (d->db_type == DB_SAVE) {
|
|
array[i].used = 0;
|
|
if (d->db_analysis)
|
|
array[i].analysis = copy(d->db_analysis);
|
|
else
|
|
array[i].analysis = NULL;
|
|
array[i++].name = copy(d->db_nodename1);
|
|
}
|
|
|
|
return (count);
|
|
}
|
|
|
|
|
|
/* v(2) --> 2, i(vds) --> vds#branch, 3 --> 3, @mn1[vth0] --> @mn1[vth0]
|
|
* derived from wordlist *gettoks(char *s)
|
|
*/
|
|
|
|
static char*
|
|
copynode(char *s)
|
|
{
|
|
char *l, *r;
|
|
char *ret = NULL;
|
|
|
|
if (strchr(s, '('))
|
|
s = stripWhiteSpacesInsideParens(s);
|
|
else
|
|
s = copy(s);
|
|
|
|
l = strrchr(s, '(');
|
|
if (!l)
|
|
return s;
|
|
|
|
r = strchr(s, ')');
|
|
if (!r) {
|
|
fprintf(cp_err, "Warning: Missing ')' in %s\n Not saved!\n", s);
|
|
tfree(s);
|
|
return NULL;
|
|
}
|
|
|
|
*r = '\0';
|
|
if (*(l - 1) == 'i' || *(l - 1) == 'I')
|
|
ret = tprintf("%s#branch", l + 1);
|
|
else
|
|
ret = copy(l + 1);
|
|
|
|
tfree(s);
|
|
return ret;
|
|
}
|