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

  1. /****************************************************************************/
  2. /*        Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991                  */
  3. /*          By MicroSim Corporation, All Rights Reserved                    */
  4. /****************************************************************************/
  5. /* mos.c
  6.  *   $Revision:   1.23  $
  7.  *   $Author:   pwt  $
  8.  *   $Date:   21 Jun 1991 13:25:00  $ */
  9.  
  10. /******************* USERS OF DEVICE EQUATIONS OPTION ***********************/
  11. /******** The definitions below access the device and model data   **********/
  12. /******** structures that are defined in the file m.h.  When the   **********/
  13. /******** routine MOSfet is called, it is passed a pointer to the  **********/
  14. /******** device structure.  From the device structure is gotten   **********/
  15. /******** a pointer to the model structure.  The overall structure **********/
  16. /******** of the subroutines and model parameters is the same as   **********/
  17. /******** the UC Berkeley Spice 2G.6.
  18.  
  19. /******** To add a model parameter and equations that use that     **********/
  20. /******** parameter, make the appropriate changes to the file m.h  **********/
  21. /******** and to this file (mos.c).  See the comments in m.h for   **********/
  22. /******** instructions on making changes there.  Then, recompile   **********/
  23. /******** this file and relink the program using the link command  **********/
  24. /******** file PSPICE.LNK.  The command file CC.BAT contains the   **********/
  25. /******** compile options you should use.                          **********/
  26.  
  27. #define    M_DEVICE
  28.  
  29. #include "option1.h"
  30. #include "mos.fd"
  31.  
  32. #define BYPASS    YES    /* NO disables bypass */
  33. #define BSIM    YES    /* NO disables BSIM code */
  34.  
  35. static double
  36.     Cox,
  37.     Xqc;
  38.  
  39. /* defines for device parameter access: simplify code appearance */
  40.  
  41. #define PARAM_DEV(a)    (Instance->a)
  42. #define DevAd        PARAM_DEV(m_ad)
  43. #define DevAs        PARAM_DEV(m_as)
  44. #define DevGbpr        PARAM_DEV(m_rb)    /* = 1/rb */
  45. #define DevGdpr        PARAM_DEV(m_rd)    /* = 1/rd */
  46. #define DevGgpr        PARAM_DEV(m_rg)    /* = 1/rg */
  47. #define DevGspr        PARAM_DEV(m_rs)    /* = 1/rs */
  48. #define DevIdsat    PARAM_DEV(m_idsat)
  49. #define DevIssat    PARAM_DEV(m_issat)
  50. #define DevL        PARAM_DEV(m_l)
  51. #define DevMode        PARAM_DEV(m_mode)
  52. #define DevM        PARAM_DEV(m_m)
  53. #define DevOff        PARAM_DEV(m_off)
  54. #define DevPd        PARAM_DEV(m_pd)
  55. #define DevPs        PARAM_DEV(m_ps)
  56. #define DevVbs        PARAM_DEV(m_vbs)
  57. #define DevVds        PARAM_DEV(m_vds)
  58. #define DevVdsat    PARAM_DEV(m_vdsat)
  59. #define DevVgs        PARAM_DEV(m_vgs)
  60. #define DevVon        PARAM_DEV(m_von)
  61. #define DevW        PARAM_DEV(m_w)
  62. #define DevXqc        PARAM_DEV(m_xqc)
  63.  
  64. /* defines for model parameter access: simplify code appearance
  65.  *     note: since the parameters are available to all routines in this file
  66.  *    they are preceeded with "Mod"
  67.  */
  68. #define PARAM_MOD(a)     ((double)Model->a)
  69. #define ModCbd        PARAM_MOD(M_cbd)
  70. #define ModCbs        PARAM_MOD(M_cbs)
  71. #define ModCgbo        PARAM_MOD(M_cgbo)
  72. #define ModCgdo        PARAM_MOD(M_cgdo)
  73. #define ModCgso        PARAM_MOD(M_cgso)
  74. #define ModCj        PARAM_MOD(M_cj)
  75. #define ModCjsw        PARAM_MOD(M_cjsw)
  76. #define ModFc        PARAM_MOD(M_fc)
  77. #define ModGamma    PARAM_MOD(M_gamma)
  78. #define ModGdspr    PARAM_MOD(M_rds)    /* = 1/Rds */
  79. #define ModKp        PARAM_MOD(M_kp)
  80. #define ModL        PARAM_MOD(M_l)
  81. #define ModLambda    PARAM_MOD(M_lambda)
  82. #define ModLd        PARAM_MOD(M_ld)
  83. #define ModLevel    NINT(PARAM_MOD(M_level))
  84. #define ModMj        PARAM_MOD(M_mj)
  85. #define ModMjsw        PARAM_MOD(M_mjsw)
  86. #define ModN        PARAM_MOD(M_n)
  87. #define ModPb        PARAM_MOD(M_pb)
  88. #define ModPbsw        PARAM_MOD(M_pbsw)
  89. #define ModPhi        PARAM_MOD(M_phi)
  90. #define ModTox        PARAM_MOD(M_tox)
  91. #define ModTt        PARAM_MOD(M_tt)
  92. #define ModVbi        PARAM_MOD(M_vbi)
  93. #define ModVinit    PARAM_MOD(M_vinit)
  94. #define ModVto        PARAM_MOD(M_vto)
  95. #define ModW        PARAM_MOD(M_w)
  96. #define ModWd        PARAM_MOD(M_wd)
  97. #define ModXqc        PARAM_MOD(M_xqc)
  98.  
  99. /* */
  100. #ifndef cc_noline
  101. #line 4 "MOSfet"
  102. #endif
  103.  
  104. #ifdef USE_DECL_ARGS
  105. int MOSfet(struct m_ *,int ,int ,int );
  106. #else
  107. int MOSfet();
  108. #endif
  109.  
  110. int MOSfet(    /* Process MOSFETs for DC and TRANSIENT analyses */
  111.   Instance,    /* a device to evaluate */
  112.   ModeFl,    /* mode control flag:    see "tran.h" */
  113.   InitFl,    /* initialization flag:    see "tran.h" */
  114.   LoadFl    /* NO: bypass MatPrm load if sol'n unchanged */
  115.   )        /* return int: did not converge (YES/NO) */
  116.   struct m_ *Instance;
  117.   int ModeFl, InitFl, LoadFl;
  118.  
  119. /*
  120. pwt    20 Aug 86    creation
  121. pwt    ?? Oct 87    many changes to split MOS models into separate files
  122. pwt    ?? Nov 87    re-do junction cap. using square-root if "mj" = .5
  123. pwt    29 Dec 87    re-do junction cap. using sidewall potential "pbsw"
  124. pwt    02 Mar 88    add transit time cap. and emission coef. to junctions
  125. pwt    16 Mar 88    add shared data area to M.H, change source to match
  126. pwt    21 Mar 88    protect PNJLIM calculations from IS==0.0
  127. pwt    06 Oct 88    add "M" (multiplier) to device calculations
  128. whjb    06 Apr 89    LoadFl==YES now forces full recalculation
  129. pwt    15 Apr 89    set T=0 cap. currents
  130. whjb    25 Aug 89    corrected cgs, cgd calculation just after CMeyer call
  131. sv    12 Feb 90    add local temperatures to models.
  132. pwt    04 May 90    remove values saved for bypass calculations
  133. pwt    08 Aug 90    apply LoadFl condition to parasitic resistors
  134. jmh    13 Jun 91    correct Ward-Dutton charge mapping re. bulk junctions
  135. */
  136. { struct M_    *Model;            /* device's model */
  137.   double
  138.     vds, vgs, vbs, vgd, vbd,        /* voltages */
  139.     von, vdsat, vte,
  140.     ibs, ibd, id, idr,            /* currents */
  141.     gbd, gbs, gds, gm, gmbs,        /* conductances */
  142.     cgd,  cgs,  cgb,            /* Meyer's capacitances */
  143.     cddb, cdgb, cdsb,            /* non-reciprocal capacitances */
  144.     cgdb, cggb, cgsb,
  145.     csdb, csgb, cssb,
  146.     cbdb, cbgb, cbsb,
  147.     ieq_qg, ieq_qb, ieq_qd,
  148.     qdrn, qgate, qsrc, qbulk, qchan,
  149.     gcddb, gcdgb, gcdsb,        /* non-rec. cap. equiv. conductances */
  150.     gcgdb, gcggb, gcgsb,
  151.     gcsdb, gcsgb, gcssb,
  152.     gcbdb, gcbgb, gcbsb,
  153.     id_hat, ib_hat,            /* predicted currents */
  154.     covlgs, covlgd, covlgb,        /* overlap capacitances */
  155.     xfact,                /* extrapolation factor */
  156.     type;                /* NMOS=+1, PMOS=-1 */
  157.  
  158.   int level;
  159.  
  160. #define    vt    VT
  161.  
  162.   int
  163.     charge,        /* flag that charge calc. be done */
  164.     jlim_fl = YES,    /* junction limiting flag: YES, NO */
  165.     pred_fl = NO,    /* pred. calculated  flag: YES, NO */
  166.     nonconv = NO;    /* non-convergence   flag: YES, NO */
  167.  
  168. /* defines & declarations for state-vector access */
  169.  
  170.   struct msv_def *sv[MSTVCT];
  171.  
  172.   EVAL_SV(sv,Instance,m_sda.m_sv);
  173.  
  174. #define ID0    (Instance->mcv_id)
  175. #define IBS0    (Instance->mcv_ibs)
  176. #define IBD0    (Instance->mcv_ibd)
  177.  
  178. #define GM0    (Instance->mcv_gm)
  179. #define GDS0    (Instance->mcv_gds)
  180. #define GMBS0    (Instance->mcv_gmbs)
  181. #define GBD0    (Instance->mcv_gbd)
  182. #define GBS0    (Instance->mcv_gbs)
  183.  
  184. #define CGGB0    (Instance->m_sda.m_ac.mac_cggb)
  185. #define CGDB0    (Instance->m_sda.m_ac.mac_cgdb)
  186. #define CGSB0    (Instance->m_sda.m_ac.mac_cgsb)
  187. #define CBGB0    (Instance->m_sda.m_ac.mac_cbgb)
  188. #define CBDB0    (Instance->m_sda.m_ac.mac_cbdb)
  189. #define CBSB0    (Instance->m_sda.m_ac.mac_cbsb)
  190. #define CDGB0    (Instance->m_sda.m_ac.mac_cdgb)
  191. #define CDDB0    (Instance->m_sda.m_ac.mac_cddb)
  192. #define CDSB0    (Instance->m_sda.m_ac.mac_cdsb)
  193. #define CBD0    (Instance->m_sda.m_ac.mac_cbd)
  194. #define CBS0    (Instance->m_sda.m_ac.mac_cbs)
  195. #define CGB0    (Instance->m_sda.m_ac.mac_cgbo)
  196. #define CGD0    (Instance->m_sda.m_ac.mac_cgdo)
  197. #define CGS0    (Instance->m_sda.m_ac.mac_cgso)
  198.  
  199. /* initialization */
  200.  
  201.   Model = Instance->m_model;        /* find the model */
  202.  
  203.   type  = Model->M_type > 0 ? 1.: -1.;
  204.  
  205.   if      ( InitFl==INSTV0 ) {        /* use prev. iteration */
  206.     double
  207.       vs = VOLTAGE(m_s);
  208.  
  209.     vds = ( VOLTAGE(m_d) - vs )*type;
  210.     vgs = ( VOLTAGE(m_g) - vs )*type;
  211.     vbs = ( VOLTAGE(m_b) - vs )*type;
  212.     }
  213.   else if ( InitFl==INTRAN ) {        /* use prev. time-step */
  214.     vds = M_VDS(1);
  215.     vgs = M_VGS(1);
  216.     vbs = M_VBS(1);
  217.     }
  218.   else if ( InitFl==INOFF &&        /* set "off" devices */
  219.             DevOff==YES)
  220.     vds = vgs = vbs = 0.;
  221.  
  222.   else if ( InitFl==ININIT ) {        /* use IC= values */
  223.  
  224.     if ( ModeFl==MDBPTR && NOSOLV==YES ) {
  225.       vds = DevVds*type;
  226.       vgs = DevVgs*type;
  227.       vbs = DevVbs*type;
  228.       }
  229.     else if ( DevOff==NO ) {
  230.       vds = 0.;
  231.       vgs = ModVto*type;
  232.       vbs = ModVinit;
  233.       }
  234.     else
  235.       vds = vgs = vbs = 0.;
  236.     }
  237.   else {
  238.     double del_vbs, del_vbd, del_vgs, del_vgd, del_vds, del_id, del_ib;
  239.  
  240.     if ( InitFl==INPRDCT ) {        /* extrapolate value */
  241.       xfact = DELTA/DELOLD[1];
  242.  
  243.       vds = xfact*( M_VDS(1) - M_VDS(2) ) + M_VDS(1);
  244.       vgs = xfact*( M_VGS(1) - M_VGS(2) ) + M_VGS(1);
  245.       vbs = xfact*( M_VBS(1) - M_VBS(2) ) + M_VBS(1);
  246.       *sv[0] = *sv[1];
  247.       }
  248.     else {                /* use current value */
  249.       double
  250.         vs = VOLTAGE(m_s);
  251.  
  252.       vds = ( VOLTAGE(m_d) - vs )*type;
  253.       vgs = ( VOLTAGE(m_g) - vs )*type;
  254.       vbs = ( VOLTAGE(m_b) - vs )*type;
  255.       }
  256.  
  257. /* compute new non-linear branch voltage */
  258.  
  259.     del_vds = vds - M_VDS(0);
  260.     del_vgs = vgs - M_VGS(0);
  261.     del_vgd = del_vgs - del_vds;
  262.     del_vbs = vbs - M_VBS(0);
  263.     del_vbd = del_vbs - del_vds;
  264.  
  265.     del_id = M_VDS(0) >= 0.
  266.            ? del_vds*GDS0 + del_vgs*GM0 - del_vbd*GBD0 + del_vbs*GMBS0
  267.            : del_vds*GDS0 - del_vgd*GM0 - del_vbd*GBD0 + del_vbd*GMBS0;
  268.     id_hat = del_id + ID0;
  269.  
  270.     del_ib = del_vbd*GBD0 + del_vbs*GBS0;
  271.     ib_hat = del_ib + IBS0 + IBD0;
  272.  
  273. /* bypass if solution not changed */
  274. /* note: check order based on frequency analysis of test suite circuits */
  275.  
  276.     if ( LoadFl ) ;
  277.     else if ( InitFl==INPRDCT && DELTA!=DELOLD[1] ) ;
  278. #if BYPASS==NO
  279.     else if (YES);
  280. #endif
  281.     else if ( fabs(del_vds) >= TOL(    vds,         M_VDS(0),RELTOL, VNTOL) ) ;
  282.     else if ( fabs(del_vgd) >= TOL(vgs-vds,M_VGS(0)-M_VDS(0),RELTOL, VNTOL) ) ;
  283.     else if ( fabs(del_vgs) >= TOL(    vgs,         M_VGS(0),RELTOL, VNTOL) ) ;
  284.     else if ( fabs(del_vbd) >= TOL(vbs-vds,M_VBS(0)-M_VDS(0),RELTOL, VNTOL) ) ;
  285.     else if ( fabs(del_vbs) >= TOL(    vbs,         M_VBS(0),RELTOL, VNTOL) ) ;
  286.     else if ( fabs(del_id)  >= TOL( id_hat,              ID0,RELTOL,ABSTOL) ) ;
  287.     else if ( fabs(del_ib)  >= TOL( ib_hat,        IBS0+IBD0,RELTOL,ABSTOL) ) ;
  288.     else {
  289.       goto done;
  290.       }
  291.     pred_fl = YES;
  292.  
  293. /* solution changed: limit non-linear branch voltages */
  294.  
  295.     vgd = vgs-vds;
  296.     vbd = vbs-vds;
  297.     von = DevVon*type;
  298.     FETlim(&vgs,M_VGS(0),         von);
  299.     FETlim(&vgd,M_VGS(0)-M_VDS(0),von);
  300.     vds = vgs-vgd;
  301.     vte = ModN*vt;
  302.  
  303.     if ( vds >= 0. ) {
  304.       if ( DevIssat > 0. ) {
  305.         double vcrit = vte*log(vte/(DevIssat*DevM*ROOT2));
  306.  
  307.         jlim_fl = PNJLIM(vbs,M_VBS(0),vte,vcrit);
  308.       } }
  309.     else {
  310.       if ( DevIdsat > 0. ) {
  311.         double vcrit = vte*log(vte/(DevIdsat*DevM*ROOT2));
  312.  
  313.         jlim_fl = PNJLIM(vbd,M_VBS(0)-M_VDS(0),vte,vcrit);
  314.         vbs     = vbd+vds;
  315.       } }
  316.     } /* end of initialization */
  317.  
  318. /* compute DC current and derivatives */
  319.  
  320.   vgd = vgs-vds;
  321.   vbd = vbs-vds;
  322.   vte = ModN*vt;
  323.   DevMode = vds >= 0. ? 1 : -1;
  324.  
  325.   if ( vbs > -10*vte ) {
  326.     double evbs = EXP(vbs/vte);
  327.  
  328.     gbs = (evbs/vte)*DevIssat*DevM + GMIN;
  329.     ibs = (evbs - 1)*DevIssat*DevM + vbs*GMIN;
  330.     }
  331.   else {
  332.     gbs = GMIN;
  333.     ibs = gbs*vbs - DevIssat*DevM;
  334.     }
  335.  
  336.   if ( vbd > -10*vte ) {
  337.     double evbd = EXP(vbd/vte);
  338.  
  339.     gbd = (evbd/vte)*DevIdsat*DevM + GMIN;
  340.     ibd = (evbd - 1)*DevIdsat*DevM + vbd*GMIN;
  341.     }
  342.   else {
  343.     gbd = GMIN;
  344.     ibd = gbd*vbd - DevIdsat*DevM;
  345.     }
  346.  
  347. /* decide if models need to calculate device charges */
  348.  
  349.   level = ModLevel;
  350.  
  351.   if ( ModeFl==MDTRAN || InitFl==INSTV0 ) {
  352.     if ( level==1 ||                /* when to use Meyer model */
  353.          level==2 && ModXqc > .5 ||
  354.          level==3 ||
  355.          level==4 && PARAM_MOD(BSIM_xpart) < 0.)
  356.       charge = NO;
  357.     else
  358.       charge = YES;
  359.     }
  360.   else
  361.     charge = NO;
  362.  
  363. /* compute drain current and derivatives (evaluate device models) */
  364.  
  365.   { double
  366.       len =  DevL - ModLd*( level==4 ? 1e-6 : 2.),
  367.       wid = (DevW - ModWd*( level==4 ? 1e-6 : 2.))*DevM;
  368.  
  369.     Cox    = ModTox==0. ? 0. : wid*len*EPSOX/ModTox;    /* save for Cmeyer */
  370.     covlgs = ModCgso*wid;
  371.     covlgd = ModCgdo*wid;
  372.     covlgb = ModCgbo*len;
  373.  
  374.     switch ( level ) {
  375.       case 1:                /* MOS1: Shichman-Hodges */
  376.         if ( DevMode > 0 ) MOS1eval(
  377.             Model,len,wid,      vgs, vds,vbs,&von,&vdsat,&idr,&gds,&gm,&gmbs
  378.             );
  379.         else               MOS1eval(
  380.             Model,len,wid,      vgd,-vds,vbd,&von,&vdsat,&idr,&gds,&gm,&gmbs
  381.             );
  382.         break;
  383.       case 2:                /* MOS2: analytic */
  384.         Xqc = ModXqc;
  385.         if ( DevMode > 0 ) MOS2eval(
  386.             Model,len,wid,DevM, vgs, vds,vbs,&von,&vdsat,&idr,&gds,&gm,&gmbs,
  387.             charge,&cggb,&cgdb,&cgsb,&cbgb,&cbdb,&cbsb,&qgate,&qchan,&qbulk
  388.             );
  389.         else               MOS2eval(
  390.             Model,len,wid,DevM, vgd,-vds,vbd,&von,&vdsat,&idr,&gds,&gm,&gmbs,
  391.             charge,&cggb,&cgsb,&cgdb,&cbgb,&cbsb,&cbdb,&qgate,&qchan,&qbulk
  392.             );
  393.         break;
  394.       case 3:                /* MOS3: semi-empirical */
  395.         if ( DevMode > 0 ) MOS3eval(
  396.             Model,len,wid,DevM, vgs, vds,vbs,&von,&vdsat,&idr,&gds,&gm,&gmbs,
  397.             charge,&cggb,&cgdb,&cgsb,&cbgb,&cbdb,&cbsb,&qgate,&qchan,&qbulk
  398.             );
  399.         else               MOS3eval(
  400.             Model,len,wid,DevM, vgd,-vds,vbd,&von,&vdsat,&idr,&gds,&gm,&gmbs,
  401.             charge,&cggb,&cgsb,&cgdb,&cbgb,&cbsb,&cbdb,&qgate,&qchan,&qbulk
  402.             );
  403.         break;
  404. #if BSIM==YES
  405.       case 4:                /* MOS4: BSIM */
  406.         if ( DevMode > 0 ) MOS4eval(
  407.             Model,len,wid,DevM, vgs, vds,vbs,&von,&vdsat,&idr,&gds,&gm,&gmbs,
  408.             charge,&cggb,&cgdb,&cgsb,&cdgb,&cddb,&cdsb,&cbgb,&cbdb,&cbsb,
  409.             &qgate,&qdrn,&qbulk
  410.             );
  411.         else               MOS4eval(
  412.             Model,len,wid,DevM, vgd,-vds,vbd,&von,&vdsat,&idr,&gds,&gm,&gmbs,
  413.             charge,&cggb,&cgsb,&cgdb,&csgb,&cssb,&csdb,&cbgb,&cbsb,&cbdb,
  414.             &qgate,&qsrc,&qbulk
  415.             );
  416.         break;
  417. #endif
  418.       default:;
  419.     } }
  420.  
  421. /* save values for next iteration */
  422.  
  423.   DevVon   = von*type;
  424.   DevVdsat = vdsat*type;
  425.  
  426.   if ( ModXqc <= .5 ) DevXqc = Xqc;
  427.  
  428. /* compute equivalent drain current source */
  429.  
  430.   id  = DevMode*idr + vds*ModGdspr*DevM - ibd;
  431.   gds = gds + ModGdspr*DevM;
  432.  
  433. /* charge calculations */
  434.  
  435.   if ( ModeFl==MDTRAN ||
  436.        InitFl==INSTV0 ||
  437.      ( ModeFl==MDBPTR && NOSOLV==YES ) ) {
  438.     double
  439.       cap_bd = 0.,    /* junction capacitances */
  440.       cap_bs = 0.,
  441.       vgb    = vgs-vbs;
  442.  
  443.     M_QCBD(0) = M_QCBS(0) = 0.;
  444.  
  445. /* calculate values for depletion capacitors */
  446.  
  447.     if ( ModCbd != 0.||
  448.          ModCbs != 0.) {
  449.       MOSpnjc(&M_QCBD(0),&cap_bd,ModCbd*DevM,       vbd,ModPb,  ModFc,ModMj);
  450.       MOSpnjc(&M_QCBS(0),&cap_bs,ModCbs*DevM,       vbs,ModPb,  ModFc,ModMj);
  451.       }
  452.     else if ( ModCj != 0.) {
  453.       MOSpnjc(&M_QCBD(0),&cap_bd,ModCj*DevAd*DevM,  vbd,ModPb,  ModFc,ModMj);
  454.       MOSpnjc(&M_QCBS(0),&cap_bs,ModCj*DevAs*DevM,  vbs,ModPb,  ModFc,ModMj);
  455.       }
  456.  
  457.     if ( ModCjsw != 0.) {
  458.       MOSpnjc(&M_QCBD(0),&cap_bd,ModCjsw*DevPd*DevM,vbd,ModPbsw,ModFc,ModMjsw);
  459.       MOSpnjc(&M_QCBS(0),&cap_bs,ModCjsw*DevPs*DevM,vbs,ModPbsw,ModFc,ModMjsw);
  460.       }
  461.  
  462.     if ( ModTt!=0. ) {            /* include transit time effects */
  463.       M_QCBD(0) += ModTt*ibd; cap_bd += ModTt*gbd;
  464.       M_QCBS(0) += ModTt*ibs; cap_bs += ModTt*gbs;
  465.       }
  466.  
  467.     M_ICBD(0) =        /* reset, so T=0 results (e.g. Probe) are correct */
  468.     M_ICBS(0) = 0.;
  469.  
  470.     if ( !(ModeFl==MDBPTR && NOSOLV==NO) ) {    /* transient analysis */
  471.       double g_eq, i_eq;
  472.  
  473. /* calculate equivalent conductances and currents for depletion capacitors */
  474.  
  475.       if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  476.         M_QCBD(2) = M_QCBD(1) = M_QCBD(0);    /* set "old" charges so */
  477.         M_QCBS(2) = M_QCBS(1) = M_QCBS(0);    /* integration works */
  478.         }
  479.  
  480.       INTEGR8(g_eq,i_eq,cap_bd,M_QIBD(0),M_QIBD(1),M_QIBD(2));
  481.       gbd += g_eq;
  482.       ibd += M_ICBD(0);
  483.       id  -= M_ICBD(0);
  484.  
  485.       INTEGR8(g_eq,i_eq,cap_bs,M_QIBS(0),M_QIBS(1),M_QIBS(2));
  486.       gbs += g_eq;
  487.       ibs += M_ICBS(0);
  488.  
  489.       if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  490.         M_ICBD(1) = M_ICBD(0);            /* set "old" currents so */
  491.         M_ICBS(1) = M_ICBS(0);            /* time-step calc. works */
  492.         }
  493.       } /* end of junction charge calculations */
  494.  
  495.     if ( charge==NO ) {            /*** Meyer capacitance model ***/
  496.       double
  497.         ieq_gs, gcgs,
  498.         ieq_gd, gcgd,
  499.         ieq_gb, gcgb;
  500.  
  501.       gcgs = ieq_gs =
  502.       gcgd = ieq_gd =
  503.       gcgb = ieq_gb = 0.;
  504.  
  505.       if ( DevMode==1 )
  506.         Cmeyer(Model,&vgs,&vgd,&vgb,&von,&vdsat,&cgs,&cgd,&cgb);
  507.       else
  508.         Cmeyer(Model,&vgd,&vgs,&vgb,&von,&vdsat,&cgd,&cgs,&cgb);
  509.  
  510.       M_CGD(0) = cgd;    /* save values for next time point */
  511.       M_CGS(0) = cgs;
  512.       M_CGB(0) = cgb;
  513.  
  514.       M_ICGD(0) =    /* reset, so T=0 results (e.g. Probe) are correct */
  515.       M_ICGS(0) =        
  516.       M_ICGB(0) = 0.;
  517.  
  518.       if ( ModeFl==MDTRAN && InitFl!=INTRAN ) {
  519.         cgd = covlgd + .5*(cgd + M_CGD(1));
  520.         cgs = covlgs + .5*(cgs + M_CGS(1));
  521.         cgb = covlgb + .5*(cgb + M_CGB(1));
  522.         }
  523.       else {
  524.         cgd += covlgd;
  525.         cgs += covlgs;
  526.         cgb += covlgb;
  527.         }
  528.  
  529.       if ( InitFl==INSTV0) {        /* store small-signal parameters */
  530.         CGD0 = cgd;            /* and update the state vector */
  531.         CGS0 = cgs;
  532.         CGB0 = cgb;
  533.         CBD0 = cap_bd;
  534.         CBS0 = cap_bs;
  535.  
  536.         gcdgb = gcddb = gcdsb =
  537.         gcsgb = gcsdb = gcssb =
  538.         gcggb = gcgdb = gcgsb =
  539.         gcbgb = gcbdb = gcbsb =
  540.         ieq_qg = ieq_qb = ieq_qd = 0.;
  541.  
  542.         goto load;
  543.         }
  544.  
  545.       if ( !(ModeFl==MDBPTR && NOSOLV==NO) ) {    /* transient analysis */
  546.  
  547.         if ( InitFl==INPRDCT ) {
  548.           M_QCGD(0) = ( M_QCGD(1) - M_QCGD(2) )*xfact + M_QCGD(1);
  549.           M_QCGS(0) = ( M_QCGS(1) - M_QCGS(2) )*xfact + M_QCGS(1);
  550.           M_QCGB(0) = ( M_QCGB(1) - M_QCGB(2) )*xfact + M_QCGB(1);
  551.           }
  552.         else {
  553.           double
  554.             vgs1 = M_VGS(1),
  555.             vgd1 = vgs1 - M_VDS(1),
  556.             vgb1 = vgs1 - M_VBS(1);
  557.  
  558.           M_QCGD(0) = (vgd - vgd1)*cgd;
  559.           M_QCGS(0) = (vgs - vgs1)*cgs;
  560.           M_QCGB(0) = (vgb - vgb1)*cgb;
  561.  
  562.           if ( ModeFl==MDTRAN && InitFl!=INTRAN ) {
  563.             M_QCGD(0) += M_QCGD(1);
  564.             M_QCGS(0) += M_QCGS(1);
  565.             M_QCGB(0) += M_QCGB(1);
  566.           } }
  567.  
  568.         if ( InitFl==INTRAN ) {        /* for 1st transient step: set */
  569.           M_QCGD(2) = M_QCGD(1) = M_QCGD(0) = vgd*cgd;    /* "old" charges so */
  570.           M_QCGS(2) = M_QCGS(1) = M_QCGS(0) = vgs*cgs;    /* integration works */
  571.           M_QCGB(2) = M_QCGB(1) = M_QCGB(0) = vgb*cgb;
  572.           }
  573.  
  574.         if ( M_CGD(0)==0. ) M_ICGD(0) = 0.;
  575.         if ( M_CGS(0)==0. ) M_ICGS(0) = 0.;
  576.         if ( M_CGB(0)==0. ) M_ICGB(0) = 0.;
  577.  
  578.         INTEGR8(gcgd,ieq_gd,cgd,M_QIGD(0),M_QIGD(1),M_QIGD(2));
  579.         ieq_gd = M_ICGD(0) - gcgd*vgd;
  580.  
  581.         INTEGR8(gcgs,ieq_gs,cgs,M_QIGS(0),M_QIGS(1),M_QIGS(2));
  582.         ieq_gs = M_ICGS(0) - gcgs*vgs;
  583.  
  584.         INTEGR8(gcgb,ieq_gb,cgb,M_QIGB(0),M_QIGB(1),M_QIGB(2));
  585.         ieq_gb = M_ICGB(0) - gcgb*vgb;
  586.  
  587.         if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  588.           M_ICGD(1) = M_ICGD(0);        /* set "old" currents so */
  589.           M_ICGS(1) = M_ICGS(0);        /* time-step calc. works */
  590.           M_ICGB(1) = M_ICGB(0);
  591.         } }
  592.  
  593.     /* map Meyer's model to charge-oriented model */
  594.  
  595.       ieq_qg =  ieq_gs + ieq_gb + ieq_gd;
  596.       ieq_qb = -ieq_gb;
  597.       ieq_qd = -ieq_gd;
  598.  
  599.       gcgdb = gcdgb = -( gcddb = gcgd );
  600.       gcgsb = gcsgb = -( gcssb = gcgs );
  601.  
  602.       gcbgb = -gcgb;
  603.  
  604.       gcggb =  gcgd + gcgs + gcgb;
  605.  
  606.       gcsdb = gcdsb =
  607.       gcbdb = gcbsb = 0.;
  608.  
  609.       } /* end of Meyer charge calculations */
  610.  
  611. #if BSIM==YES
  612.     else if ( level==4 ) {        /*** BSIM charge model ***/
  613.  
  614.       if ( DevMode > 0 )
  615.         MOS4cap(vgd,vgs,vgb,
  616.           covlgd,covlgs,covlgb,
  617.           cggb,cgdb,cgsb,
  618.           cbgb,cbdb,cbsb,
  619.           cdgb,cddb,cdsb,
  620.           &gcggb,&gcgdb,&gcgsb,
  621.           &gcbgb,&gcbdb,&gcbsb,
  622.           &gcdgb,&gcddb,&gcdsb,
  623.           &gcsgb,&gcsdb,&gcssb,
  624.           &qgate,&qbulk,&qdrn,&qsrc);
  625.       else
  626.         MOS4cap(vgs,vgd,vgb,
  627.           covlgs,covlgd,covlgb,
  628.           cggb,cgsb,cgdb,
  629.           cbgb,cbsb,cbdb,
  630.           csgb,cssb,csdb,
  631.           &gcggb,&gcgsb,&gcgdb,
  632.           &gcbgb,&gcbsb,&gcbdb,
  633.           &gcsgb,&gcssb,&gcsdb,
  634.           &gcdgb,&gcdsb,&gcddb,
  635.           &qgate,&qbulk,&qsrc,&qdrn);
  636.  
  637.       M_QCG(0) = qgate;
  638.       M_QCD(0) = qdrn;
  639.       M_QCB(0) = qbulk;
  640.  
  641.       M_ICG(0) =    /* reset, so T=0 results (e.g. Probe) are correct */
  642.       M_ICD(0) =        
  643.       M_ICB(0) = 0.;
  644.  
  645.       if ( InitFl==INSTV0 ) {        /* store small-signal parameters */
  646.         CGDB0 = cgdb;            /* and update the state vector */
  647.         CGGB0 = cggb;
  648.         CGSB0 = cgsb;
  649.  
  650.         CBDB0 = cbdb;
  651.         CBGB0 = cbgb;
  652.         CBSB0 = cbsb;
  653.  
  654.         if ( DevMode > 0 )
  655.           CDDB0 = cddb,
  656.           CDGB0 = cdgb,
  657.           CDSB0 = cdsb;
  658.         else
  659.           CDDB0 = cssb,
  660.           CDGB0 = csgb,
  661.           CDSB0 = csdb;
  662.  
  663.         CBD0 = cap_bd;
  664.         CBS0 = cap_bs;
  665.  
  666.         ieq_qg = ieq_qb = ieq_qd = 0.;
  667.  
  668.         goto load;
  669.         }
  670.  
  671.       if ( !(ModeFl==MDBPTR && NOSOLV==NO) ) {    /* transient analysis */
  672.         double g_eq, i_eq;
  673.  
  674.         if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  675.           M_QCG(2) = M_QCG(1) = M_QCG(0);    /* set "old" charges so */
  676.           M_QCD(2) = M_QCD(1) = M_QCD(0);    /* integration works */
  677.           M_QCB(2) = M_QCB(1) = M_QCB(0);
  678.           }
  679.  
  680.         INTEGR8(g_eq,i_eq,0.,M_QICG(0),M_QICG(1),M_QICG(2));
  681.         ieq_qg = M_ICG(0) - gcggb*vgb + gcgdb*vbd + gcgsb*vbs;
  682.  
  683.         INTEGR8(g_eq,i_eq,0.,M_QICD(0),M_QICD(1),M_QICD(2));
  684.         ieq_qd = M_ICD(0) - gcdgb*vgb + gcddb*vbd + gcdsb*vbs;
  685.  
  686.         INTEGR8(g_eq,i_eq,0.,M_QICB(0),M_QICB(1),M_QICB(2));
  687.         ieq_qb = M_ICB(0) - gcbgb*vgb + gcbdb*vbd + gcbsb*vbs;
  688.  
  689.         if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  690.           M_ICG(1) = M_ICG(0);            /* set "old" currents so */
  691.           M_ICD(1) = M_ICD(0);            /* time-step calc. works */
  692.           M_ICB(1) = M_ICB(0);
  693.           }
  694.       } } /* end of BSIM charge calculations */
  695. #endif
  696.  
  697.     else {            /*** Ward-Dutton charge model ***/
  698.  
  699.       if ( DevMode > 0 )
  700.         MOScap(
  701.           &vgd, &vgs, &vgb,
  702.           &covlgd, &covlgs, &covlgb,
  703.           &cggb,   &cgdb,  &cgsb,
  704.           &cbgb,   &cbdb,  &cbsb,
  705.           &gcggb, &gcgdb, &gcgsb,
  706.           &gcbgb, &gcbdb, &gcbsb,
  707.           &gcdgb, &gcddb, &gcdsb,
  708.           &gcsgb, &gcsdb, &gcssb,
  709.           &qdrn, &qgate, &qsrc, &qbulk, &qchan);
  710.       else
  711.         MOScap(
  712.           &vgs, &vgd, &vgb,
  713.           &covlgs, &covlgd, &covlgb,
  714.           &cggb,  &cgsb,  &cgdb,
  715.           &cbgb,  &cbsb,  &cbdb,
  716.           &gcggb, &gcgsb, &gcgdb,
  717.           &gcbgb, &gcbsb, &gcbdb,
  718.           &gcsgb, &gcssb, &gcsdb,
  719.           &gcdgb, &gcdsb, &gcddb,
  720.           &qsrc, &qgate, &qdrn, &qbulk, &qchan);
  721.  
  722.       M_QCG(0) = qgate;
  723.       M_QCD(0) = qdrn;
  724.       M_QCB(0) = qbulk;
  725.  
  726.       M_ICG(0) =    /* reset, so T=0 results (e.g. Probe) are correct */
  727.       M_ICD(0) =        
  728.       M_ICB(0) = 0.;
  729.  
  730.       if ( InitFl==INSTV0 ) {        /* store small-signal parameters */
  731.         CGGB0 = cggb;            /* and update the state vector */
  732.         CGDB0 = cgdb;
  733.         CGSB0 = cgsb;
  734.         CBGB0 = cbgb;
  735.         CBDB0 = cbdb;
  736.         CBSB0 = cbsb;
  737.         CBD0  = cap_bd;
  738.         CBS0  = cap_bs;
  739.  
  740.         ieq_qg = ieq_qb = ieq_qd = 0.;
  741.  
  742.         goto load;
  743.         }
  744.  
  745.       if ( !(ModeFl==MDBPTR && NOSOLV==NO) ) {    /* transient analysis */
  746.         double g_eq, i_eq;
  747.  
  748.         if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  749.           M_QCG(2) = M_QCG(1) = M_QCG(0);    /* set "old" charges so */
  750.           M_QCD(2) = M_QCD(1) = M_QCD(0);    /* integration works */
  751.           M_QCB(2) = M_QCB(1) = M_QCB(0);
  752.           }
  753.  
  754.         INTEGR8(g_eq,i_eq,0.,M_QICG(0),M_QICG(1),M_QICG(2));
  755.         ieq_qg = M_ICG(0) - gcggb*vgb + gcgdb*vbd + gcgsb*vbs;
  756.  
  757.         INTEGR8(g_eq,i_eq,0.,M_QICD(0),M_QICD(1),M_QICD(2));
  758.         ieq_qd = M_ICD(0) - gcdgb*vgb + gcddb*vbd + gcdsb*vbs;
  759.  
  760.         INTEGR8(g_eq,i_eq,0.,M_QICB(0),M_QICB(1),M_QICB(2));
  761.         ieq_qb = M_ICB(0) - gcbgb*vgb + gcbdb*vbd + gcbsb*vbs;
  762.  
  763.         if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  764.           M_ICG(1) = M_ICG(0);            /* set "old" currents so */
  765.           M_ICD(1) = M_ICD(0);            /* time-step calc. works */
  766.           M_ICB(1) = M_ICB(0);
  767.           }
  768.       } } /* end of Ward-Dutton charge calculations */
  769.  
  770.     } /* end of all charge calculations */
  771.   else {
  772.     gcdgb = gcddb = gcdsb =
  773.     gcsgb = gcsdb = gcssb =
  774.     gcggb = gcgdb = gcgsb =
  775.     gcbgb = gcbdb = gcbsb =
  776.     ieq_qg = ieq_qb = ieq_qd = 0.;
  777.     }
  778.  
  779. /* check convergence */
  780.  
  781.   if ( pred_fl && (
  782.          jlim_fl ||
  783.          fabs(id_hat-id)        > TOL(id_hat,       id,RELTOL,ABSTOL) ||
  784.          fabs(ib_hat-(ibs+ibd)) > TOL(ib_hat,(ibs+ibd),RELTOL,ABSTOL)
  785.          )
  786.        ) nonconv = YES;
  787.  
  788. load:
  789.   { int fwd = ( DevMode > 0 ? YES : NO );
  790.     double
  791.       ggpr, gdpr, gspr, gbpr,
  792.       ieq_bs = ibs - gbs*vbs,
  793.       ieq_bd = ibd - gbd*vbd,
  794.       idr_eq = fwd
  795.              ?  idr - (gm*vgs + (gds-ModGdspr*DevM)*vds + gmbs*vbs)
  796.              :-(idr - (gm*vgd - (gds-ModGdspr*DevM)*vds + gmbs*vbd) );
  797.  
  798.     /* load current vector */
  799.  
  800.     Y_MATRIX(m_ig) = -type*ieq_qg;
  801.     Y_MATRIX(m_ib) = -type*(ieq_bs + ieq_bd + ieq_qb);
  802.     Y_MATRIX(m_id) = -type*(idr_eq - ieq_bd + ieq_qd);
  803.     Y_MATRIX(m_is) =  type*(idr_eq + ieq_bs + ieq_qd + ieq_qb + ieq_qg);
  804.  
  805.     /* load conductance matrix */
  806.  
  807.     Y_MATRIX(m_gd) =  gcgdb;
  808.     Y_MATRIX(m_gs) =  gcgsb;
  809.     Y_MATRIX(m_gb) = -gcggb - gcgdb - gcgsb;
  810.     Y_MATRIX(m_gg) =  gcggb
  811.                    + ( ggpr = DevGgpr*DevM );
  812.  
  813.     Y_MATRIX(m_dg) = ( fwd ?  gm   :   -gm ) + gcdgb;
  814.     Y_MATRIX(m_ds) = ( fwd ? -gm-gmbs : 0. ) + gcdsb - gds;
  815.     Y_MATRIX(m_db) = ( fwd ?  gmbs : -gmbs ) - gcddb - gcdgb - gcdsb - gbd;
  816.     Y_MATRIX(m_dd) = ( fwd ?  0.:  gm+gmbs ) + gcddb + gds + gbd
  817.                    + ( gdpr = DevGdpr*DevM ) ;
  818.  
  819.     Y_MATRIX(m_sg) = ( fwd ? -gm   :    gm ) + gcsgb;
  820.     Y_MATRIX(m_sd) = ( fwd ?  0.: -gm-gmbs ) + gcsdb - gds;
  821.     Y_MATRIX(m_sb) = ( fwd ? -gmbs :  gmbs ) - gcssb - gcsgb - gcsdb - gbs;
  822.     Y_MATRIX(m_ss) = ( fwd ?  gm+gmbs : 0. ) + gcssb + gds + gbs
  823.                    + ( gspr = DevGspr*DevM );
  824.  
  825.     Y_MATRIX(m_bg) = gcbgb;
  826.     Y_MATRIX(m_bd) = gcbdb - gbd;
  827.     Y_MATRIX(m_bs) = gcbsb - gbs;
  828.     Y_MATRIX(m_bb) = gbd + gbs - gcbgb - gcbdb - gcbsb
  829.                    + ( gbpr = DevGbpr*DevM );
  830.  
  831.     if ( LoadFl ) {
  832.       Y_MATRIX(m_gG) = Y_MATRIX(m_Gg) = - ( Y_MATRIX(m_GG) = ggpr );
  833.       Y_MATRIX(m_dD) = Y_MATRIX(m_Dd) = - ( Y_MATRIX(m_DD) = gdpr );
  834.       Y_MATRIX(m_sS) = Y_MATRIX(m_Ss) = - ( Y_MATRIX(m_SS) = gspr );
  835.       Y_MATRIX(m_bB) = Y_MATRIX(m_Bb) = - ( Y_MATRIX(m_BB) = gbpr );
  836.     } }
  837.  
  838.   M_VDS(0) = vds;
  839.   M_VGS(0) = vgs;
  840.   M_VBS(0) = vbs;
  841.  
  842.   ID0  = id;
  843.   IBS0 = ibs;
  844.   IBD0 = ibd;
  845.  
  846.   GM0   = gm;
  847.   GDS0  = gds;
  848.   GMBS0 = gmbs;
  849.   GBD0  = gbd;
  850.   GBS0  = gbs;
  851.  
  852. done:
  853.   return nonconv;
  854.   }
  855.  
  856. /* */
  857. #ifndef cc_noline
  858. #line 4 "MOSpnjc"
  859. #endif
  860.  
  861. void MOSpnjc(    /* calc. p-n junction charge and capacitance */
  862.   chg,        /* (pointer to) charge */
  863.   cap,        /* (pointer to) capacitance */
  864.   cjo,        /* zero-bias capacitance */
  865.   vj,        /* junction bias */
  866.   pb,        /* p-n potential */
  867.   fc,        /* forward-bias capacitance coefficient */
  868.   mj        /* junction grading coefficient */
  869.   )
  870.   double *chg, *cap, cjo, vj, pb, fc, mj;
  871.  
  872. /* Discussion:
  873.     Charge and capacitance is calculated and added to the pointed-to value,
  874.     so be sure to initialize these values.  This is done so sidewall values
  875.     may be added to the area values.
  876. */
  877. /*
  878. 29 Dec 87 pwt    creation
  879. 12 Aug 88 pwt    allow grading coefficient, mj, to be 1.0 (and beyond).
  880. */
  881. { if ( vj <= fc*pb ) {
  882.     double
  883.       arg  = 1 - vj/pb,
  884.       sarg = mj==.5 ? 1/sqrt(arg) : pow(arg,-mj);
  885.  
  886.     *chg += cjo*pb*( mj==1.? -log(arg) : (1-arg*sarg)/(1-mj) );
  887.     *cap += cjo*sarg;
  888.     }
  889.   else {
  890.     double
  891.       arg  = 1-fc,
  892.       varg = (vj - fc*pb)/arg,
  893.       xarg = varg/pb,
  894.       sarg = mj==.5 ? sqrt(arg) : pow(arg,1-mj);
  895.  
  896.     *chg += cjo*( pb*( mj==1.? -log(arg) : (1-sarg)/(1-mj) )
  897.                 + (1 +.5*xarg*mj)*varg*sarg );
  898.     *cap += cjo*(1 + xarg*mj)*sarg/arg;
  899.   } }
  900. /* */
  901. #ifndef cc_noline
  902. #line 4 "MOS1eval"
  903. #endif
  904.  
  905. void MOS1eval(    /* evaluate MOS level 1 (Shichman-Hodges) model */
  906.   Model,    /* device model */
  907.   Len, Wid,    /* device size */
  908.   Vgs, Vds, Vbs,/* terminal voltages */
  909.   Von, Vdsat,    /* return: device characteristic voltages */
  910.   Id,        /* return: drain current */
  911.   Gds, Gm, Gmbs    /* return: device conductances */
  912.   )
  913.   struct M_ *Model;
  914.   double Len, Wid, Vgs, Vds, Vbs, *Von, *Vdsat, *Id, *Gds, *Gm, *Gmbs;
  915.  
  916. /*
  917. pwt    22 Aug 86    creation
  918. pwt    10 Oct 87    re-work as part of BSIM addition
  919. */
  920. { double
  921.     sarg, vgst,
  922.     beta = ModKp*Wid/Len;
  923.  
  924.   if ( Vbs > 0. ) {
  925.     sarg = sqrt(ModPhi);
  926.     sarg = sarg - .5*Vbs/sarg;
  927.     sarg = MAX(sarg,0.);
  928.     }
  929.   else
  930.     sarg = sqrt(ModPhi-Vbs);
  931.  
  932.   *Von   = ModGamma*sarg + ModVbi*(Model->M_type);
  933.   vgst   = Vgs - *Von;
  934.   *Vdsat = MAX(vgst,0.);
  935.  
  936.   if ( vgst > 0. ) {
  937.     double betap = beta*(ModLambda*Vds + 1);
  938.  
  939.     if ( vgst > Vds ) {            /* linear region */
  940.       *Gm  = betap*Vds;
  941.       *Id  = *Gm*(vgst-.5*Vds);
  942.       *Gds = betap*(vgst-Vds) + beta*ModLambda*Vds*(vgst-.5*Vds);
  943.       }
  944.     else {                /* saturated region */
  945.       *Gm  = betap*vgst;
  946.       *Id  = *Gm*.5*vgst;
  947.       *Gds = .5*ModLambda*beta*vgst*vgst;
  948.       }
  949.     *Gmbs = ( sarg > 0. ? *Gm*.5*ModGamma/sarg : 0. );
  950.     }
  951.   else                    /* cut-off region */
  952.     *Gm = *Gds = *Gmbs = *Id = 0.;
  953.  
  954.   } /* done */
  955.  
  956. /* */
  957. #ifndef cc_noline
  958. #line 4 "MOScap"
  959. #endif
  960.  
  961. void MOScap(        /* evaluate MOS capacitor equivalent conductances */
  962.   Vgd, Vgs, Vgb,    /* terminal voltages */
  963.   Covlgd, Covlgs, Covlgb,    /* overlap capacitances */
  964.   Cggb, Cgdb, Cgsb,    /* gate capacitances */
  965.   Cbgb, Cbdb, Cbsb,    /* bulk capacitances */
  966.   Gcggb, Gcgdb, Gcgsb,    /* return: gate conductances */
  967.   Gcbgb, Gcbdb, Gcbsb,    /* return: bulk conductances */
  968.   Gcdgb, Gcddb, Gcdsb,    /* return: drain conductances */
  969.   Gcsgb, Gcsdb, Gcssb,    /* return: source conductances */
  970.   Qdrn, Qgate, Qsrc,    /* return: device charges */
  971.   Qbulk, Qchan
  972.   )
  973.   double
  974.     *Vgd, *Vgs, *Vgb,
  975.     *Covlgd, *Covlgs, *Covlgb,
  976.     *Cggb, *Cgdb, *Cgsb,
  977.     *Cbgb, *Cbdb, *Cbsb,
  978.     *Gcggb, *Gcgdb, *Gcgsb,
  979.     *Gcbgb, *Gcbdb, *Gcbsb,
  980.     *Gcdgb, *Gcddb, *Gcdsb,
  981.     *Gcsgb, *Gcsdb, *Gcssb,
  982.     *Qdrn, *Qgate, *Qsrc,
  983.     *Qbulk, *Qchan;
  984.  
  985. /* Discussion: divide up the channel charge (1-xqc)/xqc to source and drain */
  986.  
  987. /*
  988. pwt    28 Aug 86    creation
  989. pwt    29 Dec 86    housekeeping
  990. pwt    19 Feb 88    bug (dating to SPICE2G.6):
  991.             remove junction caps from calculations (these are
  992.             already accounted for in I-vector and G-matrix load)
  993. pwt    18 Mar 88    re-write for clarity
  994. */
  995. { double
  996.     cg   = -(*Cggb + *Cbgb),
  997.     cgxd = cg*Xqc,
  998.     cgxs = cg-cgxd;
  999.   double
  1000.     cd   = -(*Cgdb + *Cbdb),
  1001.     cdxd = cd*Xqc,
  1002.     cdxs = cd-cdxd;
  1003.   double
  1004.     cs   = -(*Cgsb + *Cbsb),
  1005.     csxd = cs*Xqc,
  1006.     csxs = cs-csxd;
  1007.  
  1008.   *Gcdsb = AG1*csxd;
  1009.   *Gcdgb = AG1*(cgxd - *Covlgd);
  1010.   *Gcddb = AG1*(cdxd + *Covlgd);
  1011.  
  1012.   *Gcsdb = AG1*cdxs;
  1013.   *Gcsgb = AG1*(cgxs - *Covlgs);
  1014.   *Gcssb = AG1*(csxs + *Covlgs);
  1015.  
  1016.   *Gcggb = AG1*(*Cggb + *Covlgd + *Covlgs + *Covlgb);
  1017.   *Gcgdb = AG1*(*Cgdb - *Covlgd);
  1018.   *Gcgsb = AG1*(*Cgsb - *Covlgs);
  1019.  
  1020.   *Gcbgb = AG1*(*Cbgb - *Covlgb);
  1021.   *Gcbdb = AG1*(*Cbdb);
  1022.   *Gcbsb = AG1*(*Cbsb);
  1023.  
  1024. /* compute total terminal charges */
  1025.  
  1026.   { double
  1027.       qgd = *Covlgd * *Vgd,
  1028.       qgs = *Covlgs * *Vgs,
  1029.       qgb = *Covlgb * *Vgb;
  1030.  
  1031.     *Qgate += qgd + qgs + qgb;
  1032.     *Qbulk -= qgb;
  1033.  
  1034.     *Qdrn = *Qchan*Xqc - qgd;
  1035.     *Qsrc = *Qchan*(1-Xqc) - qgs;
  1036.     }
  1037.   } /* done */
  1038.  
  1039. /* */
  1040. #ifndef cc_noline
  1041. #line 4 "Cmeyer"
  1042. #endif
  1043.  
  1044. void Cmeyer(    /* evaluate MOS capacitances (Meyer model) */
  1045.   Model,    /* device model */
  1046.   Vgs, Vgd, Vgb,/* device voltages */
  1047.   Von, Vdsat,
  1048.   Cgs, Cgd, Cgb    /* return: device capacitances */
  1049.   )
  1050.   struct M_ *Model;
  1051.   double *Vgs, *Vgd, *Vgb, *Von, *Vdsat, *Cgs, *Cgd, *Cgb;
  1052.  
  1053. /*
  1054. pwt    86-08-28    creation
  1055. pwt    87-09-15    re-written to do one set of calc's at a time
  1056.             and use pointers instead of copying d.p. floats
  1057. pwt    87-12-21    correction for Microsoft optimization
  1058. */
  1059. { double
  1060.     vds  = *Vgs - *Vgd,
  1061.     vgbt = *Von - *Vgs;    /* gate: voltage "below" threshold */
  1062.  
  1063.   *Cgs = *Cgd = *Cgb = 0.;
  1064.  
  1065.   if ( vgbt >= ModPhi )
  1066.     *Cgb = Cox;
  1067.  
  1068.   else if ( vgbt >= .5*ModPhi )
  1069.     *Cgb = Cox*vgbt/ModPhi;
  1070.  
  1071.   else if ( vgbt >= 0. ) {
  1072.     *Cgb = Cox*vgbt/ModPhi;
  1073.     *Cgs = (.5*Cox - *Cgb)/.75;
  1074.     }
  1075.   else {
  1076.     double
  1077.       vbs    = *Vgs - *Vgb,
  1078.       vdbsat = *Vdsat - vbs,
  1079.       vdb    = MAX( *Vgb - *Vgd, 0.0);
  1080.  
  1081.     if ( vdbsat <= vdb )
  1082.       *Cgs = Cox/1.5;
  1083.  
  1084.     else {
  1085.       double
  1086.         vddif  = 2*vdbsat - vdb,
  1087.         vddif1 = vdbsat - vdb - 1E-12,
  1088.         vddif2 = vddif*vddif;
  1089.  
  1090.       *Cgd = Cox*(1 - vdbsat*vdbsat/vddif2)/1.5;
  1091.       *Cgs = Cox*(1 - vddif1*vddif1/vddif2)/1.5;
  1092.     } }
  1093.  
  1094. /* insure that cgd and cgs become equal for small Vds */
  1095.  
  1096.   if ( vds < .1 ) {
  1097.     double
  1098.       cgs = *Cgs,
  1099.       cgd = *Cgd,
  1100.       fact  = (vds/.1 + 1)/2;
  1101.  
  1102.     *Cgs = (cgs - cgd)*fact + cgd,
  1103.     *Cgd = (cgd - cgs)*fact + cgs;
  1104.     }
  1105.   } /* done */
  1106.  
  1107. /* */
  1108. #ifndef cc_noline
  1109. #line 4 "Mqspof"
  1110. #endif
  1111.  
  1112. void Mqspof(    /* calc. "on" capacitances and charges for MOS levels 2 & 3 */
  1113.   Model,
  1114.   Vds, Vbs, Vgs,
  1115.   Vpof, Von,
  1116.   Vdsat, Vdsat1,
  1117.   Cggb, Cgdb, Cgsb,
  1118.   Cbgb, Cbdb, Cbsb,
  1119.   Qgate, Qchan, Qbulk
  1120.   )
  1121.   struct M_    *Model;
  1122.   double Vds, Vbs, Vgs, Vpof, Von, Vdsat, Vdsat1;
  1123.   double
  1124.     *Cggb, *Cgdb, *Cgsb,
  1125.     *Cbgb, *Cbdb, *Cbsb,
  1126.     *Qgate, *Qchan, *Qbulk;
  1127.  
  1128. /*
  1129. pwt    86-08-29    creation
  1130. pwt    87-10-10    re-work as part of BSIM addition
  1131. */
  1132.   {
  1133.   double qcpof,
  1134.     qgate1, qcpof1, qbulk1, cggb1, cgdb1, cgsb1, cbgb1, cbdb1, cbsb1,
  1135.     qgate2, qcpof2, qbulk2, cggb2, cgdb2, cgsb2, cbgb2, cbdb2, cbsb2;
  1136.  
  1137. /*  Vdsat1 = MAX(Vds,Vdsat1)+1E-3;
  1138.  */
  1139.  
  1140.   switch ( ModLevel ) {
  1141.     case 2:
  1142.       MOS2cap(Model,Vds,Vbs,Vgs, Vdsat,  Cggb,  Cgdb,  Cgsb,  Cbgb,  Cbdb,  Cbsb, Qgate, Qchan,Qbulk);
  1143.       if ( Vds > Vdsat ) return;
  1144.       MOS2cap(Model,Vds,  Vbs,Vpof,Vdsat1,&cggb1,&cgdb1,&cgsb1,&cbgb1,&cbdb1,&cbsb1,&qgate1,&qcpof1,&qbulk1);
  1145.       MOS2cap(Model,Vdsat,Vbs, Vgs,Vdsat, &cggb2,&cgdb2,&cgsb2,&cbgb2,&cbdb2,&cbsb2,&qgate2,&qcpof2,&qbulk2);
  1146.       break;
  1147.     case 3:
  1148.       MOS3cap(Model,Vds,Vbs,Vpof,Von,Vdsat1,&cggb1,&cgdb1,&cgsb1,&cbgb1,&cbdb1,&cbsb1,Qgate,&qcpof,Qbulk);
  1149.       MOS3cap(Model,Vds,Vbs,Vgs, Von,Vdsat,  Cggb,  Cgdb,  Cgsb,  Cbgb,  Cbdb,  Cbsb, Qgate, Qchan,Qbulk);
  1150.       break;
  1151.     default:
  1152.       return;
  1153.     }
  1154.  
  1155. /* tangential limiting of qs */
  1156.  
  1157.   if ( Vgs > Vpof ||
  1158.        Vds < Vdsat ) {
  1159.     double qd,
  1160.       csgb1  = -(1-ModXqc)*(cggb1+cbgb1),
  1161.       qs     = csgb1*(Vgs-Vpof) + (1-ModXqc)*qcpof1,
  1162.       qspof2 = (1-ModXqc)*qcpof2;
  1163.  
  1164.     if ( fabs(qs) < fabs(qspof2) ) qs = qspof2;
  1165.  
  1166.     if ( fabs(qs) < .5*fabs(*Qchan) ) {
  1167.       Xqc = .5;
  1168.       return;
  1169.       }
  1170.  
  1171. /*  csdb = -.25*(cgdb+cbdb);
  1172.  *  qs   = qs + csdb*(Vdsat-Vds);
  1173.  *  Xqc  = MIN(.5,(*Qchan-qs)/(*Qchan));
  1174.  */
  1175.     qd  = *Qchan - qs;
  1176.     Xqc = qd/(*Qchan);
  1177.  
  1178. /* insure that Xqc = .5 @ Vds = 0 */
  1179.  
  1180.     if ( Vds < Vdsat ) Xqc = Xqc + ((Vdsat-Vds)/Vdsat)*(.5-Xqc);
  1181.  
  1182. /* constant limiting of qs */
  1183.  
  1184. /*  qdpof = qcpof*ModXqc;
  1185.  *  qspof = qcpof - qdpof;
  1186.  *
  1187.  *  if ( fabs(qspof) > .5*fabs(*Qchan) ) {
  1188.  *    qd  = *Qchan - qspof;
  1189.  *    qs  = qspof;
  1190.  *    Xqc = qd/(*Qchan);
  1191.  *    }
  1192.  *  else Xqc = .5;
  1193.  */
  1194.     }
  1195.   else Xqc = ModXqc;
  1196.  
  1197.   } /* done */
  1198.