home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************/
- /* Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991 */
- /* By MicroSim Corporation, All Rights Reserved */
- /****************************************************************************/
- /* acmos.c
- * $Revision: 1.7 $
- * $Author: pwt $
- * $Date: 13 Jun 1991 20:20:36 $ */
-
- /******************* USERS OF DEVICE EQUATIONS OPTION ***********************/
- /******** See the comments in the files mos.c and m.h for details **********/
- /******** on changing the model parameters. **********/
-
- #include "option1.h"
- #ifdef USE_DECL_ARGS
- void ACLoad_M( struct m_ *, double );
- _complex ACPrb_M( struct m_ *, double, int, int);
- #else
- void ACLoad_M();
- _complex ACPrb_M();
- #endif
-
- #define DevM (Instance->m_m) /* device size multiplier */
-
- #define GDPR (Instance->m_rd) /* ohmic conductances */
- #define GSPR (Instance->m_rs)
- #define GGPR (Instance->m_rg)
- #define GBPR (Instance->m_rb)
-
- #define GBD (Instance->mcv_gbd) /* active conductances */
- #define GBS (Instance->mcv_gbs)
- #define GDS (Instance->mcv_gds)
- #define GM (Instance->mcv_gm)
- #define GMBS (Instance->mcv_gmbs)
-
- #define CBD (Instance->m_sda.m_ac.mac_cbd) /* junction capacitances */
- #define CBS (Instance->m_sda.m_ac.mac_cbs)
-
- #define CGDB (Instance->m_sda.m_ac.mac_cgdb) /* active capacitances */
- #define CGGB (Instance->m_sda.m_ac.mac_cggb)
- #define CGSB (Instance->m_sda.m_ac.mac_cgsb)
-
- #define CBDB (Instance->m_sda.m_ac.mac_cbdb)
- #define CBGB (Instance->m_sda.m_ac.mac_cbgb)
- #define CBSB (Instance->m_sda.m_ac.mac_cbsb)
-
- #define CDDB (Instance->m_sda.m_ac.mac_cddb)
- #define CDGB (Instance->m_sda.m_ac.mac_cdgb)
- #define CDSB (Instance->m_sda.m_ac.mac_cdsb)
-
- #define CGD0 (Instance->m_sda.m_ac.mac_cgdo) /* Meyer-only overlap cap. */
- #define CGS0 (Instance->m_sda.m_ac.mac_cgso)
- #define CGB0 (Instance->m_sda.m_ac.mac_cgbo)
-
- void ACLoad_M( /* Process MOSFET for AC analysis */
- Instance, /* device to evaluate */
- Omega /* 2*pi*frequency */
- )
- struct m_ *Instance;
- double Omega;
-
- /*
- whjb 28 Mar 87 created (from code taken from ACLoad)
- pwt 17 Feb 88 re-written (found bug dating to SPICE2G.6)
- pwt 07 Mar 88 renamed (from MOSAC)
- pwt 15 Mar 88 re-written, adding BSIM capacitance model
- pwt 07 Oct 88 add "M" (multiplier) to calculations
- */
- { struct M_ *model = Instance->m_model; /* device model */
-
- int fwd = Instance->m_mode > 0 ? YES : NO ;
-
- /* Load admittances depending on capacitance model */
-
- if ( NINT(model->M_level)==4 ) { /* BSIM capacitance model */
- double
- len = Instance->m_l - model->M_ld*1e-6, /* device geometry */
- wid = (Instance->m_w - model->M_wd*1e-6)*DevM,
- covlgd = wid * model->M_cgdo, /* overlap capacitances */
- covlgs = wid * model->M_cgso,
- covlgb = len * model->M_cgbo;
-
- AC_MAT_I(m_db) = -(
- ( AC_MAT_I(m_ds) = Omega*CDSB ) +
- ( AC_MAT_I(m_dg) = Omega*(CDGB - covlgd) ) +
- ( AC_MAT_I(m_dd) = Omega*(CDDB + covlgd + CBD) ) );
-
- AC_MAT_I(m_gb) = -(
- ( AC_MAT_I(m_gd) = Omega*(CGDB - covlgd) ) +
- ( AC_MAT_I(m_gs) = Omega*(CGSB - covlgs) ) +
- ( AC_MAT_I(m_gg) = Omega*(CGGB + covlgd + covlgs + covlgb) ) );
-
- AC_MAT_I(m_sb) = -(
- ( AC_MAT_I(m_sd) = Omega*(-(CGDB+CBDB+CDDB) ) ) +
- ( AC_MAT_I(m_sg) = Omega*(-(CGGB+CBGB+CDGB) - covlgs) ) +
- ( AC_MAT_I(m_ss) = Omega*(-(CGSB+CBSB+CDSB) + covlgs + CBS) ) );
-
- AC_MAT_I(m_bb) = -(
- ( AC_MAT_I(m_bd) = Omega*(CBDB - CBD) ) +
- ( AC_MAT_I(m_bs) = Omega*(CBSB - CBS) ) +
- ( AC_MAT_I(m_bg) = Omega*(CBGB - covlgb) ) );
- }
- else if ( (double)model->M_xqc <= .5 ) { /* Ward-Dutton cap. model */
- double
- len = Instance->m_l - 2*model->M_ld, /* device geometry */
- wid = (Instance->m_w - 2*model->M_wd)*DevM,
- covlgd = wid * model->M_cgdo, /* overlap capacitances */
- covlgs = wid * model->M_cgso,
- covlgb = len * model->M_cgbo,
- xqc = Instance->m_xqc;
- double
- cg = -(CGGB+CBGB),
- cgxd = cg*xqc,
- cgxs = cg-cgxd;
- double
- cd = -(CGDB+CBDB),
- cdxd = cd*xqc,
- cdxs = cd-cdxd;
- double
- cs = -(CGSB+CBSB),
- csxd = cs*xqc,
- csxs = cs-csxd;
-
- /* load imaginary part of admittances */
-
- AC_MAT_I(m_db) = -(
- ( AC_MAT_I(m_ds) = Omega*csxd ) +
- ( AC_MAT_I(m_dg) = Omega*(cgxd - covlgd) ) +
- ( AC_MAT_I(m_dd) = Omega*(cdxd + covlgd + CBD) ) );
-
- AC_MAT_I(m_gb) = -(
- ( AC_MAT_I(m_gd) = Omega*(CGDB - covlgd) ) +
- ( AC_MAT_I(m_gs) = Omega*(CGSB - covlgs) ) +
- ( AC_MAT_I(m_gg) = Omega*(CGGB + covlgd + covlgs + covlgb) ) );
-
- AC_MAT_I(m_sb) = -(
- ( AC_MAT_I(m_sd) = Omega*cdxs ) +
- ( AC_MAT_I(m_sg) = Omega*(cgxs - covlgs) ) +
- ( AC_MAT_I(m_ss) = Omega*(csxs + covlgs + CBS) ) );
-
- AC_MAT_I(m_bb) = -(
- ( AC_MAT_I(m_bd) = Omega*(CBDB - CBD) ) +
- ( AC_MAT_I(m_bs) = Omega*(CBSB - CBS) ) +
- ( AC_MAT_I(m_bg) = Omega*(CBGB - covlgb) ) );
- }
- else { /* Meyer capacitance model */
- double xgd, xgs, xgb, xbd, xbs;
-
- /* load imaginary part of admittances */
-
- AC_MAT_I(m_dg) = AC_MAT_I(m_gd) = -( xgd = Omega*CGD0 );
- AC_MAT_I(m_gs) = AC_MAT_I(m_sg) = -( xgs = Omega*CGS0 );
- AC_MAT_I(m_gb) = AC_MAT_I(m_bg) = -( xgb = Omega*CGB0 );
- AC_MAT_I(m_db) = AC_MAT_I(m_bd) = -( xbd = Omega*CBD );
- AC_MAT_I(m_sb) = AC_MAT_I(m_bs) = -( xbs = Omega*CBS );
- AC_MAT_I(m_ds) = AC_MAT_I(m_sd) = 0.;
-
- AC_MAT_I(m_dd) = xgd+xbd;
- AC_MAT_I(m_gg) = xgd+xgs+xgb;
- AC_MAT_I(m_ss) = xgs+xbs;
- AC_MAT_I(m_bb) = xgb+xbd+xbs;
- }
-
- /* load real part of admittances */
-
- AC_MAT_R(m_Gg) = AC_MAT_R(m_gG) = /* -ggpr */
- - ( AC_MAT_R(m_GG) = AC_MAT_R(m_gg) = GGPR*DevM );
-
- AC_MAT_R(m_dg) = ( fwd ? GM : -GM );
- AC_MAT_R(m_ds) = ( fwd ? -GM-GMBS : 0. ) - GDS;
- AC_MAT_R(m_db) = ( fwd ? GMBS : -GMBS ) - GBD;
- AC_MAT_R(m_dd) = ( fwd ? 0.: GM+GMBS ) + GDS + GBD /* + gdpr; */
- - ( AC_MAT_R(m_Dd) = AC_MAT_R(m_dD) = /* - gdpr; */
- - ( AC_MAT_R(m_DD) = GDPR*DevM ) );
-
- AC_MAT_R(m_sg) = ( fwd ? -GM : GM );
- AC_MAT_R(m_sd) = ( fwd ? 0.: -GM-GMBS ) - GDS;
- AC_MAT_R(m_sb) = ( fwd ? -GMBS : GMBS ) - GBS;
- AC_MAT_R(m_ss) = ( fwd ? GM+GMBS : 0. ) + GDS + GBS /* + gspr; */
- - ( AC_MAT_R(m_Ss) = AC_MAT_R(m_sS) = /* - gspr; */
- - ( AC_MAT_R(m_SS) = GSPR*DevM ) );
-
- AC_MAT_R(m_bd) = -GBD;
- AC_MAT_R(m_bs) = -GBS;
- AC_MAT_R(m_bb) = GBD + GBS /* + gbpr; */
- - ( AC_MAT_R(m_Bb) = AC_MAT_R(m_bB) = /* -gbpr; */
- - ( AC_MAT_R(m_BB) = AC_MAT_R(m_bb) = GBPR*DevM ) );
-
- } /* End ACLoad_M */
-
-
-
-
- _complex ACPrb_M( /* Calc. MOSfet current (for Probe) for AC analysis */
- Instance, /* device to evaluate */
- Omega, /* 2*pi*frequency */
- Pin, /* pin designator: 'd'|'g'|'s'|'b' (case insensitive) */
- ForceRecalc
- )
- struct m_ *Instance;
- double Omega;
- int Pin, ForceRecalc;
-
- /*
- pwt 07 Mar 88 creation
- pwt 18 Mar 88 add BSIM calculations
- pwt 16 Aug 90 add ForceRecalc argument for report speed-up
- */
- {
- static _complex /* calculated branch currents */
- ids, ibd, ibs, iqg, iqb, iqd;
-
- static struct m_ *instance; /* "previous call" argument values */
- static double omega;
-
- if ( ForceRecalc ||
- Instance != instance ||
- Omega != omega ) {
-
- _complex
- vgd, vgs, vgb, vds, vbd, vbs, /* node voltages */
- ygm, ygmbs, yds, ybd, ybs; /* branch admittances */
- _complex zero;
- struct M_
- *model = Instance->m_model; /* device model */
-
- zero.re = 0.;
- zero.im = 0.;
-
- instance = Instance;
- omega = Omega;
-
- vgd.re = VltVct [Instance->m_g] - VltVct [Instance->m_d];
- vgd.im = VltVctI[Instance->m_g] - VltVctI[Instance->m_d];
-
- vgs.re = VltVct [Instance->m_g] - VltVct [Instance->m_s];
- vgs.im = VltVctI[Instance->m_g] - VltVctI[Instance->m_s];
-
- vgb.re = VltVct [Instance->m_g] - VltVct [Instance->m_b];
- vgb.im = VltVctI[Instance->m_g] - VltVctI[Instance->m_b];
-
- vds.re = VltVct [Instance->m_d] - VltVct [Instance->m_s];
- vds.im = VltVctI[Instance->m_d] - VltVctI[Instance->m_s];
-
- vbd.re = VltVct [Instance->m_b] - VltVct [Instance->m_d];
- vbd.im = VltVctI[Instance->m_b] - VltVctI[Instance->m_d];
-
- vbs.re = VltVct [Instance->m_b] - VltVct [Instance->m_s];
- vbs.im = VltVctI[Instance->m_b] - VltVctI[Instance->m_s];
-
- ybd.re = GBD; ybd.im = Omega*CBD;
- ybs.re = GBS; ybs.im = Omega*CBS;
- yds.re = GDS; yds.im = 0.;
- ygm.re = GM; ygm.im = 0.;
- ygmbs.re = GMBS; ygmbs.im = 0.;
-
- ibd = cmul(ybd,vbd);
- ibs = cmul(ybs,vbs);
- ids = Instance->m_mode > 0 ?
- cadd( cadd( cmul(yds,vds), cmul(ygm,vgs) ), cmul(ygmbs,vbs) ) :
- csub( csub( cmul(yds,vds), cmul(ygm,vgd) ), cmul(ygmbs,vbd) ) ;
-
- if ( NINT(model->M_level)==4 ) { /* BSIM capacitance model */
- double
- len = Instance->m_l - model->M_ld*1e-6, /* device geometry */
- wid = Instance->m_w - model->M_wd*1e-6,
- covlgd = wid * model->M_cgdo, /* overlap capacitances */
- covlgs = wid * model->M_cgso,
- covlgb = len * model->M_cgbo;
- _complex
- yggb, ygdb, ygsb,
- ydgb, yddb, ydsb,
- ybgb, ybdb, ybsb;
-
- ydsb.re = 0.; ydsb.im = Omega*(CDSB);
- ydgb.re = 0.; ydgb.im = Omega*(CDGB - covlgd);
- yddb.re = 0.; yddb.im = Omega*(CDDB + covlgd);
-
- ygdb.re = 0.; ygdb.im = Omega*(CGDB - covlgd);
- ygsb.re = 0.; ygsb.im = Omega*(CGSB - covlgs);
- yggb.re = 0.; yggb.im = Omega*(CGGB + covlgd + covlgs + covlgb);
-
- ybdb.re = 0.; ybdb.im = Omega*(CBDB);
- ybsb.re = 0.; ybsb.im = Omega*(CBSB);
- ybgb.re = 0.; ybgb.im = Omega*(CBGB - covlgb);
-
- iqg = csub( cmul(yggb,vgb), cadd( cmul(ygdb,vbd), cmul(ygsb,vbs) ) );
- iqd = csub( cmul(ydgb,vgb), cadd( cmul(yddb,vbd), cmul(ydsb,vbs) ) );
- iqb = csub( cmul(ybgb,vgb), cadd( cmul(ybdb,vbd), cmul(ybsb,vbs) ) );
- }
- else if ( (double)model->M_xqc <= .5 ) { /* Ward-Dutton cap. model */
- double
- len = Instance->m_l - 2*model->M_ld, /* device geometry */
- wid = Instance->m_w - 2*model->M_wd,
- covlgs = wid * model->M_cgso, /* overlap caps */
- covlgd = wid * model->M_cgdo,
- covlgb = len * model->M_cgbo,
- xqc = Instance->m_xqc;
- _complex
- yggb, ygdb, ygsb,
- ydgb, yddb, ydsb,
- ybgb, ybdb, ybsb;
-
- ydsb.re = 0.; ydsb.im = Omega*(-xqc*(CGSB + CBSB));
- ydgb.re = 0.; ydgb.im = Omega*(-xqc*(CGGB + CBGB) - covlgd);
- yddb.re = 0.; yddb.im = Omega*(-xqc*(CGDB + CBDB) + covlgd);
-
- ygdb.re = 0.; ygdb.im = Omega*(CGDB - covlgd);
- ygsb.re = 0.; ygsb.im = Omega*(CGSB - covlgs);
- yggb.re = 0.; yggb.im = Omega*(CGGB + covlgd + covlgs + covlgb);
-
- ybdb.re = 0.; ybdb.im = Omega*(CBDB);
- ybsb.re = 0.; ybsb.im = Omega*(CBSB);
- ybgb.re = 0.; ybgb.im = Omega*(CBGB - covlgb);
-
- iqg = csub( cmul(yggb,vgb), cadd( cmul(ygdb,vbd), cmul(ygsb,vbs) ) );
- iqd = csub( cmul(ydgb,vgb), cadd( cmul(yddb,vbd), cmul(ydsb,vbs) ) );
- iqb = csub( cmul(ybgb,vgb), cadd( cmul(ybdb,vbd), cmul(ybsb,vbs) ) );
- }
- else { /* Meyer capacitance model */
- _complex ygd, ygs, ygb, igd, igs, igb;
-
- ygd.re = 0.; ygd.im = Omega*CGD0;
- ygs.re = 0.; ygs.im = Omega*CGS0;
- ygb.re = 0.; ygb.im = Omega*CGB0;
-
- igd = cmul(ygd,vgd);
- igs = cmul(ygs,vgs);
- igb = cmul(ygb,vgb);
-
- iqg = cadd(igb,cadd(igd,igs));
- iqb = csub(zero,igb);
- iqd = csub(zero,igd);
- }
- }
-
- switch ( toupper(Pin) ) { /* select pin and combine currents */
- case 'D': return cadd(csub(ids,ibd),iqd);
- case 'G': return iqg;
- case 'S': return csub(cadi(ids,ibs),cadd(cadd(iqd,iqb),iqg));
- case 'B': return cadd(cadd(ibd,ibs),iqb);
- }
-
- } /* end of ACPrb_M */