From 5ba0b8b86cfec63d9a776a05ec9618050336a2a1 Mon Sep 17 00:00:00 2001 From: pnenzi Date: Tue, 9 Aug 2011 18:41:36 +0000 Subject: [PATCH] Statistics patch: added netlist loading and parsing time in acct command. Added devhelp command to obtain information about available devices and device parameters Added inventory command to print the number of instances per device. --- src/frontend/Makefile.am | 2 + src/frontend/commands.c | 24 ++++- src/frontend/device.c | 177 +++++++++++++++++++++++++++++++++ src/frontend/device.h | 4 + src/frontend/inp.c | 22 +++- src/frontend/inventory.c | 52 ++++++++++ src/frontend/mw_coms.c | 3 + src/frontend/resource.c | 30 ++++++ src/include/Makefile.am | 1 + src/include/ftedefs.h | 3 + src/include/fteext.h | 7 ++ src/include/fteoptdefs.h | 25 +++++ src/include/optdefs.h | 12 ++- src/spicelib/devices/cktcrte.c | 9 ++ src/spicelib/devices/cktinit.c | 6 ++ visualc/vngspice.vcproj | 12 +++ 16 files changed, 382 insertions(+), 7 deletions(-) create mode 100644 src/frontend/inventory.c create mode 100644 src/include/fteoptdefs.h 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" > + +