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

  1. /****************************************************************************/
  2. /*        Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991                  */
  3. /*          By MicroSim Corporation, All Rights Reserved                    */
  4. /****************************************************************************/
  5. /* acmos.c
  6.  *   $Revision:   1.7  $
  7.  *   $Author:   pwt  $
  8.  *   $Date:   13 Jun 1991 20:20:36  $ */
  9.  
  10. /******************* USERS OF DEVICE EQUATIONS OPTION ***********************/
  11. /******** See the comments in the files mos.c and m.h for details  **********/
  12. /******** on changing the model parameters.                        **********/
  13.  
  14. #include "option1.h"
  15. #ifdef USE_DECL_ARGS
  16. void ACLoad_M(    struct m_ *, double );
  17. _complex ACPrb_M(    struct m_ *, double, int, int);
  18. #else
  19. void ACLoad_M();
  20. _complex ACPrb_M();
  21. #endif
  22.  
  23. #define DevM    (Instance->m_m)        /* device size multiplier */
  24.  
  25. #define GDPR    (Instance->m_rd)    /* ohmic conductances */
  26. #define GSPR    (Instance->m_rs)
  27. #define GGPR    (Instance->m_rg)
  28. #define GBPR    (Instance->m_rb)
  29.  
  30. #define GBD    (Instance->mcv_gbd)    /* active conductances */
  31. #define GBS    (Instance->mcv_gbs)
  32. #define GDS    (Instance->mcv_gds)
  33. #define GM    (Instance->mcv_gm)
  34. #define GMBS    (Instance->mcv_gmbs)
  35.  
  36. #define CBD    (Instance->m_sda.m_ac.mac_cbd)    /* junction capacitances */
  37. #define CBS    (Instance->m_sda.m_ac.mac_cbs)
  38.  
  39. #define CGDB    (Instance->m_sda.m_ac.mac_cgdb)    /* active capacitances */
  40. #define CGGB    (Instance->m_sda.m_ac.mac_cggb)
  41. #define CGSB    (Instance->m_sda.m_ac.mac_cgsb)
  42.  
  43. #define CBDB    (Instance->m_sda.m_ac.mac_cbdb)
  44. #define CBGB    (Instance->m_sda.m_ac.mac_cbgb)
  45. #define CBSB    (Instance->m_sda.m_ac.mac_cbsb)
  46.  
  47. #define CDDB    (Instance->m_sda.m_ac.mac_cddb)
  48. #define CDGB    (Instance->m_sda.m_ac.mac_cdgb)
  49. #define CDSB    (Instance->m_sda.m_ac.mac_cdsb)
  50.  
  51. #define CGD0    (Instance->m_sda.m_ac.mac_cgdo)    /* Meyer-only overlap cap. */
  52. #define CGS0    (Instance->m_sda.m_ac.mac_cgso)
  53. #define CGB0    (Instance->m_sda.m_ac.mac_cgbo)
  54.  
  55. void ACLoad_M(    /* Process MOSFET for AC analysis */
  56.   Instance,    /* device to evaluate */
  57.   Omega        /* 2*pi*frequency */
  58.   )
  59. struct m_ *Instance;
  60. double Omega;
  61.  
  62. /*
  63. whjb    28 Mar 87    created (from code taken from ACLoad)
  64. pwt    17 Feb 88    re-written (found bug dating to SPICE2G.6)
  65. pwt    07 Mar 88    renamed (from MOSAC)
  66. pwt    15 Mar 88    re-written, adding BSIM capacitance model
  67. pwt    07 Oct 88    add "M" (multiplier) to calculations
  68. */
  69. { struct M_ *model = Instance->m_model;    /* device model */
  70.  
  71.   int fwd = Instance->m_mode > 0 ? YES : NO ;
  72.  
  73. /* Load admittances depending on capacitance model */
  74.  
  75.   if ( NINT(model->M_level)==4 ) {        /* BSIM capacitance model */
  76.     double
  77.       len =  Instance->m_l - model->M_ld*1e-6,    /* device geometry */
  78.       wid = (Instance->m_w - model->M_wd*1e-6)*DevM,
  79.       covlgd = wid * model->M_cgdo,        /* overlap capacitances */
  80.       covlgs = wid * model->M_cgso,
  81.       covlgb = len * model->M_cgbo;
  82.  
  83.     AC_MAT_I(m_db) = -(
  84.       ( AC_MAT_I(m_ds) = Omega*CDSB                  ) +
  85.       ( AC_MAT_I(m_dg) = Omega*(CDGB - covlgd)       ) +
  86.       ( AC_MAT_I(m_dd) = Omega*(CDDB + covlgd + CBD) ) );
  87.  
  88.     AC_MAT_I(m_gb) = -(
  89.       ( AC_MAT_I(m_gd) = Omega*(CGDB - covlgd)                   ) +
  90.       ( AC_MAT_I(m_gs) = Omega*(CGSB - covlgs)                   ) +
  91.       ( AC_MAT_I(m_gg) = Omega*(CGGB + covlgd + covlgs + covlgb) ) );
  92.  
  93.     AC_MAT_I(m_sb) = -(
  94.       ( AC_MAT_I(m_sd) = Omega*(-(CGDB+CBDB+CDDB) )               ) +
  95.       ( AC_MAT_I(m_sg) = Omega*(-(CGGB+CBGB+CDGB) - covlgs)       ) +
  96.       ( AC_MAT_I(m_ss) = Omega*(-(CGSB+CBSB+CDSB) + covlgs + CBS) ) );
  97.  
  98.     AC_MAT_I(m_bb) = -(
  99.       ( AC_MAT_I(m_bd) = Omega*(CBDB - CBD)    ) +
  100.       ( AC_MAT_I(m_bs) = Omega*(CBSB - CBS)    ) +
  101.       ( AC_MAT_I(m_bg) = Omega*(CBGB - covlgb) ) );
  102.     }
  103.   else if ( (double)model->M_xqc <= .5 ) {    /* Ward-Dutton cap. model */
  104.     double
  105.       len =  Instance->m_l - 2*model->M_ld,    /* device geometry */
  106.       wid = (Instance->m_w - 2*model->M_wd)*DevM,
  107.       covlgd = wid * model->M_cgdo,        /* overlap capacitances */
  108.       covlgs = wid * model->M_cgso,
  109.       covlgb = len * model->M_cgbo,
  110.       xqc = Instance->m_xqc;
  111.     double
  112.       cg   = -(CGGB+CBGB),
  113.       cgxd = cg*xqc,
  114.       cgxs = cg-cgxd;
  115.     double
  116.       cd   = -(CGDB+CBDB),
  117.       cdxd = cd*xqc,
  118.       cdxs = cd-cdxd;
  119.     double
  120.       cs   = -(CGSB+CBSB),
  121.       csxd = cs*xqc,
  122.       csxs = cs-csxd;
  123.  
  124. /* load imaginary part of admittances */
  125.  
  126.     AC_MAT_I(m_db) = -(
  127.       ( AC_MAT_I(m_ds) = Omega*csxd                  ) +
  128.       ( AC_MAT_I(m_dg) = Omega*(cgxd - covlgd)       ) +
  129.       ( AC_MAT_I(m_dd) = Omega*(cdxd + covlgd + CBD) ) );
  130.  
  131.     AC_MAT_I(m_gb) = -(
  132.       ( AC_MAT_I(m_gd) = Omega*(CGDB - covlgd)                   ) +
  133.       ( AC_MAT_I(m_gs) = Omega*(CGSB - covlgs)                   ) +
  134.       ( AC_MAT_I(m_gg) = Omega*(CGGB + covlgd + covlgs + covlgb) ) );
  135.  
  136.     AC_MAT_I(m_sb) = -(
  137.       ( AC_MAT_I(m_sd) = Omega*cdxs                    ) +
  138.       ( AC_MAT_I(m_sg) = Omega*(cgxs - covlgs)         ) +
  139.       ( AC_MAT_I(m_ss) = Omega*(csxs + covlgs + CBS) ) );
  140.  
  141.     AC_MAT_I(m_bb) = -(
  142.       ( AC_MAT_I(m_bd) = Omega*(CBDB - CBD)    ) +
  143.       ( AC_MAT_I(m_bs) = Omega*(CBSB - CBS)    ) +
  144.       ( AC_MAT_I(m_bg) = Omega*(CBGB - covlgb) ) );
  145.     }
  146.   else {                    /* Meyer capacitance model */
  147.     double xgd, xgs, xgb, xbd, xbs;
  148.  
  149. /* load imaginary part of admittances */
  150.  
  151.     AC_MAT_I(m_dg) = AC_MAT_I(m_gd) = -( xgd = Omega*CGD0 );
  152.     AC_MAT_I(m_gs) = AC_MAT_I(m_sg) = -( xgs = Omega*CGS0 );
  153.     AC_MAT_I(m_gb) = AC_MAT_I(m_bg) = -( xgb = Omega*CGB0 );
  154.     AC_MAT_I(m_db) = AC_MAT_I(m_bd) = -( xbd = Omega*CBD  );
  155.     AC_MAT_I(m_sb) = AC_MAT_I(m_bs) = -( xbs = Omega*CBS  );
  156.     AC_MAT_I(m_ds) = AC_MAT_I(m_sd) = 0.;
  157.  
  158.     AC_MAT_I(m_dd) = xgd+xbd;
  159.     AC_MAT_I(m_gg) = xgd+xgs+xgb;
  160.     AC_MAT_I(m_ss) = xgs+xbs;
  161.     AC_MAT_I(m_bb) = xgb+xbd+xbs;
  162.     }
  163.  
  164. /* load real part of admittances */
  165.  
  166.   AC_MAT_R(m_Gg) = AC_MAT_R(m_gG) = /* -ggpr */
  167.                  - ( AC_MAT_R(m_GG) = AC_MAT_R(m_gg) = GGPR*DevM );
  168.  
  169.   AC_MAT_R(m_dg) = ( fwd ?  GM   :   -GM );
  170.   AC_MAT_R(m_ds) = ( fwd ? -GM-GMBS : 0. ) - GDS;
  171.   AC_MAT_R(m_db) = ( fwd ?  GMBS : -GMBS ) - GBD;
  172.   AC_MAT_R(m_dd) = ( fwd ?  0.:  GM+GMBS ) + GDS + GBD /* + gdpr; */
  173.                  - ( AC_MAT_R(m_Dd) = AC_MAT_R(m_dD) = /* - gdpr; */
  174.                  - ( AC_MAT_R(m_DD) = GDPR*DevM ) );
  175.  
  176.   AC_MAT_R(m_sg) = ( fwd ? -GM   :    GM );
  177.   AC_MAT_R(m_sd) = ( fwd ?  0.: -GM-GMBS ) - GDS;
  178.   AC_MAT_R(m_sb) = ( fwd ? -GMBS :  GMBS ) - GBS;
  179.   AC_MAT_R(m_ss) = ( fwd ?  GM+GMBS : 0. ) + GDS + GBS /* + gspr; */
  180.                  - ( AC_MAT_R(m_Ss) = AC_MAT_R(m_sS) = /* - gspr; */
  181.                  - ( AC_MAT_R(m_SS) = GSPR*DevM ) );
  182.  
  183.   AC_MAT_R(m_bd) = -GBD;
  184.   AC_MAT_R(m_bs) = -GBS;
  185.   AC_MAT_R(m_bb) =  GBD + GBS /* + gbpr; */
  186.                  - ( AC_MAT_R(m_Bb) = AC_MAT_R(m_bB) = /* -gbpr; */
  187.                  - ( AC_MAT_R(m_BB) = AC_MAT_R(m_bb) = GBPR*DevM ) );
  188.  
  189.   } /* End ACLoad_M */
  190.  
  191.  
  192.  
  193.  
  194. _complex ACPrb_M(    /* Calc. MOSfet current (for Probe) for AC analysis */
  195.   Instance,    /* device to evaluate */
  196.   Omega,    /* 2*pi*frequency */
  197.   Pin,        /* pin designator: 'd'|'g'|'s'|'b' (case insensitive) */
  198.   ForceRecalc
  199.   )
  200. struct m_ *Instance;
  201. double Omega;
  202. int Pin, ForceRecalc;
  203.  
  204. /*
  205. pwt    07 Mar 88    creation
  206. pwt    18 Mar 88    add BSIM calculations
  207. pwt    16 Aug 90    add ForceRecalc argument for report speed-up
  208. */
  209. {
  210.   static _complex            /* calculated branch currents */
  211.     ids, ibd, ibs, iqg, iqb, iqd;
  212.  
  213.   static struct m_ *instance;        /* "previous call" argument values */
  214.   static double omega;
  215.  
  216.   if ( ForceRecalc ||
  217.        Instance != instance ||
  218.        Omega    != omega ) {
  219.  
  220.     _complex
  221.       vgd, vgs, vgb, vds, vbd, vbs,    /* node voltages */
  222.       ygm, ygmbs,    yds, ybd, ybs;    /* branch admittances */
  223.     _complex zero;
  224.     struct M_
  225.       *model = Instance->m_model;    /* device model */
  226.  
  227.     zero.re = 0.;
  228.     zero.im = 0.;
  229.  
  230.     instance = Instance;
  231.     omega    = Omega;
  232.  
  233.     vgd.re = VltVct [Instance->m_g] - VltVct [Instance->m_d];
  234.     vgd.im = VltVctI[Instance->m_g] - VltVctI[Instance->m_d];
  235.  
  236.     vgs.re = VltVct [Instance->m_g] - VltVct [Instance->m_s];
  237.     vgs.im = VltVctI[Instance->m_g] - VltVctI[Instance->m_s];
  238.  
  239.     vgb.re = VltVct [Instance->m_g] - VltVct [Instance->m_b];
  240.     vgb.im = VltVctI[Instance->m_g] - VltVctI[Instance->m_b];
  241.  
  242.     vds.re = VltVct [Instance->m_d] - VltVct [Instance->m_s];
  243.     vds.im = VltVctI[Instance->m_d] - VltVctI[Instance->m_s];
  244.  
  245.     vbd.re = VltVct [Instance->m_b] - VltVct [Instance->m_d];
  246.     vbd.im = VltVctI[Instance->m_b] - VltVctI[Instance->m_d];
  247.  
  248.     vbs.re = VltVct [Instance->m_b] - VltVct [Instance->m_s];
  249.     vbs.im = VltVctI[Instance->m_b] - VltVctI[Instance->m_s];
  250.  
  251.     ybd.re   = GBD;  ybd.im   = Omega*CBD;
  252.     ybs.re   = GBS;  ybs.im   = Omega*CBS;
  253.     yds.re   = GDS;  yds.im   = 0.;
  254.     ygm.re   = GM;   ygm.im   = 0.;
  255.     ygmbs.re = GMBS; ygmbs.im = 0.;
  256.  
  257.     ibd = cmul(ybd,vbd);
  258.     ibs = cmul(ybs,vbs);
  259.     ids = Instance->m_mode > 0 ?
  260.             cadd( cadd( cmul(yds,vds), cmul(ygm,vgs) ), cmul(ygmbs,vbs) ) :
  261.             csub( csub( cmul(yds,vds), cmul(ygm,vgd) ), cmul(ygmbs,vbd) ) ;
  262.  
  263.     if ( NINT(model->M_level)==4 ) {        /* BSIM capacitance model */
  264.       double
  265.         len = Instance->m_l - model->M_ld*1e-6,    /* device geometry */
  266.         wid = Instance->m_w - model->M_wd*1e-6,
  267.         covlgd = wid * model->M_cgdo,        /* overlap capacitances */
  268.         covlgs = wid * model->M_cgso,
  269.         covlgb = len * model->M_cgbo;
  270.       _complex
  271.         yggb, ygdb, ygsb,
  272.         ydgb, yddb, ydsb,
  273.         ybgb, ybdb, ybsb;
  274.  
  275.       ydsb.re = 0.; ydsb.im = Omega*(CDSB);
  276.       ydgb.re = 0.; ydgb.im = Omega*(CDGB - covlgd);
  277.       yddb.re = 0.; yddb.im = Omega*(CDDB + covlgd);
  278.  
  279.       ygdb.re = 0.; ygdb.im = Omega*(CGDB - covlgd);
  280.       ygsb.re = 0.; ygsb.im = Omega*(CGSB - covlgs);
  281.       yggb.re = 0.; yggb.im = Omega*(CGGB + covlgd + covlgs + covlgb);
  282.  
  283.       ybdb.re = 0.; ybdb.im = Omega*(CBDB);
  284.       ybsb.re = 0.; ybsb.im = Omega*(CBSB);
  285.       ybgb.re = 0.; ybgb.im = Omega*(CBGB - covlgb);
  286.  
  287.       iqg = csub( cmul(yggb,vgb), cadd( cmul(ygdb,vbd), cmul(ygsb,vbs) ) );
  288.       iqd = csub( cmul(ydgb,vgb), cadd( cmul(yddb,vbd), cmul(ydsb,vbs) ) );
  289.       iqb = csub( cmul(ybgb,vgb), cadd( cmul(ybdb,vbd), cmul(ybsb,vbs) ) );
  290.       }
  291.     else if ( (double)model->M_xqc <= .5 ) {    /* Ward-Dutton cap. model */
  292.       double
  293.         len = Instance->m_l - 2*model->M_ld,    /* device geometry */
  294.         wid = Instance->m_w - 2*model->M_wd,
  295.         covlgs = wid * model->M_cgso,        /* overlap caps */
  296.         covlgd = wid * model->M_cgdo,
  297.         covlgb = len * model->M_cgbo,
  298.         xqc = Instance->m_xqc;
  299.       _complex
  300.         yggb, ygdb, ygsb,
  301.         ydgb, yddb, ydsb,
  302.         ybgb, ybdb, ybsb;
  303.  
  304.       ydsb.re = 0.; ydsb.im = Omega*(-xqc*(CGSB + CBSB));
  305.       ydgb.re = 0.; ydgb.im = Omega*(-xqc*(CGGB + CBGB) - covlgd);
  306.       yddb.re = 0.; yddb.im = Omega*(-xqc*(CGDB + CBDB) + covlgd);
  307.  
  308.       ygdb.re = 0.; ygdb.im = Omega*(CGDB - covlgd);
  309.       ygsb.re = 0.; ygsb.im = Omega*(CGSB - covlgs);
  310.       yggb.re = 0.; yggb.im = Omega*(CGGB + covlgd + covlgs + covlgb);
  311.  
  312.       ybdb.re = 0.; ybdb.im = Omega*(CBDB);
  313.       ybsb.re = 0.; ybsb.im = Omega*(CBSB);
  314.       ybgb.re = 0.; ybgb.im = Omega*(CBGB - covlgb);
  315.  
  316.       iqg = csub( cmul(yggb,vgb), cadd( cmul(ygdb,vbd), cmul(ygsb,vbs) ) );
  317.       iqd = csub( cmul(ydgb,vgb), cadd( cmul(yddb,vbd), cmul(ydsb,vbs) ) );
  318.       iqb = csub( cmul(ybgb,vgb), cadd( cmul(ybdb,vbd), cmul(ybsb,vbs) ) );
  319.       }
  320.     else {                    /* Meyer capacitance model */
  321.       _complex ygd, ygs, ygb, igd, igs, igb;
  322.  
  323.       ygd.re = 0.; ygd.im = Omega*CGD0;
  324.       ygs.re = 0.; ygs.im = Omega*CGS0;
  325.       ygb.re = 0.; ygb.im = Omega*CGB0;
  326.  
  327.       igd = cmul(ygd,vgd);
  328.       igs = cmul(ygs,vgs);
  329.       igb = cmul(ygb,vgb);
  330.  
  331.       iqg = cadd(igb,cadd(igd,igs));
  332.       iqb = csub(zero,igb);
  333.       iqd = csub(zero,igd);
  334.       }
  335.     }
  336.  
  337.   switch ( toupper(Pin) ) {    /* select pin and combine currents */
  338.     case 'D': return cadd(csub(ids,ibd),iqd);
  339.     case 'G': return iqg;
  340.     case 'S': return csub(cadi(ids,ibs),cadd(cadd(iqd,iqb),iqg));
  341.     case 'B': return cadd(cadd(ibd,ibs),iqb);
  342.     }
  343.  
  344.   } /* end of ACPrb_M */
  345.