From 3ad93a50e8161d5808c6544c4b8002dbfdfa8dc5 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 25 Apr 2020 18:54:22 +0200 Subject: [PATCH] Add EXITPOINTs, if reading inputs etc. fails --- src/ciderlib/input/dopset.c | 29 ++- src/ciderlib/oned/oneadmit.c | 8 +- src/ciderlib/oned/onedopng.c | 1 + src/ciderlib/support/suprem.c | 153 ++++++++++---- src/ciderlib/support/suprmitf.c | 358 +++++++++++++++++++++----------- src/ciderlib/twod/twodext.h | 2 +- src/ciderlib/twod/twodopng.c | 2 + src/ciderlib/twod/twosolve.c | 184 +++++++++------- 8 files changed, 480 insertions(+), 257 deletions(-) diff --git a/src/ciderlib/input/dopset.c b/src/ciderlib/input/dopset.c index d543713fb..ad69fe23e 100644 --- a/src/ciderlib/input/dopset.c +++ b/src/ciderlib/input/dopset.c @@ -4,18 +4,19 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group Modifed: 2001 Paolo Nenzi **********/ -#include "ngspice/ngspice.h" +#include "ngspice/carddefs.h" +#include "ngspice/cidersupt.h" #include "ngspice/cktdefs.h" -#include "ngspice/numenum.h" +#include "ngspice/ciderinp.h" +#include "ngspice/cpextern.h" #include "ngspice/dopdefs.h" #include "ngspice/meshext.h" +#include "ngspice/ngspice.h" +#include "ngspice/numenum.h" #include "ngspice/profile.h" #include "ngspice/gendev.h" #include "ngspice/sperror.h" #include "ngspice/suffix.h" -#include "ngspice/cidersupt.h" -#include "ngspice/carddefs.h" -#include "ngspice/ciderinp.h" /* @@ -234,17 +235,29 @@ DOPsetup(DOPcard *cardList, DOPprofile **profileList, DOPtable **tableList, break; case DOP_SUPREM3: newProfile->type = LOOKUP; - readSupremData( card->DOPinFile, 0, card->DOPimpurityType, tableList ); + if (readSupremData( card->DOPinFile, 0, card->DOPimpurityType, + tableList) != 0) { + (void) fprintf(cp_err, "Doping setup failed.\n"); + return -1; + } newProfile->IMPID = ++impurityId; break; case DOP_SUPASCII: newProfile->type = LOOKUP; - readSupremData( card->DOPinFile, 1, card->DOPimpurityType, tableList ); + if (readSupremData( card->DOPinFile, 1, card->DOPimpurityType, + tableList) != 0) { + (void) fprintf(cp_err, "Doping setup failed.\n"); + return -1; + } newProfile->IMPID = ++impurityId; break; case DOP_ASCII: newProfile->type = LOOKUP; - readAsciiData( card->DOPinFile, card->DOPimpurityType, tableList ); + if (readAsciiData(card->DOPinFile, card->DOPimpurityType, + tableList) != 0) { + (void) fprintf(cp_err, "Doping setup failed.\n"); + return -1; + } newProfile->IMPID = ++impurityId; break; default: diff --git a/src/ciderlib/oned/oneadmit.c b/src/ciderlib/oned/oneadmit.c index 9920a2f55..13df2f602 100644 --- a/src/ciderlib/oned/oneadmit.c +++ b/src/ciderlib/oned/oneadmit.c @@ -40,7 +40,7 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd) int index, i; double yReal, yImag; double *solutionReal, *solutionImag; - SPcomplex yAc, cOmega; + SPcomplex yAc_adm, cOmega; SPcomplex *y; BOOLEAN SORFailed; double startTime; @@ -146,13 +146,13 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd) startTime = SPfrontEnd->IFseconds(); pNode = pDevice->elemArray[1]->pLeftNode; y = computeAdmittance(pNode, FALSE, solutionReal, solutionImag, &cOmega); - CMPLX_ASSIGN_VALUE(yAc, -y->real, -y->imag); - CMPLX_ASSIGN(*yd, yAc); + CMPLX_ASSIGN_VALUE(yAc_adm, -y->real, -y->imag); + CMPLX_ASSIGN(*yd, yAc_adm); CMPLX_MULT_SELF_SCALAR(*yd, GNorm * pDevice->area); pDevice->pStats->miscTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime; return (AcAnalysisMethod); -} +} /* end of function NUMDadmittance */ int diff --git a/src/ciderlib/oned/onedopng.c b/src/ciderlib/oned/onedopng.c index 24d6e0322..ab0fc4ca9 100644 --- a/src/ciderlib/oned/onedopng.c +++ b/src/ciderlib/oned/onedopng.c @@ -77,6 +77,7 @@ ONEdopingValue(DOPprofile *pProfile, DOPtable *pTable, double x) } else { value = pProfile->PEAK_CONC * exp(-argP); } + break; case EXP: argP = ABS(argP); if (argP > 80.0) { diff --git a/src/ciderlib/support/suprem.c b/src/ciderlib/support/suprem.c index 7aded0e3b..bd6cc572b 100644 --- a/src/ciderlib/support/suprem.c +++ b/src/ciderlib/support/suprem.c @@ -5,26 +5,36 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group **********/ /* Functions to read SUPREM (Binary or Ascii) & ASCII input files */ +#include +#include +#include "ngspice/cidersupt.h" +#include "ngspice/cpextern.h" #include "ngspice/ngspice.h" #include "ngspice/profile.h" -#include "ngspice/cidersupt.h" -void -readAsciiData( char *fileName, int impType, DOPtable **ppTable ) + +static void free_profile_data(double **p); +static double **alloc_profile_data(size_t n); + + +int readAsciiData(const char *fileName, int impType, DOPtable **ppTable) { - FILE *fpAscii; + int xrc = 0; + FILE *fpAscii = (FILE *) NULL; int index; double x, y; int numPoints; - DOPtable *tmpTable; - double **profileData; + DOPtable *tmpTable = (DOPtable *) NULL; + double **profileData = (double **) NULL; double sign; /* Open Input File */ if ((fpAscii = fopen( fileName, "r" )) == NULL) { - perror( fileName ); - exit(-1); + (void) fprintf(cp_err, "unable to open SUPREM file \"%s\": %s\n", + fileName, strerror(errno)); + xrc = -1; + goto EXITPOINT; } /* Get sign of concentrations */ @@ -35,31 +45,43 @@ readAsciiData( char *fileName, int impType, DOPtable **ppTable ) } /* read the number of points */ - fscanf( fpAscii, "%d", &numPoints ); + if (fscanf(fpAscii, "%d", &numPoints) != 1) { + (void) fprintf(cp_err, "unable to read point count " + "from SUPREM file \"%s\"\n", + fileName); + xrc = -1; + goto EXITPOINT; + } + /* allocate 2-D array to read in data of x-coordinate and N(x) */ - XCALLOC( profileData, double *, 2 ); - for( index = 0; index <= 1; index++ ) { - XCALLOC( profileData[ index ], double, 1 + numPoints ); - } + profileData = alloc_profile_data((size_t) numPoints + 1); + /* the number of points is stored as profileData[0][0] */ profileData[0][0] = numPoints; - for( index = 1; index <= numPoints; index++ ) { - fscanf( fpAscii, "%lf %lf ", &x, &y ); - profileData[ 0 ][ index ] = x; - profileData[ 1 ][ index ] = sign * ABS(y); - } + for (index = 1; index <= numPoints; index++ ) { + if (fscanf(fpAscii, "%lf %lf ", &x, &y) != 2) { + (void) fprintf(cp_err, "unable to read point %d" + "from SUPREM file \"%s\"\n", + index + 1, fileName); + xrc = -1; + goto EXITPOINT; + } + profileData[0][index] = x; + profileData[1][index] = sign * ABS(y); + } /* end of loop over points */ /* Now create a new lookup table */ - XCALLOC( tmpTable, DOPtable, 1 ); - if ( *ppTable == NULL ) { + XCALLOC(tmpTable, DOPtable, 1); + if (*ppTable == NULL) { /* First Entry */ tmpTable->impId = 1; tmpTable->dopData = profileData; tmpTable->next = NULL; *ppTable = tmpTable; - } else { + } + else { tmpTable->impId = (*ppTable)->impId + 1; tmpTable->dopData = profileData; tmpTable->next = *ppTable; @@ -72,9 +94,21 @@ readAsciiData( char *fileName, int impType, DOPtable **ppTable ) printf("\n %e %e", profileData[ 0 ][ index ], profileData[ 1 ][ index ]); } */ - fclose(fpAscii); - return; -} +EXITPOINT: + if (fpAscii != (FILE *) NULL) { /* close data file if open */ + fclose(fpAscii); + } + + /* Free resources on error */ + if (xrc != 0) { + free_profile_data(profileData); + free(tmpTable); + } + + return xrc; +} /* end of function readAsciiData */ + + /* interface routine based on notes provided by Steve Hansen of Stanford */ @@ -108,40 +142,45 @@ readAsciiData( char *fileName, int impType, DOPtable **ppTable ) */ -void -readSupremData(char *fileName, int fileType, int impType, DOPtable **ppTable) +int readSupremData(const char *fileName, int fileType, int impType, + DOPtable **ppTable) { + int xrc = 0; #define MAX_GRID 500 float x[ MAX_GRID ], conc[ MAX_GRID ]; int index; - DOPtable *tmpTable; - double **profileData; + DOPtable *tmpTable = (DOPtable *) NULL; + double **profileData = (double **) NULL; int numNodes; /* read the Suprem data file */ if ( fileType == 0 ) { /* BINARY FILE */ - SUPbinRead( fileName, x, conc, &impType, &numNodes ); + const int rc = SUPbinRead(fileName, x, conc, &impType, + &numNodes); + if (rc != 0) { + (void) fprintf(cp_err, "Data input failed.\n"); + xrc = -1; + goto EXITPOINT; + } } else { SUPascRead( fileName, x, conc, &impType, &numNodes ); } /* allocate 2-D array to read in data of x-coordinate and N(x) */ - XCALLOC( profileData, double *, 2 ); - for( index = 0; index <= 1; index++ ) { - XCALLOC( profileData[ index ], double, 1 + numNodes ); - } + profileData = alloc_profile_data((size_t) numNodes + 1); + /* the number of points is stored as profileData[0][0] */ profileData[0][0] = numNodes; for( index = 1; index <= numNodes; index++ ) { - profileData[ 0 ][ index ] = x[ index ]; - profileData[ 1 ][ index ] = conc[ index ]; + profileData[ 0 ][ index ] = x[ index ]; + profileData[ 1 ][ index ] = conc[ index ]; } /* Now create a new lookup table */ - XCALLOC( tmpTable, DOPtable, 1 ); + XCALLOC(tmpTable, DOPtable, 1); if ( *ppTable == NULL ) { /* First Entry */ tmpTable->impId = 1; @@ -161,8 +200,46 @@ readSupremData(char *fileName, int fileType, int impType, DOPtable **ppTable) printf("%e %e\n", profileData[ 0 ][ index ], profileData[ 1 ][ index ]); } */ - return; -} +EXITPOINT: + if (xrc != 0) { + free_profile_data(profileData); + free(tmpTable); + } + return xrc; +} /* end of function readSupremData */ + + + +/* Allocate a profile data */ +static double **alloc_profile_data(size_t n) +{ + double **p; + XCALLOC(p, double *, 2); + XCALLOC(p[0], double, n); + XCALLOC(p[1], double, n); + return p; +} /* end of function alloc_profile_data */ + + + +/* Free a profile data */ +static void free_profile_data(double **p) +{ + /* Immediate exit if no allocation */ + if (p == (double **) NULL) { + return; + } + + free(p[0]); + free(p[1]); + free(p); +} /* end of function alloc_profile_data */ + + + + + + /* main program to debug readSupremData */ diff --git a/src/ciderlib/support/suprmitf.c b/src/ciderlib/support/suprmitf.c index 3baafc548..9b9d1afa2 100644 --- a/src/ciderlib/support/suprmitf.c +++ b/src/ciderlib/support/suprmitf.c @@ -8,25 +8,31 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group * the data is read and stored in two arrays x and conc */ +#include +#include -#include "ngspice/ngspice.h" #include "ngspice/cidersupt.h" +#include "ngspice/cpextern.h" +#include "ngspice/ngspice.h" #define MAXMAT 10 #define MAXIMP 4 #define MAXLAYER 10 #define MAXGRID 500 -#define GFREAD( fp, ptr, type, num ) if (num && (fread( ptr,\ - sizeof(type), (unsigned)num, fp ) != (unsigned)num)) {\ - return;\ - } +#define GFREAD( fp, ptr, type, num )\ + if (num && (fread( ptr, sizeof(type), (size_t) num,\ + fp ) != (size_t) num)) {\ + xrc = -1;\ + goto EXITPOINT;\ + } #define DEBUG if (0) -void -SUPbinRead(char *inFile, float *x, float *conc, int *impId, int *numNod) +int SUPbinRead(const char *inFile, float *x, float *conc, int *impId, + int *numNod) { + int xrc = 0; int idata, recordMark; int ldata; int i, j; @@ -37,18 +43,20 @@ SUPbinRead(char *inFile, float *x, float *conc, int *impId, int *numNod) float xStart; float layerTh[10]; float con[500]; - FILE *fpSuprem; + FILE *fpSuprem = (FILE *) NULL; /* Clear Concentration Array */ for ( i=0; i < MAXGRID; i++ ) { conc[i] = 0.0; } - /* Open Input File */ - if ((fpSuprem = fopen( inFile, "r" )) == NULL) { - perror(inFile); - return; - } + /* Open Input File */ + if ((fpSuprem = fopen( inFile, "r" )) == NULL) { + (void) fprintf(cp_err, "Unable to read file \"%s\": %s.\n", + inFile, strerror(errno)); + xrc = -1; + goto EXITPOINT; + } /* * The first record contains the number of layers (I4), the number of @@ -199,17 +207,27 @@ SUPbinRead(char *inFile, float *x, float *conc, int *impId, int *numNod) DEBUG fprintf(stderr," %d\n", ldata ); GFREAD( fpSuprem, &recordMark, int, 1 ); - fclose( fpSuprem ); + if (fclose(fpSuprem) != 0) { + (void) fprintf(cp_err, "Unable to close file \"%s\": %s.\n", + inFile, strerror(errno)); + xrc = -1; + goto EXITPOINT; + } + fpSuprem = (FILE *) NULL; -/* shift silicon layer to beginning of array */ - for ( j=numLay; --j >= 0; ) - if (matTyp[ j ] == 1) - break; + /* shift silicon layer to beginning of array */ + for (j = numLay; --j >= 0; ) { + if (matTyp[j] == 1) { + break; + } + } + + if (j < 0) { + (void) fprintf(cp_err, "internal error in %s!\n", __FUNCTION__); + xrc = -1; + goto EXITPOINT; + } - if(j < 0) { - fprintf(stderr, "internal error in %s, bye !\n", __FUNCTION__); - controlled_exit(1); - } siIndex = j; @@ -223,15 +241,26 @@ SUPbinRead(char *inFile, float *x, float *conc, int *impId, int *numNod) /* Store number of valid nodes using pointer */ *numNod = numGrid; - return; -} -void -SUPascRead(char *inFile, float *x, float *conc, int *impId, int *numNod) +EXITPOINT: + if (fpSuprem != (FILE *) NULL) { + if (fclose(fpSuprem) != 0) { + (void) fprintf(cp_err, "Unable to close \"%s\" at exit: %s\n", + inFile, strerror(errno)); + xrc = -1; + } + } + + return xrc; +} /* end of function SUPbinRead */ + + + +int SUPascRead(const char *inFile, float *x, float *conc, int *impId, + int *numNod) { - int idata; + int xrc = 0; int i, j; - float rdata; char cdata[21]; int numLay, numImp, numGrid; int impTyp[4], matTyp[10], topNod[10], siIndex, offset; @@ -245,119 +274,196 @@ SUPascRead(char *inFile, float *x, float *conc, int *impId, int *numNod) conc[i] = 0.0; } - /* Open Input File */ - if ((fpSuprem = fopen( inFile, "r" )) == NULL) { - perror(inFile); - return; - } + /* Open Input File */ + if ((fpSuprem = fopen( inFile, "r" )) == NULL) { + (void) fprintf(cp_err, "Unable to open file \"%s\": %s.\n", + inFile, strerror(errno)); + xrc = -1; + goto EXITPOINT; + } /* * The first line contains the number of layers (I4), the number of * impurities (I4), and the number of nodes (I4) present in the structure. */ - fscanf( fpSuprem, "%d %d %d\n", &numLay, &numImp, &numGrid ); + if (fscanf( fpSuprem, "%d %d %d\n", &numLay, &numImp, &numGrid) != 3) { + (void) fprintf(cp_err, "Unable to read file first line of \"%s\"\n", + inFile); + xrc = -1; + goto EXITPOINT; + } + DEBUG fprintf( stderr, "set 1: %d %d %d\n", numLay, numImp, numGrid); -/* - * The second set of lines contains, for each layer, the material name (A20), - * the material type (I4), the layer thickness (R4), and the pointer to - * the top node of the layer (I4), and an unknown int and unknown float. - * The material type code: - * 1 - Si - * 2 - SiO2 - * 3 - Poly - * 4 - Si3N4 - * 5 - Alum - */ - for ( i=0; i < numLay; i++ ) { - fscanf( fpSuprem, "%s\n %d %e %d %d %e\n", - cdata, &matTyp[i], &layerTh[i], &topNod[i], &idata, &rdata ); - DEBUG fprintf(stderr,"set 2: %s: %d %f %d\n", - cdata, matTyp[i], layerTh[i], topNod[i] ); - } + /* + * The second set of lines contains, for each layer, the material name + * (A20), the material type (I4), the layer thickness (R4), and the + * pointer to the top node of the layer (I4), and an unknown int and + * unknown float. + * + * The material type code: + * 1 - Si + * 2 - SiO2 + * 3 - Poly + * 4 - Si3N4 + * 5 - Alum + */ + for (i = 0; i < numLay; ++i) { + int idata; + float rdata; + if (fscanf(fpSuprem, "%s\n %d %e %d %d %e\n", + cdata, &matTyp[i], &layerTh[i], &topNod[i], + &idata, &rdata) != 6) { + (void) fprintf(cp_err, "Unable to read layer %d " + "from file \"%s\".\n", + i + 1, inFile); + xrc = -1; + goto EXITPOINT; + } -/* - * The third set of lines contains, for each impurity, the name of the - * impurity (A20) and the type of impurity (I4). - */ - for ( i=0; i < numImp; i++ ) { - fscanf( fpSuprem, "%s\n %d\n", cdata, &impTyp[i] ); - DEBUG fprintf(stderr,"set 3: %s: %d\n", cdata, impTyp[i] ); - } + DEBUG fprintf(stderr,"set 2: %s: %d %f %d\n", + cdata, matTyp[i], layerTh[i], topNod[i]); + } /* end of loop over layers */ -/* - * The fourth set of lines contains, for each layer by each impurity, the - * integrated dopant (R4), and the interior concentration of the - * polysilicon grains (R4). - */ - for ( j=0; j < numLay; j++ ) { - for ( i=0; i < numImp; i++ ) { - fscanf( fpSuprem, "%e", &rdata ); - fscanf( fpSuprem, "%e", &rdata ); + /* + * The third set of lines contains, for each impurity, the name of the + * impurity (A20) and the type of impurity (I4). + */ + for (i = 0; i < numImp; ++i) { + if (fscanf( fpSuprem, "%s\n %d\n", cdata, &impTyp[i]) != 2) { + (void) fprintf(cp_err, "Unable to read impurity %d " + "from file \"%s\".\n", + i + 1, inFile); + xrc = -1; + goto EXITPOINT; + } + DEBUG fprintf(stderr,"set 3: %s: %d\n", cdata, impTyp[i]); + } /* end of loop over impurities */ + + /* + * The fourth set of lines contains, for each layer by each impurity, + * the integrated dopant (R4), and the interior concentration of the + * polysilicon grains (R4). + */ + for (j = 0; j < numLay; ++j) { + for (i = 0; i < numImp; ++i) { + float rdata; + if (fscanf(fpSuprem, "%e%e", &rdata, &rdata) != 2) { + (void) fprintf(cp_err, "Unable to read integrated dopant " + "and interior concentration of layer %d and " + "impurity %d from file \"%s\".\n", + j + 1, i + 1, inFile); + xrc = -1; + goto EXITPOINT; + } + } } - } - DEBUG fprintf(stderr,"set 4:\n" ); + DEBUG fprintf(stderr,"set 4:\n" ); -/* - * The fifth set of lines contains, for each node in the structure, - * the distance to the next deepest node (R4), the distance from the - * surface (R4), and, for each impurity type, the impurity's - * chemical concentration (R4) and the impurity's active concentration (R4). - */ - for ( i=1; i <= numGrid; i++ ) { - fscanf( fpSuprem, "%e %e", &rdata, &x[i] ); + /* + * The fifth set of lines contains, for each node in the structure, + * the distance to the next deepest node (R4), the distance from the + * surface (R4), and, for each impurity type, the impurity's + * chemical concentration (R4) and the impurity's active concentration (R4). + */ + for (i = 1; i <= numGrid; ++i) { + float rdata; + if (fscanf(fpSuprem, "%e %e", &rdata, &x[i]) != 2) { + (void) fprintf(cp_err, "Unable to read grid %d " + "from file \"%s\".\n", + i + 1, inFile); + xrc = -1; + goto EXITPOINT; + } - for ( j=0; j < numImp; j++ ) { -/* chemical concentration - not required */ - fscanf( fpSuprem, "%e", &con[i] ); - -/* store active concentration */ - fscanf( fpSuprem, "%e", &con[i] ); + for (j = 0; j < numImp; j++) { + float junk; + /* chemical concentration - not required */ + if (fscanf(fpSuprem, "%e", &junk) != 1) { + (void) fprintf(cp_err, "Unable to chemical concentration " + "%d of layer %d " + "from file \"%s\".\n", + j + 1, i + 1, inFile); + xrc = -1; + goto EXITPOINT; + } -/* orient sign properly */ - if (impTyp[j] == *impId) { -/*...Boron...*/ - if (impTyp[j] == 1) { - conc[i] = - con[i]; - } else { -/*...All Other Impurities: P, As, Sb ...*/ - conc[i] = con[i]; - } - } + /* store active concentration */ + if (fscanf(fpSuprem, "%e", &con[i]) != 1) { + (void) fprintf(cp_err, "Unable to active concentration " + "%d of layer %d " + "from file \"%s\".\n", + j + 1, i + 1, inFile); + xrc = -1; + goto EXITPOINT; + } + + /* orient sign properly */ + if (impTyp[j] == *impId) { + /*...Boron...*/ + if (impTyp[j] == 1) { + conc[i] = - con[i]; + } + else { + /*...All Other Impurities: P, As, Sb ...*/ + conc[i] = con[i]; + } + } + } + } /* end of loop over num grid */ + DEBUG fprintf( stderr, "set 5: %e %e\n", x[1], conc[1] ); + + /* + * The last line in the file contains some random stuff that might be + * useful to some people, the temperature in degrees Kelvin of the last + * diffusion step (R4), the phosphorus implant dose (R4), the arsenic + * implant flag (L4). However, we can just ignore that stuff. + */ + if (fclose(fpSuprem) != 0) { + (void) fprintf(cp_err, "Unable to close file \"%s\": %s.\n", + inFile, strerror(errno)); + xrc = -1; + goto EXITPOINT; } - } - DEBUG fprintf( stderr, "set 5: %e %e\n", x[1], conc[1] ); + fpSuprem = (FILE *) NULL; -/* - * The last line in the file contains some random stuff that might be - * useful to some people, the temperature in degrees Kelvin of the last - * diffusion step (R4), the phosphorus implant dose (R4), the arsenic - * implant flag (L4). However, we can just ignore that stuff. - */ - fclose( fpSuprem ); + /* shift silicon layer to beginning of array */ + for (j = numLay; --j >= 0; ) { + if (matTyp[j] == 1) { + break; + } + } + + if (j < 0) { + (void) fprintf(cp_err, "internal error in %s!\n", __FUNCTION__); + xrc = -1; + goto EXITPOINT; + } + + siIndex = j; + + offset = topNod[siIndex] - 1; + numGrid -= offset; + xStart = x[1 + offset]; + for (i = 1; i <= numGrid; i++) { + x[i] = x[i + offset] - xStart; + conc[i] = conc[i + offset]; + } + + /* Store number of valid nodes using pointer */ + *numNod = numGrid; + +EXITPOINT: + if (fpSuprem != (FILE *) NULL) { + if (fclose(fpSuprem) != 0) { + (void) fprintf(cp_err, "Unable to close \"%s\" at exit: %s\n", + inFile, strerror(errno)); + xrc = -1; + } + } + + return xrc; +} /* end of function SUPascRead */ -/* shift silicon layer to beginning of array */ - for ( j=numLay; --j >= 0; ) - if (matTyp[ j ] == 1) - break; - if(j < 0) { - fprintf(stderr, "internal error in %s, bye !\n", __FUNCTION__); - controlled_exit(1); - } - - siIndex = j; - - offset = topNod[ siIndex ] - 1; - numGrid -= offset; - xStart = x[1 + offset]; - for ( i=1; i <= numGrid; i++ ) { - x[i] = x[i + offset] - xStart; - conc[i] = conc[i + offset]; - } - -/* Store number of valid nodes using pointer */ - *numNod = numGrid; - return; -} diff --git a/src/ciderlib/twod/twodext.h b/src/ciderlib/twod/twodext.h index 6a8330536..c2adf9ee9 100644 --- a/src/ciderlib/twod/twodext.h +++ b/src/ciderlib/twod/twodext.h @@ -153,7 +153,7 @@ extern BOOLEAN TWOdeltaConverged(TWOdevice *); extern BOOLEAN TWOdeviceConverged(TWOdevice *); extern void TWOresetJacobian(TWOdevice *); extern void TWOstoreNeutralGuess(TWOdevice *); -extern void TWOequilSolve(TWOdevice *); +extern int TWOequilSolve(TWOdevice *); extern void TWObiasSolve(TWOdevice *, int, BOOLEAN, TWOtranInfo *); extern void TWOstoreEquilibGuess(TWOdevice *); extern void TWOstoreInitialGuess(TWOdevice *); diff --git a/src/ciderlib/twod/twodopng.c b/src/ciderlib/twod/twodopng.c index 779831123..77d0d4d05 100644 --- a/src/ciderlib/twod/twodopng.c +++ b/src/ciderlib/twod/twodopng.c @@ -98,6 +98,7 @@ TWOdopingValue(DOPprofile *pProfile, DOPtable *pTable, double x, } else { value = pProfile->PEAK_CONC * exp( -argP ); } + break; case EXP: argP = ABS(argP); if ( argP > 80.0 ) { @@ -143,6 +144,7 @@ TWOdopingValue(DOPprofile *pProfile, DOPtable *pTable, double x, } else { value *= exp( -argL ); } + break; case EXP: argL = ABS(argL); if ( argL > 80.0 ) { diff --git a/src/ciderlib/twod/twosolve.c b/src/ciderlib/twod/twosolve.c index 1ea8c7730..7be06a1fe 100644 --- a/src/ciderlib/twod/twosolve.c +++ b/src/ciderlib/twod/twosolve.c @@ -4,21 +4,20 @@ Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group Author: 1991 David A. Gates, U. C. Berkeley CAD Group **********/ +#include "../../maths/misc/norm.h" +#include "ngspice/bool.h" +#include "ngspice/cidersupt.h" +#include "ngspice/cpextern.h" +#include "ngspice/ifsim.h" +#include "ngspice/macros.h" #include "ngspice/ngspice.h" -#include "ngspice/numglobs.h" #include "ngspice/numenum.h" +#include "ngspice/numglobs.h" +#include "ngspice/spmatrix.h" #include "ngspice/twodev.h" #include "ngspice/twomesh.h" -#include "ngspice/spmatrix.h" -#include "ngspice/bool.h" -#include "ngspice/macros.h" #include "twoddefs.h" #include "twodext.h" -#include "ngspice/cidersupt.h" -#include "../../maths/misc/norm.h" - - -#include "ngspice/ifsim.h" extern IFfrontEnd *SPfrontEnd; @@ -96,19 +95,24 @@ TWOdcSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN newSolver, error = spFactor(pDevice->matrix); factorTime += SPfrontEnd->IFseconds() - startTime; if (newSolver) { - if (pDevice->iterationNumber == 1) { - orderTime = factorTime; - } else if (pDevice->iterationNumber == 2) { - orderTime -= factorTime - orderTime; - factorTime -= orderTime; - if (pDevice->poissonOnly) { - pDevice->pStats->orderTime[STAT_SETUP] += orderTime; - } else { - pDevice->pStats->orderTime[STAT_DC] += orderTime; - } - newSolver = FALSE; - } - } + if (pDevice->iterationNumber == 1) { + orderTime = factorTime; + } + else if (pDevice->iterationNumber == 2) { + orderTime -= factorTime - orderTime; + factorTime -= orderTime; + if (pDevice->poissonOnly) { + pDevice->pStats->orderTime[STAT_SETUP] += orderTime; + } + else { + pDevice->pStats->orderTime[STAT_DC] += orderTime; + } + /* After first two iterations, no special handling for a + * new solver */ + newSolver = FALSE; + } /* end of case of iteratin 2 */ + } /* end of special processing for a new solver */ + if (foundError(error)) { if (error == spSINGULAR) { int badRow, badCol; @@ -430,58 +434,69 @@ TWOstoreNeutralGuess(TWOdevice *pDevice) /* computing the equilibrium solution; solution of Poisson's eqn */ /* the solution is used as an initial starting point for bias conditions */ - -void -TWOequilSolve(TWOdevice *pDevice) +int TWOequilSolve(TWOdevice *pDevice) { - BOOLEAN newSolver = FALSE; - int error; - int nIndex, eIndex; - TWOelem *pElem; - TWOnode *pNode; - double startTime, setupTime, miscTime; + BOOLEAN newSolver = FALSE; + int error; + int nIndex, eIndex; + TWOelem *pElem; + TWOnode *pNode; + double startTime, setupTime, miscTime; - setupTime = miscTime = 0.0; + setupTime = miscTime = 0.0; - /* SETUP */ - startTime = SPfrontEnd->IFseconds(); - switch (pDevice->solverType) { - case SLV_SMSIG: - case SLV_BIAS: - /* free up memory allocated for the bias solution */ - FREE(pDevice->dcSolution); - FREE(pDevice->dcDeltaSolution); - FREE(pDevice->copiedSolution); - FREE(pDevice->rhs); - FREE(pDevice->rhsImag); - spDestroy(pDevice->matrix); - case SLV_NONE: - pDevice->poissonOnly = TRUE; - pDevice->numEqns = pDevice->dimEquil - 1; - XCALLOC(pDevice->dcSolution, double, pDevice->dimEquil); - XCALLOC(pDevice->dcDeltaSolution, double, pDevice->dimEquil); - XCALLOC(pDevice->copiedSolution, double, pDevice->dimEquil); - XCALLOC(pDevice->rhs, double, pDevice->dimEquil); - pDevice->matrix = spCreate(pDevice->numEqns, 0, &error); - if (error == spNO_MEMORY) { - printf("TWOequilSolve: Out of Memory\n"); - exit(-1); - } - newSolver = TRUE; - spSetReal(pDevice->matrix); - TWOQjacBuild(pDevice); - pDevice->numOrigEquil = spElementCount(pDevice->matrix); - pDevice->numFillEquil = 0; - case SLV_EQUIL: - pDevice->solverType = SLV_EQUIL; - break; - default: - fprintf(stderr, "Panic: Unknown solver type in equil solution.\n"); - exit(-1); - break; - } - TWOstoreNeutralGuess(pDevice); - setupTime += SPfrontEnd->IFseconds() - startTime; + /* SETUP */ + startTime = SPfrontEnd->IFseconds(); + + /* Set up pDevice to compute the equilibrium solution. If the solver + * is for bias, the arrays must be freed and allocated to the correct + * sizes for an equilibrium solution; if it is a new solver, they are + * only allocated; and if already an equilibrium solve, nothing + * needs to be done */ + /* FALLTHROUGH added to suppress GCC warning due to + * -Wimplicit-fallthrough flag */ + switch (pDevice->solverType) { + case SLV_SMSIG: + case SLV_BIAS: + /* Free memory allocated for the bias solution */ + FREE(pDevice->dcSolution); + FREE(pDevice->dcDeltaSolution); + FREE(pDevice->copiedSolution); + FREE(pDevice->rhs); + FREE(pDevice->rhsImag); + spDestroy(pDevice->matrix); + /* FALLTHROUGH */ + case SLV_NONE: { + /* Allocate memory needed for an equilibrium solution */ + const int n_dim = pDevice->dimEquil; + const int n_eqn = n_dim - 1; + pDevice->poissonOnly = TRUE; + pDevice->numEqns = n_eqn; + XCALLOC(pDevice->dcSolution, double, n_dim); + XCALLOC(pDevice->dcDeltaSolution, double, n_dim); + XCALLOC(pDevice->copiedSolution, double, n_dim); + XCALLOC(pDevice->rhs, double, n_dim); + pDevice->matrix = spCreate(n_eqn, 0, &error); + if (error == spNO_MEMORY) { + (void) fprintf(cp_err, "TWOequilSolve: Out of Memory\n"); + return E_NOMEM; + } + newSolver = TRUE; + spSetReal(pDevice->matrix); /* set to a real matrix */ + TWOQjacBuild(pDevice); + pDevice->numOrigEquil = spElementCount(pDevice->matrix); + pDevice->numFillEquil = 0; + pDevice->solverType = SLV_EQUIL; + break; + } + case SLV_EQUIL: /* Nothing to do if already equilibrium solver */ + break; + default: /* Invalid data */ + fprintf(stderr, "Panic: Unknown solver type in equil solution.\n"); + return E_PANIC; + } /* end of switch over solve type */ + TWOstoreNeutralGuess(pDevice); + setupTime += SPfrontEnd->IFseconds() - startTime; /* SOLVE */ TWOdcSolve(pDevice, MaxIterations, newSolver, FALSE, NULL); @@ -510,6 +525,8 @@ TWOequilSolve(TWOdevice *pDevice) miscTime += SPfrontEnd->IFseconds() - startTime; pDevice->pStats->setupTime[STAT_SETUP] += setupTime; pDevice->pStats->miscTime[STAT_SETUP] += miscTime; + + return 0; } /* compute the solution under an applied bias */ @@ -530,15 +547,20 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis, /* SETUP */ startTime = SPfrontEnd->IFseconds(); - switch (pDevice->solverType) { - case SLV_EQUIL: - /* free up the vectors allocated in the equilibrium solution */ - FREE(pDevice->dcSolution); - FREE(pDevice->dcDeltaSolution); - FREE(pDevice->copiedSolution); - FREE(pDevice->rhs); - spDestroy(pDevice->matrix); + /* Set up for solving for bias */ + /* FALLTHROUGH added to suppress GCC warning due to + * -Wimplicit-fallthrough flag */ + switch (pDevice->solverType) { + case SLV_EQUIL: + /* free up the vectors allocated in the equilibrium solution */ + FREE(pDevice->dcSolution); + FREE(pDevice->dcDeltaSolution); + FREE(pDevice->copiedSolution); + FREE(pDevice->rhs); + spDestroy(pDevice->matrix); + /* FALLTHROUGH */ case SLV_NONE: + /* Set up for bias */ pDevice->poissonOnly = FALSE; pDevice->numEqns = pDevice->dimBias - 1; XCALLOC(pDevice->dcSolution, double, pDevice->dimBias); @@ -562,11 +584,13 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis, pDevice->numOrigBias = spElementCount(pDevice->matrix); pDevice->numFillBias = 0; TWOstoreInitialGuess(pDevice); + /* FALLTHROUGH */ case SLV_SMSIG: spSetReal(pDevice->matrix); - case SLV_BIAS: pDevice->solverType = SLV_BIAS; break; + case SLV_BIAS: + break; default: fprintf(stderr, "Panic: Unknown solver type in bias solution.\n"); exit(-1);