diff --git a/examples/cider/bjt/README b/examples/cider/bjt/README new file mode 100644 index 000000000..06d07127d --- /dev/null +++ b/examples/cider/bjt/README @@ -0,0 +1,11 @@ + +Run: + + ngspice -b pz1.cir + +and the operating point file 'PEBJT1--OP.0.q1' is generated. + +The .model in the included library 'pebjt1.lib' has an output rootfile +parameter which determines the PEBJT1-- prefix. The mixed case in the name +of the generated OP file is retained. Without any rootfile or output statement +in the .model, the file created will be named 'OP.0.q1'. diff --git a/examples/cider/bjt/ecp.cir b/examples/cider/bjt/ecp.cir index 6fb2bda9b..904f19b32 100644 --- a/examples/cider/bjt/ecp.cir +++ b/examples/cider/bjt/ecp.cir @@ -10,8 +10,6 @@ IEE 13 2 0.1mA Q1 11 12 13 M_NPN AREA=8 Q2 21 22 13 M_NPN AREA=8 -.DC VBBP 2.75v 3.25001v 10mv -.PRINT V(21) V(11) .MODEL M_NPN nbjt level=2 + title TWO-DIMENSIONAL NUMERICAL POLYSILICON EMITTER BIPOLAR TRANSISTOR @@ -54,4 +52,6 @@ Q2 21 22 13 M_NPN AREA=8 + models bgn srh auger conctau concmob fieldmob .OPTIONS ACCT BYPASS=1 +.DC VBBP 2.75v 3.25001v 10mv +.PRINT DC V(21) V(11) .END diff --git a/examples/cider/bjt/pebjt1.lib b/examples/cider/bjt/pebjt1.lib new file mode 100644 index 000000000..b830c4758 --- /dev/null +++ b/examples/cider/bjt/pebjt1.lib @@ -0,0 +1,72 @@ +** +* Numerical models for a +* polysilicon emitter complementary bipolar process. +* The default device size is 1um by 10um (LxW) +** + +.model M_NPN nbjt level=1 ++ title One-Dimensional Numerical Bipolar ++ options base.depth=0.15 base.area=0.1 base.length=1.0 defa=10p ++ x.mesh loc=-0.2 n=1 ++ x.mesh loc=0.0 n=51 ++ x.mesh wid=0.15 h.e=0.0001 h.m=.004 r=1.2 ++ x.mesh wid=1.15 h.s=0.0001 h.m=.004 r=1.2 ++ domain num=1 material=1 x.l=0.0 ++ domain num=2 material=2 x.h=0.0 ++ material num=1 silicon ++ mobility mat=1 concmod=ct fieldmod=ct ++ material num=2 polysilicon ++ mobility mat=2 concmod=ct fieldmod=ct ++ doping gauss n.type conc=3e20 x.l=-0.2 x.h=0.0 char.len=0.047 ++ doping gauss p.type conc=5e18 x.l=-0.2 x.h=0.0 char.len=0.100 ++ doping unif n.type conc=1e16 x.l=0.0 x.h=1.3 ++ doping gauss n.type conc=5e19 x.l=1.3 x.h=1.3 char.len=0.100 ++ models bgn srh auger conctau concmob fieldmob ^aval ++ method devtol=1e-12 ac=direct itlim=15 ++ output rootfile="PEBJT1--" Psi N.CONC P.conc + +.model M_NPSUB numd level=1 ++ title One-Dimensional Numerical Collector-Substrate Diode ++ options defa=10p ++ x.mesh loc=1.3 n=1 ++ x.mesh loc=2.0 n=101 ++ domain num=1 material=1 ++ material num=1 silicon ++ mobility mat=1 concmod=ct fieldmod=ct ++ doping gauss n.type conc=5e19 x.l=1.3 x.h=1.3 char.len=0.100 ++ doping unif p.type conc=1e15 x.l=0.0 x.h=2.0 ++ models bgn srh auger conctau concmob fieldmob ^aval ++ method devtol=1e-12 itlim=10 + +.model M_PNP nbjt level=1 ++ title One-Dimensional Numerical Bipolar ++ options base.depth=0.2 base.area=0.1 base.length=1.0 defa=10p ++ x.mesh loc=-0.2 n=1 ++ x.mesh loc=0.0 n=51 ++ x.mesh wid=0.20 h.e=0.0001 h.m=.004 r=1.2 ++ x.mesh wid=1.10 h.s=0.0001 h.m=.004 r=1.2 ++ domain num=1 material=1 x.l=0.0 ++ domain num=2 material=2 x.h=0.0 ++ material num=1 silicon ++ mobility mat=1 concmod=ct fieldmod=ct ++ material num=2 polysilicon ++ mobility mat=2 concmod=ct fieldmod=ct ++ doping gauss p.type conc=3e20 x.l=-0.2 x.h=0.0 char.len=0.047 ++ doping gauss n.type conc=5e17 x.l=-0.2 x.h=0.0 char.len=0.200 ++ doping unif p.type conc=1e16 x.l=0.0 x.h=1.3 ++ doping gauss p.type conc=5e19 x.l=1.3 x.h=1.3 char.len=0.100 ++ models bgn srh auger conctau concmob fieldmob ^aval ++ method devtol=1e-12 ac=direct itlim=15 + +.model M_PNSUB numd level=1 ++ title One-Dimensional Numerical Collector-Substrate Diode ++ options defa=10p ++ x.mesh loc=1.3 n=1 ++ x.mesh loc=2.0 n=101 ++ domain num=1 material=1 ++ material num=1 silicon ++ mobility mat=1 concmod=ct fieldmod=ct ++ doping gauss p.type conc=5e19 x.l=1.3 x.h=1.3 char.len=0.100 ++ doping unif n.type conc=1e15 x.l=0.0 x.h=2.0 ++ models bgn srh auger conctau concmob fieldmob ^aval ++ method devtol=1e-12 itlim=10 diff --git a/examples/cider/bjt/pz.cir b/examples/cider/bjt/pz.cir index ad3ee6757..5a6a47315 100644 --- a/examples/cider/bjt/pz.cir +++ b/examples/cider/bjt/pz.cir @@ -13,4 +13,5 @@ CL 5 0 0.1pF .PZ 3 0 5 0 vol pz +.PRINT PZ ALL .END diff --git a/examples/cider/bjt/pz1.cir b/examples/cider/bjt/pz1.cir new file mode 100644 index 000000000..36458c0ca --- /dev/null +++ b/examples/cider/bjt/pz1.cir @@ -0,0 +1,18 @@ +PZ Analysis of a Common Emitter Amplifier + +Vcc 1 0 5v +Vee 2 0 0v + +Vin 3 0 0.7838 AC 1 +RS 3 4 1K +Q1 5 4 2 M_NPN AREA=4 SAVE +RL 1 5 2.5k +CL 5 0 0.1pF + +.INCLUDE pebjt1.lib + +.PZ 3 0 5 0 vol pz + +.PRINT PZ ALL +.OP +.END diff --git a/examples/cider/diode/README b/examples/cider/diode/README new file mode 100644 index 000000000..c12144b82 --- /dev/null +++ b/examples/cider/diode/README @@ -0,0 +1,18 @@ + +Run: + + ngspice -b pd1.cir + +This will generate the operating point file 'Pre-Pin-Diode-OP.0.d1', which +is read as the ic.file (initial condition file) for 'pindiode.cir'. +Note that if there is no output line in the .model section of 'pd1.cir', +the generated file will be named 'OP.0.d1'. In this case the ic.file value +in 'pindiode.cir' would need to be chenged to match it. + +Then: + + ngspice -b pindiode.cir + +can be run which will input 'Pre-Pin-Diode-OP.0.d1'. If you do not run +'pd1.cir' first, the 'pindiode.cir' simulation will run OK but tell you it +cannot find the iinitial condition file. diff --git a/examples/cider/diode/diode.cir b/examples/cider/diode/diode.cir index e0ace324f..527de4af9 100644 --- a/examples/cider/diode/diode.cir +++ b/examples/cider/diode/diode.cir @@ -29,7 +29,8 @@ D1 1 2 M_PN AREA=100 .option acct bypass=0 abstol=1e-18 itl2=100 .op .ac dec 10 100kHz 10gHz +.print ac i(Vpp) .dc Vpp -3.0v 2.0001v 50mv -.print i(Vpp) +.print dc i(Vpp) .END diff --git a/examples/cider/diode/diotran.cir b/examples/cider/diode/diotran.cir index 110d2550f..354b88218 100644 --- a/examples/cider/diode/diotran.cir +++ b/examples/cider/diode/diotran.cir @@ -26,6 +26,6 @@ D1 3 2 M_PN area=100 .option acct bypass=1 abstol=1e-15 itl2=100 .tran 0.001ns 1.0ns -.print i(Vpp) +.print tran i(Vpp) .END diff --git a/examples/cider/diode/pd1.cir b/examples/cider/diode/pd1.cir new file mode 100644 index 000000000..fe76a3c30 --- /dev/null +++ b/examples/cider/diode/pd1.cir @@ -0,0 +1,44 @@ +PRE-PIN-DIODE TWO-DIMENSIONAL PIN-DIODE CIRCUIT + +VIN 1 0 0.0v (PWL 0ns 0.8v 1ns -50.0v) +L1 1 2 0.5uH +VD 2 3 0.0v +D1 3 0 M_PIN AREA=200 save +VRC 2 4 0.0v +R1 4 5 100 +C1 5 0 1.0nF + +.MODEL M_PIN NUMD LEVEL=2 ++ options defw=1000u ++ x.mesh n=1 l=0.0 ++ x.mesh n=2 l=0.2 ++ x.mesh n=4 l=0.4 ++ x.mesh n=8 l=0.6 ++ x.mesh n=13 l=1.0 ++ ++ y.mesh n=1 l=0.0 ++ y.mesh n=9 l=4.0 ++ y.mesh n=24 l=10.0 ++ y.mesh n=29 l=15.0 ++ y.mesh n=34 l=20.0 ++ ++ domain num=1 material=1 ++ material num=1 silicon tn=20ns tp=20ns ++ ++ electrode num=1 x.l=0.6 x.h=1.0 y.h=0.0 ++ electrode num=2 y.l=20.0 ++ ++ doping gauss p.type conc=1.0e20 char.len=1.076 x.l=0.75 x.h=1.1 y.h=0.0 ++ + lat.rotate ratio=0.1 ++ doping unif n.type conc=1.0e14 ++ doping gauss n.type conc=1.0e20 char.len=1.614 x.l=-0.1 x.h=1.1 y.l=20.0 ++ ++ models bgn srh auger conctau concmob fieldmob ++ output rootfile="Pre-Pin-Diode-" + +.OPTION ACCT BYPASS=1 +* .TRAN 1NS 100NS +* .PRINT TRAN v(3) I(VIN) +.op + +.END diff --git a/examples/cider/diode/pindiode.cir b/examples/cider/diode/pindiode.cir index 1eb18b421..1fe756a8b 100644 --- a/examples/cider/diode/pindiode.cir +++ b/examples/cider/diode/pindiode.cir @@ -3,7 +3,7 @@ TWO-DIMENSIONAL PIN-DIODE CIRCUIT VIN 1 0 0.0v (PWL 0ns 0.8v 1ns -50.0v) L1 1 2 0.5uH VD 2 3 0.0v -D1 3 0 M_PIN AREA=200 IC.FILE="OP.0.d1" +D1 3 0 M_PIN AREA=200 IC.FILE="Pre-Pin-Diode-OP.0.d1" VRC 2 4 0.0v R1 4 5 100 C1 5 0 1.0nF @@ -38,5 +38,6 @@ C1 5 0 1.0nF .OPTION ACCT BYPASS=1 .TRAN 1NS 100NS .PRINT TRAN v(3) I(VIN) +.PLOT TRAN v(3) I(VIN) .END diff --git a/examples/cider/mos/bootinv.cir b/examples/cider/mos/bootinv.cir index 4c2ea40db..f84c86ac2 100644 --- a/examples/cider/mos/bootinv.cir +++ b/examples/cider/mos/bootinv.cir @@ -54,6 +54,6 @@ CB 3 4 0.1pf + method ac=direct onec .tran 0.2ns 40ns -.print v(4) +.print tran v(4) .options acct bypass=1 method=gear .end diff --git a/examples/cider/parallel/clkfeed.cir b/examples/cider/parallel/clkfeed.cir index d0a06f157..d24d2838d 100644 --- a/examples/cider/parallel/clkfeed.cir +++ b/examples/cider/parallel/clkfeed.cir @@ -31,4 +31,5 @@ IREF 7 0 50UA .TRAN 0.1NS 50NS .OPTIONS ACCT BYPASS=1 METHOD=GEAR +.PRINT TRAN I(VB) .END diff --git a/examples/cider/parallel/cmosamp.cir b/examples/cider/parallel/cmosamp.cir index f88115b56..f28c1fea7 100644 --- a/examples/cider/parallel/cmosamp.cir +++ b/examples/cider/parallel/cmosamp.cir @@ -26,4 +26,5 @@ M8 8 9 1 1 M_PMOS_1 W=15U L=1U .DC VPL -5MV 5MV 0.1MV .OPTIONS ACCT BYPASS=1 METHOD=GEAR +.print DC V(3) V(4) V(8) .END diff --git a/examples/cider/parallel/ringosc.2u.cir b/examples/cider/parallel/ringosc.2u.cir index c79885ab1..da7f07f63 100644 --- a/examples/cider/parallel/ringosc.2u.cir +++ b/examples/cider/parallel/ringosc.2u.cir @@ -109,6 +109,6 @@ VBN 2 26 0.0V + OUTPUT ^ALL.DEBUG .TRAN 0.1NS 5.0NS -.PRINT V(4) +.PRINT TRAN V(4) .OPTIONS ACCT BYPASS=1 METHOD=GEAR .END diff --git a/examples/cider/resistor/gaasres.cir b/examples/cider/resistor/gaasres.cir index c35d0ddc0..81cfb8a57 100644 --- a/examples/cider/resistor/gaasres.cir +++ b/examples/cider/resistor/gaasres.cir @@ -24,7 +24,7 @@ D1 1 2 M_RES AREA=1 *.OP *.DC VPP 0.0v 10.01v 0.1v .TRAN 1s 10.001s 0s 0.1s -.PRINT I(VPP) +.PRINT TRAN I(VPP) .OPTION ACCT BYPASS=1 .END diff --git a/examples/cider/resistor/sires.cir b/examples/cider/resistor/sires.cir index 45e2aa12a..dd6d75dfc 100644 --- a/examples/cider/resistor/sires.cir +++ b/examples/cider/resistor/sires.cir @@ -20,7 +20,7 @@ D1 1 2 M_RES AREA=1 *.OP .DC VPP 0.0v 10.01v 0.1v *.TRAN 1s 100.001s 0s 0.2s -.PRINT I(VPP) +.PRINT DC I(VPP) .OPTION ACCT BYPASS=1 RELTOL=1e-12 .END diff --git a/examples/cider/serial/dbridge.cir b/examples/cider/serial/dbridge.cir index 052ae4f07..82252f7e0 100644 --- a/examples/cider/serial/dbridge.cir +++ b/examples/cider/serial/dbridge.cir @@ -26,5 +26,5 @@ RL 1 2 1.0K .OPTION ACCT BYPASS=1 METHOD=GEAR .TRAN 0.5MS 50MS -.PRINT I(VLINE) +.PRINT TRAN I(VLINE) .END diff --git a/examples/cider/serial/recovery.cir b/examples/cider/serial/recovery.cir index cd33be1e0..b210037ff 100644 --- a/examples/cider/serial/recovery.cir +++ b/examples/cider/serial/recovery.cir @@ -35,6 +35,6 @@ DT 4 2 M_PIN AREA=1 .OPTION ACCT BYPASS=1 .TRAN 0.1NS 10NS -.PRINT TRAN V(3) I(VIN) +.PRINT TRAN V(3) I(VNN) .END diff --git a/src/ciderlib/oned/oneprint.c b/src/ciderlib/oned/oneprint.c index 41796f999..7e7ae33f8 100644 --- a/src/ciderlib/oned/oneprint.c +++ b/src/ciderlib/oned/oneprint.c @@ -354,6 +354,7 @@ ONEmemStats(FILE *file, ONEdevice *pDevice) int numContactNodes; + if (!pDevice) { return; } fprintf(file, "----------------------------------------\n"); fprintf(file, "Device %s Memory Usage:\n", pDevice->name); fprintf(file, "Item Count Bytes\n"); @@ -425,10 +426,12 @@ void ONEcpuStats(FILE *file, ONEdevice *pDevice) { static const char cpuFormat[] = "%-20s%10g%10g%10g%10g%10g\n"; - ONEstats *pStats = pDevice->pStats; + ONEstats *pStats = NULL; double total; int iTotal; + if (!pDevice) { return; } + pStats = pDevice->pStats; fprintf(file, "----------------------------------------------------------------------\n"); fprintf(file, diff --git a/src/ciderlib/support/suprem.c b/src/ciderlib/support/suprem.c index bd6cc572b..9ad72ab58 100644 --- a/src/ciderlib/support/suprem.c +++ b/src/ciderlib/support/suprem.c @@ -34,7 +34,7 @@ int readAsciiData(const char *fileName, int impType, DOPtable **ppTable) (void) fprintf(cp_err, "unable to open SUPREM file \"%s\": %s\n", fileName, strerror(errno)); xrc = -1; - goto EXITPOINT; + return xrc; /* return immediately, nothing to free */ } /* Get sign of concentrations */ @@ -156,16 +156,15 @@ int readSupremData(const char *fileName, int fileType, int impType, /* read the Suprem data file */ if ( fileType == 0 ) { /* BINARY FILE */ - const int rc = SUPbinRead(fileName, x, conc, &impType, - &numNodes); - if (rc != 0) { - (void) fprintf(cp_err, "Data input failed.\n"); - xrc = -1; - goto EXITPOINT; - } + xrc = SUPbinRead(fileName, x, conc, &impType, &numNodes); } else { - SUPascRead( fileName, x, conc, &impType, &numNodes ); + xrc = SUPascRead( fileName, x, conc, &impType, &numNodes ); + } + if (xrc != 0) { + (void) fprintf(cp_err, "Data input failed.\n"); + xrc = -1; + return xrc; /* return immediately, nothing to free */ } /* allocate 2-D array to read in data of x-coordinate and N(x) */ @@ -200,7 +199,7 @@ int readSupremData(const char *fileName, int fileType, int impType, printf("%e %e\n", profileData[ 0 ][ index ], profileData[ 1 ][ index ]); } */ -EXITPOINT: + if (xrc != 0) { free_profile_data(profileData); free(tmpTable); diff --git a/src/ciderlib/twod/twoprint.c b/src/ciderlib/twod/twoprint.c index 1a294a1bf..2e204fcc2 100644 --- a/src/ciderlib/twod/twoprint.c +++ b/src/ciderlib/twod/twoprint.c @@ -380,6 +380,7 @@ TWOmemStats(FILE *file, TWOdevice *pDevice) TWOchannel *pChannel; int numContactNodes; + if (!pDevice) { return; } fprintf(file, "----------------------------------------\n"); fprintf(file, "Device %s Memory Usage:\n", pDevice->name ); fprintf(file, "Item Count Bytes\n"); @@ -460,10 +461,12 @@ void TWOcpuStats(FILE *file, TWOdevice *pDevice) { static const char cpuFormat[] = "%-20s%10g%10g%10g%10g%10g\n"; - TWOstats *pStats = pDevice->pStats; + TWOstats *pStats = NULL; double total; int iTotal; + if (!pDevice) { return; } + pStats = pDevice->pStats; fprintf(file, "----------------------------------------------------------------------\n"); fprintf(file, diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 5e1d05e83..cae6998e7 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -209,6 +209,72 @@ static int inp_poly_2g6_compat(struct card* deck); static void inp_poly_err(struct card *deck); #endif +#ifdef CIDER +static char *keep_case_of_cider_param(char *buffer) +{ + int numq = 0, keep_case = 0; + char *s = 0; + /* Retain the case of strings enclosed in double quotes for + output rootfile and doping infile params within Cider .model + statements. Also for the ic.file filename param in an element + instantiation statement. + No nested double quotes. + */ + for (s = buffer; *s && (*s != '\n'); s++) { + if (*s == '\"') { + numq++; + } + } + if (numq == 2) { + /* One pair of double quotes */ + for (s = buffer; *s && (*s != '\n'); s++) { + if (*s == '\"') { + keep_case = (keep_case == 0 ? 1 : 0); + } + if (!keep_case) { + *s = tolower_c(*s); + } + } + } else { + for (s = buffer; *s && (*s != '\n'); s++) { + *s = tolower_c(*s); + } + } + return s; +} + +static int is_comment_or_blank(char *buffer) +{ + /* Assume line buffers have initial whitespace removed */ + switch (buffer[0]) { + case '*': + case '$': + case '#': + case '\n': + case '\0': + return 1; + default: + return 0; + } +} + +static int turn_off_case_retention(char *buffer) +{ + if (buffer[0] == '.') { + if (ciprefix(".model", buffer)) { + return 0; + } else { + return 1; + } + } else if (is_comment_or_blank(buffer)) { + return 0; + } else if (buffer[0] == '+') { + return 0; + } else { + return 1; + } +} +#endif /* insert a new card, just behind the given card */ static struct card *insert_new_line( @@ -1012,6 +1078,9 @@ struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name, static int is_control = 0; /* We are reading from a .control section */ bool found_end = FALSE, shell_eol_continuation = FALSE; +#ifdef CIDER + static int in_cider_model = 0; +#endif /* First read in all lines & put them in the struct cc */ for (;;) { @@ -1238,6 +1307,27 @@ struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name, * double quotes are printed. */ { char *s; +#ifdef CIDER + if (ciprefix(".model", buffer)) { + if (strcasestr(buffer, " numos") || + strcasestr(buffer, " numd") || /* Also numd2 */ + strcasestr(buffer, " nbjt")) { /* Also nbjt2 */ + in_cider_model = 1; + } else { + in_cider_model = 0; + } +#ifdef TRACE + printf("Found .model Cider model is %s\n", + (in_cider_model ? "ON" : "OFF")); +#endif + } + if (in_cider_model && turn_off_case_retention(buffer)) { + in_cider_model = 0; +#ifdef TRACE + printf("Cider model is OFF\n"); +#endif + } +#endif if (ciprefix("plot", buffer) || ciprefix("gnuplot", buffer) || ciprefix("hardcopy", buffer)) { /* lower case excluded for tokens following title, xlabel, @@ -1316,6 +1406,15 @@ struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name, *s = tolower_c(*s); } } +#ifdef CIDER + else if (in_cider_model && !is_comment_or_blank(buffer) && + (ciprefix(".model", buffer) || buffer[0] == '+')) { + s = keep_case_of_cider_param(buffer); + } + else if (strcasestr(buffer, "ic.file")) { + s = keep_case_of_cider_param(buffer); + } +#endif /* no lower case letters for lines beginning with: */ else if (!ciprefix("write", buffer) && !ciprefix("wrdata", buffer) && diff --git a/src/spicelib/devices/numd2/nud2ask.c b/src/spicelib/devices/numd2/nud2ask.c index 7e21b05c0..dc71cce1e 100644 --- a/src/spicelib/devices/numd2/nud2ask.c +++ b/src/spicelib/devices/numd2/nud2ask.c @@ -30,7 +30,7 @@ NUMD2ask(CKTcircuit *ckt, GENinstance *inInst, int which, IFvalue *value, IFvalu return (OK); case NUMD2_AREA: value->rValue = inst->NUMD2area; - break; + return (OK); case NUMD2_TEMP: value->rValue = inst->NUMD2temp - CONSTCtoK; return (OK);