home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 13 / 13.iso / p / p064 / 3.ddi / MOS4.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-01  |  17.4 KB  |  558 lines

  1. /****************************************************************************/
  2. /*        Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991                  */
  3. /*          By MicroSim Corporation, All Rights Reserved                    */
  4. /****************************************************************************/
  5. /* mos4.c
  6.  *   $Revision:   1.9  $
  7.  *   $Author:   jmh  $
  8.  *   $Date:   13 Jun 1991 21:06:40  $ */
  9.  
  10. #include "option1.h"
  11. #include "mos.fd"
  12.  
  13. #define PARAM(a)     ((double)Model->a)
  14. #define VDD        PARAM(BSIM_vdd)
  15. #define BSIM_phi0    M_phi
  16. #define BSIM_eta0    M_eta
  17. #define BSIM_tox    M_tox
  18.  
  19. /* */
  20. #ifndef cc_noline
  21. #line 4 "MOS4eval"
  22. #endif
  23.  
  24. void MOS4eval(        /* evaluate MOS level 4 (BSIM) model */
  25.             /* (BSIM: Berkeley Short-Channel IGFET Model) */
  26.   Model,        /* (pointer to) model */
  27.   Len, Wid, Mdev,    /* device size */
  28.   Vgs, Vds, Vbs,    /* terminal voltages */
  29.   Von, Vdsat,
  30.   Id,            /* (pointer to) drain current (returned) */
  31.   Gds, Gm, Gmbs,    /* (pointer to) device conductances (returned) */
  32.   Charge,        /* do charge calculations: YES/NO */
  33.   Cggb, Cgdb, Cgsb,    /* (pointer to) gate-related cap. (returned) */
  34.   Cdgb, Cddb, Cdsb,    /* (pointer to) drain-related cap. (returned) */
  35.   Cbgb, Cbdb, Cbsb,    /* (pointer to) bulk-related cap. (returned) */
  36.   Qg, Qd, Qb        /* (pointer to) device charges (returned) */
  37.   )
  38.   struct M_    *Model;
  39.   double    Len, Wid, Mdev, Vgs, Vds, Vbs, *Von, *Vdsat, *Id, *Gds, *Gm, *Gmbs;
  40.   int        Charge;
  41.   double    *Cggb, *Cgdb, *Cgsb,
  42.         *Cdgb, *Cddb, *Cdsb,
  43.         *Cbgb, *Cbdb, *Cbsb;
  44.   double    *Qg, *Qd, *Qb;
  45.  
  46.  
  47. /*
  48. 87-12-30 pwt    - creation
  49. 88-03-10 pwt    - bug fix re. Burr-Brown beta-site
  50. 89-04-15 pwt    - add device multiplier, to fix delta Width parameter calc.
  51. 89-06-12 whjb   - Made use of EXP() macro
  52. 90-02-12 sv    - add local temperatures to models.
  53. */
  54.  
  55. { double
  56.     vgst, vpb, sqrt_vpb,
  57.     G, dG_dvbs,
  58.     A, dA_dvbs,
  59.     ugs, dugs_dvbs,
  60.     uds, duds_dvbs, duds_dvds,
  61.     eta, deta_dvbs, deta_dvds,
  62.     dvth_dvbs, dvth_dvds,
  63.     cox = 3.453e-13/(PARAM(BSIM_tox)*1e-4), /* tox in microns, cox in F/cm^2 */
  64.     cox_wl = cox*Wid/Len,
  65.     betaZero = cox_wl*Model->BSIM_mobZero;
  66.  
  67.  
  68.  
  69.  
  70. #define    vt    VT
  71.  
  72.  
  73. /* device parameter set-up: this is done once in SPICE3, but every time in
  74.  * PSpice to save storage and facilitate Monte Carlo, parameter sweeps, etc.
  75.  */
  76.  
  77. #define BSIMsetup(a0,aL,aW) (Model->a0 + Model->aL*olen + Model->aW*owid)
  78.  
  79.   double
  80.     olen = (1e-6)/Len,        /* in 1/micron */
  81.     owid = (1e-6)/(Wid/Mdev),    /* in 1/micron */
  82.     vfb  = BSIMsetup(    BSIM_vfb0,    BSIM_vfbL,    BSIM_vfbW ),
  83.     phi  = BSIMsetup(    BSIM_phi0,    BSIM_phiL,    BSIM_phiW ),
  84.     K1   = BSIMsetup(    BSIM_K10,    BSIM_K1L,    BSIM_K1W ),
  85.     K2   = BSIMsetup(    BSIM_K20,    BSIM_K2L,    BSIM_K2W );
  86.  
  87.  
  88.   if ( phi < .1) phi = .1;
  89.   if ( K1  < 0.) K1  = 0.;
  90.   if ( K2  < 0.) K2  = 0.;
  91.  
  92.   *Von = /* vt0 = */ vfb + phi + K1*sqrt(phi) - K2*phi;
  93.  
  94.   { double
  95.       ugsB = BSIMsetup( BSIM_ugsB0, BSIM_ugsBL, BSIM_ugsBW );
  96.  
  97.     ugs     = BSIMsetup( BSIM_ugs0, BSIM_ugsL, BSIM_ugsW );
  98.     ugs += ugsB*Vbs;
  99.     if ( ugs <= 0.)
  100.       ugs = dugs_dvbs = 0.;
  101.     else
  102.       dugs_dvbs = ugsB;
  103.     }
  104.  
  105.   { double
  106.       udsB = BSIMsetup( BSIM_udsB0, BSIM_udsBL, BSIM_udsBW ),
  107.       udsD = BSIMsetup( BSIM_udsD0, BSIM_udsDL, BSIM_udsDW );
  108.  
  109.     uds  = BSIMsetup( BSIM_uds0, BSIM_udsL, BSIM_udsW );
  110.     uds += udsB*Vbs + udsD*(Vds-VDD);
  111.     if ( uds <= 0.)
  112.       uds = duds_dvbs = duds_dvds = 0.;
  113.     else {
  114.       uds      *= olen;
  115.       duds_dvbs = udsB*olen;
  116.       duds_dvds = udsD*olen;
  117.     } }
  118.  
  119.   { double
  120.       etaB = BSIMsetup( BSIM_etaB0, BSIM_etaBL, BSIM_etaBW ),
  121.       etaD = BSIMsetup( BSIM_etaD0, BSIM_etaDL, BSIM_etaDW );
  122.  
  123.     eta  = BSIMsetup( BSIM_eta0, BSIM_etaL, BSIM_etaW );
  124.     eta += etaB*Vbs + etaD*(Vds-VDD);
  125.     if ( eta <= 0.)
  126.       eta = deta_dvds = deta_dvbs = 0.;
  127.     else if ( eta > 1.) {
  128.       eta = 1.;
  129.       deta_dvds = deta_dvbs = 0.;
  130.       }
  131.     else {
  132.       deta_dvds = etaD;
  133.       deta_dvbs = etaB;
  134.     } }
  135.  
  136.   vpb     = Vbs < 0. ? phi - Vbs : phi;
  137.   sqrt_vpb = sqrt( vpb );
  138.  
  139.   *Von = vfb + phi + K1*sqrt_vpb - K2*vpb - eta*Vds;
  140.   vgst = Vgs - *Von;
  141.  
  142.   dvth_dvds = -(eta + deta_dvds*Vds);
  143.   dvth_dvbs = K2 - .5*K1/sqrt_vpb - deta_dvbs*Vds;
  144.  
  145.   G = 1 - 1/(1.744 + .8364*vpb);
  146.   A = 1 + .5*G*K1/sqrt_vpb;
  147.   A = MAX( A, 1.);    /* Modified */
  148.   dG_dvbs = -.8364*(1-G)*(1-G);
  149.   dA_dvbs = .25*K1/sqrt_vpb*(2*dG_dvbs + G/vpb);
  150.  
  151.   if ( vgst < 0.)            /* cutoff */
  152.     *Id = *Gds = *Gm = *Gmbs = 0.;
  153.  
  154.   else {    /* Quadratic Interpolation for Beta0 (Beta @ vgs=0, vds=Vds) */
  155.     double
  156.       beta, dbeta_dvgs, dbeta_dvds, dbeta_dvbs,
  157.       beta0, dbeta0_dvds, dbeta0_dvbs,
  158.       beta_vds_0, dbetaVdd_dvds,
  159.       term1, K,
  160.       betaZeroB = cox_wl*BSIMsetup( BSIM_mobZeroB0, BSIM_mobZeroBL, BSIM_mobZeroBW ),
  161.       betaVdd   = cox_wl*BSIMsetup( BSIM_mobVdd0,   BSIM_mobVddL,   BSIM_mobVddW ),
  162.       betaVddB  = cox_wl*BSIMsetup( BSIM_mobVddB0,  BSIM_mobVddBL,  BSIM_mobVddBW ),
  163.       betaVddD  = cox_wl*BSIMsetup( BSIM_mobVddD0,  BSIM_mobVddDL,  BSIM_mobVddDW );
  164.  
  165.     if ( betaVddD < 0.) betaVddD = 0.;
  166.  
  167.     beta_vds_0 = betaZero + betaZeroB*Vbs;
  168.     betaVdd   += betaVddB*Vbs;
  169.     dbetaVdd_dvds = MAX( betaVddD, 0.);    /* Modified */
  170.  
  171.     if ( Vds > VDD ) {
  172.       beta0       = betaVdd + dbetaVdd_dvds*(Vds-VDD);
  173.       dbeta0_dvds = dbetaVdd_dvds;
  174.       dbeta0_dvbs = betaVddB;
  175.       }
  176.     else {
  177.       double
  178.         vdd_sq = VDD*VDD,
  179.         C1 = (-betaVdd + beta_vds_0 + dbetaVdd_dvds*VDD)/vdd_sq,
  180.         C2 = 2*(betaVdd - beta_vds_0)/VDD - dbetaVdd_dvds,
  181.         dbeta_vds_0_dvbs = betaZeroB,
  182.         dbetaVdd_dvbs    = betaVddB,
  183.         dC1_dvbs = (dbeta_vds_0_dvbs - dbetaVdd_dvbs)/vdd_sq,
  184.         dC2_dvbs = -2*dC1_dvbs*VDD;
  185.  
  186.       beta0       = (C1*Vds + C2)*Vds + beta_vds_0;
  187.       dbeta0_dvds = 2*C1*Vds + C2;
  188.       dbeta0_dvbs = (dC1_dvbs*Vds + dC2_dvbs)*Vds + dbeta_vds_0_dvbs;
  189.       }
  190.  
  191.     { double arg  = 1/MAX(1 + ugs*vgst, 1.);
  192.  
  193.       beta = beta0*arg ;
  194.       dbeta_dvgs = -beta*ugs*arg;
  195.       dbeta_dvds = dbeta0_dvds*arg - dbeta_dvgs*dvth_dvds ;
  196.       dbeta_dvbs = (dbeta0_dvbs + beta*ugs*dvth_dvbs - beta*vgst*dugs_dvbs)*arg;
  197.       }
  198.  
  199.     { double vc = uds*vgst/A;
  200.  
  201.       if ( vc < 0.) vc = 0.;
  202.       term1 = sqrt(1 + 2*vc);
  203.       K     = .5*(1 + vc + term1);
  204.       }
  205. /*  *Vdsat = MAX(vgst/(A + uds*vgst), 0.);*/
  206.     *Vdsat = MAX(vgst/(A*sqrt(K)), 0.);
  207.  
  208.     if ( Vds < *Vdsat ) {            /* triode region */
  209.       double 
  210. /*      arg1 = 1 + uds*Vds, */
  211.         arg1 = MAX(1+uds*Vds, 1.),
  212.         arg2 = vgst - .5*A*Vds;
  213.  
  214.       *Id   = beta*arg2*Vds/arg1;
  215.       *Gm   = ( dbeta_dvgs*arg2*Vds + beta*Vds )/arg1;
  216.       *Gds  = ( dbeta_dvds*arg2*Vds +
  217.                 beta*(vgst - Vds*dvth_dvds - A*Vds) -
  218.                 *Id*(Vds*duds_dvds + uds)
  219.                 )/arg1;
  220.       *Gmbs = ( dbeta_dvbs*arg2*Vds +
  221.                 beta*Vds*(-dvth_dvbs - .5*Vds*dA_dvbs) -
  222.                 *Id*Vds*duds_dvbs
  223.                 )/arg1;
  224.       }
  225.     else {                /* saturation region */
  226.       double
  227.         args1 = 1 + 1/term1,
  228.         args2 = vgst/A/K,
  229.         args3 = args2*vgst,
  230.         dvc_dvgs = uds/A,
  231.         dvc_dvds = vgst*duds_dvds/A - dvc_dvgs*dvth_dvds,
  232.         dvc_dvbs = (vgst*duds_dvbs - uds*(dvth_dvbs + vgst*dA_dvbs/A))/A,
  233.         dK_dvc  = .5*args1,
  234.         dK_dvgs = dK_dvc*dvc_dvgs,
  235.         dK_dvds = dK_dvc*dvc_dvds,
  236.         dK_dvbs = dK_dvc*dvc_dvbs;
  237.  
  238.       *Id   = .5*args3*beta;
  239.       *Gm   = .5*args3*dbeta_dvgs + args2*beta - *Id*dK_dvgs/K;
  240.       *Gds  = .5*args3*dbeta_dvds - args2*beta*dvth_dvds - *Id*dK_dvds/K;
  241.       *Gmbs = .5*args3*dbeta_dvbs - args2*beta*dvth_dvbs - *Id*(dA_dvbs/A + dK_dvbs/K);
  242.     } }
  243.  
  244. /* subthreshold calculations */
  245.  
  246.     { double
  247.       N0 = BSIMsetup( BSIM_subthSlope0,  BSIM_subthSlopeL,  BSIM_subthSlopeW );
  248.  
  249.       if ( !( N0 >= 200.)) {      
  250.         double
  251.         NB     = BSIMsetup( BSIM_subthSlopeB0, BSIM_subthSlopeBL, BSIM_subthSlopeBW ),
  252.         ND     = BSIMsetup( BSIM_subthSlopeD0, BSIM_subthSlopeDL, BSIM_subthSlopeDW ),
  253.         N      = N0 + NB*Vbs + ND*Vds;    /* subthreshold slope */
  254.  
  255.         if ( N < .5 ) N = .5; 
  256.         { double        
  257.           warg1     = EXP(-Vds/vt),
  258.           wds       = 1 - warg1,
  259.           wgs       = EXP(vgst/(N*vt)),
  260.           vdvt      = Vds/(vt*.1),
  261.           warg2     = vt*vt*betaZero*6.04965,
  262.           ilimit    = vt*vt*betaZero*4.5,        
  263.           ilimit_t  = ilimit*tanh(vdvt),
  264.           iexp      = warg2*wgs*wds,
  265.           temp1     = ilimit_t/(ilimit_t + iexp),
  266.           terms     = (EXP(vgst/(vt*N)) * (-ND*vgst - N*dvth_dvds))/(vt*N*N),
  267.           temp3     =  1/(cosh(vdvt)*cosh(vdvt)*vt*.1),
  268.           uu        = iexp+ilimit*tanh(vdvt), 
  269.           diedvd    = warg2*(terms*wds + wgs*warg1/vt);
  270.           temp1     *= temp1;
  271.           *Id       += iexp*ilimit_t/(ilimit_t + iexp);
  272.           terms     = tanh(vdvt);
  273.           *Gds      += ilimit*(ilimit*terms*terms*diedvd+iexp*iexp*temp3)/(uu*uu);
  274.           *Gm       += temp1*iexp/(N*vt);
  275.           *Gmbs     += temp1*iexp*(dvth_dvbs + vgst*NB/N)/(N*vt);              
  276.           }  
  277.         }
  278.       }
  279.  
  280. /* limiting of some DC values */
  281.  
  282.   if ( *Id   < 0.) *Id   = 0.;
  283.   if ( *Gm   < 0.) *Gm   = 0.;
  284.   if ( *Gds  < 0.) *Gds  = 0.;
  285.   if ( *Gmbs < 0.) *Gmbs = 0.;
  286.  
  287. /* charge calculations */
  288.  
  289.   if ( Charge==NO ) {
  290.     *Qg = *Qd = *Qb =
  291.     *Cggb = *Cgsb = *Cgdb =
  292.     *Cdgb = *Cdsb = *Cddb =
  293.     *Cbgb = *Cbsb = *Cbdb = 0.;
  294.     }
  295.   else {
  296.     double
  297.       cgbb, cdbb, cbbb,
  298.       co4v15 = 4./15.,
  299.       wl_cox = cox*Wid*Len*1e4,    /* F */
  300.       vth0 = vfb + phi + K1*sqrt_vpb,
  301.       vgst = Vgs - vth0,
  302.       arg1 = A*Vds,
  303.       arg2 = vgst - .5*arg1,
  304.       arg3 = Vds - arg1,
  305.       arg5 = arg1*arg1,
  306.       dvth_dvbs = -.5*K1/sqrt_vpb,
  307.       dA_dvbs   = .5*K1*(.5*G/vpb - .8364*(1-G)*(1-G))/sqrt_vpb,
  308.       ent       = MAX(arg2,1e-8),
  309.       dent_dvds = -.5*A,
  310.       dent_dvbs = -(dvth_dvbs + .5*Vds*dA_dvbs),
  311.       vcom = vgst*vgst/6 - .125*arg1*vgst + .025*arg5,
  312.       vds_pinchoff = MAX( vgst/A, 0.),
  313.       vgb     = Vgs - Vbs,
  314.       vgb_vfb = vgb - vfb;
  315.  
  316. /* 0/100 partitioning for drain/source charges at the saturation region*/
  317.  
  318.     if ( PARAM(BSIM_xpart) >= 1.) {
  319.  
  320.       if ( vgb_vfb < 0.) {        /* accumulation region */
  321.         *Qg = wl_cox*vgb_vfb;
  322.         *Qb = -*Qg;
  323.         *Qd = 0.;
  324.  
  325.         *Cggb = wl_cox;
  326.         *Cgdb = *Cgsb = 0.;
  327.         *Cbgb = -wl_cox;
  328.         *Cbdb = *Cbsb = 0.;
  329.         *Cdgb = *Cddb = *Cdsb = 0.;
  330.         }
  331.       else if ( Vgs < vth0 ) {        /* subthreshold region */
  332.  
  333.         *Qg = .5*wl_cox*K1*K1*(-1 + sqrt(1 + 4*vgb_vfb/(K1*K1)) );
  334.         *Qb = -*Qg;
  335.         *Qd = 0.;
  336.  
  337.         *Cggb = wl_cox/sqrt(1 + 4*vgb_vfb/(K1*K1));
  338.         *Cgdb = *Cgsb = 0.;
  339.         *Cbgb = -*Cggb;
  340.         *Cbdb = *Cbsb = 0.;
  341.         *Cdgb = *Cddb = *Cdsb = 0.;
  342.         }
  343.       else if ( Vds < vds_pinchoff ) {    /* triode region  */
  344.         double
  345.           argt1, argt2, argt3, argt5, argt7, argt8, argt9;
  346.  
  347.         argt1 = 12*ent*ent;
  348.         argt2 = 1 - A;
  349.         argt3 = arg1*Vds;
  350.       /*argt4 = vcom/(ent*ent*ent); never used */
  351.         if ( ent > 1e-8) {
  352.           argt5 = arg1/ent;
  353.         /*argt6 = vcom/(ent*ent); never used */
  354.           }
  355.         else {
  356.           argt5 = 2.;
  357.         /*argt6 = 4./15.; never used */
  358.           }
  359.         argt7 = argt5/12;
  360.         argt8 = 6*ent;
  361.         argt9 = .125*argt5*argt5;
  362.  
  363.         *Qg =  wl_cox*(Vgs - vfb - phi - .5*Vds + Vds*argt7);
  364.         *Qb =  wl_cox*(-vth0 + vfb + phi + .5*arg3 - arg3*argt7);
  365.         *Qd = -wl_cox*(.5*vgst - .75*arg1 + .125*arg1*argt5);
  366.  
  367.         *Cggb = wl_cox*(1 - argt3/argt1);
  368.         *Cgdb = wl_cox*(-.5 + arg1/argt8 - argt3*dent_dvds/argt1);
  369.          cgbb = wl_cox*(Vds*Vds*dA_dvbs*ent - argt3*dent_dvbs)/argt1;
  370.         *Cgsb = -(*Cggb + *Cgdb + cgbb);
  371.  
  372.         *Cbgb = wl_cox*argt3*argt2/argt1;
  373.         *Cbdb = wl_cox*argt2*(.5 - arg1/argt8 + argt3*dent_dvds/argt1);
  374.          cbbb = -wl_cox*(dvth_dvbs + .5*Vds*dA_dvbs +
  375.                 Vds*Vds*((1 - 2*A)*dA_dvbs*ent - argt2*A*dent_dvbs)/argt1);
  376.         *Cbsb = -(*Cbgb + *Cbdb + cbbb);
  377.  
  378.         *Cdgb = -wl_cox*(.5 - argt9);
  379.         *Cddb = wl_cox*(.75*A - .25*A*arg1/ent + argt9*dent_dvds);
  380.          cdbb = wl_cox*(.5*dvth_dvbs + Vds*dA_dvbs*(.75 - .25*argt5) + argt9*dent_dvbs);
  381.         *Cdsb = -(*Cdgb + *Cddb + cdbb);
  382.         }
  383.       else if ( Vds >= vds_pinchoff ) {    /* saturation region */
  384.         double
  385.           args1 = 1/(3*A);
  386.  
  387.         *Qg = wl_cox*(Vgs - vfb - phi - vgst*args1);
  388.         *Qb = wl_cox*(vfb + phi - vth0 + (1-A)*vgst*args1);
  389.         *Qd = 0.;
  390.  
  391.         *Cggb = wl_cox*(1-args1);
  392.         *Cgdb = 0.;
  393.          cgbb = wl_cox*args1*(dvth_dvbs + vgst*dA_dvbs/A);
  394.         *Cgsb = -(*Cggb + *Cgdb + cgbb);
  395.  
  396.         *Cbgb = wl_cox*(args1 - 1./3.);
  397.         *Cbdb = 0.;
  398.          cbbb = -wl_cox*((2./3.+ args1)*dvth_dvbs + vgst*args1*dA_dvbs/A);    /* Modified */
  399.         *Cbsb = -(*Cbgb + *Cbdb + cbbb);
  400.  
  401.         *Cdgb = *Cddb = *Cdsb = 0.;
  402.       } }
  403.  
  404. /* 40/60 partitioning for drain/source charges at the saturation region*/
  405.  
  406.     else {                /* ChannelChargePartionFlag < 1 */
  407.  
  408.       if ( vgb_vfb < 0.) {        /* accumulation region */
  409.         *Qg = wl_cox*vgb_vfb;
  410.         *Qb = -*Qg;
  411.         *Qd = 0.;
  412.  
  413.         *Cggb = wl_cox;
  414.         *Cgdb = *Cgsb = 0.;
  415.         *Cbgb = -wl_cox;
  416.         *Cbdb = *Cbsb = 0.;
  417.         *Cdgb = *Cddb = *Cdsb = 0.;
  418.         }
  419.       else if ( Vgs < vth0 ) {        /* subthreshold region */
  420.  
  421.         *Qg = .5*wl_cox*K1*K1*(-1 + sqrt(1 + 4*vgb_vfb/(K1*K1)) );
  422.         *Qb = -*Qg;
  423.         *Qd = 0.;
  424.  
  425.         *Cggb = wl_cox/sqrt(1+4*vgb_vfb/(K1*K1));
  426.         *Cgdb = *Cgsb = 0.;
  427.         *Cbgb = -*Cggb;
  428.         *Cbdb = *Cbsb = 0.;
  429.         *Cdgb = *Cddb = *Cdsb = 0.;
  430.         }
  431.       else if ( Vds < vds_pinchoff ) {    /* triode region */
  432.         double
  433.           argt1, argt2, argt3, argt4, argt5, argt6, argt7, argt8;
  434.  
  435.         argt1 = 12*ent*ent;
  436.         argt2 = 1 - A;
  437.         argt3 = arg1*Vds;
  438.         argt4 = vcom/(ent*ent*ent);
  439.         if ( ent > 1e-8 ) {
  440.           argt5 = arg1/ent;
  441.           argt6 = vcom/(ent*ent);
  442.           }
  443.         else {
  444.           argt5 = 2.;
  445.           argt6 = 4./15.;
  446.           }
  447.         argt7 = argt5/12;
  448.         argt8 = 6*ent;
  449.  
  450.         *Qg =  wl_cox*(Vgs - vfb - phi - .5*Vds + Vds*argt7);
  451.         *Qb =  wl_cox*(-vth0 + vfb + phi + .5*arg3 - arg3*argt7);
  452.         *Qd = -wl_cox*(.5*(vgst-arg1) + arg1*argt6);
  453.  
  454.         *Cggb =  wl_cox*(1 - argt3/argt1);
  455.         *Cgdb =  wl_cox*(-.5 + arg1/argt8 - argt3*dent_dvds/argt1);
  456.          cgbb =  wl_cox*(Vds*Vds*dA_dvbs*ent - argt3*dent_dvbs)/argt1;
  457.         *Cgsb = -(*Cggb + *Cgdb + cgbb);
  458.  
  459.         *Cbgb =  wl_cox*argt3*argt2/argt1;
  460.         *Cbdb =  wl_cox*argt2*(.5 - arg1/argt8 + argt3*dent_dvds/argt1);
  461.          cbbb = -wl_cox*(dvth_dvbs + .5*Vds*dA_dvbs +
  462.                 Vds*Vds*((1 - 2*A)*dA_dvbs*ent - argt2*A*dent_dvbs)/argt1);
  463.         *Cbsb = -(*Cbgb + *Cbdb + cbbb);
  464.  
  465.         *Cdgb = -wl_cox*(.5 + arg1*(4*vgst - 1.5*arg1)/argt1 - 2*arg1*argt4);
  466.         *Cddb =  wl_cox*(.5*A + 2*arg1*dent_dvds*argt4 -
  467.                 A*(2*vgst*vgst - 3*arg1*vgst + .9*arg5)/argt1);
  468.          cdbb =  wl_cox*(.5*dvth_dvbs + .5*Vds*dA_dvbs + 2*arg1*dent_dvbs*argt4 -
  469.                    Vds*( 2*vgst*vgst*dA_dvbs - 4*A*vgst*dvth_dvbs -
  470.                      3*arg1*vgst*dA_dvbs + 1.5*A*arg1*dvth_dvbs +.9*arg5*dA_dvbs
  471.                      )/argt1);
  472.         *Cdsb = -(*Cdgb + *Cddb + cdbb);
  473.         }
  474.       else if ( Vds >= vds_pinchoff ) {    /* saturation region */
  475.         double
  476.           args1 = 1/(3*A);
  477.  
  478.         *Qg =  wl_cox*(Vgs - vfb - phi - vgst*args1);
  479.         *Qb =  wl_cox*(vfb + phi - vth0 + (1-A)*vgst*args1);
  480.         *Qd = -co4v15*wl_cox*vgst;
  481.   
  482.         *Cggb = wl_cox*(1-args1);
  483.         *Cgdb = 0.;
  484.          cgbb = wl_cox*args1*(dvth_dvbs + vgst*dA_dvbs/A);
  485.         *Cgsb = -(*Cggb + *Cgdb + cgbb);
  486.   
  487.         *Cbgb = wl_cox*(args1 - 1./3.);
  488.         *Cbdb = 0.;
  489.          cbbb = -wl_cox*((2./3.+ args1)*dvth_dvbs + vgst*args1*dA_dvbs/A);
  490.         *Cbsb = -(*Cbgb + *Cbdb + cbbb);
  491.   
  492.         *Cdgb = -co4v15*wl_cox;
  493.         *Cddb = 0.;
  494.          cdbb = co4v15*wl_cox*dvth_dvbs;
  495.         *Cdsb = -(*Cdgb + *Cddb + cdbb);
  496.     } } }
  497.   } /* done */
  498. /* */
  499. #ifndef cc_noline
  500. #line 4 "MOS4cap"
  501. #endif
  502.  
  503. void MOS4cap(    /* calc. MOS4 equiv. conductance and total terminal charges */
  504.   Vgd, Vgs, Vgb,
  505.   CgdOvl, CgsOvl, CgbOvl,
  506.   Cggb, Cgdb, Cgsb,
  507.   Cbgb, Cbdb, Cbsb,
  508.   Cdgb, Cddb, Cdsb,
  509.   Gcggb, Gcgdb, Gcgsb,
  510.   Gcbgb, Gcbdb, Gcbsb,
  511.   Gcdgb, Gcddb, Gcdsb,
  512.   Gcsgb, Gcsdb, Gcssb,
  513.   Qgat, Qsub, Qdrn, Qsrc
  514.   )
  515.   double
  516.     Vgd, Vgs, Vgb,
  517.     CgdOvl, CgsOvl, CgbOvl,
  518.     Cggb, Cgdb, Cgsb,
  519.     Cbgb, Cbdb, Cbsb,
  520.     Cdgb, Cddb, Cdsb,
  521.     *Gcggb, *Gcgdb, *Gcgsb,
  522.     *Gcbgb, *Gcbdb, *Gcbsb,
  523.     *Gcdgb, *Gcddb, *Gcdsb,
  524.     *Gcsgb, *Gcsdb, *Gcssb,
  525.     *Qgat, *Qsub, *Qdrn, *Qsrc;
  526. /*
  527. pwt    31 Dec 87    creation
  528. pwt    19 Feb 88    bug (see MOS.C: MOScap)
  529. */
  530. {                    /* calc. equivalent conductances */
  531.   *Gcdgb = AG1*(Cdgb - CgdOvl);
  532.   *Gcddb = AG1*(Cddb + CgdOvl);
  533.   *Gcdsb = AG1*Cdsb;
  534.  
  535.   *Gcsgb = AG1* -(Cggb + Cbgb + Cdgb + CgsOvl);
  536.   *Gcsdb = AG1* -(Cgdb + Cbdb + Cddb);
  537.   *Gcssb = AG1* -(Cgsb + Cbsb + Cdsb - CgsOvl);
  538.  
  539.   *Gcggb = AG1*(Cggb + CgdOvl + CgsOvl + CgbOvl);
  540.   *Gcgdb = AG1*(Cgdb - CgdOvl);
  541.   *Gcgsb = AG1*(Cgsb - CgsOvl);
  542.  
  543.   *Gcbgb = AG1*(Cbgb - CgbOvl);
  544.   *Gcbdb = AG1*(Cbdb);
  545.   *Gcbsb = AG1*(Cbsb);
  546.  
  547.   { double                /* calc. total terminal charge */
  548.       qgd = CgdOvl * Vgd,
  549.       qgs = CgsOvl * Vgs,
  550.       qgb = CgbOvl * Vgb;
  551.  
  552.     *Qgat += qgd + qgs + qgb;
  553.     *Qsub -= qgb;
  554.     *Qdrn -= qgd;
  555.     *Qsrc = -(*Qgat + *Qsub + *Qdrn);
  556.     }
  557.   } /* done */
  558.