home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / alt / sources / 3108 < prev    next >
Encoding:
Text File  |  1993-01-28  |  51.4 KB  |  1,764 lines

  1. Path: sparky!uunet!ferkel.ucsb.edu!taco!rock!stanford.edu!ames!haven.umd.edu!darwin.sura.net!ukma!cs.widener.edu!dsinc!ub!galileo.cc.rochester.edu!ee.rochester.edu!rbc!al
  2. From: al@rbc.uucp (Al Davis)
  3. Newsgroups: alt.sources
  4. Subject: ACS  circuit simulator  part 14/20
  5. Message-ID: <1993Jan27.040850.11696@rbc.uucp>
  6. Date: 27 Jan 93 04:08:50 GMT
  7. Sender: al@rbc.uucp (Al Davis)
  8. Organization: Huh?
  9. Lines: 1753
  10.  
  11. #! /bin/sh
  12. # This is a shell archive, meaning:
  13. # 1. Remove everything above the #! /bin/sh line.
  14. # 2. Save the resulting text in a file.
  15. # 3. Execute the file with /bin/sh (not csh) to create the files:
  16. #    src/d_mos.c
  17. #    src/d_mos2.c
  18. #    src/d_mosc.c
  19. # This archive created: Tue Jan 26 22:51:04 1993
  20. export PATH; PATH=/bin:$PATH
  21. if test -f 'src/d_mos.c'
  22. then
  23.     echo shar: will not over-write existing file "'src/d_mos.c'"
  24. else
  25. cat << \SHAR_EOF > 'src/d_mos.c'
  26. /* dev_mos.c  01/05/92
  27.  * Copyright 1983-1992   Albert Davis
  28.  * mos model basics
  29.  * netlist syntax:
  30.  * device:  mxxxx d g s b mname <device args> <model card args>
  31.  * model:   .model mname NMOS <args>
  32.  *    or  .model mname PMOS <args>
  33.  */
  34. #include "ecah.h"
  35. #include "argparse.h"
  36. #include "branch.h"
  37. #include "convstat.h"
  38. #include "dev.h"
  39. #include "d_diode.h"
  40. #include "d_mos.h"
  41. #include "error.h"
  42. #include "io.h"
  43. #include "mode.h"
  44. #include "options.h"
  45. #include "status.h"
  46. #include "types.h"
  47. #include "declare.h"
  48. /*--------------------------------------------------------------------------*/
  49. static     branch_t *create_mos(const branch_t*);
  50. static     void    parse_mos(branch_t*,const char*,int*);
  51. static     void    print_mos(const branch_t*,int,int);
  52. static    branch_t *create_model_mos(const branch_t*);
  53. static     void    parse_model_mos(branch_t*,const char*,int*);
  54. static     void    print_model_mos(const branch_t*,int,int);
  55. static    double    trprobe_mos(const branch_t*,const char*);
  56. static     int    tr_mos(branch_t*);
  57. static     void    un_mos(branch_t*);
  58. static     void    ac_mos(branch_t*);
  59. static    void    expand_mos(branch_t*);
  60. static    double    tr_review_mos(branch_t*);
  61. /*--------------------------------------------------------------------------*/
  62. functions_t dev_mos = {
  63.    sizeof(branch_t),
  64.    create_mos,
  65.    parse_mos,
  66.    print_mos,
  67.    expand_mos,
  68.    trprobe_mos,
  69.    (double(*)())NULL,/* acprobe */
  70.    tr_mos,
  71.    un_mos,
  72.    ac_mos,
  73.    (void(*)())NULL,    /* trfun1 */
  74.    (void(*)())NULL,    /* trfun0 */
  75.    (complex_t(*)())NULL,/* acfun */
  76.    (void(*)())NULL,    /* tr_guess */
  77.    (void(*)())NULL,    /* tr_advance */
  78.    tr_review_mos
  79. };
  80. functions_t model_mos = {
  81.    sizeof(branch_t),
  82.    create_model_mos,
  83.    parse_model_mos,
  84.    print_model_mos,
  85.    (void(*)())NULL,    /* expand */
  86.    (double(*)())NULL,    /* trprobe */
  87.    (double(*)())NULL,/* acprobe */
  88.    (int(*)())NULL,    /* dotr */
  89.    (void(*)())NULL,    /* untr */
  90.    (void(*)())NULL,    /* doac */
  91.    (void(*)())NULL,    /* trfun1 */
  92.    (void(*)())NULL,    /* trfun0 */
  93.    (complex_t(*)())NULL,/* acfun */
  94.    (void(*)())NULL,    /* tr_guess */
  95.    (void(*)())NULL,    /* tr_advance */
  96.    (double(*)())NULL    /* tr_review */
  97. };
  98. /*--------------------------------------------------------------------------*/
  99. extern struct ioctrl io;
  100. extern const struct options opt;
  101. extern const struct status stats;
  102.  
  103. extern const int inc_mode;    /* make incremental changes            */
  104. extern const int sim_mode;
  105. extern const int currents_bad;
  106. extern const int *nm;
  107.  
  108. static struct dmod mos_diode_model = {(generic_t*)NULL, sizeof(struct dmod),
  109.    mdDEFMOD_js, mdDEFMOD_rs, mdDEFMOD_n, mdDEFMOD_tt, mdDEFMOD_cj,
  110.    mdDEFMOD_pb, mdDEFMOD_mj, mdDEFMOD_eg, mdDEFMOD_xti, mdDEFMOD_kf,
  111.    mdDEFMOD_af, mdDEFMOD_fc, mdDEFMOD_bv, mdDEFMOD_ibv, mdDEFMOD_cjsw,
  112.    mdDEFMOD_mjsw, mdDEFMOD_fcpb};
  113. static struct mos defalt = {(generic_t*)NULL, sizeof(struct mos),
  114.    (struct mmod*)NULL, mDEFDEV_modelname, mDEFDEV_l, mDEFDEV_w,
  115.    mDEFDEV_ad, mDEFDEV_as, mDEFDEV_pd, mDEFDEV_ps, mDEFDEV_nrd,
  116.    mDEFDEV_nrs, mDEFDEV_ic_vds, mDEFDEV_ic_vgs, mDEFDEV_ic_vbs,
  117.    NO, NO};
  118. static struct mmod defaltmodel = {&mos_diode_model, sizeof(struct mmod),
  119.    mDEFMOD_vto, mDEFMOD_kp, mDEFMOD_gamma, mDEFMOD_phi, mDEFMOD_lambda,
  120.    mDEFMOD_rd, mDEFMOD_rs, mDEFMOD_cbd, mDEFMOD_cbs, mDEFMOD_is,
  121.    mDEFMOD_pb, mDEFMOD_cgso, mDEFMOD_cgdo, mDEFMOD_cgbo, mDEFMOD_rsh,
  122.    mDEFMOD_js, mDEFMOD_tox, mDEFMOD_nsub, mDEFMOD_nss, mDEFMOD_nfs,
  123.    mDEFMOD_xj, mDEFMOD_ld, mDEFMOD_uo, mDEFMOD_ucrit, mDEFMOD_uexp,
  124.    mDEFMOD_utra, mDEFMOD_vmax, mDEFMOD_neff, mDEFMOD_kf, mDEFMOD_af,
  125.    mDEFMOD_delta, mDEFMOD_theta, mDEFMOD_eta, mDEFMOD_kappa,
  126.    mDEFMOD_level, mDEFMOD_tpg, mDEFMOD_polarity, mDEFMOD_xd,
  127.    mDEFMOD_cox, mDEFMOD_vfb, mDEFMOD_vbi, mDEFMOD_xwb, mDEFMOD_vbp,
  128.    mDEFMOD_cfsox};
  129. static branch_t modellist = {(generic_t*)&defaltmodel, sizeof(branch_t),
  130.    &model_mos, &modellist, &modellist, &modellist, &modellist,
  131.    (branch_t*)NULL, (branch_t*)NULL, mDEFMOD_modelname, /* more */};
  132. /*--------------------------------------------------------------------------*/
  133. static branch_t *create_mos(proto)
  134. const branch_t *proto;
  135. {
  136.  return createbranch(proto,(generic_t*)&defalt,&dev_mos);
  137. }
  138. /*--------------------------------------------------------------------------*/
  139. static void parse_mos(brh,cmd,cnt)
  140. branch_t *brh;
  141. const char *cmd;
  142. int *cnt;
  143. {
  144.  struct mos *x;
  145.  
  146.  x = (struct mos*)brh->x;
  147.  
  148.  parselabel(brh,cmd,cnt);
  149.  (void)parsenodes(brh,cmd,cnt,4);
  150.  (void)ctostr(cmd, cnt, x->modelname, LABELEN);
  151.  x->m = (struct mmod*)NULL;
  152.  if (isdigit(cmd[*cnt])  ||  cmd[*cnt] == '.'){
  153.     x->w = fabs(ctof(cmd,cnt)) * SCALE;
  154.     if (cmd[*cnt] == '/'){
  155.        (*cnt)++;
  156.        x->lo = fabs(ctof(cmd,cnt)) * SCALE;
  157.     }
  158.  }
  159.  
  160.  for (;;){
  161.     if (argparse(cmd,cnt,REPEAT,
  162.      "L",    aUDOUBLE,    &x->lo,
  163.      "W",    aUDOUBLE,    &x->w,
  164.      "AD",    aUDOUBLE,    &x->ad,
  165.      "AS",    aUDOUBLE,    &x->as,
  166.      "PD",    aUDOUBLE,    &x->pd,
  167.      "PS",    aUDOUBLE,    &x->ps,
  168.      "NRD",    aUDOUBLE,    &x->nrd,
  169.      "NRS",    aUDOUBLE,    &x->nrs,
  170.      ""))
  171.        ;
  172.     else{
  173.        syntax(cmd,cnt,bWARNING);
  174.        break;
  175.     }
  176.  }
  177. }
  178. /*--------------------------------------------------------------------------*/
  179. static void print_mos(brh,where,detail)
  180. const branch_t *brh;
  181. int where;
  182. int detail;
  183. {
  184.  struct mos *x;
  185.  
  186.  x = (struct mos*)brh->x;
  187.  
  188.  (void)printlabel(brh,where);
  189.  printnodes(brh,where);
  190.  mprintf(where, " %s ",    x->modelname);
  191.  mprintf(where, " l=%s ",  ftos(x->lo, "", 7, 0));
  192.  mprintf(where, " w=%s ",  ftos(x->w,  "", 7, 0));
  193.  if (x->ad != NOT_INPUT)
  194.     mprintf(where, " ad=%s ", ftos(x->ad, "", 7, 0));
  195.  if (x->as != NOT_INPUT)
  196.     mprintf(where, " as=%s ", ftos(x->as, "", 7, 0));
  197.  if (x->pd != 0.)
  198.     mprintf(where, " pd=%s ", ftos(x->pd, "", 7, 0));
  199.  if (x->ps != 0.)
  200.     mprintf(where, " ps=%s ", ftos(x->ps, "", 7, 0));
  201.  mprintf(where, " nrd=%s ",ftos(x->nrd,"", 7, 0));
  202.  mprintf(where, " nrs=%s ",ftos(x->nrs,"", 7, 0));
  203.  
  204.  if (x->icset){
  205.     int i;
  206.     mprintf(where, "  IC=");
  207.     for (i=0;  i<NUM_INIT_COND;  i++)
  208.        mprintf(where, "%s ",ftos(x->ic[i],"", 7, 0));
  209.  }
  210.  mprintf(where, "\n");
  211. }
  212. /*--------------------------------------------------------------------------*/
  213. static branch_t *create_model_mos(proto)
  214. const branch_t *proto;
  215. {
  216.  branch_t *brh;
  217.  
  218.  brh = createbranch(proto,(generic_t*)&defaltmodel,&model_mos);
  219.  brh->stprev = &modellist;
  220.  return brh;
  221. }
  222. /*--------------------------------------------------------------------------*/
  223. static void parse_model_mos(brh,cmd,cnt)
  224. branch_t *brh;
  225. const char *cmd;
  226. int *cnt;
  227. {
  228.  struct mmod *m;
  229.  
  230.  m = (struct mmod*)brh->x;
  231.  
  232.  (void)ctostr(cmd, cnt, brh->label, LABELEN);
  233.  if (argparse(cmd,cnt,ONEPASS,
  234.     "NMos",    aENUM,        &m->polarity,    pN,
  235.     "PMos",    aENUM,        &m->polarity,    pP,
  236.      ""))
  237.         ;
  238.  else
  239.     syntax(cmd,cnt,bWARNING);
  240.  
  241.  (void)skiplparen(cmd,cnt);
  242.  for (;;){
  243.     if (argparse(cmd,cnt,REPEAT,
  244.      "LEvel",aFINT,        &m->level,
  245.      "VTO",    aSDOUBLE,    &m->vto,    (double)m->polarity,
  246.      "KP",    aDOUBLE,    &m->kp,
  247.      "GAmma",aDOUBLE,    &m->gamma,
  248.      "PHI",    aUDOUBLE,    &m->phi,
  249.      "LAmbda",aDOUBLE,    &m->lambda,
  250.      "RD",    aDOUBLE,    &m->rd,
  251.      "RS",    aDOUBLE,    &m->rs,
  252.      "CBD",    aDOUBLE,    &m->cbd,
  253.      "CBS",    aDOUBLE,    &m->cbs,
  254.      "IS",    aDOUBLE,    &m->is,
  255.      "PB",    aUDOUBLE,    &m->pb,
  256.      "CGSo",    aDOUBLE,    &m->cgso,
  257.      "CGDo",    aDOUBLE,    &m->cgdo,
  258.      "CGBo",    aDOUBLE,    &m->cgbo,
  259.      "RSH",    aDOUBLE,    &m->rsh,
  260.      "CJ",    aDOUBLE,    &m->d->cj,
  261.      "MJ",    aDOUBLE,    &m->d->mj,
  262.      "CJSw",    aDOUBLE,    &m->d->cjsw,
  263.      "MJSw",    aDOUBLE,    &m->d->mjsw,
  264.      "JS",    aDOUBLE,    &m->js,
  265.     ""))
  266.     ;
  267.     else if (argparse(cmd,cnt,REPEAT,
  268.      "TOX",    aUDOUBLE,    &m->tox,
  269.      "NSUb",    aSDOUBLE,    &m->nsub,    ICM2M3,
  270.      "NSS",    aSDOUBLE,    &m->nss,    ICM2M2,
  271.      "NFS",    aSDOUBLE,    &m->nfs,    ICM2M2,
  272.      "TPG",    aFINT,        &m->tpg,
  273.      "XJ",    aUDOUBLE,    &m->xj,
  274.      "LD",    aDOUBLE,    &m->ld,
  275.      "UO",    aSDOUBLE,    &m->uo,        CM2M2,
  276.      "UCRit",aSDOUBLE,    &m->ucrit,    ICM2M,
  277.      "UEXp",    aDOUBLE,    &m->uexp,
  278.      "UTRa",    aDOUBLE,    &m->utra,
  279.      "VMAx",    aDOUBLE,    &m->vmax,
  280.      "NEFf",    aUDOUBLE,    &m->neff,
  281.      "KF",    aDOUBLE,    &m->kf,
  282.      "AF",    aDOUBLE,    &m->af,
  283.      "FC",    aDOUBLE,    &m->d->fc,
  284.      "DELta",aDOUBLE,    &m->delta,
  285.      "THEta",aDOUBLE,    &m->theta,
  286.      "ETA",    aDOUBLE,    &m->eta,
  287.      "KAPpa",aDOUBLE,    &m->kappa,
  288.      ""))
  289.         ;
  290.     else{
  291.        (void)skiprparen(cmd,cnt);
  292.        syntax(cmd,cnt,bWARNING);
  293.        break;
  294.     }
  295.  }
  296.  
  297.  if ((m->rs == NOT_INPUT)  &&  (m->rd != NOT_INPUT)){
  298.     error(bWARNING, "%s: rd input, but not rs. setting rs = 0.\n",
  299.             printlabel(brh,NO));
  300.     m->rs = 0.;
  301.  }else if ((m->rd == NOT_INPUT)  &&  (m->rs != NOT_INPUT)){
  302.     error(bWARNING, "%s: rs input, but not rd. setting rd = 0.\n",
  303.             printlabel(brh,NO));
  304.     m->rd = 0.;
  305.  }
  306.  
  307.  if ((m->rsh != NOT_INPUT)  &&  (m->rd != NOT_INPUT)){
  308.     error(bWARNING, "%s: rsh - rs - rd conflict: using %s\n",
  309.         printlabel(brh,NO),
  310.         ((m->rd <= 0.)  &&  (m->rs <= 0.)) ? "rsh" : "rs,rd" );
  311.  }else if ((m->rsh == NOT_INPUT)  &&  (m->rd == NOT_INPUT)){
  312.     m->rsh = 0.;
  313.  }
  314.  
  315.  if (m->tox == 0.){
  316.     error(bWARNING, "%s: tox == 0: using %s\n",
  317.             printlabel(brh,NO),
  318.         ftos(mDEFMOD_tox,        "", 7, 0));
  319.     m->tox = mDEFMOD_tox;
  320.  }
  321.  m->cox = E_OX / m->tox;
  322.  
  323.  if (m->kp == NOT_INPUT){
  324.     m->kp = m->uo * m->cox;
  325.     m->calc.kp = YES;
  326.  }
  327.  
  328.  if (m->is == NOT_INPUT  &&  m->js == NOT_INPUT){
  329.     m->is = mDEFMODLR_is;
  330.  }else if (m->is != NOT_INPUT  &&  m->js != NOT_INPUT){
  331.     error(bWARNING, "%s: is - js conflict\n", printlabel(brh,NO));
  332.  }
  333.  
  334.  if (m->nsub != NOT_INPUT){
  335.     m->nsub = fabs(m->nsub);
  336.     if (m->nsub < NI){
  337.        error(bWARNING, "%s: nsub < ni\n", printlabel(brh,NO));
  338.        m->nsub = NI;
  339.     }
  340.      
  341.     if (m->d->cj == NOT_INPUT){
  342.        m->d->cj = sqrt(E_SI * Q * m->nsub / (2. * m->pb));
  343.        m->calc.cj = YES;
  344.     }
  345.  
  346.     if (m->phi == NOT_INPUT){
  347.        m->phi = (2.*K/Q)*opt.tempamb*log(m->nsub/NI);
  348.        if (m->phi < .1){
  349.          error(bWARNING, "%s: calculated phi too small, using .1\n",
  350.          printlabel(brh,NO));
  351.          m->phi = .1;
  352.        }
  353.        m->calc.phi = YES;
  354.     }
  355.  
  356.     if (m->gamma == NOT_INPUT){
  357.        m->gamma = sqrt(2. * E_SI * Q * m->nsub) / m->cox;
  358.        m->calc.gamma = YES;
  359.     }
  360.  
  361.     if (m->vto == NOT_INPUT){
  362.        double phi_ms;
  363.        double eg;
  364.        eg = 1.16 - (7.02e-4 * opt.tempamb*opt.tempamb) / (opt.tempamb + 1108.);
  365.  
  366.        if (m->tpg == gMETAL)
  367.           phi_ms = -.05 - (eg + m->polarity * m->phi) / 2.;
  368.        else
  369.           phi_ms = -m->polarity * (m->tpg * eg + m->phi) / 2.;
  370.  
  371.        m->vfb = phi_ms - Q * m->nss / m->cox;
  372.        m->vto = m->vfb + m->polarity * (m->phi + m->gamma * sqrt(m->phi));
  373.        m->calc.vto = YES;
  374.     }
  375.     m->xd = sqrt((2. * E_SI / Q) / m->nsub);
  376.     m->xwb = m->xd * sqrt(m->pb);
  377.  }else{
  378.     if (m->vto == NOT_INPUT)
  379.        m->vto = mDEFMODLR_vto;
  380.     if (m->gamma == NOT_INPUT)
  381.        m->gamma = mDEFMODLR_gamma;
  382.     if (m->phi == NOT_INPUT)
  383.        m->phi = mDEFMODLR_phi;
  384.     if (m->d->cj == NOT_INPUT)
  385.        m->d->cj = mDEFMODLR_cj;
  386.     m->xd = m->xwb / sqrt(m->pb);
  387.  }
  388.  if (m->lambda != NOT_INPUT  &&  m->lambda > .2)
  389.     error(bWARNING, "%s: lambda too large (> .2)\n", printlabel(brh,NO));
  390.  if (m->vfb == NOT_INPUT)
  391.     m->vfb = m->vto - (m->phi + m->gamma * sqrt(m->phi));
  392.  m->vbi = m->vfb + m->phi;
  393.  m->vbp = m->ucrit * E_SI / m->cox;
  394.  m->cfsox = Q * m->nfs / m->cox;
  395.  m->d->fcpb = m->d->fc * m->d->pb;
  396. }
  397. /*--------------------------------------------------------------------------*/
  398. static void print_model_mos(brh,where,detail)
  399. const branch_t *brh;
  400. int where;
  401. int detail;
  402. {
  403.  struct mmod *m;
  404.  m = (struct mmod*)brh->x;
  405.  
  406.  mprintf(where, ".model %s ", brh->label);
  407.  mprintf(where, " %s (",     (m->polarity < 0) ? "pmos" : "nmos");
  408.  mprintf(where, " level=%d ", m->level);
  409.  if (!m->calc.vto)
  410.     mprintf(where, " vto=%s ",   ftos(m->vto*m->polarity,"", 7, 0));
  411.  if (!m->calc.kp)
  412.     mprintf(where, " kp=%s ",    ftos(m->kp,         "", 7, 0));
  413.  if (!m->calc.gamma)
  414.     mprintf(where, " gamma=%s ", ftos(m->gamma,      "", 7, 0));
  415.  if (!m->calc.phi)
  416.     mprintf(where, " phi=%s ",   ftos(m->phi,        "", 7, 0));
  417.  if (m->lambda != NOT_INPUT)
  418.     mprintf(where, " lambda=%s ",ftos(m->lambda,     "", 7, 0));
  419.  if (m->rd != NOT_INPUT)
  420.     mprintf(where, " rd=%s ",    ftos(m->rd,         "", 7, 0));
  421.  if (m->rs != NOT_INPUT)
  422.     mprintf(where, " rs=%s ",    ftos(m->rs,         "", 7, 0));
  423.  if (m->cbd != NOT_INPUT)
  424.     mprintf(where, " cbd=%s ",   ftos(m->cbd,        "", 7, 0));
  425.  if (m->cbs != NOT_INPUT)
  426.     mprintf(where, " cbs=%s ",   ftos(m->cbs,        "", 7, 0));
  427.  if (m->is != NOT_INPUT)
  428.     mprintf(where, " is=%s ",    ftos(m->is,         "", 7, 0));
  429.  mprintf(where, " pb=%s ",    ftos(m->pb,         "", 7, 0));
  430.  mprintf(where, " cgso=%s ",  ftos(m->cgso,       "", 7, 0));
  431.  mprintf(where, " cgdo=%s ",  ftos(m->cgdo,       "", 7, 0));
  432.  mprintf(where, " cgbo=%s ",  ftos(m->cgbo,       "", 7, 0));
  433.  if (m->rsh != NOT_INPUT)
  434.     mprintf(where, " rsh=%s ",   ftos(m->rsh,        "", 7, 0));
  435.  if (!m->calc.cj)
  436.     mprintf(where, " cj=%s ",    ftos(m->d->cj,      "", 7, 0));
  437.  mprintf(where, " mj=%s ",    ftos(m->d->mj,      "", 7, 0));
  438.  mprintf(where, " cjsw=%s ",  ftos(m->d->cjsw,    "", 7, 0));
  439.  mprintf(where, " mjsw=%s ",  ftos(m->d->mjsw,    "", 7, 0));
  440.  if (m->js != NOT_INPUT)
  441.     mprintf(where, " js=%s ",    ftos(m->js,         "", 7, 0));
  442.  mprintf(where, " tox=%s ",   ftos(m->tox,         "", 7, 0));
  443.  if (m->nsub != NOT_INPUT)
  444.     mprintf(where, " nsub=%s ",  ftos(m->nsub/ICM2M3,"", 7, 0));
  445.  if (m->nss != mDEFMOD_nss  ||  m->nsub != NOT_INPUT)
  446.     mprintf(where, " nss=%s ",   ftos(m->nss /ICM2M2,"", 7, 0));
  447.  mprintf(where, " nfs=%s ",   ftos(m->nfs /ICM2M2,"", 7, 0));
  448.  mprintf(where, " tpg=%d ",   m->tpg);
  449.  if (m->xj != NOT_INPUT)
  450.     mprintf(where, " xj=%s ",    ftos(m->xj,         "", 7, 0));
  451.  mprintf(where, " ld=%s ",    ftos(m->ld,         "", 7, 0));
  452.  mprintf(where, " uo=%s ",    ftos(m->uo   /CM2M2,"", 7, 0));
  453.  if (m->ucrit != mDEFMOD_ucrit  ||  m->uexp != NOT_INPUT)
  454.     mprintf(where, " ucrit=%s ", ftos(m->ucrit/ICM2M,"", 7, 0));
  455.  if (m->uexp != NOT_INPUT)
  456.     mprintf(where, " uexp=%s ",  ftos(m->uexp,       "", 7, 0));
  457.  if (m->utra != NOT_INPUT)
  458.     mprintf(where, " utra=%s ",  ftos(m->utra,       "", 7, 0));
  459.  if (m->vmax != NOT_INPUT)
  460.     mprintf(where, " vmax=%s ",  ftos(m->vmax,       "", 7, 0));
  461.  if (m->neff != mDEFMOD_neff  ||  m->lambda == NOT_INPUT)
  462.     mprintf(where, " neff=%s ",  ftos(m->neff,       "", 7, 0));
  463.  if (m->kf != NOT_INPUT)
  464.     mprintf(where, " kf=%s ",    ftos(m->kf,         "", 7, 0));
  465.  if (m->af != NOT_INPUT)
  466.     mprintf(where, " af=%s ",    ftos(m->af,         "", 7, 0));
  467.  mprintf(where, " fc=%s ",    ftos(m->d->fc,      "", 7, 0));
  468.  mprintf(where, " delta=%s ", ftos(m->delta,      "", 7, 0));
  469.  if (m->theta != NOT_INPUT)
  470.     mprintf(where, " theta=%s ", ftos(m->theta,      "", 7, 0));
  471.  if (m->eta != NOT_INPUT)
  472.     mprintf(where, " eta=%s ",   ftos(m->eta,        "", 7, 0));
  473.  if (m->kappa != NOT_INPUT)
  474.     mprintf(where, " kappa=%s ", ftos(m->kappa,      "", 7, 0));
  475.  mprintf(where, ")\n*+(");
  476.  mprintf(where, "* vfb=%s ",  ftos(m->vfb,        "", 7, 0));
  477.  if (m->calc.vto)
  478.     mprintf(where, "* vto=%s ",   ftos(m->vto*m->polarity,        "", 7, 0));
  479.  if (m->calc.kp)
  480.     mprintf(where, "* kp=%s ",    ftos(m->kp,         "", 7, 0));
  481.  if (m->calc.gamma)
  482.     mprintf(where, "* gamma=%s ", ftos(m->gamma,      "", 7, 0));
  483.  if (m->calc.phi)
  484.     mprintf(where, "* phi=%s ",   ftos(m->phi,        "", 7, 0));
  485.  if (m->calc.cj)
  486.     mprintf(where, "* cj=%s ",    ftos(m->d->cj,         "", 7, 0));
  487.  mprintf(where, ")\n");
  488. }
  489. /*--------------------------------------------------------------------------*/
  490. static double trprobe_mos(brh,what)
  491. const branch_t *brh;
  492. const char *what;
  493. {
  494.  struct mos *x;
  495.  int dummy = 0;
  496.  
  497.  x = (struct mos*)brh->x;
  498.  if (!x->m  ||  !brh->subckt)
  499.     error(bERROR, "internal error: %s not expanded\n", printlabel(brh,NO));
  500.  
  501.  setmatch(what,&dummy);
  502.  if (rematch("Vds")){
  503.     return tr_volts(brh->nDRAIN,brh->nSOURCE);
  504.  }else if (rematch("VGS")){
  505.     return tr_volts(brh->nGATE,brh->nSOURCE);
  506.  }else if (rematch("VBS")){
  507.     return tr_volts(brh->nBULK,brh->nSOURCE);
  508.  }else if (rematch("VDG")){
  509.     return tr_volts(brh->nDRAIN,brh->nGATE);
  510.  }else if (rematch("Id")){
  511.     return (x->Rd)
  512.     ?   trprobe_branch(x->Rd,"I")
  513.     :   trprobe_branch(x->Ids,"I")
  514.       + trprobe_branch(x->Gmf,"I")
  515.       + trprobe_branch(x->Gmr,"I")
  516.       + trprobe_branch(x->Yds,"I")
  517.       + trprobe_branch(x->Gmbf,"I")
  518.       + trprobe_branch(x->Gmbr,"I")
  519.       - trprobe_branch(x->Cgd,"I")
  520.       + trprobe_branch(x->Ddb,"I") * x->m->polarity;
  521.  }else if (rematch("IS")){
  522.     return (x->Rd)
  523.     ?   trprobe_branch(x->Rs,"I")
  524.     : - trprobe_branch(x->Ids,"I")
  525.       - trprobe_branch(x->Gmf,"I")
  526.       - trprobe_branch(x->Gmr,"I")
  527.       - trprobe_branch(x->Yds,"I")
  528.       - trprobe_branch(x->Gmbf,"I")
  529.       - trprobe_branch(x->Gmbr,"I")
  530.       - trprobe_branch(x->Cgs,"I")
  531.       + trprobe_branch(x->Dsb,"I") * x->m->polarity;
  532.  }else if (rematch("IG")){
  533.     return trprobe_branch(x->Cgs,"I")
  534.      + trprobe_branch(x->Cgd,"I")
  535.      + trprobe_branch(x->Cgb,"I");
  536.  }else if (rematch("IB")){
  537.     return - trprobe_branch(x->Ddb,"I") * x->m->polarity
  538.        - trprobe_branch(x->Dsb,"I") * x->m->polarity
  539.        - trprobe_branch(x->Cgb,"I");
  540.  }else if (rematch("P")){
  541.     branch_t *pb, *stop;
  542.     double power = 0.;
  543.     stop = pb = brh->subckt;
  544.     do {
  545.        power += trprobe_branch(pb,"P");
  546.     } while (pb=nextbranch_dev(pb), pb != stop);
  547.     return power;
  548.  }else if (rematch("REgion")){
  549.     return (double)(
  550.       (!x->cutoff)
  551.     + (!x->subthreshold * 2)
  552.     + (x->saturated * 4)
  553.     + (x->sbfwd * 10)
  554.     + (x->dbfwd * 20)
  555.     ) * ((x->reversed)? -1 : 1);
  556.  }else{ /* bad parameter */
  557.     return NOT_VALID;
  558.  }
  559. /*NOTREACHED*/
  560. }
  561. /*--------------------------------------------------------------------------*/
  562. static int tr_mos(brh)
  563. branch_t *brh;
  564. {
  565.  struct mos *x;
  566.  struct mmod *m;
  567.  double vds, vgs, vbs;
  568.  
  569.  if (brh->iter == stats.iter[iTOTAL]){
  570.     return brh->status;
  571.  }else{
  572.     brh->iter = stats.iter[iTOTAL];
  573.  }
  574.  x = (struct mos*)brh->x;
  575.  if (!(x->m && brh->subckt))
  576.     error(bERROR, "internal error: %s not expanded\n", printlabel(brh,NO));
  577.  m = x->m;
  578.  
  579.  x->sourcenode.m = nm[x->sourcenode.t];
  580.  x->drainnode.m  = nm[x->drainnode.t];
  581.  
  582.  vds = m->polarity * tr_volts_limited(x->drainnode,x->sourcenode);
  583.  x->reversed = vds < 0.;
  584.  if (x->reversed){
  585.     vds = -vds;
  586.     vgs = m->polarity * tr_volts_limited(brh->nGATE,x->drainnode);
  587.     vbs = m->polarity * tr_volts_limited(brh->nBULK,x->drainnode);
  588.     if (!io.suppresserrors)
  589.        error(bTRACE, "%s: reversed\n", printlabel(brh,NO));
  590.  }else{
  591.     vgs = m->polarity * tr_volts_limited(brh->nGATE,x->sourcenode);
  592.     vbs = m->polarity * tr_volts_limited(brh->nBULK,x->sourcenode);
  593.  }
  594.  
  595.  if (!opt.bypass || currents_bad){
  596.     brh->bypass = NO;
  597.     x->vds = vds;
  598.     x->vgs = vgs;
  599.     x->vbs = vbs;
  600.     eval_mos2(brh);
  601.     brh->status = tr_fill_rl(brh->subckt);
  602.  }else{
  603.     if (brh->status == cGOOD){
  604.        brh->status  = conchk(x->vds, vds, opt.vntol);
  605.        brh->status |= conchk(x->vgs, vgs, opt.vntol);
  606.        brh->status |= conchk(x->vbs, vbs, opt.vntol);
  607.        if (brh->status & cNONCONVERGE){
  608.           error(bTRACE, "%s: deconverged\n", printlabel(brh,0));
  609.       brh->bypass = NO;
  610.       x->vds = vds;
  611.       x->vgs = vgs;
  612.       x->vbs = vbs;
  613.       eval_mos2(brh);
  614.       brh->status = tr_fill_rl(brh->subckt);
  615.        }else{
  616.       brh->bypass = YES;
  617.       if (!inc_mode){
  618.          (void)tr_fill_rl(brh->subckt);
  619.       }
  620.        }
  621.     }else{ /* not converged */
  622.        if (opt.bypass == bVOLT){
  623.       brh->status  = conchk(x->vds, vds, opt.vntol);
  624.       brh->status |= conchk(x->vgs, vgs, opt.vntol);
  625.       brh->status |= conchk(x->vbs, vbs, opt.vntol);
  626.        }
  627.        if (brh->status & cNONCONVERGE){
  628.       brh->bypass = NO;
  629.       x->vds = vds;
  630.       x->vgs = vgs;
  631.       x->vbs = vbs;
  632.       eval_mos2(brh);
  633.       brh->status = tr_fill_rl(brh->subckt);
  634.        }else{
  635.           error(bWARNING, "%s: ambitious bypass\n", printlabel(brh,0));
  636.       brh->bypass = YES;
  637.       if (!inc_mode){
  638.          (void)tr_fill_rl(brh->subckt);
  639.       }
  640.        }
  641.     }
  642.  }
  643.  
  644.  return brh->status;
  645. }
  646. /*--------------------------------------------------------------------------*/
  647. static void un_mos(brh)
  648. branch_t *brh;
  649. {
  650.  tr_unfill_rl(brh->subckt);
  651. }
  652. /*--------------------------------------------------------------------------*/
  653. static void ac_mos(brh)
  654. branch_t *brh;
  655. {
  656.  struct mos *x;
  657.  x = (struct mos*)brh->x;
  658.  if (!(x->m && brh->subckt))
  659.     error(bERROR, "internal error: %s not expanded\n", printlabel(brh,NO));
  660.  ac_fill_rl(brh->subckt);
  661. }
  662. /*--------------------------------------------------------------------------*/
  663. static void expand_mos(brh)
  664. branch_t *brh;
  665. {
  666.  const struct mmod *m;
  667.  struct mos *x;
  668.  
  669.  expandgeneric(brh,&modellist);
  670.  x = (struct mos*)brh->x;
  671.  m = x->m;
  672.  
  673.  if (m->level != 2)
  674.     error(bWARNING, "%s: level %d not supported, using level 2\n",
  675.             printlabel(brh,NO), m->level);
  676.  
  677.  x->le = x->lo - 2. * m->ld;                /* calculate parameters */
  678.  x->cgate = m->cox * x->w * x->le;
  679.  if (x->cgate <= 0.)
  680.     error(bERROR, "%s: cgate is negative?\n", printlabel(brh,NO));
  681.  x->beta = m->kp * x->w / x->le;
  682.  x->relxj = (m->xj != NOT_INPUT  &&  m->xj > 0.)
  683.     ? .5 * m->xj / x->le
  684.     : NOT_INPUT;
  685.  x->eta_1 = (PI/4.) * E_SI * m->delta / x->cgate * x->le;
  686.  x->eta = x->eta_1 + 1.;
  687.  x->eta_2 = x->eta / 2.;
  688.                                 /* build subckt */
  689.                                    /* resistors */
  690.  if (m->rsh != NOT_INPUT  &&  m->rd <= 0.  &&  m->rs <= 0.){
  691.     x->rd = m->rsh * x->nrd;
  692.     x->rs = m->rsh * x->nrs;
  693.  }else{
  694.     x->rd = (m->rd != NOT_INPUT) ? m->rd : 0.;
  695.     x->rs = (m->rs != NOT_INPUT) ? m->rs : 0.;
  696.  }
  697.  if (x->rs != 0.){
  698.     x->sourcenode.t = newnode_model();
  699.     x->Rs = (*(dev_resistor.create))((branch_t*)NULL);
  700.     x->Rs->parent = brh;
  701.     strcpy(x->Rs->label,"Rs");
  702.     x->Rs->n[OUT1] = brh->nSOURCE;
  703.     x->Rs->n[OUT2] = x->sourcenode;
  704.     x->Rs->val = x->rs;
  705.     x->Rs->next = brh->subckt;
  706.     brh->subckt = insertbranch(x->Rs);
  707.  }else{
  708.     x->sourcenode = brh->nSOURCE;
  709.     x->Rs = (branch_t*)NULL;
  710.  }
  711.  if (x->rd != 0.){
  712.     x->drainnode.t = newnode_model();
  713.     x->Rd = (*(dev_resistor.create))((branch_t*)NULL);
  714.     x->Rd->parent = brh;
  715.     strcpy(x->Rd->label,"Rd");
  716.     x->Rd->n[OUT1] = brh->nDRAIN;
  717.     x->Rd->n[OUT2] = x->drainnode;
  718.     x->Rd->val = x->rd;
  719.     x->Rd->next = brh->subckt;
  720.     brh->subckt = insertbranch(x->Rd);
  721.  }else{
  722.     x->drainnode = brh->nDRAIN;
  723.     x->Rd = (branch_t*)NULL;
  724.  }
  725.  
  726.                                   /* diodes */
  727.  if (m->js == NOT_INPUT  ||  x->ad == NOT_INPUT  ||  x->as == NOT_INPUT){
  728.     x->idsat = x->issat = m->is;
  729.  }else{
  730.     x->idsat = m->js * x->ad;
  731.     x->issat = m->js * x->as;
  732.  }
  733.  if (brh->nBULK.t != x->drainnode.t   &&   x->idsat != 0.){
  734.     struct diode *xd;
  735.     if (!x->Ddb)
  736.        x->Ddb = (*(dev_diode.create))((branch_t*)NULL);
  737.     x->Ddb->parent = brh;
  738.     xd = (struct diode*)x->Ddb->x;
  739.     strcpy(x->Ddb->label,"Ddb");
  740.     if (m->polarity == pN){
  741.        x->Ddb->n[OUT1] = brh->nBULK;
  742.        x->Ddb->n[OUT2] = x->drainnode;
  743.     }else{ /* m->polarity == pP */
  744.        x->Ddb->n[OUT2] = brh->nBULK;
  745.        x->Ddb->n[OUT1] = x->drainnode;
  746.     }
  747.     strcpy(xd->modelname,mdDEFMOD_modelname);
  748.     xd->area = (x->ad != NOT_INPUT) ? x->ad : 1.;
  749.     xd->perim = x->pd;
  750.     xd->is = x->idsat;
  751.     xd->m = x->m->d;
  752.     x->Ddb->next = brh->subckt;
  753.     x->Ddb->prev = (branch_t*)NULL;
  754.     brh->subckt = insertbranch(x->Ddb);
  755.  }else{
  756.     x->Ddb = (branch_t*)NULL;
  757.  }
  758.  
  759.  if (brh->nBULK.t != x->sourcenode.t   &&   x->issat != 0.){
  760.     struct diode *xd;
  761.     if (!x->Dsb)
  762.        x->Dsb = (*(dev_diode.create))((branch_t*)NULL);
  763.     x->Dsb->parent = brh;
  764.     xd = (struct diode*)x->Dsb->x;
  765.     strcpy(x->Dsb->label,"Dsb");
  766.     if (m->polarity == pN){
  767.        x->Dsb->n[OUT1] = brh->nBULK;
  768.        x->Dsb->n[OUT2] = x->sourcenode;
  769.     }else{ /* m->polarity == pP */
  770.        x->Dsb->n[OUT2] = brh->nBULK;
  771.        x->Dsb->n[OUT1] = x->sourcenode;
  772.     }
  773.     strcpy(xd->modelname,mdDEFMOD_modelname);
  774.     xd->area = (x->as != NOT_INPUT) ? x->as : 1.;
  775.     xd->perim = x->ps;
  776.     xd->is = x->issat;
  777.     xd->m = x->m->d;
  778.     x->Dsb->next = brh->subckt;
  779.     x->Dsb->prev = (branch_t*)NULL;
  780.     brh->subckt = insertbranch(x->Dsb);
  781.  }else{
  782.     x->Dsb = (branch_t*)NULL;
  783.  }
  784.                                   /* capacitors */
  785.  if (brh->nGATE.t != x->sourcenode.t   &&   m->cgso != 0.){
  786.     if (!x->Cgs){
  787.        static functions_t *ff;
  788.        x->Cgs = (*(dev_cap.create))((branch_t*)NULL);
  789.        if (!ff){
  790.       ff = (functions_t*)calloc(1, sizeof(functions_t));
  791.       *ff = *(x->Cgs->f);
  792.       ff->expand = (void(*)())NULL;        /* no gate capacitance */
  793.       ff->trfun1 = mos_cgs1;        /* if no overlap cap */
  794.       ff->trfun0 = mos_cgs0;
  795.       ff->acfun = (complex_t(*)())NULL;
  796.        }
  797.        x->Cgs->f = ff;
  798.     }
  799.     x->Cgs->parent = brh;
  800.     strcpy(x->Cgs->label,"Cgs");
  801.     x->Cgs->n[OUT1] = brh->nGATE;
  802.     x->Cgs->n[OUT2] = x->sourcenode;
  803.     x->Cgs->val = m->cgso * x->w;
  804.     x->Cgs->next = brh->subckt;
  805.     x->Cgs->prev = (branch_t*)NULL;
  806.     brh->subckt = insertbranch(x->Cgs);
  807.  }else{
  808.     x->Cgs = (branch_t*)NULL;
  809.  }
  810.  
  811.  if (brh->nGATE.t != x->drainnode.t   &&   m->cgdo != 0.){
  812.     if (!x->Cgd){
  813.        static functions_t *ff;
  814.        x->Cgd = (*(dev_cap.create))((branch_t*)NULL);
  815.        if (!ff){
  816.       ff = (functions_t*)calloc(1, sizeof(functions_t));
  817.       *ff = *(x->Cgd->f);
  818.       ff->expand = (void(*)())NULL;
  819.       ff->trfun1 = mos_cgd1;
  820.       ff->trfun0 = mos_cgd0;
  821.       ff->acfun = (complex_t(*)())NULL;
  822.        }
  823.        x->Cgd->f = ff;
  824.     }
  825.     x->Cgd->parent = brh;
  826.     strcpy(x->Cgd->label,"Cgd");
  827.     x->Cgd->n[OUT1] = brh->nGATE;
  828.     x->Cgd->n[OUT2] = x->drainnode;
  829.     x->Cgd->val = m->cgdo * x->w;
  830.     x->Cgd->next = brh->subckt;
  831.     x->Cgd->prev = (branch_t*)NULL;
  832.     brh->subckt = insertbranch(x->Cgd);
  833.  }else{
  834.     x->Cgd = (branch_t*)NULL;
  835.  }
  836.  
  837.  if (brh->nBULK.t != brh->nGATE.t   &&   m->cgbo != 0.){
  838.     if (!x->Cgb){
  839.        static functions_t *ff;
  840.        x->Cgb = (*(dev_cap.create))((branch_t*)NULL);
  841.        if (!ff){
  842.       ff = (functions_t*)calloc(1, sizeof(functions_t));
  843.       *ff = *(x->Cgb->f);
  844.       ff->expand = (void(*)())NULL;
  845.       ff->trfun1 = mos_cgb1;
  846.       ff->trfun0 = mos_cgb0;
  847.       ff->acfun = (complex_t(*)())NULL;
  848.        }
  849.        x->Cgb->f = ff;
  850.     }
  851.     x->Cgb->parent = brh;
  852.     strcpy(x->Cgb->label,"Cgb");
  853.     x->Cgb->n[OUT1] = brh->nGATE;
  854.     x->Cgb->n[OUT2] = brh->nBULK;
  855.     x->Cgb->val = m->cgbo * x->le;
  856.     x->Cgb->next = brh->subckt;
  857.     x->Cgb->prev = (branch_t*)NULL;
  858.     brh->subckt = insertbranch(x->Cgb);
  859.  }else{
  860.     x->Cgb = (branch_t*)NULL;
  861.  }
  862.                                /* model sources */
  863.  if (brh->nBULK.t != x->sourcenode.t){
  864.     if (!x->Gmbf){
  865.        static functions_t *ff;
  866.        x->Gmbf = (*(dev_vccs.create))((branch_t*)NULL);
  867.        if (!ff){
  868.       ff = (functions_t*)calloc(1, sizeof(functions_t));
  869.       *ff = *(x->Gmbf->f);
  870.       ff->expand = (void(*)())NULL;
  871.       ff->trfun1 = mos2_gmbf1;
  872.       ff->trfun0 = mos2_gmbf0;
  873.       ff->acfun = (complex_t(*)())NULL;
  874.        }
  875.        x->Gmbf->f = ff;
  876.     }
  877.     x->Gmbf->parent = brh;
  878.     strcpy(x->Gmbf->label,"Gmbf");
  879.     x->Gmbf->n[OUT1] = x->drainnode;
  880.     x->Gmbf->n[OUT2] = x->sourcenode;
  881.     x->Gmbf->n[IN1] = brh->nBULK;
  882.     x->Gmbf->n[IN2] = x->sourcenode;
  883.     x->Gmbf->next = brh->subckt;
  884.     x->Gmbf->prev = (branch_t*)NULL;
  885.     brh->subckt = insertbranch(x->Gmbf);
  886.  }else{
  887.     x->Gmbf = (branch_t*)NULL;
  888.  }
  889.  
  890.  if (brh->nBULK.t != x->drainnode.t){
  891.     if (!x->Gmbr){
  892.        static functions_t *ff;
  893.        x->Gmbr = (*(dev_vccs.create))((branch_t*)NULL);
  894.        if (!ff){
  895.       ff = (functions_t*)calloc(1, sizeof(functions_t));
  896.       *ff = *(x->Gmbr->f);
  897.       ff->expand = (void(*)())NULL;
  898.       ff->trfun1 = mos2_gmbr1;
  899.       ff->trfun0 = mos2_gmbr0;
  900.       ff->acfun = (complex_t(*)())NULL;
  901.        }
  902.        x->Gmbr->f = ff;
  903.     }
  904.     x->Gmbr->parent = brh;
  905.     strcpy(x->Gmbr->label,"Gmbr");
  906.     x->Gmbr->n[OUT1] = x->sourcenode;
  907.     x->Gmbr->n[OUT2] = x->drainnode;
  908.     x->Gmbr->n[IN1] = brh->nBULK;
  909.     x->Gmbr->n[IN2] = x->drainnode;
  910.     x->Gmbr->next = brh->subckt;
  911.     x->Gmbr->prev = (branch_t*)NULL;
  912.     brh->subckt = insertbranch(x->Gmbr);
  913.  }else{
  914.     x->Gmbr = (branch_t*)NULL;
  915.  }
  916.  
  917.  if (!x->Yds){
  918.     static functions_t *ff;
  919.     x->Yds = (*(dev_admittance.create))((branch_t*)NULL);
  920.     if (!ff){
  921.        ff = (functions_t*)calloc(1, sizeof(functions_t));
  922.        *ff = *(x->Yds->f);
  923.        ff->expand = (void(*)())NULL;
  924.        ff->trfun1 = mos2_gds1;
  925.        ff->trfun0 = mos2_gds0;
  926.        ff->acfun = (complex_t(*)())NULL;
  927.     }
  928.     x->Yds->f = ff;
  929.  }
  930.  x->Yds->parent = brh;
  931.  strcpy(x->Yds->label,"Yds");
  932.  x->Yds->n[OUT1] = x->drainnode;
  933.  x->Yds->n[OUT2] = x->sourcenode;
  934.  x->Yds->next = brh->subckt;
  935.  x->Yds->prev = (branch_t*)NULL;
  936.  brh->subckt = insertbranch(x->Yds);
  937.  
  938.  if (brh->nGATE.t != x->sourcenode.t){
  939.     if (!x->Gmf){
  940.        static functions_t *ff;
  941.        x->Gmf = (*(dev_vccs.create))((branch_t*)NULL);
  942.        if (!ff){
  943.       ff = (functions_t*)calloc(1, sizeof(functions_t));
  944.       *ff = *(x->Gmf->f);
  945.       ff->expand = (void(*)())NULL;
  946.       ff->trfun1 = mos2_gmf1;
  947.       ff->trfun0 = mos2_gmf0;
  948.       ff->acfun = (complex_t(*)())NULL;
  949.        }
  950.        x->Gmf->f = ff;
  951.     }
  952.     x->Gmf->parent = brh;
  953.     strcpy(x->Gmf->label,"Gmf");
  954.     x->Gmf->n[OUT1] = x->drainnode;
  955.     x->Gmf->n[OUT2] = x->sourcenode;
  956.     x->Gmf->n[IN1] = brh->nGATE;
  957.     x->Gmf->n[IN2] = x->sourcenode;
  958.     x->Gmf->next = brh->subckt;
  959.     x->Gmf->prev = (branch_t*)NULL;
  960.     brh->subckt = insertbranch(x->Gmf);
  961.  }else{
  962.     x->Gmf = (branch_t*)NULL;
  963.  }
  964.  
  965.  if (brh->nGATE.t != x->drainnode.t){
  966.     if (!x->Gmr){
  967.        static functions_t *ff;
  968.        x->Gmr = (*(dev_vccs.create))((branch_t*)NULL);
  969.        if (!ff){
  970.       ff = (functions_t*)calloc(1, sizeof(functions_t));
  971.       *ff = *(x->Gmr->f);
  972.       ff->expand = (void(*)())NULL;
  973.       ff->trfun1 = mos2_gmr1;
  974.       ff->trfun0 = mos2_gmr0;
  975.       ff->acfun = (complex_t(*)())NULL;
  976.        }
  977.        x->Gmr->f = ff;
  978.     }
  979.     x->Gmr->parent = brh;
  980.     strcpy(x->Gmr->label,"Gmr");
  981.     x->Gmr->n[OUT1] = x->sourcenode;
  982.     x->Gmr->n[OUT2] = x->drainnode;
  983.     x->Gmr->n[IN1] = brh->nGATE;
  984.     x->Gmr->n[IN2] = x->drainnode;
  985.     x->Gmr->prev = (branch_t*)NULL;
  986.     x->Gmr->next = brh->subckt;
  987.     brh->subckt = insertbranch(x->Gmr);
  988.  }else{
  989.     x->Gmr = (branch_t*)NULL;
  990.  }
  991.  
  992.  if (!x->Ids){
  993.     static functions_t *ff;
  994.     x->Ids = (*(dev_cs.create))((branch_t*)NULL);
  995.     if (!ff){
  996.        ff = (functions_t*)calloc(1, sizeof(functions_t));
  997.        *ff = *(x->Ids->f);
  998.        ff->expand = (void(*)())NULL;
  999.        ff->trfun1 = mos2_ids1;
  1000.        ff->trfun0 = mos2_ids0;
  1001.        ff->acfun = (complex_t(*)())NULL;
  1002.     }
  1003.     x->Ids->f = ff;
  1004.  }
  1005.  x->Ids->parent = brh;
  1006.  strcpy(x->Ids->label,"Ids");
  1007.  x->Ids->n[OUT1] = x->drainnode;
  1008.  x->Ids->n[OUT2] = x->sourcenode;
  1009.  x->Ids->next = brh->subckt;
  1010.  x->Ids->prev = (branch_t*)NULL;
  1011.  brh->subckt = insertbranch(x->Ids);
  1012.  brh->tracesubckt = NO;
  1013. }
  1014. /*--------------------------------------------------------------------------*/
  1015. static double tr_review_mos(brh)
  1016. branch_t *brh;
  1017. {
  1018.  return tr_review_rl(brh->subckt);
  1019. }
  1020. /*--------------------------------------------------------------------------*/
  1021. /*--------------------------------------------------------------------------*/
  1022. SHAR_EOF
  1023. fi # end of overwriting check
  1024. if test -f 'src/d_mos2.c'
  1025. then
  1026.     echo shar: will not over-write existing file "'src/d_mos2.c'"
  1027. else
  1028. cat << \SHAR_EOF > 'src/d_mos2.c'
  1029. /* dev_mos2  03/27/92
  1030.  * Copyright 1983-1992   Albert Davis
  1031.  * mos model equations: spice level 2 equivalent
  1032.  */
  1033. #include "ecah.h"
  1034. #include "branch.h"
  1035. #include "d_mos.h"
  1036. #include "error.h"
  1037. #include "io.h"
  1038. #include "declare.h"
  1039. /*--------------------------------------------------------------------------*/
  1040.     void    eval_mos2(branch_t*);
  1041. /*--------------------------------------------------------------------------*/
  1042. #define short_channel    (m->xj != NOT_INPUT  &&  m->xj > 0.)
  1043. #define do_subthreshold    (m->nfs != 0.)
  1044.  
  1045. extern const struct ioctrl io;
  1046. extern const double temp;
  1047. /*--------------------------------------------------------------------------*/
  1048. void eval_mos2(brh)
  1049. branch_t *brh;
  1050. {
  1051. static struct mos *x;
  1052. static struct mmod *m;
  1053.  double sarg, dsarg_dvbs/*ds*/;
  1054.  double bargx;
  1055.  double gamma_s/*mb*/, dgamma_s_dvds/*ds*/, dgamma_s_dvbs/*mb*/;
  1056.  double beta;
  1057.  double body;
  1058.  double dvdsat_dvgs = 0./*m*/;
  1059.  double dvdsat_dvbs = 0./*mb*/;
  1060.  double vdsx;
  1061.  double vgst;
  1062.  double ufact;
  1063.  double dudvgs/*m*/, dudvds/*ds*/, dudvbs/*mb*/;
  1064.  double clfact;
  1065.  double dldvgs/*m*/, dldvds/*ds*/, dldvbs/*mb*/;
  1066.  double dodvbs/*mb*/;
  1067.  double xn = 0.;
  1068.  double vtxn = 0.;
  1069.  double expg;
  1070.  double dxndvb =0./*mb*/;    /* subthreshold only */
  1071.  double ids_on, didvds;
  1072.  double vt/*ds*/;
  1073.  double v_phi_d, v_phi_s, v_phi_ds;
  1074.  double d2sdb2;
  1075.  double barg, dbarg_dvbs, d2bdb2;
  1076.  double bsarg, dbsarg_dvbs;
  1077.  double vbdsat;
  1078.  double dgddb2;
  1079.  double vc, vbin, vc_eta;
  1080.  double bodys;
  1081.  double lambda;
  1082.  double vbd;
  1083.  double von;
  1084.  double ueff = 0.;
  1085.  
  1086.  int use_vmax;
  1087.  
  1088.  x = (struct mos*)brh->x;
  1089.  m = x->m;
  1090.   
  1091.  use_vmax = m->vmax != NOT_INPUT;
  1092.  vt = (K/Q) * temp;
  1093.  
  1094.  v_phi_s = m->phi - x->vbs;
  1095.  if (x->vbs <= 0.){
  1096.     sarg = sqrt(v_phi_s);
  1097.     dsarg_dvbs = -.5 / sarg;
  1098.     d2sdb2 = .5 * dsarg_dvbs / v_phi_s;
  1099.     x->sbfwd = NO;
  1100.  }else{
  1101.     double sphi3 = pow(m->phi, 1.5);
  1102.     sarg = sqrt(m->phi) / (1. + .5 * x->vbs / m->phi);
  1103.     dsarg_dvbs = -.5 * sarg * sarg / sphi3;
  1104.     d2sdb2 = -dsarg_dvbs * sarg / sphi3;
  1105.     x->sbfwd = YES;
  1106.     if (!io.suppresserrors){
  1107.        error((x->vbs < -.01) ? bPICKY : bTRACE,
  1108.           "%s: source fwd biased.  vbs=%g\n", printlabel(brh,NO), x->vbs);
  1109.     }
  1110.  }
  1111.  
  1112.  vbd = x->vbs - x->vds;
  1113.  v_phi_d = m->phi - vbd;
  1114.  if (vbd <= 0.){
  1115.     barg = sqrt(v_phi_d);
  1116.     dbarg_dvbs = -.5 / barg;
  1117.     d2bdb2 = .5 * dbarg_dvbs / v_phi_d;
  1118.     x->dbfwd = NO;
  1119.  }else{
  1120.     double sphi3 = pow(m->phi, 1.5);
  1121.     barg = sqrt(m->phi) / (1. + .5 * vbd / m->phi);
  1122.     dbarg_dvbs = -.5 * barg * barg / sphi3;
  1123.     d2bdb2 = -dbarg_dvbs * barg / sphi3;
  1124.     x->dbfwd = YES;
  1125.     if (!io.suppresserrors){
  1126.        error((vbd < -.01) ? bPICKY : bTRACE,
  1127.           "%s: drain fwd biased.  vbd=%g\n", printlabel(brh,NO), vbd);
  1128.     }
  1129.  }
  1130.  
  1131.  if (short_channel){
  1132.     double wd, ws;
  1133.     double alpha_d, alpha_s;
  1134.     double dalpha_d_dvds, dalpha_d_dvbs;
  1135.     double dalpha_s_dvbs;
  1136.     double argxs, argxd;
  1137.     double args, argd;
  1138.     double dasdb2, daddb2;
  1139.  
  1140.     wd = m->xd * barg;
  1141.     argxd = 1. + 2.*wd/m->xj;
  1142.     argd = sqrt(argxd);
  1143.     alpha_d = x->relxj * (argd - 1.);
  1144.     dalpha_d_dvds = m->xd / (4. * x->le * argd * barg);
  1145.     dalpha_d_dvbs = -dalpha_d_dvds;
  1146.     
  1147.     ws = m->xd * sarg;
  1148.     argxs = 1. + 2.*ws/m->xj;
  1149.     args = sqrt(argxs);
  1150.     alpha_s = x->relxj * (args - 1.);
  1151.     dalpha_s_dvbs = -m->xd / (4. * x->le * args * sarg);
  1152.     
  1153.     gamma_s = m->gamma * (1. - alpha_s - alpha_d);
  1154.     dgamma_s_dvds = -m->gamma *  dalpha_d_dvds;
  1155.     dgamma_s_dvbs = -m->gamma * (dalpha_d_dvbs + dalpha_s_dvbs);
  1156.  
  1157.     dasdb2 = -m->xd*(d2sdb2 + dsarg_dvbs*dsarg_dvbs*m->xd / (m->xj*argxs))
  1158.                     / (x->le*args);
  1159.     daddb2 = -m->xd*(d2bdb2 + dbarg_dvbs*dbarg_dvbs*m->xd / (m->xj*argxd))
  1160.                     / (x->le*argd);
  1161.     dgddb2 = -.5 * m->gamma * (dasdb2 + daddb2);
  1162.  
  1163.     if (gamma_s <= 0. && m->gamma > 0.){
  1164.        error(bWARNING, "%s: gamma is negative\n", printlabel(brh,NO));
  1165.        error(bTRACE  , "+   gamma_s=%g, alpha_s=%g, alpha_d=%g\n",
  1166.                        gamma_s,    alpha_s,    alpha_d);
  1167.     }
  1168.  }else{
  1169.     gamma_s = m->gamma;
  1170.     dgamma_s_dvds = dgamma_s_dvbs = 0.;
  1171.     dgddb2 = 0.;
  1172.  }
  1173.  
  1174.  
  1175.  vbin = m->vbi + x->eta_1 * v_phi_s;
  1176.  von = vbin + gamma_s * sarg;
  1177.  
  1178.  dodvbs = -x->eta_1 + dgamma_s_dvbs * sarg + gamma_s * dsarg_dvbs;
  1179.  if (do_subthreshold){
  1180.     double cdonco;
  1181.     dxndvb = 2. * dgamma_s_dvbs * dsarg_dvbs
  1182.                    + gamma_s * d2sdb2 + dgddb2 * sarg;
  1183.     dodvbs += vt * dxndvb;
  1184.     cdonco = - (gamma_s * dsarg_dvbs + dgamma_s_dvbs * sarg) + x->eta_1;
  1185.     xn = 1. + m->cfsox + cdonco;
  1186.     vtxn = vt * xn;
  1187.     von += vtxn;
  1188.     x->subthreshold = (x->vgs < von);
  1189.     x->cutoff = NO;
  1190.  }else if (x->vgs < von){
  1191.     x->cutoff = YES;
  1192.     x->ids = 0.;
  1193.     x->gm = 0.;
  1194.     x->gds = 0.;
  1195.     x->gmb = 0.;
  1196.     return;
  1197.  }else{
  1198.     x->cutoff = x->subthreshold = NO;
  1199.  }
  1200.  
  1201.  x->vgsx = (x->subthreshold) ? von : x->vgs;
  1202.  vc = x->vgsx - vbin;
  1203.  vc_eta = vc / x->eta;
  1204.  vgst = x->vgs - von;
  1205.  
  1206.  if (m->uexp != NOT_INPUT  &&  vgst > m->vbp){
  1207.     ufact = pow(m->vbp/vgst, m->uexp);
  1208.     dudvgs = -ufact * m->uexp / vgst;
  1209.     dudvds = 0.;    /* wrong, but as per spice2 */
  1210.     dudvbs = dodvbs * ufact * m->uexp / vgst;
  1211.  }else{
  1212.     ufact = 1.;
  1213.     dudvgs = dudvds = dudvbs = 0.;
  1214.  }
  1215.  
  1216.  if (use_vmax){
  1217.     double sarg3, gammad;
  1218.     double v1, v2, xv, a1, b1, c1, d1;
  1219.     double a, b, c, r, s, r3, s2, p, p0, p2, y3;
  1220.     double xvalid = 0.;
  1221.     double x4[8];
  1222.     int iknt, j;
  1223.     int root_count;
  1224.     sarg3 = sarg*sarg*sarg;
  1225.     gammad = gamma_s / x->eta;
  1226.     ueff = m->uo * ufact;
  1227.     v1 = vc_eta + v_phi_s;
  1228.     v2 = v_phi_s;
  1229.     xv = m->vmax * x->le / ueff;
  1230.     a1 = gammad * (4./3.);
  1231.     b1 = -2. * (v1+xv);
  1232.     c1 = -2. * gammad * xv;                /* end of scope */
  1233.     d1 = 2.*v1*(v2+xv) - v2*v2 - (4./3.)*gammad*sarg3;     /* xv, v1, v2, sarg3 */
  1234.     a = -b1;
  1235.     b = a1 * c1 - 4. * d1;
  1236.     c = -d1 * (a1*a1 - 4.*b1) - c1*c1;
  1237.     r = -a*a / 3. + b;
  1238.     s = 2. * a*a*a / 27. - a*b / 3. + c;        /* b, c */
  1239.     r3 = r*r*r;                        /* r */
  1240.     s2 = s*s;
  1241.     p = s2 / 4. + r3 / 27.;                /* r3 */
  1242.     p0 = fabs(p);
  1243.     p2 = sqrt(p0);
  1244.     if (p < 0.){                    /* p */
  1245.        double ro, fi;
  1246.        ro = pow((s2 / 4. + p0), (1./6.));        /* s2, p0 */
  1247.        fi = atan(-2. * p2 / s);
  1248.        y3 = 2. * ro * cos(fi/3.) - a / 3.;
  1249.     }else{
  1250.        double p3, p4;
  1251.        p3 = pow((fabs(-s/2.+p2)), (1./3.));
  1252.        p4 = pow((fabs(-s/2.-p2)), (1./3.));        /* s, p2 */
  1253.        y3 = p3 + p4 - a / 3.;                /* a */
  1254.     }
  1255.  
  1256.     iknt = 0;
  1257.     if (a1*a1 / 4. - b1 + y3  < 0.  &&  y3*y3 / 4. - d1  < 0.){
  1258.        error(bWARNING,
  1259.           "%s: internal error: a3,b4, a1=%g, b1=%g, y3=%g, d1=%g\n",
  1260.            printlabel(brh,NO),          a1,    b1,    y3,    d1);
  1261.     }else{
  1262.        double a3, b3;
  1263.        int i;
  1264.        a3 = sqrt(a1*a1 / 4. - b1 + y3);
  1265.        b3 = sqrt(y3*y3 / 4. - d1);
  1266.        for (i = 0;   i < 4;   i++){
  1267.           double delta4;
  1268.           double a4, b4;
  1269.           static const double sig1[4] = {1., -1., 1., -1.};
  1270.           static const double sig2[4] = {1., 1., -1., -1.};
  1271.           a4 = a1 / 2. + sig1[i] * a3;
  1272.           b4 = y3 / 2. + sig2[i] * b3;            /* y3 */
  1273.           delta4 = a4*a4 / 4. - b4;
  1274.           if (delta4 >= 0.){
  1275.              x4[iknt++] = - a4 / 2. + sqrt(delta4);
  1276.              x4[iknt++] = - a4 / 2. - sqrt(delta4);    /* i */
  1277.           }
  1278.        }
  1279.     }
  1280.  
  1281.     root_count = 0;
  1282.     for (j = 0;   j < iknt;   j++){            /* iknt */
  1283.        if (x4[j] > 0.){
  1284.           double poly4;
  1285.           poly4 =      x4[j]*x4[j]*x4[j]*x4[j]    /* ~= 0, used as check    */
  1286.         + a1 * x4[j]*x4[j]*x4[j]    /* roundoff error not    */
  1287.         + b1 * x4[j]*x4[j]        /* propagated, so ok    */
  1288.         + c1 * x4[j]
  1289.         + d1;                    /* a1, b1, c1, d1 */
  1290.           if (fabs(poly4) <= 1e-6){
  1291.              root_count++;
  1292.              if (root_count <= 1)    /* xvalid = min(x4[j]) */
  1293.                 xvalid=x4[j];
  1294.              if (x4[j] <= xvalid)
  1295.                 xvalid=x4[j];                /* x4[], j */
  1296.       }else{
  1297.       }
  1298.        }
  1299.     }
  1300.     if (root_count <= 0){                /* root_count */
  1301.        if (!io.suppresserrors)
  1302.           error(bDEBUG, "%s: Baum's theory rejected\n", printlabel(brh,NO));
  1303.        use_vmax = NO;
  1304.     }else{
  1305.        x->vdsat = xvalid*xvalid - v_phi_s;
  1306.     }
  1307.  }
  1308.  
  1309.  if (!use_vmax){
  1310.     if (gamma_s > 0.){
  1311.        double argv;
  1312.        argv = vc_eta + v_phi_s;
  1313.        if (argv > 0.){
  1314.           double gammad, gammd2, arg;
  1315.           gammad = gamma_s / x->eta;
  1316.           gammd2 = gammad * gammad;
  1317.           arg = sqrt(1. + 4. * argv / gammd2);
  1318.           x->vdsat = vc_eta  +  gammd2 * (1.-arg) / 2.;
  1319.           dvdsat_dvgs = (1. - 1./arg) / x->eta;
  1320.           dvdsat_dvbs = (gammad * (1.-arg) + 2.*argv / (gammad*arg))
  1321.               / x->eta * dgamma_s_dvbs
  1322.             + 1./arg + x->eta_1 * dvdsat_dvgs;
  1323.        }else{
  1324.           x->vdsat = 0.;
  1325.           dvdsat_dvgs = dvdsat_dvbs = 0.;
  1326.           error(bWARNING, "%s: vdsat: argv is negative\n", printlabel(brh,NO));
  1327.           error(bTRACE  , "+   vc=%g, argv=%g, vdsat=%g\n",
  1328.                      vc,    argv,    x->vdsat);
  1329.        }
  1330.     }else{
  1331.        x->vdsat = vc_eta;
  1332.        dvdsat_dvgs = 1.;
  1333.        dvdsat_dvbs = 0.;
  1334.     }
  1335.  }
  1336.  
  1337.  if (x->vdsat < 0.){
  1338.     error(bWARNING, "%s: calculated vdsat (%g) < 0.  using vdsat = 0.\n",
  1339.             printlabel(brh,NO), x->vdsat);
  1340.     x->vdsat = 0.;
  1341.  }
  1342.  
  1343.  vbdsat = x->vbs - x->vdsat;
  1344.  v_phi_ds = m->phi - vbdsat;
  1345.  if (vbdsat <= 0.){
  1346.     bsarg = sqrt(v_phi_ds);
  1347.     dbsarg_dvbs = -.5 / bsarg;
  1348.  }else{
  1349.     double sphi3 = pow(m->phi, 1.5);
  1350.     bsarg = sqrt(m->phi) / (1. + .5 * vbdsat / m->phi);
  1351.     dbsarg_dvbs = -.5 * bsarg * bsarg / sphi3;
  1352.  }
  1353.  bodys = bsarg*bsarg*bsarg - sarg*sarg*sarg;
  1354.  
  1355.  if (use_vmax){
  1356.     double argv, vqchan, dqdsat, vl, dfunds, dfundg, dfundb, gdbdvs;
  1357.     gdbdvs = 2. * gamma_s * (bsarg*bsarg*dbsarg_dvbs - sarg*sarg*dsarg_dvbs);
  1358.     argv = vc_eta - x->vdsat;
  1359.     vqchan = argv - gamma_s * bsarg;
  1360.     dqdsat = -1. + gamma_s * dbsarg_dvbs;
  1361.     vl = m->vmax * x->le;
  1362.     dfunds = vl * dqdsat - ueff * vqchan;
  1363.     dfundg = (vl - ueff * x->vdsat) / x->eta;
  1364.     dfundb = -vl * (1. + dqdsat - x->eta_1 / x->eta)
  1365.                + ueff * (gdbdvs - dgamma_s_dvbs * bodys / 1.5) / x->eta;
  1366.     dvdsat_dvgs = -dfundg / dfunds;
  1367.     dvdsat_dvbs = -dfundb / dfunds;
  1368.  }
  1369.  
  1370.  if (m->lambda == NOT_INPUT){
  1371.     if (x->vds != 0.){
  1372.        double dldsat;
  1373.        if (use_vmax){
  1374.       double xdv, xlv, argv, xls;
  1375.           xdv = m->xd / sqrt(m->neff);
  1376.           xlv = m->vmax * xdv / (2. * ueff);
  1377.           argv = x->vds - x->vdsat;
  1378.           if (argv < 0.)
  1379.              argv = 0.;
  1380.           xls = sqrt(xlv*xlv + argv);
  1381.           lambda = (xls-xlv) * xdv / (x->le * x->vds);
  1382.           dldsat = xdv / (2. * xls * x->le);
  1383.        }else{
  1384.           double argv, sargv, dl;
  1385.           argv = (x->vds - x->vdsat) / 4.;
  1386.       sargv = sqrt(1. + argv*argv);
  1387.       if (argv + sargv >= 0.){
  1388.          dl = m->xd * sqrt(argv + sargv);
  1389.              lambda = dl / (x->le * x->vds);
  1390.              dldsat = lambda * x->vds / (8. * sargv);
  1391.              }else{
  1392.          lambda = 0.;
  1393.          dldsat = 0.;
  1394.          error(bWARNING, "%s: internal error: vds(%g) < vdsat(%g)\n",
  1395.                        printlabel(brh,NO), x->vds,   x->vdsat);
  1396.       }
  1397.        }
  1398.        dldvgs =  dvdsat_dvgs * dldsat;
  1399.        dldvds =              - dldsat;
  1400.        dldvbs =  dvdsat_dvbs * dldsat;
  1401.     }else{
  1402.        lambda = 0.;
  1403.        dldvgs = dldvds = dldvbs = 0.;
  1404.     }
  1405.  }else{
  1406.     lambda = m->lambda;
  1407.     dldvgs = dldvbs = 0.;
  1408.     dldvds = -lambda;
  1409.  }
  1410.  
  1411.  clfact = (1. - lambda * x->vds);
  1412.  if (clfact < m->xwb/x->le){
  1413.     double leff, dfact;
  1414.     leff = m->xwb / (2. - (clfact * x->le / m->xwb));
  1415.     clfact = leff / x->le;
  1416.     dfact = (leff * leff) / (m->xwb * m->xwb);
  1417.     dldvgs *= dfact;
  1418.     dldvds *= dfact;
  1419.     dldvbs *= dfact;
  1420.  }
  1421.  
  1422.  x->saturated = (x->vds > x->vdsat);
  1423.  vdsx =  (x->saturated) ? x->vdsat : x->vds;
  1424.  bargx = (x->saturated) ? bsarg : barg;
  1425.  body = bargx*bargx*bargx - sarg*sarg*sarg;
  1426.  expg = (x->subthreshold) ? exp(vgst / vtxn) : 1.;
  1427.  beta = x->beta * ufact / clfact;
  1428.  
  1429.  ids_on = beta * ((vc - x->eta_2 * vdsx) * vdsx  - (2./3.) * gamma_s * body);
  1430.  didvds = beta * (vc  -  x->eta * vdsx  -  gamma_s * bargx);
  1431.  
  1432.  x->ids = ids_on * expg;
  1433.  
  1434.  x->gm = beta * vdsx;
  1435.  x->gm += ids_on * (dudvgs/ufact - dldvgs/clfact);
  1436.  if (x->saturated)
  1437.     x->gm += didvds * dvdsat_dvgs;
  1438.  if (x->subthreshold){
  1439.     x->gm = ids_on / vtxn;
  1440.     if (x->saturated)
  1441.        x->gm += didvds * dvdsat_dvgs;
  1442.     x->gm *= expg;
  1443.  }
  1444.  x->gds = (x->saturated) ? 0.: didvds;
  1445.  x->gds += ids_on * (dudvds/ufact - dldvds/clfact);
  1446.  if (short_channel)
  1447.     x->gds -= beta * (2./3.) * body * dgamma_s_dvds;
  1448.  if (x->subthreshold){
  1449.     double dodvds, dxndvd, gmw;
  1450.     dxndvd = dgamma_s_dvds * dsarg_dvbs;
  1451.     dodvds = dgamma_s_dvds * sarg + vt * dxndvd;
  1452.     gmw = x->ids * vgst / (vtxn * xn);
  1453.     x->gds *= expg;
  1454.     x->gds -= x->gm * dodvds + gmw * dxndvd;
  1455.  }
  1456.  x->gmb = beta * (x->eta_1 * vdsx - gamma_s * (sarg - bargx));
  1457.  x->gmb += ids_on * (dudvbs/ufact - dldvbs/clfact);
  1458.  if (short_channel)
  1459.     x->gmb -= beta * (2./3.) * body * dgamma_s_dvbs;
  1460.  if (x->saturated)
  1461.     x->gmb += didvds * dvdsat_dvbs;
  1462.  if (x->subthreshold){
  1463.     double gmw;
  1464.     gmw = x->ids * vgst / (vtxn * xn);
  1465.     x->gmb += beta * dodvbs * vdsx;
  1466.     x->gmb *= expg;
  1467.     x->gmb -= x->gm * dodvbs + gmw * dxndvb;
  1468.  }
  1469. }
  1470. /*--------------------------------------------------------------------------*/
  1471. /*--------------------------------------------------------------------------*/
  1472. SHAR_EOF
  1473. fi # end of overwriting check
  1474. if test -f 'src/d_mosc.c'
  1475. then
  1476.     echo shar: will not over-write existing file "'src/d_mosc.c'"
  1477. else
  1478. cat << \SHAR_EOF > 'src/d_mosc.c'
  1479. /* dev_mosc  03/31/92
  1480.  * Copyright 1983-1992   Albert Davis
  1481.  * mos model subcircuit functions
  1482.  */
  1483. #include "ecah.h"
  1484. #include "branch.h"
  1485. #include "d_mos.h"
  1486. #include "declare.h"
  1487. /*--------------------------------------------------------------------------*/
  1488.     void    mos2_ids0(branch_t*);
  1489.     void    mos2_gmf0(branch_t*);
  1490.     void    mos2_gmr0(branch_t*);
  1491.     void    mos2_gds0(branch_t*);
  1492.     void    mos2_gmbf0(branch_t*);
  1493.     void    mos2_gmbr0(branch_t*);
  1494.     void    mos_cgb0(branch_t*);
  1495.     void    mos_cgd0(branch_t*);
  1496.     void    mos_cgs0(branch_t*);
  1497.     void    mos2_ids1(branch_t*);
  1498.     void    mos2_gmf1(branch_t*);
  1499.     void    mos2_gmr1(branch_t*);
  1500.     void    mos2_gds1(branch_t*);
  1501.     void    mos2_gmbf1(branch_t*);
  1502.     void    mos2_gmbr1(branch_t*);
  1503.     void    mos_cgb1(branch_t*);
  1504.     void    mos_cgd1(branch_t*);
  1505.     void    mos_cgs1(branch_t*);
  1506. /*--------------------------------------------------------------------------*/
  1507. /*--------------------------------------------------------------------------*/
  1508. /*--------------------------------------------------------------------------*/
  1509. /* mos2_ids: drain-source current calculations
  1510.  * returns ids
  1511.  */
  1512. /*--------------------------------------------------------------------------*/
  1513. void mos2_ids0(brh)
  1514. branch_t *brh;
  1515. {
  1516.  brh->y0.f0 = brh->y0.x * brh->y0.f1;
  1517. }
  1518. /*--------------------------------------------------------------------------*/
  1519. void mos2_ids1(brh)
  1520. branch_t *brh;
  1521. {
  1522.  struct mos *x;
  1523.  struct mmod *m;
  1524.  
  1525.  x = (struct mos*)brh->parent->x;
  1526.  m = x->m;
  1527.  if (brh->bypass){
  1528.     brh->y0 = brh->y1;
  1529.     brh->y1 = brh->y2;
  1530.  }else{
  1531.     double ids = (x->reversed) ? -x->ids : x->ids;
  1532.     brh->y0.f1 = m->polarity * ids;
  1533.     brh->y0.f0 = brh->y0.x * brh->y0.f1;
  1534.     brh->y0.f0 = LINEAR;
  1535.  }
  1536. }
  1537. /*--------------------------------------------------------------------------*/
  1538. /*--------------------------------------------------------------------------*/
  1539. /* mos2_gmf: gate transconductance calculations forward mode
  1540.  * returns gm or 0
  1541.  */
  1542. /*--------------------------------------------------------------------------*/
  1543. /*ARGSUSED*/
  1544. void mos2_gmf0(brh)
  1545. branch_t *brh;
  1546. {;}
  1547. /*--------------------------------------------------------------------------*/
  1548. void mos2_gmf1(brh)
  1549. branch_t *brh;
  1550. {
  1551.  struct mos *x;
  1552.  
  1553.  x = (struct mos*)brh->parent->x;
  1554.  if (brh->bypass){
  1555.     brh->y0 = brh->y1;
  1556.     brh->y1 = brh->y2;
  1557.  }else{
  1558.     brh->y0.f1 = (x->reversed) ? 0. : x->gm;
  1559.     brh->y0.f0 = 0.;
  1560.  }
  1561. }
  1562. /*--------------------------------------------------------------------------*/
  1563. /*--------------------------------------------------------------------------*/
  1564. /* mos2_gmr: gate transconductance calculations reversed mode
  1565.  * returns gm or 0
  1566.  */
  1567. /*--------------------------------------------------------------------------*/
  1568. /*ARGSUSED*/
  1569. void mos2_gmr0(brh)
  1570. branch_t *brh;
  1571. {;}
  1572. /*--------------------------------------------------------------------------*/
  1573. void mos2_gmr1(brh)
  1574. branch_t *brh;
  1575. {
  1576.  struct mos *x;
  1577.  
  1578.  x = (struct mos*)brh->parent->x;
  1579.  if (brh->bypass){
  1580.     brh->y0 = brh->y1;
  1581.     brh->y1 = brh->y2;
  1582.  }else{
  1583.     brh->y0.f1 = (x->reversed) ? x->gm : 0.;
  1584.     brh->y0.f0 = 0.;
  1585.  }
  1586. }
  1587. /*--------------------------------------------------------------------------*/
  1588. /*--------------------------------------------------------------------------*/
  1589. /* mos2_gds: self-conductance calculations
  1590.  * returns gds
  1591.  */
  1592. /*--------------------------------------------------------------------------*/
  1593. /*ARGSUSED*/
  1594. void mos2_gds0(brh)
  1595. branch_t *brh;
  1596. {;}
  1597. /*--------------------------------------------------------------------------*/
  1598. void mos2_gds1(brh)
  1599. branch_t *brh;
  1600. {
  1601.  struct mos *x;
  1602.  
  1603.  x = (struct mos*)brh->parent->x;
  1604.  if (brh->bypass){
  1605.     brh->y0 = brh->y1;
  1606.     brh->y1 = brh->y2;
  1607.  }else{
  1608.     brh->y0.f1 = x->gds;
  1609.     brh->y0.f0 = 0.;
  1610.  }
  1611. }
  1612. /*--------------------------------------------------------------------------*/
  1613. /*--------------------------------------------------------------------------*/
  1614. /* mos2_gmbf: bulk transconductance calculations, forward mode
  1615.  * returns gmb or 0
  1616.  */
  1617. /*--------------------------------------------------------------------------*/
  1618. /*ARGSUSED*/
  1619. void mos2_gmbf0(brh)
  1620. branch_t *brh;
  1621. {;}
  1622. /*--------------------------------------------------------------------------*/
  1623. void mos2_gmbf1(brh)
  1624. branch_t *brh;
  1625. {
  1626.  struct mos *x;
  1627.  
  1628.  x = (struct mos*)brh->parent->x;
  1629.  if (brh->bypass){
  1630.     brh->y0 = brh->y1;
  1631.     brh->y1 = brh->y2;
  1632.  }else{
  1633.     brh->y0.f1 = (x->reversed) ? 0. : x->gmb;
  1634.     brh->y0.f0 = 0.;
  1635.  }
  1636. }
  1637. /*--------------------------------------------------------------------------*/
  1638. /*--------------------------------------------------------------------------*/
  1639. /* mos2_gmbr: bulk transconductance calculations, reversed mode
  1640.  * returns gmb or 0
  1641.  */
  1642. /*--------------------------------------------------------------------------*/
  1643. /*ARGSUSED*/
  1644. void mos2_gmbr0(brh)
  1645. branch_t *brh;
  1646. {;}
  1647. /*--------------------------------------------------------------------------*/
  1648. void mos2_gmbr1(brh)
  1649. branch_t *brh;
  1650. {
  1651.  struct mos *x;
  1652.  
  1653.  x = (struct mos*)brh->parent->x;
  1654.  if (brh->bypass){
  1655.     brh->y0 = brh->y1;
  1656.     brh->y1 = brh->y2;
  1657.  }else{
  1658.     brh->y0.f1 = (x->reversed) ? x->gmb : 0.;
  1659.     brh->y0.f0 = 0.;
  1660.  }
  1661. }
  1662. /*--------------------------------------------------------------------------*/
  1663. /*--------------------------------------------------------------------------*/
  1664. void mos_cgb0(brh)
  1665. branch_t *brh;
  1666. {
  1667.  brh->y0.f0 = brh->y0.x * brh->y0.f1;
  1668. }
  1669. /*--------------------------------------------------------------------------*/
  1670. void mos_cgb1(brh)
  1671. branch_t *brh;
  1672. {
  1673.  double c;
  1674.  struct mos *x;
  1675.  struct mmod *m;
  1676.  
  1677.  x = (struct mos*)brh->parent->x;
  1678.  m = x->m;
  1679.  
  1680.  c = brh->val;
  1681.  if (x->vgsx <= -m->phi){
  1682.     c += x->cgate;
  1683.  }else if (x->vgsx <= 0.){
  1684.     c -= x->vgsx * x->cgate / m->phi;
  1685.  }
  1686.     
  1687.  brh->y0.f1 = c;
  1688.  brh->y0.f0 = brh->y0.x * brh->y0.f1;
  1689. }
  1690. /*--------------------------------------------------------------------------*/
  1691. /*--------------------------------------------------------------------------*/
  1692. void mos_cgd0(brh)
  1693. branch_t *brh;
  1694. {
  1695.  brh->y0.f0 = brh->y0.x * brh->y0.f1;
  1696. }
  1697. /*--------------------------------------------------------------------------*/
  1698. void mos_cgd1(brh)
  1699. branch_t *brh;
  1700. {
  1701.  double c;
  1702.  double vdbsat;
  1703.  double vdb;
  1704.  struct mos *x;
  1705.  
  1706.  x = (struct mos*)brh->parent->x;
  1707.  vdbsat = x->vdsat - x->vbs;
  1708.  vdb = x->vds - x->vbs;
  1709.  
  1710.  c = brh->val;
  1711.  if (vdbsat > vdb){
  1712.     double vddif = 2. * vdbsat - vdb;
  1713.     c += x->cgate * (1. - (vdbsat*vdbsat)/(vddif*vddif))/1.5;
  1714.  }
  1715.  brh->y0.f1 = c;
  1716.  brh->y0.f0 = brh->y0.x * brh->y0.f1;
  1717. }
  1718. /*--------------------------------------------------------------------------*/
  1719. /*--------------------------------------------------------------------------*/
  1720. void mos_cgs0(brh)
  1721. branch_t *brh;
  1722. {
  1723.  brh->y0.f0 = brh->y0.x * brh->y0.f1;
  1724. }
  1725. /*--------------------------------------------------------------------------*/
  1726. void mos_cgs1(brh)
  1727. branch_t *brh;
  1728. {
  1729.  double c;
  1730.  double vdbsat;
  1731.  double vdb;
  1732.  struct mos *x;
  1733.  struct mmod *m;
  1734.  
  1735.  x = (struct mos*)brh->parent->x;
  1736.  m = x->m;
  1737.  vdbsat = x->vdsat - x->vbs;
  1738.  vdb = x->vds - x->vbs;
  1739.  
  1740.  c = brh->val;
  1741.  if (x->vgsx > 0.){
  1742.     if (vdbsat > vdb){
  1743.        double vddif = 2. * vdbsat - vdb;
  1744.        double vddif1 = vdbsat - vdb - 1.e-12; /* fudge??? */
  1745.        c += x->cgate * (1. - (vddif1*vddif1)/(vddif*vddif))/1.5;
  1746.     }else{
  1747.        c += x->cgate / 1.5;
  1748.     }
  1749.  }else if (x->vgsx > -m->phi/2.){
  1750.     c += x->cgate / (.75*m->phi) * x->vgsx + x->cgate / 1.5;
  1751.  }
  1752.  
  1753.  brh->y0.f1 = c;
  1754.  brh->y0.f0 = brh->y0.x * brh->y0.f1;
  1755. }
  1756. /*--------------------------------------------------------------------------*/
  1757. /*--------------------------------------------------------------------------*/
  1758. /*--------------------------------------------------------------------------*/
  1759. /*--------------------------------------------------------------------------*/
  1760. SHAR_EOF
  1761. fi # end of overwriting check
  1762. #    End of shell archive
  1763. exit 0
  1764.