5 * Created by Anthony on 29/04/2008.
6 * Copyright 2008 Avertec SA. All rights reserved.
10 #include "mcc_mod_cmi_interface.h"
11 #include "mcc_mod_cmi.h"
15 static mcc_modext AVTCMI
= {
32 mcc_modext
*pAVTCMI
= &AVTCMI
;
35 mcc_initparam_cmi(mcc_modellist
*ptmodel
)
40 if (!cmi_initlibrary(ptmodel
)) exit(1);
41 if (getenv("CMI_DEBUG") != NULL
) CMI_DEBUG
= 1;
45 cmi_reset_alter_models();
50 mcc_clean_cmi(mcc_modellist
*ptmodel
)
52 cmi_cleaninstance(ptmodel
);
53 cmi_clean_alter_models();
54 cmi_reset_alter_models();
58 mcc_calcQint_cmi(mcc_modellist
*ptmodel
,
69 elp_lotrs_param
*lotrsparam
)
72 alter_param changes
[5];
77 if (cmi_set_alter_model(CMI_QINT_MODEL
) != 0) {
78 changes
[i
].name
= "cgdo"; changes
[i
++].value
= 0.0;
79 changes
[i
].name
= "cgdl"; changes
[i
++].value
= 0.0;
80 changes
[i
].name
= "cgso"; changes
[i
++].value
= 0.0;
81 changes
[i
].name
= "cgdl"; changes
[i
++].value
= 0.0;
82 changes
[i
].name
= NULL
;
83 cmi_initmodel(ptmodel
, changes
);
84 cmi_initinstance(ptmodel
, CMI_QINT_MODEL
, lotrsparam
, L
, W
, -1, -1, -1, -1);
87 cmi_evalinstance(ptmodel
, &slot
, vgs
, vds
, vbs
, 1);
89 if (ptQg
) *ptQg
= slot
.qg
/s
;
90 if (ptQs
) *ptQs
= slot
.qs
/s
;
91 if (ptQd
) *ptQd
= slot
.qd
/s
;
92 if (ptQb
) *ptQb
= slot
.qb
/s
;
93 if (CMI_DEBUG
) printf("[CMI] mcc_calcQint_cmi for \"%s\" (W=%g, L=%g) (Vgs=%g, Vds=%g, Vbs=%g): Qg=%g, Qs=%g, Qd=%g, Qb=%g\n", ptmodel
->NAME
, W
, L
, vgs
, vds
, vbs
, ptQg
?(*ptQg
):-1, ptQs
?(*ptQs
):-1, ptQd
?(*ptQd
):-1, ptQb
?(*ptQb
):-1);
96 /* Perimeter contribution of gate capacitance */
98 mcc_calcCGP_cmi(mcc_modellist
*ptmodel
,
99 elp_lotrs_param
*lotrsparam
,
106 double cgp
, qgunitint
, qgint
, qgtot
;
109 if (cmi_set_alter_model(CMI_DEFAULT_MODEL
) != 0) {
110 cmi_initmodel(ptmodel
, NULL
);
111 cmi_initinstance(ptmodel
, CMI_DEFAULT_MODEL
, lotrsparam
, L
, W
, -1, -1, -1, -1);
114 cmi_evalinstance(ptmodel
, &slot
, vgx
, 0, 0, 1);
118 mcc_calcQint_cmi(ptmodel
, L
, W
, temp
, vgx
, 0, 0, &qgunitint
, NULL
, NULL
, NULL
, lotrsparam
);
119 qgint
= qgunitint
*(W
*L
);
120 *ptQov
= (qgtot
-qgint
)/(2*W
);
122 if (CMI_DEBUG
) printf("[CMI] mcc_calcCGP_cmi for \"%s\" (W=%g, L=%g) (Vgs=%g, Vds=%g, Vbs=%g): Cgp=%g, Qov=%g\n", ptmodel
->NAME
, W
, L
, vgx
, vgx
, vgx
, cgp
, ptQov
?(*ptQov
):-1);
126 /* Surface contribution of gate-drain capacitance */
128 mcc_calcCGD_cmi(mcc_modellist
*ptmodel
,
136 elp_lotrs_param
*lotrsparam
)
138 double qinit
=0.0, qfinal
=0.0, cgd
=0.0;
141 if (mcc_getparam_quick(ptmodel
,__MCC_QUICK_XPART
) < 0.0) return 0.0;
143 if (cmi_set_alter_model(CMI_DEFAULT_MODEL
) != 0) {
144 cmi_initmodel(ptmodel
, NULL
);
145 cmi_initinstance(ptmodel
, CMI_DEFAULT_MODEL
, lotrsparam
, L
, W
, -1, -1, -1, -1);
148 cmi_evalinstance(ptmodel
, &slot
, vgs0
, vds
, vbs
, 1);
150 cmi_evalinstance(ptmodel
, &slot
, vgs1
, vds
, vbs
, 1);
153 cgd
= fabs((qfinal
-qinit
)/(vgs1
-vgs0
))/(W
*L
);
154 if (CMI_DEBUG
) printf("[CMI] mcc_calcCGD_cmi for \"%s\" (W=%g, L=%g) (Vgs=[%g:%g], Vds=%g, Vbs=%g): Cgd=%g, Qinit=%g, Qfinal=%g\n", ptmodel
->NAME
, W
, L
, vgs0
, vgs1
, vds
, vbs
, cgd
, qinit
, qfinal
);
159 /* Surface contribution of gate-drain capacitance */
161 mcc_calcCGSI_cmi(mcc_modellist
*ptmodel
,
168 elp_lotrs_param
*lotrsparam
)
170 double qinit
=0.0, qfinal
=0.0, cgsi
=0.0;
173 if (cmi_set_alter_model(CMI_DEFAULT_MODEL
) != 0) {
174 cmi_initmodel(ptmodel
, NULL
);
175 cmi_initinstance(ptmodel
, CMI_DEFAULT_MODEL
, lotrsparam
, L
, W
, -1, -1, -1, -1);
178 cmi_evalinstance(ptmodel
, &slot
, 0.0, vds
, vbs
, 1);
180 cmi_evalinstance(ptmodel
, &slot
, vgs
, vds
, vbs
, 1);
183 cgsi
= fabs((qfinal
-qinit
)/vgs
)/(W
*L
);
184 if (CMI_DEBUG
) printf("[CMI] mcc_calcCGSI_cmi for \"%s\" (W=%g, L=%g) (Vgs=[%g:%g], Vds=%g, Vbs=%g): Cgp=%g, Qinit=%g, Qfinal=%g\n", ptmodel
->NAME
, W
, L
, 0.0, vgs
, vds
, vbs
, cgsi
, qinit
, qfinal
);
189 mcc_calcVTH_cmi(mcc_modellist
*ptmodel
,
195 elp_lotrs_param
*lotrsparam
)
200 if (cmi_set_alter_model(CMI_DEFAULT_MODEL
) != 0) {
201 cmi_initmodel(ptmodel
, NULL
);
202 cmi_initinstance(ptmodel
, CMI_DEFAULT_MODEL
, lotrsparam
, L
, W
, -1, -1, -1, -1);
205 cmi_evalinstance(ptmodel
, &slot
, vds
, vds
, vbs
, 0);
208 // if (ptmodel->TYPE == MCC_TRANS_P) vth = -vth ;
209 if (CMI_DEBUG
) printf("[CMI] mcc_calcVTH_cmi for \"%s\" (W=%g, L=%g) (Vgs=%g, Vds=%g, Vbs=%g): Vth=%g\n", ptmodel
->NAME
, W
, L
, vds
, vds
, vbs
, vth
);
214 mcc_calcIDS_cmi(mcc_modellist
*ptmodel
,
221 elp_lotrs_param
*lotrsparam
)
225 if (cmi_set_alter_model(CMI_DEFAULT_MODEL
) != 0) {
226 cmi_initmodel(ptmodel
, NULL
);
227 cmi_initinstance(ptmodel
, CMI_DEFAULT_MODEL
, lotrsparam
, L
, W
, -1, -1, -1, -1);
230 cmi_evalinstance(ptmodel
, &slot
, vgs
, vds
, vbs
, 0);
231 if (CMI_DEBUG
) printf("[CMI] mcc_calcIDS_cmi for \"%s\" (W=%g, L=%g) (Vgs=%g, Vds=%g, Vbs=%g): Ids=%g\n", ptmodel
->NAME
, W
, L
, vgs
, vds
, vbs
, slot
.ids
);
235 /* Offset for effective drain channel junction width */
236 double mcc_calcDWCJ_cmi( mcc_modellist
*ptmodel
,
237 elp_lotrs_param
*lotrsparam
,
243 /* OK for Hynix model but we need a general solution */
247 /* Area contribution of channel junction capacitance for drain */
249 mcc_calcCDS_cmi(mcc_modellist
*ptmodel
,
250 elp_lotrs_param
*lotrsparam
,
258 alter_param changes
[3];
259 double qinit
=0.0, qfinal
=0.0, cds
=0.0;
262 if (cmi_set_alter_model(CMI_CDS_MODEL
) != 0) {
263 changes
[i
].name
= "cjswd"; changes
[i
++].value
= 0.0;
264 changes
[i
].name
= "cjswgd"; changes
[i
++].value
= 0.0;
265 changes
[i
].name
= NULL
;
266 cmi_initmodel(ptmodel
, changes
);
267 cmi_initinstance(ptmodel
, CMI_CDS_MODEL
, lotrsparam
, L
, W
, W
*W
, 0, W
*W
, 0);
270 cmi_evalinstance(ptmodel
, &slot
, 0.0, vbx0
, 0.0, 1);
272 cmi_evalinstance(ptmodel
, &slot
, 0.0, vbx1
, 0.0, 1);
274 cmi_set_alter_model(CMI_DEFAULT_MODEL
);
276 cds
= fabs((qfinal
-qinit
)/(vbx1
-vbx0
))/(W
*W
);
277 if (CMI_DEBUG
) printf("[CMI] mcc_calcCDS_cmi for \"%s\" (W=%g, L=%g) (Vgs=%g, Vds=[%g:%g], Vbs=%g): Cgp=%g, Qinit=%g, Qfinal=%g\n", ptmodel
->NAME
, W
, L
, 0.0, vbx0
, vbx1
, 0.0, cds
, qinit
, qfinal
);
281 /* Sidewall contribution of channel junction capacitance for drain */
283 mcc_calcCDP_cmi(mcc_modellist
*ptmodel
,
284 elp_lotrs_param
*lotrsparam
,
292 alter_param changes
[3];
293 double qinit
=0.0, qfinal
=0.0, cdp
=0.0;
296 if (cmi_set_alter_model(CMI_CDP_MODEL
) != 0) {
297 changes
[i
].name
= "cjd"; changes
[i
++].value
= 0.0;
298 changes
[i
].name
= "cjswgd"; changes
[i
++].value
= 0.0;
299 changes
[i
].name
= NULL
;
300 cmi_initmodel(ptmodel
, changes
);
301 cmi_initinstance(ptmodel
, CMI_CDP_MODEL
, lotrsparam
, L
, W
, 0, W
, 0, W
);
304 cmi_evalinstance(ptmodel
, &slot
, 0.0, vbx0
, 0.0, 1);
306 cmi_evalinstance(ptmodel
, &slot
, 0.0, vbx1
, 0.0, 1);
308 cmi_set_alter_model(CMI_DEFAULT_MODEL
);
310 cdp
= fabs((qfinal
-qinit
)/(vbx1
-vbx0
))/W
;
311 if (CMI_DEBUG
) printf("[CMI] mcc_calcCDP_cmi for \"%s\" (W=%g, L=%g) (Vgs=%g, Vds=[%g:%g], Vbs=%g): Cdp=%g, Qinit=%g, Qfinal=%g\n", ptmodel
->NAME
, W
, L
, 0.0, vbx0
, vbx1
, 0.0, cdp
, qinit
, qfinal
);
315 /* Gate sidewall contribution of channel junction capacitance for drain */
317 mcc_calcCDW_cmi(mcc_modellist
*ptmodel
,
318 elp_lotrs_param
*lotrsparam
,
326 alter_param changes
[3];
327 double qinit
=0.0, qfinal
=0.0, cdw
=0.0;
330 if (cmi_set_alter_model(CMI_CDW_MODEL
) != 0) {
331 changes
[i
].name
= "cjd"; changes
[i
++].value
= 0.0;
332 changes
[i
].name
= "cjswd"; changes
[i
++].value
= 0.0;
333 changes
[i
].name
= NULL
;
334 cmi_initmodel(ptmodel
, changes
);
335 cmi_initinstance(ptmodel
, CMI_CDW_MODEL
, lotrsparam
, L
, W
, 0, 0, 0, 0);
338 cmi_evalinstance(ptmodel
, &slot
, 0.0, vbx0
, 0.0, 1);
340 cmi_evalinstance(ptmodel
, &slot
, 0.0, vbx1
, 0.0, 1);
342 cmi_set_alter_model(CMI_DEFAULT_MODEL
);
344 cdw
= fabs((qfinal
-qinit
)/(vbx1
-vbx0
))/W
;
345 if (CMI_DEBUG
) printf("[CMI] mcc_calcCDW_cmi for \"%s\" (W=%g, L=%g) (Vgs=%g, Vds=[%g:%g], Vbs=%g): Cdw=%g, Qinit=%g, Qfinal=%g\n", ptmodel
->NAME
, W
, L
, 0.0, vbx0
, vbx1
, 0.0, cdw
, qinit
, qfinal
);
349 /* Calculate effective Perimeter & Area if undefined */
351 mcc_calcPA_cmi(lotrs_list
*ptlotrs
,
352 mcc_modellist
*ptmodel
,
353 elp_lotrs_param
*lotrsparam
,
359 mcc_calcPAfromgeomod_bsim4(ptlotrs
, ptmodel
, lotrsparam
, as
, ad
, ps
, pd
);