diff --git a/src/frontend/Makefile.am b/src/frontend/Makefile.am
index 1bcbe86bd..968f241ff 100644
--- a/src/frontend/Makefile.am
+++ b/src/frontend/Makefile.am
@@ -76,6 +76,7 @@ libfte_la_SOURCES = \
control.h \
control.c \
ftehelp.h \
+ ftesopt.c \
hcomp.c \
hcomp.h \
init.c \
@@ -129,6 +130,7 @@ libfte_la_SOURCES = \
inpcom.h \
interp.c \
interp.h \
+ inventory.c \
linear.c \
linear.h \
measure.c \
diff --git a/src/frontend/commands.c b/src/frontend/commands.c
index 089b7812d..5531322c0 100644
--- a/src/frontend/commands.c
+++ b/src/frontend/commands.c
@@ -560,7 +560,16 @@ struct comm spcp_coms[] = {
{ 040000, 040000, 040000, 040000 }, E_DEFHMASK, 0, LOTS,
NULL,
" [ vec ... ] : Convert plot into one with linear scale." } ,
- { 0, NULL, FALSE, FALSE, { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
+ { "devhelp", com_devhelp, FALSE, FALSE,
+ { 040000, 0400000, 040000, 040000 }, E_DEFHMASK, 0, 5 ,
+ NULL,
+ "devspecs : show device information." },
+ { "inventory", com_inventory, TRUE, FALSE,
+ { 0, 0, 0, 0 }, E_DEFHMASK, 0, 0,
+ NULL,
+ ": Print circuit inventory" },
+ { 0, NULL, FALSE, FALSE,
+ { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
NULL,
NULL }
};
@@ -940,9 +949,16 @@ struct comm nutcp_coms[] = {
{ 040000, 040000, 040000, 040000 }, E_DEFHMASK, 0, LOTS,
NULL,
" [ vec ... ] : Convert plot into one with linear scale." } ,
-
- { 0, NULL, FALSE, FALSE, { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
+ { "devhelp",NULL, FALSE, FALSE,
+ { 040, 040, 040, 040 }, E_DEFHMASK, 0, 5 ,
+ NULL,
+ " devspecs : show device information." },
+ { "inventory", NULL, TRUE, FALSE,
+ { 0, 0, 0, 0 }, E_DEFHMASK, 0, 0,
+ NULL,
+ ": Print circuit inventory" } ,
+ { 0, NULL, FALSE, FALSE,
+ { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
NULL,
NULL }
-
} ;
diff --git a/src/frontend/device.c b/src/frontend/device.c
index 0c2a35039..d77881ce0 100644
--- a/src/frontend/device.c
+++ b/src/frontend/device.c
@@ -26,6 +26,183 @@ static wordlist *devexpand(char *name);
static void all_show(wordlist *wl, int mode);
static void all_show_old(wordlist *wl, int mode);
+/*
+ * devhelp: lists available devices and information on parameters
+ * devhelp : shows all available devices
+ * devhelp devname : shows all parameters of that model/instance
+ * devhelp devname parname : shows parameter meaning
+ * Options: -csv (comma separated value for generating docs)
+ *
+ */
+
+void com_devhelp(wordlist *wl)
+{
+ /* Just a simple driver now */
+ devhelp(wl);
+}
+
+void devhelp(wordlist *wl)
+{
+ int i, k = 0;
+ int devindex = -1, devInstParNo = 0 , devModParNo = 0;
+ bool found = FALSE;
+ bool csv = FALSE;
+ wordlist *wlist;
+ IFparm *plist;
+
+ /*First copy the base pointer */
+ wlist = wl;
+
+ /* If there are no arguments output the list of available devices */
+ if (!wlist) {
+ out_init();
+ out_printf("\nDevices available in the simulator\n\n");
+ for (k = 0; k < ft_sim->numDevices; k++) {
+ if (ft_sim->devices[k])
+ out_printf("%-*s:\t%s\n",
+ DEV_WIDTH, ft_sim->devices[k]->name,
+ ft_sim->devices[k]->description);
+ }
+ out_send("\n");
+ return;
+ }
+
+ /* The first argument must be the csv option or a device name */
+ if (wlist && wlist->wl_word && eq(wlist->wl_word, "-csv")) {
+ csv = TRUE;
+ if (wlist->wl_next)
+ wlist = wlist->wl_next;
+ else
+ return;
+ }
+
+ /* This argument, if exists, must be the device name */
+ if (wlist && wlist->wl_word) {
+ while (k < ft_sim->numDevices && !found) {
+ if (ft_sim->devices[k])
+ if (strcasecmp(ft_sim->devices[k]->name, wlist->wl_word) == 0) {
+ devindex = k;
+ if (ft_sim->devices[devindex]->numInstanceParms)
+ devInstParNo = *(ft_sim->devices[devindex]->numInstanceParms);
+ else
+ devInstParNo = 0;
+
+ if (ft_sim->devices[devindex]->numModelParms)
+ devModParNo = *(ft_sim->devices[devindex]->numModelParms);
+ else
+ devModParNo = 0;
+
+ wlist = wlist->wl_next;
+ found = TRUE;
+ }
+ k++;
+ }
+
+ if (!found) {
+ fprintf(cp_out, "Error: Device %s not found\n", wlist->wl_word);
+ return;
+ }
+ }
+
+/* At this point, found is TRUE and we have found the device.
+ * Now we have to scan the model and instance parameters to print
+ * the string
+ */
+ found = FALSE;
+ if (wlist && wlist->wl_word) {
+ plist = ft_sim->devices[devindex]->modelParms;
+ for (i = 0; i < devModParNo; i++) { /* Scan model parameters first */
+ if (strcasecmp(plist[i].keyword, wlist->wl_word) == 0) {
+ found = TRUE;
+ out_init();
+ printdesc(plist[i], csv);
+ out_send("\n");
+ }
+ }
+
+ if (!found) {
+ plist = ft_sim->devices[devindex]->instanceParms;
+ for (i = 0; i < devInstParNo; i++) { /* Scan instance parameters then */
+ if (strcasecmp(plist[i].keyword, wlist->wl_word) == 0) {
+ found = TRUE;
+ out_init();
+ printdesc(plist[i], csv);
+ out_send("\n");
+ }
+ }
+ }
+
+ if (!found)
+ fprintf(cp_out, "Error: Parameter %s not found\n", wlist->wl_word);
+ return;
+
+ }
+
+/* No arguments - we want all the parameters*/
+ out_init();
+ out_printf("%s - %s\n\n", ft_sim->devices[devindex]->name, ft_sim->devices[devindex]->description);
+ out_printf("Model Parameters\n");
+ if (csv)
+ out_printf("id#, Name, Dir, Description\n");
+ else
+ out_printf("%5s\t %-10s\t Dir\t Description\n", "id#", "Name");
+
+ plist = ft_sim->devices[devindex]->modelParms;
+ for (i = 0; i < devModParNo; i++)
+ printdesc(plist[i], csv);
+ out_printf("\n");
+ out_printf("Instance Parameters\n");
+ if (csv)
+ out_printf("id#, Name, Dir, Description\n");
+ else
+ out_printf("%5s\t %-10s\t Dir\t Description\n", "id#", "Name");
+
+ plist = ft_sim->devices[devindex]->instanceParms;
+ for (i = 0; i < devInstParNo; i++)
+ printdesc(plist[i], csv);
+
+ out_send("\n");
+}
+
+
+
+/*
+ * Pretty print parameter descriptions
+ * This function prints description of device parameters
+ */
+void printdesc(IFparm p, bool csv)
+{
+ char sep;
+ int spacer1, spacer2;
+
+ /* First we indentify the separator */
+ if (csv) {
+ sep = ',';
+ spacer1 = 0;
+ spacer2 = 0;
+ } else {
+ sep = '\t';
+ spacer1 = 5;
+ spacer2 = 10;
+ }
+
+ out_printf("%*d%c %-*s%c ", spacer1, p.id, sep, spacer2, p.keyword, sep);
+
+ if (p.dataType & IF_SET)
+ if (p.dataType & IF_ASK)
+ out_printf("inout%c ", sep);
+ else
+ out_printf("in%c ", sep);
+ else
+ out_printf("out%c ", sep);
+
+ if (p.description)
+ out_printf("%s\n", p.description);
+ else
+ out_printf("n.a.\n");
+}
+
+
/*
* show: list device operating point info
* show
diff --git a/src/frontend/device.h b/src/frontend/device.h
index b4289aa9f..a208891d0 100644
--- a/src/frontend/device.h
+++ b/src/frontend/device.h
@@ -21,6 +21,10 @@ int printvals(dgen *dg, IFparm *p, int i);
int printvals_old(dgen *dg, IFparm *p, int i);
void old_show(wordlist *wl);
+/* DEVHELP*/
+void devhelp(wordlist *wl);
+void printdesc(IFparm p, bool csv);
+
diff --git a/src/frontend/inp.c b/src/frontend/inp.c
index cca6669ef..25bddf0d6 100644
--- a/src/frontend/inp.c
+++ b/src/frontend/inp.c
@@ -26,6 +26,7 @@ $Id$
#include "breakp2.h"
#include "../misc/util.h" /* ngdirname() */
#include "../misc/mktemp.h"
+#include "../misc/misc_time.h"
#include "subckt.h"
#include "spiceif.h"
#include "error.h" /* controlled_exit() */
@@ -323,9 +324,14 @@ inp_spsource(FILE *fp, bool comfile, char *filename)
FILE *lastin, *lastout, *lasterr;
double temperature_value;
+ double startTime, endTime;
+
/* read in the deck from a file */
char *filename_dup = ( filename == NULL ) ? strdup(".") : strdup(filename);
+
+ startTime = seconds();
inp_readall(fp, &deck, 0, ngdirname(filename_dup), comfile);
+ endTime = seconds();
tfree(filename_dup);
/* if nothing came back from inp_readall, just close fp and return to caller */
@@ -585,6 +591,8 @@ inp_spsource(FILE *fp, bool comfile, char *filename)
if (ft_curckt) {
ft_curckt->ci_param = NULL;
ft_curckt->ci_meas = NULL;
+ /* PN add here stats*/
+ ft_curckt->FTEstats->FTESTATnetLoadTime = endTime - startTime;
}
for (dd = deck; dd; dd = dd->li_next) {
@@ -711,6 +719,8 @@ inp_dodeck(
bool noparse, ii;
int print_listing;
+ double startTime;
+
/* First throw away any old error messages there might be and fix
the case of the lines. */
for (dd = deck; dd; dd = dd->li_next) {
@@ -729,6 +739,9 @@ inp_dodeck(
NULL);
}
ft_curckt = ct = alloc(struct circ);
+
+ /*PN FTESTATS*/
+ ft_curckt->FTEstats = TMALLOC(FTESTATistics, 1);
}
noparse = cp_getvar("noparse", CP_BOOL, NULL);
@@ -785,18 +798,23 @@ inp_dodeck(
* if_inpdeck which takes the deck and returns a
* a pointer to the circuit ckt.
*---------------------------------------------------*/
- if (!noparse)
+ if (!noparse) {
+ startTime = seconds();
ckt = if_inpdeck(deck, &tab);
- else
+ ft_curckt->FTEstats->FTESTATnetParseTime = seconds() - startTime;
+ } else
ckt = NULL;
out_init();
+ ft_curckt->FTEstats->FTESTATdeckNumLines = 0;
/*----------------------------------------------------
* Now run through the deck and look to see if there are
* errors on any line.
*---------------------------------------------------*/
for (dd = deck; dd; dd = dd->li_next) {
+
+ ft_curckt->FTEstats->FTESTATdeckNumLines += 1;
#ifdef TRACE
/* SDB debug statement */
diff --git a/src/frontend/inventory.c b/src/frontend/inventory.c
new file mode 100644
index 000000000..c829b51a2
--- /dev/null
+++ b/src/frontend/inventory.c
@@ -0,0 +1,52 @@
+/**********
+Copyright 2010 Paolo Nenzi. All rights reserved.
+Author: 2010 Paolo Nenzi
+**********/
+
+#include "ngspice.h"
+#include "cktdefs.h"
+#include "cpdefs.h"
+#include "ftedefs.h"
+#include "optdefs.h"
+#include "dvec.h"
+#include "ftehelp.h"
+#include "hlpdefs.h"
+
+#include "circuits.h"
+#include "where.h"
+
+/*
+ The inventory command shows the number of instances for each device
+ in the current circuit.
+*/
+
+void
+com_inventory(wordlist *wl)
+{
+ CKTcircuit *circuit = NULL;
+ STATistics *stat = NULL;
+ STATdevList *devList = NULL;
+ int k;
+
+ NG_IGNORE(wl);
+
+ if (!ft_curckt) {
+ fprintf(cp_err, "There is no current circuit\n");
+ return;
+ }
+
+ circuit = ft_curckt->ci_ckt;
+ stat = circuit->CKTstat;
+ devList = stat->STATdevNum;
+
+ out_init();
+ out_send("Circuit Inventory\n\n");
+ for (k = 0; k < ft_sim->numDevices; k++) {
+ if (ft_sim->devices[k])
+ out_printf("%s: %d\n",
+ ft_sim->devices[k]->name,
+ devList[k].instNum);
+ }
+ out_send("\n");
+ return;
+}
diff --git a/src/frontend/mw_coms.c b/src/frontend/mw_coms.c
index a32fd1969..8aefcf1c5 100644
--- a/src/frontend/mw_coms.c
+++ b/src/frontend/mw_coms.c
@@ -49,6 +49,9 @@ com_removecirc(wordlist *wl)
tfree(v);
}
+ /* PN FTESTATS*/
+ tfree(ct->FTEstats);
+
ct->ci_vars = NULL;
caux=ft_circuits;
namecircuit = strdup(ft_curckt->ci_name);
diff --git a/src/frontend/resource.c b/src/frontend/resource.c
index 0b667a486..080bfaad1 100644
--- a/src/frontend/resource.c
+++ b/src/frontend/resource.c
@@ -395,6 +395,36 @@ printres(char *name)
#endif
}
+ /* PN Now get all the frontend resource stuff */
+ if (ft_curckt) {
+ if (name && eq(name, "task")) {
+ vfree = v = ft_getstat(ft_curckt, NULL);
+ } else {
+ vfree = v = ft_getstat(ft_curckt, name);
+ }
+
+ if (name && v) {
+ fprintf(cp_out, "%s= ", v->va_name);
+ wl_print(cp_varwl(v), cp_out);
+ (void)putc('\n', cp_out);
+ yy = TRUE;
+ } else if (v) {
+ (void) putc('\n', cp_out);
+ while (v) {
+ wordlist *wlpr = cp_varwl(v);
+ fprintf(cp_out, "%s = ", v->va_name);
+ wl_print(wlpr, cp_out);
+ wl_free(wlpr);
+ (void) putc('\n', cp_out);
+ v = v->va_next;
+ }
+ yy = TRUE;
+ }
+ }
+
+ if(vfree)
+ free_struct_variable(vfree);
+
/* Now get all the spice resource stuff. */
if (ft_curckt && ft_curckt->ci_ckt) {
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 4c0f0d404..8cd884269 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -39,6 +39,7 @@ noinst_HEADERS = \
ftedbgra.h \
ftedebug.h \
ftedefs.h \
+ fteoptdefs.h \
ftedev.h \
fteext.h \
fteinp.h \
diff --git a/src/include/ftedefs.h b/src/include/ftedefs.h
index 23f25e25f..5e5144125 100644
--- a/src/include/ftedefs.h
+++ b/src/include/ftedefs.h
@@ -15,6 +15,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#define IPOINTMIN 20 /* When we start plotting incremental plots. */
#include "fteparse.h"
#include "fteinp.h"
+#include "fteoptdefs.h"
struct save_info {
char *name;
@@ -48,6 +49,8 @@ struct circ {
JOB *ci_specOpt; /* the special options anal. for command line jobs */
JOB *ci_curOpt; /* the most recent options anal. for the circuit */
char *ci_last_an; /* name of last analysis run */
+
+ FTESTATistics *FTEstats; /* Statistics for the front end */
} ;
diff --git a/src/include/fteext.h b/src/include/fteext.h
index 4487e7e89..6bffa2fa1 100644
--- a/src/include/fteext.h
+++ b/src/include/fteext.h
@@ -123,6 +123,10 @@ extern void *cx_group_delay(void *, short int , int , int *, short int *, struct
extern struct pnode *ft_substdef(const char *name, struct pnode *args);
extern void ft_pnode(struct pnode *pn);
+/* DEVHELP*/
+extern void com_devhelp(wordlist *wl);
+extern void com_inventory(wordlist *wl);
+
/* dotcards.c */
extern bool ft_acctprint;
@@ -151,6 +155,9 @@ extern void externalerror(char *);
extern struct dvec *ft_evaluate(struct pnode *node);
+/* ftesopt.c */
+extern struct variable *ft_getstat(struct circ *, char *);
+
/* ginterface.c
extern bool gi_init();
diff --git a/src/include/fteoptdefs.h b/src/include/fteoptdefs.h
new file mode 100644
index 000000000..b4f83a0bf
--- /dev/null
+++ b/src/include/fteoptdefs.h
@@ -0,0 +1,25 @@
+/**********
+Author: 2010 Paolo Nenzi
+**********/
+
+#ifndef FTEOPT
+#define FTEOPT
+
+ /* Structure used to describe the frontend statistics to be collected */
+ /* This is similar to the STATististics in optdefs.h but collects */
+ /* statistics pertaining to ngspice frontend */
+
+typedef struct sFTESTATistics {
+
+ int FTESTATdeckNumLines; /* number of lines in spice deck */
+
+ double FTESTATnetLoadTime; /* total time required to load the spice deck */
+ double FTESTATnetParseTime; /* total time required to parse the netlist */
+} FTESTATistics;
+
+
+#define FTEOPT_NLDECK 1
+#define FTEOPT_NLT 2
+#define FTEOPT_NPT 3
+
+#endif /*FTEOPT*/
diff --git a/src/include/optdefs.h b/src/include/optdefs.h
index 5df48e853..e3948b626 100644
--- a/src/include/optdefs.h
+++ b/src/include/optdefs.h
@@ -9,6 +9,12 @@ Modified: 2000 AlansFixes
/* structure used to describe the statistics to be collected */
+typedef struct sSTATdevList {
+ struct sSTATdevList *STATnextDev;
+ int modNum;
+ int instNum;
+} STATdevList;
+
typedef struct {
int STATnumIter; /* number of total iterations performed */
@@ -20,6 +26,8 @@ typedef struct {
int STATaccepted; /* number of timepoints accepted */
int STATrejected; /* number of timepoints rejected */
+ int STATtotalDev; /* PN: number of total devices in the netlist */
+
double STATtotAnalTime; /* total time for all analysis */
double STATloadTime; /* total time spent in device loading */
double STATdecompTime; /* total time spent in LU decomposition */
@@ -40,7 +48,7 @@ typedef struct {
double STATacLoadTime; /* time spent in AC device loading */
double STATacCombTime; /* time spent in AC combining */
double STATacSyncTime; /* time spent in transient sync'ing */
-
+ STATdevList *STATdevNum; /* PN: Number of instances and models for each device */
} STATistics;
#define OPT_GMIN 1
@@ -130,4 +138,6 @@ typedef struct {
/* gtri - end - wbk - add new options */
#endif
+#define OPT_TOTALDEV 200 /* Total devices in the netlist */
+
#endif /*OPT*/
diff --git a/src/spicelib/devices/cktcrte.c b/src/spicelib/devices/cktcrte.c
index c08e345a4..a2a71f6d5 100644
--- a/src/spicelib/devices/cktcrte.c
+++ b/src/spicelib/devices/cktcrte.c
@@ -49,6 +49,15 @@ CKTcrtElt(CKTcircuit *ckt, GENmodel *modPtr, GENinstance **inInstPtr, IFuid name
if (instPtr == NULL)
return E_NOMEM;
+ /* PN: adding instance number for statistical purpose */
+ ckt->CKTstat->STATdevNum[type].instNum ++;
+ ckt->CKTstat->STATtotalDev ++;
+
+#if 0
+ printf("device: %s number %d\n",
+ DEVices[type]->DEVpublic.name, ckt->CKTstat->STATdevNum[type].instNum);
+#endif
+
instPtr->GENname = name;
instPtr->GENmodPtr = modPtr;
diff --git a/src/spicelib/devices/cktinit.c b/src/spicelib/devices/cktinit.c
index b6677e234..3f668286f 100644
--- a/src/spicelib/devices/cktinit.c
+++ b/src/spicelib/devices/cktinit.c
@@ -74,7 +74,13 @@ CKTinit(CKTcircuit **ckt) /* new circuit to create */
sckt->CKTdefaultMosAS = 0;
sckt->CKTsrcFact=1;
sckt->CKTdiagGmin=0;
+ /* PN: additions for circuit inventory */
sckt->CKTstat = TMALLOC(STATistics, 1);
+ if(sckt->CKTstat == NULL)
+ return(E_NOMEM);
+ sckt->CKTstat->STATdevNum = TMALLOC(STATdevList, DEVmaxnum);
+ if(sckt->CKTstat->STATdevNum == NULL)
+ return(E_NOMEM);
sckt->CKTtroubleNode = 0;
sckt->CKTtroubleElt = NULL;
sckt->CKTtimePoints = NULL;
diff --git a/visualc/vngspice.vcproj b/visualc/vngspice.vcproj
index 3d9ba049f..072a87e72 100644
--- a/visualc/vngspice.vcproj
+++ b/visualc/vngspice.vcproj
@@ -1941,6 +1941,10 @@
RelativePath="..\src\include\ftedefs.h"
>
+
+
@@ -5685,6 +5689,10 @@
RelativePath="..\src\misc\hash.c"
>
+
+
@@ -6309,6 +6317,10 @@
RelativePath="..\src\frontend\interp.c"
>
+
+