ngspice/src/ciderlib/support/suprmitf.c

357 lines
9.8 KiB
C

/**********
Copyright 1991 Regents of the University of California. All rights reserved.
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
**********/
/*
* Translated FORTRAN subroutine to read the SUPREM-3 binary file
* the data is read and stored in two arrays x and conc
*/
#include "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 DEBUG if (0)
void
SUPbinRead( inFile, x, conc, impId, numNod )
char *inFile;
float *x, *conc;
int *impId, *numNod;
{
int idata, recordMark;
int ldata;
int i, j;
float rdata;
char cdata[21];
int numLay, numImp, numGrid;
int impTyp[4], matTyp[10], topNod[10], siIndex, offset;
float xStart;
float layerTh[10];
float con[500];
FILE *fpSuprem;
/* Clear Concentration Array */
for ( i=0; i < MAXGRID; i++ ) {
conc[i] = 0.0;
}
/* Open Input File */
if (!(fpSuprem = fopen( inFile, "r" ))) {
perror(inFile);
return;
}
/*
* The first record contains the number of layers (I4), the number of
* impurities (I4), and the number of nodes (I4) present in the structure.
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
GFREAD( fpSuprem, &numLay, int, 1 );
GFREAD( fpSuprem, &numImp, int, 1 );
GFREAD( fpSuprem, &numGrid, int, 1 );
DEBUG fprintf(stderr,"rec 1: %d %d %d\n", numLay, numImp, numGrid);
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* The second record contains, for each layer, the material type (I4), the
* layer thickness (R4), and the pointer to the top node of the layer (I4).
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
for ( i=0; i < numLay; i++ ) {
GFREAD( fpSuprem, &matTyp[i], int, 1 );
GFREAD( fpSuprem, &layerTh[i], float, 1 );
GFREAD( fpSuprem, &topNod[i], int, 1 );
DEBUG fprintf(stderr,"rec 2: %d %f %d\n", matTyp[i], layerTh[i], topNod[i] );
}
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* The third record contains, for each layer, the material name (A20).
*/
/* Put a null at the end */
cdata[20] = '\0';
GFREAD( fpSuprem, &recordMark, int, 1 );
for ( i=0; i < numLay; i++ ) {
GFREAD( fpSuprem, cdata, char, 20 );
DEBUG fprintf(stderr,"rec 3: %s\n", cdata );
}
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* The fourth record contains, for each layer, the crystalline orientation
* (I4), and the poly-crystalline grain size in microns (R4).
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
for ( i=0; i < numLay; i++ ) {
GFREAD( fpSuprem, &idata, int, 1 );
GFREAD( fpSuprem, &rdata, float, 1 );
DEBUG fprintf(stderr,"rec 4: %d %f\n", idata, rdata );
}
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* The fifth record contains, for each impurity, the type of impurity (I4).
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
for ( i=0; i < numImp; i++ ) {
GFREAD( fpSuprem, &impTyp[i], int, 1 );
DEBUG fprintf(stderr,"rec 5: %d\n", impTyp[i] );
}
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* The sixth record contains, for each impurity, the impurity name (A20).
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
for ( i=0; i < numImp; i++ ) {
GFREAD( fpSuprem, cdata, char, 20 );
DEBUG fprintf(stderr,"rec 6: %s\n", cdata );
}
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* The seventh record contains, for each layer by each impurity, the
* integrated dopant (R4), and the interior concentration of the
* polysilicon grains (R4).
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
for ( j=0; j < numLay; j++ ) {
for ( i=0; i < numImp; i++ ) {
GFREAD( fpSuprem, &rdata, float, 1 );
DEBUG fprintf(stderr,"rec 7: %e", rdata );
GFREAD( fpSuprem, &rdata, float, 1 );
DEBUG fprintf(stderr," %e\n", rdata );
}
}
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* The eighth record contains, for each node in the structure, the distance
* to the next deepest node (R4).
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
for ( i=0; i < numGrid; i++ ) {
GFREAD( fpSuprem, &rdata, float, 1 );
}
DEBUG fprintf(stderr,"rec 8: %f\n", rdata );
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* The ninth record contains, for each node in the structure, the distance
* from the surface (R4).
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
GFREAD( fpSuprem, &x[1], float, numGrid );
DEBUG fprintf(stderr,"rec 9: %f\n", x[1] );
GFREAD( fpSuprem, &recordMark, int, 1 );
/*
* Next, for each impurity there is a record containing the impurity's
* chemical concentration at each node (R4) and a record containing the
* impurity's active concentration at each node (R4).
*/
for ( j=0; j < numImp; j++ ) {
/* chemical concentration - not required */
GFREAD( fpSuprem, &recordMark, int, 1 );
GFREAD( fpSuprem, &con[1], float, numGrid );
DEBUG fprintf(stderr,"rec 10: %e\n", con[1] );
GFREAD( fpSuprem, &recordMark, int, 1 );
/* store active concentration */
GFREAD( fpSuprem, &recordMark, int, 1 );
GFREAD( fpSuprem, &con[1], float, numGrid );
DEBUG fprintf(stderr,"rec 11: %e\n", con[1] );
GFREAD( fpSuprem, &recordMark, int, 1 );
if (impTyp[j] == *impId) {
/*...Boron...*/
if (impTyp[j] == 1) {
for ( i=1; i <= numGrid; i++ ) conc[i] = - con[i];
} else {
/*...All Other Impurities: P, As, Sb ...*/
for ( i=1; i <= numGrid; i++ ) conc[i] = con[i];
}
}
}
/*
* The last record 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).
*/
GFREAD( fpSuprem, &recordMark, int, 1 );
GFREAD( fpSuprem, &rdata, float, 1 );
DEBUG fprintf(stderr,"rec 12: %f", rdata );
GFREAD( fpSuprem, &rdata, float, 1 );
DEBUG fprintf(stderr," %e", rdata );
GFREAD( fpSuprem, &ldata, int, 1 );
DEBUG fprintf(stderr," %d\n", ldata );
GFREAD( fpSuprem, &recordMark, int, 1 );
fclose( fpSuprem );
/* shift silicon layer to beginning of array */
for ( j=0; j < numLay; j++ ) {
if (matTyp[ j ] == 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;
}
void
SUPascRead( inFile, x, conc, impId, numNod )
char *inFile;
float *x, *conc;
int *impId, *numNod;
{
int idata;
int i, j;
float rdata;
char cdata[21];
int numLay, numImp, numGrid;
int impTyp[4], matTyp[10], topNod[10], siIndex, offset;
float xStart;
float layerTh[10];
float con[500];
FILE *fpSuprem;
/* Clear Concentration Array */
for ( i=0; i < MAXGRID; i++ ) {
conc[i] = 0.0;
}
/* Open Input File */
if (!(fpSuprem = fopen( inFile, "r" ))) {
perror(inFile);
return;
}
/*
* 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 );
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 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] );
}
/*
* 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 );
}
}
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] );
for ( j=0; j < numImp; j++ ) {
/* chemical concentration - not required */
fscanf( fpSuprem, "%e", &con[i] );
/* store active concentration */
fscanf( fpSuprem, "%e", &con[i] );
/* 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];
}
}
}
}
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.
*/
fclose( fpSuprem );
/* shift silicon layer to beginning of array */
for ( j=0; j < numLay; j++ ) {
if (matTyp[ j ] == 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;
}