testing
[gnucap-felix.git] / src / d_mos1.model
blob2562780ed94c5f80d34c6b09d58e037b2410aa3d
1 /* $Id: d_mos1.model,v 26.133 2009/11/26 04:58:04 al Exp $ -*- C++ -*-
2  * Copyright (C) 2001 Albert Davis
3  * Author: Albert Davis <aldavis@gnu.org>
4  *
5  * This file is part of "Gnucap", the Gnu Circuit Analysis Package
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301, USA.
21  *------------------------------------------------------------------
22  * mos model equations: spice level 1 equivalent
23  */
24 h_headers {
25 #include "d_mos123.h"
27 cc_headers {
29 /*--------------------------------------------------------------------------*/
30 model BUILT_IN_MOS1 {
31   level 1;
32   public_keys {
33     nmos1 polarity=pN;
34     pmos1 polarity=pP;
35     nmos polarity=pN;
36     pmos polarity=pP;
37   }
38   dev_type BUILT_IN_MOS;
39   inherit BUILT_IN_MOS123;
40   independent {
41     override {
42       double mjsw "" default=.5;
43       double cox "" final_default=0.;
44       double vto "" final_default=0.;
45       double gamma "" final_default=0.;
46       double phi "" final_default=.6;
47       int mos_level "back-annotate for diode" name=DIODElevel 
48         print_test="mos_level != LEVEL" default=LEVEL;
49     }
50     raw_parameters {
51       double kp "transconductance parameter"
52         name=KP final_default=2e-5 
53         print_test="!calc_kp" calc_print_test="calc_kp";
54     }
55     calculated_parameters {
56       bool calc_kp "" default=false;
57     }
58     code_pre {
59       if (tox != NA) {
60         cox = P_EPS_OX / tox;
61         if (kp == NA) {
62           kp = uo * cox;
63           calc_kp = true;
64         }
65         if (nsub != NA) {
66           if (phi == NA) {
67             phi = (2. * P_K_Q) * tnom_k * log(nsub/NI);
68             if (phi < .1) {
69               untested();
70               error(((!_sim->is_first_expand()) ? (bDEBUG) : (bWARNING)),
71                     long_label() + ": calculated phi too small, using .1\n");
72               phi = .1;
73             }
74             calc_phi = true;
75           }
76           if (gamma == NA) {
77             gamma = sqrt(2. * P_EPS_SI * P_Q * nsub) / cox;
78             calc_gamma = true;
79           }
80           if (vto == NA) {
81             double phi_ms = (tpg == gtMETAL)
82               ? polarity * (-.05 - (egap + polarity * phi) / 2.)
83               : -(tpg * egap + phi) / 2.;
84             double vfb = phi_ms - polarity * P_Q * nss / cox;
85             vto = vfb + phi + gamma * sqrt(phi);
86             calc_vto = true;
87           }
88         }else{
89           // tox is input, nsub isn't
90         }
91       }
92     }
93   }
94   temperature_dependent {
95     calculated_parameters {
96       double phi "" calculate="m->phi*tempratio + (-2*vt*(1.5*log(tempratio)+P_Q*(arg)))";
97       double beta "" calculate="(m->kp / tempratio4) * s->w_eff / s->l_eff";
98       double sqrt_phi "" calculate="sqrt(phi)";
99       double egap "" calculate="egap_";
100     }
101     code_pre {
102       double temp = d->_sim->_temp_c + P_CELSIUS0;
103       double tempratio  = temp / m->tnom_k;
104       double tempratio4 = tempratio * sqrt(tempratio);
105       double kt = temp * P_K;
106       double vt = temp * P_K_Q;
107       double egap_ = 1.16 - (7.02e-4*temp*temp) / (temp+1108.);
108       double arg = (m->egap*tempratio - egap_) / (2*kt);
109     }
110   }
111   /*-----------------------------------------------------------------------*/
112   tr_eval {
113     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
114     trace0(d->long_label().c_str());
115     trace3("", d->vds, d->vgs, d->vbs);
116     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
117     d->reverse_if_needed();
118     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
119     double sarg, dsarg_dvbs;
120     {
121       if (d->vbs <= 0.) {
122         sarg = sqrt(t->phi - d->vbs);
123         dsarg_dvbs = -.5 / sarg;
124         d->sbfwd = false;
125         trace2("sb-ok", sarg, dsarg_dvbs);
126       }else{
127         untested();
128         sarg = t->sqrt_phi / (1. + .5 * d->vbs / t->phi);
129         dsarg_dvbs = -.5 * sarg * sarg / t->phi*t->sqrt_phi; /* is wrong!! */
130         d->sbfwd = true;
131         trace2("***sb-reversed***", sarg, dsarg_dvbs);
132       }
133     }
134     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
135     d->von = m->vto + m->gamma * (sarg - sqrt(m->phi))
136       + .5 * (m->egap - t->egap) + .5 * (t->phi - m->phi);
137     d->vgst = d->vdsat = d->vgs - d->von;
138     if (d->vdsat < 0.) {
139       d->vdsat = 0.;
140     }
141     d->cutoff = (d->vgst < 0.);
142     d->saturated = (d->vds > d->vdsat);
143     trace3("", d->von, d->vgst, d->vdsat);
144     double Lambda = (m->lambda != NA) ? m->lambda : 0.;
145     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
146     if (d->cutoff) {
147       d->gds = d->gmf = d->ids = d->gmbf = 0.;
148       trace4("cut", d->ids, d->gmf, d->gds, d->gmbf);
149     }else if (d->saturated) {
150       d->gmf  = t->beta * d->vgst * (1. + Lambda * d->vds);
151       d->ids = d->gmf * (.5 * d->vgst);
152       d->gds = .5 * t->beta * Lambda * d->vgst * d->vgst;
153       d->gmbf = - d->gmf * m->gamma * dsarg_dvbs;
154       trace4("sat", d->ids, d->gmf, d->gds, d->gmbf);
155     }else{ /* triode */
156       d->gmf  = t->beta * d->vds * (1. + Lambda * d->vds);
157       d->ids = d->gmf * (d->vgst - .5*d->vds);
158       d->gds = t->beta * ((d->vgst - d->vds) 
159                          + Lambda * d->vds * (2.*d->vgst - 1.5*d->vds));
160       d->gmbf = -d->gmf * m->gamma * dsarg_dvbs;
161       trace4("lin", d->ids, d->gmf, d->gds, d->gmbf);
162     }
163     if (d->reversed) {
164       d->ids *= -1;
165       d->gmr = d->gmf;
166       d->gmbr = d->gmbf;
167       d->gmf = d->gmbf = 0;
168     }else{
169       d->gmr = d->gmbr = 0.;
170     }
171   }
173 /*--------------------------------------------------------------------------*/
174 /*--------------------------------------------------------------------------*/