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" > + +