Beispiel #1
0
int
BJTsAcLoad(GENmodel *inModel, CKTcircuit *ckt)
{

    BJTmodel *model = (BJTmodel*)inModel;
    BJTinstance *here;
    double SaveState[25];
    int    error;
    int    flag;
    double vbeOp;
    double vbcOp;
    double A0;
    double DELA = 0.0;
    double Apert;
    double DELAinv;
    double vte = 0.0;
    double gcpr;
    double gepr;
    double gpi;
    double gmu;
    double go;
    double xgm;
    double td;
    double arg;
    double gm;
    double gx;
    double xcpi;
    double xcmu;
    double xcbx;
    double xccs;
    double xcmcb;
    double cx,icx;
    double cbx,icbx;
    double ccs,iccs;
    double cbc,icbc;
    double cbe,icbe;
    double cce,icce;
    double cb,icb;
    double cbprm,icbprm;
    double cc,icc;
    double ccprm,iccprm;
    double ce,ice;
    double ceprm,iceprm;
    double cs,ics;
    double vcpr,ivcpr;
    double vepr,ivepr;
    double vx,ivx;
    double vbx,ivbx;
    double vcs,ivcs;
    double vbc,ivbc;
    double vbe,ivbe;
    double vce,ivce;
    double cb0,icb0;
    double cbprm0,icbprm0;
    double cc0,icc0;
    double ccprm0,iccprm0;
    double ce0,ice0;
    double ceprm0,iceprm0;
    double cs0,ics0;
    double DvDp = 0.0;
    int iparmno,i;
    SENstruct *info;


#ifdef SENSDEBUG
    printf("BJTsenacload \n");
    printf("BJTsenacload \n");
#endif /* SENSDEBUG */

    info = ckt->CKTsenInfo;
    info->SENstatus = PERTURBATION;

    /*  loop through all the models */
    for( ; model != NULL; model = model->BJTnextModel ) {

        /* loop through all the instances of the model */
        for (here = model->BJTinstances; here != NULL ;
                here=here->BJTnextInstance) {


            /* save the unperturbed values in the state vector */
            for(i=0; i <= 20; i++) {
                *(SaveState + i) = *(ckt->CKTstate0 + here->BJTstate + i);
            }

            vcpr = *(ckt->CKTrhsOld + here->BJTcolNode) 
                - *(ckt->CKTrhsOld + here->BJTcolPrimeNode) ;
            ivcpr = *(ckt->CKTirhsOld + here->BJTcolNode) 
                - *(ckt->CKTirhsOld + here->BJTcolPrimeNode) ;
            vepr = *(ckt->CKTrhsOld + here->BJTemitNode) 
                - *(ckt->CKTrhsOld + here->BJTemitPrimeNode) ;
            ivepr = *(ckt->CKTirhsOld + here->BJTemitNode) 
                - *(ckt->CKTirhsOld + here->BJTemitPrimeNode) ;
            vx = *(ckt->CKTrhsOld + here->BJTbaseNode) 
                - *(ckt->CKTrhsOld + here->BJTbasePrimeNode) ;/* vb_bprm */
            ivx = *(ckt->CKTirhsOld + here->BJTbaseNode)
                - *(ckt->CKTirhsOld + here->BJTbasePrimeNode) ;/* ivb_bprm */
            vcs = *(ckt->CKTrhsOld + here->BJTcolPrimeNode) 
                - *(ckt->CKTrhsOld + here->BJTsubstNode) ;
            ivcs = *(ckt->CKTirhsOld + here->BJTcolPrimeNode) 
                - *(ckt->CKTirhsOld + here->BJTsubstNode) ;
            vbc = *(ckt->CKTrhsOld + here->BJTbasePrimeNode) 
                - *(ckt->CKTrhsOld + here->BJTcolPrimeNode) ;/* vbprm_cprm */
            ivbc = *(ckt->CKTirhsOld + here->BJTbasePrimeNode)
                - *(ckt->CKTirhsOld + here->BJTcolPrimeNode) ;/* ivbprm_cprm */
            vbe = *(ckt->CKTrhsOld + here->BJTbasePrimeNode) 
                - *(ckt->CKTrhsOld + here->BJTemitPrimeNode) ;/* vbprm_eprm */
            ivbe = *(ckt->CKTirhsOld + here->BJTbasePrimeNode)
                - *(ckt->CKTirhsOld + here->BJTemitPrimeNode) ;/* ivbprm_eprm */
            vce = vbe - vbc ;
            ivce = ivbe - ivbc ;
            vbx = vx + vbc ;
            ivbx = ivx + ivbc ;



            vbeOp =model->BJTtype * ( *(ckt->CKTrhsOp +  here->BJTbasePrimeNode)
                -  *(ckt->CKTrhsOp +  here->BJTemitPrimeNode));
            vbcOp =model->BJTtype * ( *(ckt->CKTrhsOp +  here->BJTbasePrimeNode)
                -  *(ckt->CKTrhsOp +  here->BJTcolPrimeNode));

#ifdef SENSDEBUG
            printf("\n without perturbation\n");
#endif /* SENSDEBUG */
            /* without perturbation */
            A0 = here->BJTarea;
            here->BJTsenPertFlag = ON;
            *(ckt->CKTstate0 + here->BJTvbe) = vbeOp;
            *(ckt->CKTstate0 + here->BJTvbc) = vbcOp;
            /* info->SENacpertflag == 1 only for first frequency */

            if(info->SENacpertflag == 1){

                /* store the  unperturbed values of small signal parameters */

	      if ((error = BJTload((GENmodel*)model,ckt)))
		     return(error);

                *(here->BJTsenGpi)= *(ckt->CKTstate0 + here->BJTgpi);
                *(here->BJTsenGmu)= *(ckt->CKTstate0 + here->BJTgmu);
                *(here->BJTsenGm)= *(ckt->CKTstate0 + here->BJTgm);
                *(here->BJTsenGo)= *(ckt->CKTstate0 + here->BJTgo);
                *(here->BJTsenGx)= *(ckt->CKTstate0 + here->BJTgx);
                *(here->BJTsenCpi)= *(ckt->CKTstate0 + here->BJTcqbe);
                *(here->BJTsenCmu)= *(ckt->CKTstate0 + here->BJTcqbc);
                *(here->BJTsenCbx)= *(ckt->CKTstate0 + here->BJTcqbx);
                *(here->BJTsenCcs)= *(ckt->CKTstate0 + here->BJTcqcs);
                *(here->BJTsenCmcb)= *(ckt->CKTstate0 + here->BJTcexbc);
            }
            gcpr = model->BJTcollectorConduct * A0;
            gepr = model->BJTemitterConduct * A0;
            gpi= *(here->BJTsenGpi);
            gmu= *(here->BJTsenGmu);
            gm= *(here->BJTsenGm);
            go= *(here->BJTsenGo);
            gx= *(here->BJTsenGx);
            xgm=0;
            td=model->BJTexcessPhase;
            if(td != 0) {
                arg = td*ckt->CKTomega;
                gm = gm+go;
                xgm = -gm * sin(arg);
                gm = gm * cos(arg)-go;
            }
            xcpi= *(here->BJTsenCpi) * ckt->CKTomega;
            xcmu= *(here->BJTsenCmu) * ckt->CKTomega;
            xcbx= *(here->BJTsenCbx) * ckt->CKTomega;
            xccs= *(here->BJTsenCcs) * ckt->CKTomega;
            xcmcb= *(here->BJTsenCmcb) * ckt->CKTomega;


            cx=gx * vx ;
            icx=gx * ivx;
            cbx=( -xcbx * ivbx) ;
            icbx= xcbx * vbx ;
            ccs=( -xccs * ivcs) ;
            iccs= xccs * vcs ;
            cbc=(gmu * vbc -xcmu * ivbc) ;
            icbc=xcmu * vbc +  gmu * ivbc ;
            cbe=gpi * vbe -xcpi * ivbe - xcmcb * ivbc ;
            icbe=xcpi * vbe +  gpi * ivbe + xcmcb * vbc;
            cce= go * vce + gm * vbe - xgm * ivbe;
            icce=go * ivce + gm * ivbe + xgm * vbe ;

            cc0=gcpr * vcpr ;
            icc0=gcpr * ivcpr ;
            ce0=gepr * vepr;
            ice0=gepr * ivepr ;
            cb0 = cx + cbx;
            icb0 = icx + icbx;
            if(here->BJTbaseNode != here->BJTbasePrimeNode){
                cbprm0 = (- cx + cbe + cbc);
                icbprm0 = (- icx + icbe + icbc);
            }
            else{
                cbprm0 = ( cbx + cbe + cbc);
                icbprm0 = (icbx + icbe + icbc);
            }
            ccprm0 = (- cbx - cc0 + ccs + cce - cbc);
            iccprm0 = (- icbx - icc0 + iccs + icce - icbc);
            ceprm0 = (- cbe - cce - ce0);
            iceprm0 = (- icbe - icce - ice0);
            cs0 = (- ccs) ;
            ics0 = (- iccs) ;

#ifdef SENSDEBUG
            printf("gepr0 = %.7e , gcpr0 = %.7e , gmu0 = %.7e, gpi0 = %.7e\n",
                    gepr,gcpr,gmu,gpi);
            printf("gm0 = %.7e , go0 = %.7e , gx0 = %.7e, xcpi0 = %.7e\n",
                    gm,go,gx,xcpi);
            printf("xcmu0 = %.7e , xcbx0 = %.7e , xccs0 = %.7e, xcmcb0 = %.7e\n"
                    ,xcmu,xcbx,xccs,xcmcb);
            printf("vepr = %.7e + j%.7e , vcpr = %.7e + j%.7e\n",
                    vepr,ivepr,vcpr,ivcpr);
            printf("vbx = %.7e + j%.7e , vx = %.7e + j%.7e\n",
                    vbx,ivbx,vx,ivx);
            printf("vbc = %.7e + j%.7e , vbe = %.7e + j%.7e\n",
                    vbc,ivbc,vbe,ivbe);
            printf("vce = %.7e + j%.7e , vcs = %.7e + j%.7e\n",
                    vce,ivce,vcs,ivcs);
            printf("cce0 = %.7e + j%.7e , cbe0 = %.7e + j%.7e\n",
                    cce,icce,cbe,icbe);
            printf("cbc0 = %.7e + j%.7e\n",
                    cbc,icbc);
            printf("cc0 = %.7e + j%.7e , ce0 = %.7e + j%.7e\n",
                    cc0,icc0,ce0,ice0);
            printf("cb0 = %.7e + j%.7e , cs0 = %.7e + j%.7e\n",
                    cb0,icb0,cs0,ics0);
            printf("cbprm0 = %.7e + j%.7e , ceprm0 = %.7e + j%.7e\n",
                    cbprm0,icbprm0,ceprm0,iceprm0);
            printf("ccprm0 = %.7e + j%.7e \n",
                    ccprm0,iccprm0);
            printf("\nPerturbation of Area\n");
#endif /* SENSDEBUG */
            /* Perturbation of Area */
            if(here->BJTsenParmNo == 0){
                flag = 0;
                goto next1;
            }

            DELA = info->SENpertfac * A0;
            Apert = A0 + DELA;
            DELAinv = 1.0/DELA;
            here->BJTarea = Apert;

            *(ckt->CKTstate0 + here->BJTvbe) = vbeOp;
            *(ckt->CKTstate0 + here->BJTvbc) = vbcOp;
            if(info->SENacpertflag == 1){

                /* store the  small signal parameters 
                 * corresponding to perturbed area 
                 */
                if ((error = BJTload((GENmodel*)model,ckt)))
		  return(error);

                *(here->BJTsenGpi + 1)= *(ckt->CKTstate0 + here->BJTgpi);
                *(here->BJTsenGmu + 1)= *(ckt->CKTstate0 + here->BJTgmu);
                *(here->BJTsenGm + 1)= *(ckt->CKTstate0 + here->BJTgm);
                *(here->BJTsenGo + 1)= *(ckt->CKTstate0 + here->BJTgo);
                *(here->BJTsenGx + 1)= *(ckt->CKTstate0 + here->BJTgx);
                *(here->BJTsenCpi + 1)= *(ckt->CKTstate0 + here->BJTcqbe);
                *(here->BJTsenCmu + 1)= *(ckt->CKTstate0 + here->BJTcqbc);
                *(here->BJTsenCbx + 1)= *(ckt->CKTstate0 + here->BJTcqbx);
                *(here->BJTsenCcs + 1)= *(ckt->CKTstate0 + here->BJTcqcs);
                *(here->BJTsenCmcb + 1)= *(ckt->CKTstate0 + here->BJTcexbc);
            }


            flag = 0;
            goto load;



pertvbx:    /* Perturbation of vbx */
#ifdef SENSDEBUG
            printf("\nPerturbation of vbx\n");
#endif /* SENSDEBUG */
            here->BJTarea = A0;
            A0 = model->BJTtype * (*(ckt->CKTrhsOp + here->BJTbaseNode)
                - *(ckt->CKTrhsOp + here->BJTcolPrimeNode));
            DELA = info->SENpertfac * A0 + 1e-8; 
            Apert = A0 + DELA;
            DELAinv = model->BJTtype * 1.0/DELA;
            *(ckt->CKTrhsOp + here->BJTbaseNode) += DELA;
            *(ckt->CKTstate0 + here->BJTvbe) = vbeOp;
            *(ckt->CKTstate0 + here->BJTvbc) = vbcOp;

            if(info->SENacpertflag == 1){

                /* store the  small signal parameters 
                 * corresponding to perturbed vbx 
                 */
                if ((error = BJTload((GENmodel*)model,ckt)))
		  return(error);

                *(here->BJTsenGpi + 2)= *(ckt->CKTstate0 + here->BJTgpi);
                *(here->BJTsenGmu + 2)= *(ckt->CKTstate0 + here->BJTgmu);
                *(here->BJTsenGm + 2)= *(ckt->CKTstate0 + here->BJTgm);
                *(here->BJTsenGo + 2)= *(ckt->CKTstate0 + here->BJTgo);
                *(here->BJTsenGx + 2)= *(ckt->CKTstate0 + here->BJTgx);
                *(here->BJTsenCpi + 2)= *(ckt->CKTstate0 + here->BJTcqbe);
                *(here->BJTsenCmu + 2)= *(ckt->CKTstate0 + here->BJTcqbc);
                *(here->BJTsenCbx + 2)= *(ckt->CKTstate0 + here->BJTcqbx);
                *(here->BJTsenCcs + 2)= *(ckt->CKTstate0 + here->BJTcqcs);
                *(here->BJTsenCmcb + 2)= *(ckt->CKTstate0 + here->BJTcexbc);
            }


            flag = 1;
            goto load;


pertvbe:    /* Perturbation of vbe */
#ifdef SENSDEBUG
            printf("\nPerturbation of vbe\n");
#endif /* SENSDEBUG */
            if (*(here->BJTsenCbx) != 0){ 
                *(ckt->CKTrhsOp + here ->BJTbaseNode) -= DELA;
            }
            vte=model->BJTleakBEemissionCoeff*CONSTvt0;
            A0 = vbeOp;
            DELA = info->SENpertfac * vte ;
            Apert = A0 + DELA;
            DELAinv = 1.0/DELA;
            *(ckt->CKTstate0 + here->BJTvbe) = Apert;
            *(ckt->CKTstate0 + here->BJTvbc) = vbcOp;

            if(info->SENacpertflag == 1){

                /* store the  small signal parameters 
                 * corresponding to perturbed vbe 
                 */
                if ((error = BJTload((GENmodel*)model,ckt)))
		  return(error);

                *(here->BJTsenGpi + 3)= *(ckt->CKTstate0 + here->BJTgpi);
                *(here->BJTsenGmu + 3)= *(ckt->CKTstate0 + here->BJTgmu);
                *(here->BJTsenGm + 3)= *(ckt->CKTstate0 + here->BJTgm);
                *(here->BJTsenGo + 3)= *(ckt->CKTstate0 + here->BJTgo);
                *(here->BJTsenGx + 3)= *(ckt->CKTstate0 + here->BJTgx);
                *(here->BJTsenCpi + 3)= *(ckt->CKTstate0 + here->BJTcqbe);
                *(here->BJTsenCmu + 3)= *(ckt->CKTstate0 + here->BJTcqbc);
                *(here->BJTsenCbx + 3)= *(ckt->CKTstate0 + here->BJTcqbx);
                *(here->BJTsenCcs + 3)= *(ckt->CKTstate0 + here->BJTcqcs);
                *(here->BJTsenCmcb + 3)= *(ckt->CKTstate0 + here->BJTcexbc);
            }


            flag = 2;
            goto load;


pertvbc:    /* Perturbation of vbc */
#ifdef SENSDEBUG
            printf("\nPerturbation of vbc\n");
#endif /* SENSDEBUG */
            *(ckt->CKTstate0 + here->BJTvbe) = A0;

            A0 = vbcOp;
            DELA = info->SENpertfac * vte ;
            Apert = A0 + DELA;
            DELAinv = 1.0/DELA;


            *(ckt->CKTstate0 + here->BJTvbc) = Apert;

            *(ckt->CKTstate0 + here->BJTvbe) = vbeOp;



            if(info->SENacpertflag == 1){

                /* store the  small signal parameters 
                 * corresponding to perturbed vbc 
                 */
                if ((error = BJTload((GENmodel*)model,ckt)))
		  return(error);
                *(here->BJTsenGpi + 4)= *(ckt->CKTstate0 + here->BJTgpi);
                *(here->BJTsenGmu + 4)= *(ckt->CKTstate0 + here->BJTgmu);
                *(here->BJTsenGm + 4)= *(ckt->CKTstate0 + here->BJTgm);
                *(here->BJTsenGo + 4)= *(ckt->CKTstate0 + here->BJTgo);
                *(here->BJTsenGx + 4)= *(ckt->CKTstate0 + here->BJTgx);
                *(here->BJTsenCpi + 4)= *(ckt->CKTstate0 + here->BJTcqbe);
                *(here->BJTsenCmu + 4)= *(ckt->CKTstate0 + here->BJTcqbc);
                *(here->BJTsenCbx + 4)= *(ckt->CKTstate0 + here->BJTcqbx);
                *(here->BJTsenCcs + 4)= *(ckt->CKTstate0 + here->BJTcqcs);
                *(here->BJTsenCmcb + 4)= *(ckt->CKTstate0 + here->BJTcexbc);

            }


            flag = 3;
            goto load;



pertvcs:    /* Perturbation of vcs */
#ifdef SENSDEBUG
            printf("\nPerturbation of vcs\n");
#endif /* SENSDEBUG */
            *(ckt->CKTstate0 + here->BJTvbc) = A0;
            A0 = model->BJTtype * (*(ckt->CKTrhsOp + here->BJTsubstNode)
                -  *(ckt->CKTrhsOp + here->BJTcolPrimeNode));
            DELA = info->SENpertfac * A0 + 1e-8; 
            Apert = A0 + DELA;
            DELAinv = model->BJTtype * 1.0/DELA;
            *(ckt->CKTrhsOp + here->BJTsubstNode) += DELA;
            *(ckt->CKTstate0 + here->BJTvbe) = vbeOp;
            *(ckt->CKTstate0 + here->BJTvbc) = vbcOp;

            if(info->SENacpertflag == 1){

                /* store the  small signal parameters 
                 * corresponding to perturbed vcs 
                 */
                if ((error = BJTload((GENmodel*)model,ckt)))
		  return(error);
                *(here->BJTsenCcs + 5)= *(ckt->CKTstate0 + here->BJTcqcs);

            }


            flag = 4;

            *(ckt->CKTrhsOp + here->BJTsubstNode) -= DELA;
            xccs= *(here->BJTsenCcs + 5) * ckt->CKTomega;

            ccs=( -xccs * ivcs) ;
            iccs= xccs * vcs ;
            cs = -ccs;
            ics = -iccs;
            ccprm = ccprm0 +  cs0 - cs;
            iccprm = iccprm0 + ics0 - ics;
            cbprm = cbprm0;
            icbprm = icbprm0;
            ceprm = ceprm0;
            iceprm = iceprm0;
            cc = cc0;
            icc = icc0;
            ce = ce0;
            ice = ice0;
            cb = cb0;
            icb = icb0;
            goto next2;

load:
            gcpr=model->BJTcollectorConduct * here->BJTarea;
            gepr=model->BJTemitterConduct * here->BJTarea;
            gpi= *(here->BJTsenGpi + flag+1);
            gmu= *(here->BJTsenGmu + flag+1);
            gm= *(here->BJTsenGm + flag+1);
            go= *(here->BJTsenGo + flag+1);
            gx= *(here->BJTsenGx + flag+1);
            xgm=0;
            td=model->BJTexcessPhase;
            if(td != 0) {
                arg = td*ckt->CKTomega;
                gm = gm+go;
                xgm = -gm * sin(arg);
                gm = gm * cos(arg)-go;
            }
            xcpi= *(here->BJTsenCpi + flag+1) * ckt->CKTomega;
            xcmu= *(here->BJTsenCmu + flag+1) * ckt->CKTomega;
            xcbx= *(here->BJTsenCbx + flag+1) * ckt->CKTomega;
            xccs= *(here->BJTsenCcs + flag+1) * ckt->CKTomega;
            xcmcb= *(here->BJTsenCmcb + flag+1) * ckt->CKTomega;


            cc=gcpr * vcpr ;
            icc=gcpr * ivcpr ;
            ce=gepr * vepr;
            ice=gepr * ivepr ;
            cx=gx * vx ;
            icx=gx * ivx;
            cbx=( -xcbx * ivbx) ;
            icbx= xcbx * vbx ;
            ccs=( -xccs * ivcs) ;
            iccs= xccs * vcs ;
            cbc=(gmu * vbc -xcmu * ivbc) ;
            icbc=xcmu * vbc +  gmu * ivbc ;
            cbe=gpi * vbe -xcpi * ivbe - xcmcb * ivbc ;
            icbe=xcpi * vbe +  gpi * ivbe + xcmcb * vbc;
            cce= go * vce + gm * vbe - xgm * ivbe;
            icce=go * ivce + gm * ivbe + xgm * vbe ;


            cb= cx + cbx;
            icb= icx + icbx;
            if(here->BJTbaseNode != here->BJTbasePrimeNode){
                cbprm=(- cx + cbe + cbc);
                icbprm=(- icx + icbe + icbc);
            }
            else{
                cbprm=( cbx + cbe + cbc);
                icbprm=(icbx + icbe + icbc);
            }
            ccprm=(- cbx - cc + ccs + cce - cbc);
            iccprm=(- icbx - icc + iccs + icce - icbc);
            ceprm=(- cbe - cce - ce);
            iceprm=(- icbe - icce - ice);
            cs= (- ccs) ;
            ics= (- iccs) ;

#ifdef SENSDEBUG
            printf("A0 = %.7e , Apert = %.7e , DELA = %.7e\n"
                    ,A0,Apert,DELA);
            printf("gepr = %.7e , gcpr = %.7e , gmu = %.7e, gpi = %.7e\n"
                    ,gepr,gcpr,gmu,gpi);
            printf("gm = %.7e , go = %.7e , gx = %.7e, xcpi = %.7e\n"
                    ,gm,go,gx,xcpi);
            printf("xcmu = %.7e , xcbx = %.7e , xccs = %.7e, xcmcb = %.7e\n"
                    ,xcmu,xcbx,xccs,xcmcb);

            printf("cx = %.7e + j%.7e , cbx = %.7e + j%.7e\n"
                    ,cx,icx,cbx,icbx);
            printf("ccs %.7e + j%.7e , cbc = %.7e + j%.7e"
                    ,ccs,iccs,cbc,icbc);
            printf("cbe %.7e + j%.7e , cce = %.7e + j%.7e\n"
                    ,cbe,icbe,cce,icce);

            printf("cc = %.7e + j%.7e , ce = %.7e + j%.7e,",
                    ,cc,icc,ce,ice);
            printf("ccprm = %.7e + j%.7e , ceprm = %.7e + j%.7e",
                    ccprm,iccprm,ceprm,iceprm);
            printf("cb = %.7e + j%.7e , cbprm = %.7e + j%.7e , ",
                    cb,icb,cbprm,icbprm)
            printf("cs = %.7e + j%.7e\n",
                    cs,ics);
#endif /* SENSDEBUG */


            /* load the RHS matrix */
next2:
            for(iparmno = 1;iparmno<=info->SENparms;iparmno++){
                if( (!flag) && (iparmno != here->BJTsenParmNo) ) continue;
                switch(flag){

                case 0: 
                    /* area : so no DC sensitivity term involved */
                    DvDp = 1.0; 

                    break;
                    /* calculate the DC sensitivities of operating points */
                case 1: 
                    DvDp = model->BJTtype * 
                            (info->SEN_Sap[here->BJTbaseNode][iparmno]
                            -  info->SEN_Sap[here->BJTcolPrimeNode][iparmno]);
                    break;
                case 2: 
                    DvDp = model->BJTtype * 
                            (info->SEN_Sap[here->BJTbasePrimeNode][iparmno]
                            -  info->SEN_Sap[here->BJTemitPrimeNode][iparmno]);
                    break;
                case 3: 
                    DvDp = model->BJTtype * 
                            (info->SEN_Sap[here->BJTbasePrimeNode][iparmno]
                            -  info->SEN_Sap[here->BJTcolPrimeNode][iparmno]);
                    break;
                case 4: 
                    DvDp = model->BJTtype * 
                            (info->SEN_Sap[here->BJTsubstNode][iparmno]
                            -  info->SEN_Sap[here->BJTcolPrimeNode][iparmno]);
                    break;
                }
#ifdef SENSDEBUG
                printf("before loading\n");  
                printf("BJTtype = %d\n",model->BJTtype);  
                printf("DvDp = %.7e , flag = %d , iparmno = %d,senparmno = %d\n"
                        ,DvDp,flag,iparmno,here->BJTsenParmNo);
                printf("senb = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTbaseNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTbaseNode] + iparmno));
                printf("senbrm = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTbasePrimeNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTbasePrimeNode] + iparmno));
                printf("senc = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTcolNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTcolNode] + iparmno));
                printf("sencprm = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTcolPrimeNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTcolPrimeNode] + iparmno));
                printf("sene = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTemitNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTemitNode] + iparmno));
                printf("seneprm = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTemitPrimeNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTemitPrimeNode] + iparmno));
                printf("sens = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTsubstNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTsubstNode] + iparmno));
#endif /* SENSDEBUG */


                if(here->BJTbaseNode != here->BJTbasePrimeNode){
                    *(info->SEN_RHS[here->BJTbaseNode] + iparmno) -=  
                            ( cb  - cb0) * DELAinv * DvDp;
                    *(info->SEN_iRHS[here->BJTbaseNode] + iparmno) -=  
                            ( icb  - icb0) * DELAinv * DvDp;
                }

                *(info->SEN_RHS[here->BJTbasePrimeNode] + iparmno) -=  
                        ( cbprm  - cbprm0) * DELAinv * DvDp;
                *(info->SEN_iRHS[here->BJTbasePrimeNode] + iparmno) -=  
                        ( icbprm  - icbprm0) * DELAinv * DvDp;

                if(here->BJTcolNode != here->BJTcolPrimeNode){
                    *(info->SEN_RHS[here->BJTcolNode] + iparmno) -=  
                            ( cc  - cc0) * DELAinv * DvDp;
                    *(info->SEN_iRHS[here->BJTcolNode] + iparmno) -=  
                            ( icc  - icc0) * DELAinv * DvDp;
                }

                *(info->SEN_RHS[here->BJTcolPrimeNode] + iparmno) -=  
                        ( ccprm  - ccprm0) * DELAinv * DvDp;
                *(info->SEN_iRHS[here->BJTcolPrimeNode] + iparmno) -=  
                        ( iccprm  - iccprm0) * DELAinv * DvDp;

                if(here->BJTemitNode != here->BJTemitPrimeNode){
                    *(info->SEN_RHS[here->BJTemitNode] + iparmno) -= 
                            ( ce  - ce0) * DELAinv * DvDp;
                    *(info->SEN_iRHS[here->BJTemitNode] + iparmno) -= 
                            ( ice  - ice0) * DELAinv * DvDp;
                }

                *(info->SEN_RHS[here->BJTemitPrimeNode] + iparmno) -= 
                        ( ceprm  - ceprm0) * DELAinv * DvDp;
                *(info->SEN_iRHS[here->BJTemitPrimeNode] + iparmno) -= 
                        ( iceprm  - iceprm0) * DELAinv * DvDp;
                *(info->SEN_RHS[here->BJTsubstNode] + iparmno) -=  
                        ( cs  - cs0) * DELAinv * DvDp;
                *(info->SEN_iRHS[here->BJTsubstNode] + iparmno) -=  
                        ( ics  - ics0) * DELAinv * DvDp;
#ifdef SENSDEBUG
                printf("after loading\n");                  

                printf("senb = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTbaseNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTbaseNode] + iparmno));
                printf("senbrm = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTbasePrimeNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTbasePrimeNode] + iparmno));
                printf("senc = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTcolNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTcolNode] + iparmno));
                printf("sencprm = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTcolPrimeNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTcolPrimeNode] + iparmno));
                printf("sene = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTemitNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTemitNode] + iparmno));
                printf("seneprm = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTemitPrimeNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTemitPrimeNode] + iparmno));
                printf("sens = %.7e + j%.7e\n "
                        ,*(info->SEN_RHS[here->BJTsubstNode] + iparmno),
                        *(info->SEN_iRHS[here->BJTsubstNode] + iparmno));
#endif /* SENSDEBUG */

            }


next1:          
            switch(flag){
            case 0: 
                if (*(here->BJTsenCbx) == 0){ 
                    here->BJTarea = A0;
                    goto pertvbe ;
                }
                else{
                    goto pertvbx;
                }
            case 1: 
                goto pertvbe ; 
            case 2: 
                goto pertvbc ;
            case 3: 
                goto pertvcs ;
            case 4: 
                break; 
            }

            /* put the unperturbed values back into the state vector */
            for(i=0; i <= 20; i++) {
                *(ckt->CKTstate0 + here->BJTstate + i) = *(SaveState + i);
            }
            here->BJTsenPertFlag = OFF;
        }

    }
    info->SENstatus = NORMAL;
#ifdef SENSDEBUG
    printf("BJTsenacload end\n");
#endif /* SENSDEBUG */
    return(OK);
}
Beispiel #2
0
int
BJTsLoad(GENmodel *inModel, CKTcircuit *ckt)
{
    BJTmodel *model = (BJTmodel*)inModel;
    BJTinstance *here;
    double   SaveState0[27];
    int    i;
    int    iparmno;
    int    error;
    double A0;
    double DELA;
    double Apert;
    double DELAinv;
    double cb0;
    double cb;
    double cc0;
    double cc;
    double cx0;
    double ccpr0;
    double cepr0;
    double DcbDp;
    double DccDp;
    double DceDp;
    double DccprDp;
    double DceprDp;
    double DcxDp;
    double DbprmDp;
    double DcprmDp;
    double DeprmDp;
    double gx;
    double gx0;
    double tag0;
    double tag1;
    double qbe0;
    double qbe;
    double qbc0;
    double qbc;
    double qcs0;
    double qcs;
    double qbx0;
    double qbx;
    double DqbeDp = 0.0;
    double DqbcDp = 0.0;
    double DqcsDp = 0.0;
    double DqbxDp = 0.0;
    double Osxpbe;
    double Osxpbc;
    double Osxpcs;
    double Osxpbx;
    SENstruct *info;

    tag0 = ckt->CKTag[0];
    tag1 = ckt->CKTag[1];
    if(ckt->CKTorder == 1){
        tag1 = 0;
    }
#ifdef SENSDEBUG
    printf("BJTsenload \n");
    printf("CKTtime = %.5e\n",ckt->CKTtime);
    printf("CKTorder = %.5e\n",ckt->CKTorder);
    printf("tag0=%.7e,tag1=%.7e\n",tag0,tag1);
#endif /* SENSDEBUG */
    info = ckt->CKTsenInfo;

    info->SENstatus = PERTURBATION;

    /*  loop through all the models */
    for( ; model != NULL; model = model->BJTnextModel ) {

        /* loop through all the instances of the model */
        for (here = model->BJTinstances; here != NULL ;
                here=here->BJTnextInstance) {

#ifdef SENSDEBUG
            printf("base = %d , baseprm = %d ,col = %d, colprm = %d\n",
                    here->BJTbaseNode ,here->BJTbasePrimeNode,
                    here->BJTcolNode,here->BJTcolPrimeNode);
            printf("emit = %d , emitprm = %d ,subst = %d, senparmno = %d\n",
                    here->BJTemitNode ,here->BJTemitPrimeNode,
                    here->BJTsubstNode,here->BJTsenParmNo);
#endif /* SENSDEBUG */


            /* save the unperturbed values in the state vector */
            for(i=0; i <= 20; i++){
                *(SaveState0 + i) = *(ckt->CKTstate0 + here->BJTstate + i);
            }
            *(SaveState0 + 21) = *(ckt->CKTstate1 + here->BJTcexbc);
            *(SaveState0 + 22) = *(ckt->CKTstate2 + here->BJTcexbc);
            *(SaveState0 + 23) = here->BJTcapbe;
            *(SaveState0 + 24) = here->BJTcapbc;
            *(SaveState0 + 25) = here->BJTcapsub;
            *(SaveState0 + 26) = here->BJTcapbx;

            if(here->BJTsenParmNo == 0) goto next;

            cx0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
            ccpr0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
            cepr0 = -cx0 - ccpr0;

            here->BJTsenPertFlag = ON;
            error =  BJTload((GENmodel*)model,ckt);
            if(error) return(error);

            cb0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
            cc0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
            gx0 = *(ckt->CKTstate0 + here->BJTgx);

            qbe0 = *(ckt->CKTstate0 + here->BJTqbe);
            qbc0 = *(ckt->CKTstate0 + here->BJTqbc);
            qcs0 = *(ckt->CKTstate0 + here->BJTqsub);
            qbx0 = *(ckt->CKTstate0 + here->BJTqbx);

            /* perturbation of area */

            A0 = here->BJTarea;
            DELA = info->SENpertfac * A0;
            Apert = A0 + DELA;
            DELAinv = 1.0/DELA;
            here->BJTsenPertFlag = ON;
            here->BJTarea = Apert;
            error =  BJTload((GENmodel*)model,ckt);
            if(error) return(error);
            here->BJTarea = A0;
            here->BJTsenPertFlag = OFF;


            cb = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
            cc = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
            gx = *(ckt->CKTstate0 + here->BJTgx);

            qbe = *(ckt->CKTstate0 + here->BJTqbe);
            qbc = *(ckt->CKTstate0 + here->BJTqbc);
            qcs = *(ckt->CKTstate0 + here->BJTqsub);
            qbx = *(ckt->CKTstate0 + here->BJTqbx);

            /* compute the gradients of currents */
            DcbDp = (cb - cb0) * DELAinv;
            DccDp = (cc - cc0) * DELAinv;
            DceDp = DcbDp + DccDp;

            DccprDp  = 0;
            DceprDp  = 0;
            DcxDp  = 0;
            if(here->BJTcolNode != here->BJTcolPrimeNode)
                DccprDp = ccpr0 * info->SENpertfac * DELAinv;
            if(here->BJTemitNode != here->BJTemitPrimeNode)
                DceprDp = cepr0 * info->SENpertfac * DELAinv;
            if(here->BJTbaseNode != here->BJTbasePrimeNode){
                if(gx0) DcxDp =  cx0 * DELAinv * (gx-gx0)/gx0;
            }
            DbprmDp = DcbDp - DcxDp;
            DcprmDp = DccDp - DccprDp;
            DeprmDp = - DceDp  - DceprDp;

            DqbeDp = (qbe - qbe0)*DELAinv;
            DqbcDp = (qbc - qbc0)*DELAinv;
            DqcsDp = (qcs - qcs0)*DELAinv;
            DqbxDp = (qbx - qbx0)*DELAinv;

            *(here->BJTdphibedp) = DqbeDp;
            *(here->BJTdphibcdp) = DqbcDp;
            *(here->BJTdphisubdp) = DqcsDp;
            *(here->BJTdphibxdp) = DqbxDp;

#ifdef SENSDEBUG
            printf("cb0 = %.7e ,cb = %.7e,\n",cb0,cb); 
            printf("cc0 = %.7e ,cc = %.7e,\n",cc0,cc); 
            printf("ccpr0 = %.7e \n",ccpr0); 
            printf("cepr0 = %.7e \n",cepr0); 
            printf("cx0 = %.7e \n",cx0); 
            printf("qbe0 = %.7e ,qbe = %.7e,\n",qbe0,qbe); 
            printf("qbc0 = %.7e ,qbc = %.7e,\n",qbc0,qbc); 
            printf("qcs0 = %.7e ,qcs = %.7e,\n",qcs0,qcs); 
            printf("qbx0 = %.7e ,qbx = %.7e,\n",qbx0,qbx); 
            printf("\n");

#endif /* SENSDEBUG */

            if((info->SENmode == TRANSEN) &&
                (ckt->CKTmode & MODEINITTRAN))
                goto restore;

            /* load the RHS matrix */

            *(info->SEN_RHS[here->BJTbaseNode] + here->BJTsenParmNo)
                -= DcxDp;
            *(info->SEN_RHS[here->BJTbasePrimeNode] + here->BJTsenParmNo)
                -= DbprmDp;
            *(info->SEN_RHS[here->BJTcolNode] + here->BJTsenParmNo)
                -= DccprDp;
            *(info->SEN_RHS[here->BJTcolPrimeNode] + here->BJTsenParmNo)
                -= DcprmDp;
            *(info->SEN_RHS[here->BJTemitNode] + here->BJTsenParmNo)
                -= DceprDp;
            *(info->SEN_RHS[here->BJTemitPrimeNode] + here->BJTsenParmNo)
                -= DeprmDp;
#ifdef SENSDEBUG
            printf("after loading\n");
            printf("DcxDp=%.7e\n",
                    *(info->SEN_RHS[here->BJTbaseNode] + here->BJTsenParmNo));
            printf("DcbprmDp=%.7e\n",
                    *(info->SEN_RHS[here->BJTbasePrimeNode] + 
                    here->BJTsenParmNo));
            printf("DccprDp=%.7e\n",
                    *(info->SEN_RHS[here->BJTcolNode] + here->BJTsenParmNo));
            printf("DcprmDp=%.7e\n",
                    *(info->SEN_RHS[here->BJTcolPrimeNode] + 
                    here->BJTsenParmNo));
            printf("DceprDp=%.7e\n",
                    *(info->SEN_RHS[here->BJTemitNode] +
                    here->BJTsenParmNo));
            printf("DceprmDp=%.7e\n",
                    *(info->SEN_RHS[here->BJTemitPrimeNode] + 
                    here->BJTsenParmNo));
#endif /* SENSDEBUG */

next:       
            if((info->SENmode == DCSEN)||(ckt->CKTmode&MODETRANOP))goto restore;
            if((info->SENmode == TRANSEN) &&
                (ckt->CKTmode & MODEINITTRAN))
                goto restore;

            for(iparmno = 1;iparmno<=info->SENparms;iparmno++){
                Osxpbe = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbe +
                        8*(iparmno - 1))
                    + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbe +
                        8*(iparmno - 1) + 1);

                Osxpbc = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbc +
                        8*(iparmno - 1))
                    + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbc +
                        8*(iparmno - 1) + 1);

                Osxpcs = tag0 * *(ckt->CKTstate1 + here->BJTsensxpsub +
                        8*(iparmno - 1))
                    + tag1 * *(ckt->CKTstate1 + here->BJTsensxpsub +
                        8*(iparmno - 1) + 1);

                Osxpbx = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbx +
                        8*(iparmno - 1))
                    + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbx +
                        8*(iparmno - 1) + 1);
#ifdef SENSDEBUG
                printf("iparmno=%d\n",iparmno);
                printf("Osxpbe=%.7e,Osxpbc=%.7e\n",Osxpbe,Osxpbc);
                printf("Osxpcs=%.7e,Osxpbx=%.7e\n",Osxpcs,Osxpbx);
                printf("sxpbe=%.7e,sdbe=%.7e\n",
                        *(ckt->CKTstate1 + here->BJTsensxpbe + 8*(iparmno - 1))
                        ,*(ckt->CKTstate1 + here->BJTsensxpbe + 
                        8*(iparmno - 1) + 1));
                printf("sxpbc=%.7e,sdbc=%.7e\n",
                        *(ckt->CKTstate1 + here->BJTsensxpbc + 8*(iparmno - 1))
                        ,*(ckt->CKTstate1 + here->BJTsensxpbc + 
                        8*(iparmno - 1) + 1));
                printf("\n");
#endif /* SENSDEBUG */

                if(iparmno == here->BJTsenParmNo){ 
                    Osxpbe = Osxpbe -  tag0 * DqbeDp;
                    Osxpbc = Osxpbc -  tag0 * DqbcDp;
                    Osxpcs = Osxpcs -  tag0 * DqcsDp;
                    Osxpbx = Osxpbx -  tag0 * DqbxDp;
                }

#ifdef SENSDEBUG

                printf("Osxpbe=%.7e,Osxpbc=%.7e\n",Osxpbe,Osxpbc);
                printf("Osxpcs=%.7e,Osxpbx=%.7e\n",Osxpcs,Osxpbx);
#endif /* SENSDEBUG */

                *(info->SEN_RHS[here->BJTbaseNode] + iparmno) 
                    += model->BJTtype * Osxpbx;

                *(info->SEN_RHS[here->BJTbasePrimeNode] + iparmno) 
                    += model->BJTtype * (Osxpbe + Osxpbc);

                *(info->SEN_RHS[here->BJTcolPrimeNode] + iparmno) 
                    -= model->BJTtype * (Osxpbc + Osxpcs + Osxpbx );

                *(info->SEN_RHS[here->BJTemitPrimeNode] + iparmno) 
                    -= model->BJTtype * Osxpbe;

                *(info->SEN_RHS[here->BJTsubstNode] + iparmno) 
                    += model->BJTtype * Osxpcs;

            }


            /* put the unperturbed values back into the state vector */
restore:    
            for(i=0; i <= 20; i++){
                *(ckt->CKTstate0 + here->BJTstate + i) = *(SaveState0 + i);
            }
            *(ckt->CKTstate1 + here->BJTcexbc) = *(SaveState0 + 21);
            *(ckt->CKTstate1 + here->BJTcexbc) = *(SaveState0 + 21);
            here->BJTcapbe = *(SaveState0 + 23) ;
            here->BJTcapbc = *(SaveState0 + 24) ;
            here->BJTcapsub = *(SaveState0 + 25) ;
            here->BJTcapbx = *(SaveState0 + 26) ;

        }
    }
    info->SENstatus = NORMAL;
#ifdef SENSDEBUG
    printf("BJTsenload end\n");
#endif /* SENSDEBUG */
    return(OK);
}