1 /****************************************************************************/
3 /* Chaine de CAO & VLSI Alliance */
5 /* Produit : TAS Version 5 */
6 /* Fichier : tas_tpiv.c */
8 /* (c) copyright 1991-1998 Laboratoire LIP6 equipe ASIM */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
12 /* Auteur(s) : Grégoire Avot */
14 /****************************************************************************/
15 /* calcul des temps de propagation entre une sortie de cone */
16 /* et toutes ses entrees */
17 /****************************************************************************/
21 int TPIV_DEBUG_IBR
= 0 ;
23 mcc_trans_mcc
* tpiv_addtransmcc( tpiv
*br
, stm_solver_maillon
*stmm
, link_list
*link
)
25 mcc_trans_mcc
*trsmcc
;
30 vg
= tpiv_get_voltage_driving_lotrs( link
->ULINK
.LOTRS
);
32 if( TAS_CONTEXT
->TAS_LEVEL
== 2 )
33 elp_lotrs_param_get( link
->ULINK
.LOTRS
,NULL
,NULL
, NULL
, NULL
,NULL
, NULL
, NULL
, NULL
,NULL
,&vbulk
,NULL
,NULL
,NULL
,NULL
);
35 if( MLO_IS_TRANSP(link
->ULINK
.LOTRS
->TYPE
) )
36 vbulk
= tas_getparam( link
->ULINK
.LOTRS
, TAS_CASE
, TP_VDDmax
);
41 trsmcc
= mcc_create_trans_mcc( link
->ULINK
.LOTRS
,
42 tas_getparam ( link
->ULINK
.LOTRS
, TAS_CASE
, TP_VDDmax
),
49 if( getptype( link
->USER
, TAS_LINK_CARAC
) ) {
50 trsmcc
->TRWIDTH
= TAS_GETWIDTH( link
) ;
51 trsmcc
->TRLENGTH
= TAS_GETLENGTH( link
);
54 br
->HEADTRSMCC
= addchain( br
->HEADTRSMCC
, trsmcc
);
57 head
= addchain( head
, trsmcc
);
58 stm_solver_add_model( stmm
,
59 (char(*)(void*,float,float,float*))mcc_mcc_ids_list
,
60 (char(*)(void*,float,float,float*))mcc_mcc_vds_list
,
68 void tpiv_addtransmcc_switch( tpiv
*br
, stm_solver_maillon
*stmm
, link_list
*link
, lotrs_list
*lotrs
)
77 if( !V_BOOL_TAB
[ __AVT_NEW_SWITCH_MODEL
].VALUE
) {
79 trs1
= tpiv_addtransmcc( br
, stmm
, link
);
81 rate
= tas_get_current_rate( link
) ;
82 trs1
->TRWIDTH
= trs1
->TRWIDTH
* rate
;
87 vg
= tpiv_get_voltage_driving_lotrs( link
->ULINK
.LOTRS
);
89 if( TAS_CONTEXT
->TAS_LEVEL
== 2 )
90 elp_lotrs_param_get( link
->ULINK
.LOTRS
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &vbulk
,NULL
,NULL
,NULL
,NULL
);
92 if( MLO_IS_TRANSP(link
->ULINK
.LOTRS
->TYPE
) )
93 vbulk
= tas_getparam( link
->ULINK
.LOTRS
, TAS_CASE
, TP_VDDmax
);
98 trs1
= mcc_create_trans_mcc( link
->ULINK
.LOTRS
,
99 tas_getparam ( link
->ULINK
.LOTRS
, TAS_CASE
, TP_VDDmax
),
106 if( getptype( link
->USER
, TAS_LINK_CARAC
) ) {
107 trs1
->TRWIDTH
= TAS_GETWIDTH( link
) ;
108 trs1
->TRLENGTH
= TAS_GETLENGTH( link
);
111 vg
= tpiv_get_voltage_driving_lotrs( lotrs
);
113 if( TAS_CONTEXT
->TAS_LEVEL
== 2 )
114 elp_lotrs_param_get( lotrs
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &vbulk
,NULL
,NULL
,NULL
,NULL
);
116 if( MLO_IS_TRANSP(lotrs
->TYPE
) )
117 vbulk
= tas_getparam( lotrs
, TAS_CASE
, TP_VDDmax
);
122 trs2
= mcc_create_trans_mcc( lotrs
,
123 tas_getparam ( lotrs
, TAS_CASE
, TP_VDDmax
),
129 /* the TAS_LINK_CARAC needs to update transistor dimension is not available
130 here... to be done ! */
132 br
->HEADTRSMCC
= addchain( br
->HEADTRSMCC
, trs1
);
133 br
->HEADTRSMCC
= addchain( br
->HEADTRSMCC
, trs2
);
136 head
= addchain( head
, trs1
);
137 head
= addchain( head
, trs2
);
138 stm_solver_add_model( stmm
,
139 (char(*)(void*,float,float,float*))mcc_mcc_ids_list
,
140 (char(*)(void*,float,float,float*))mcc_mcc_vds_list
,
148 /******************************************************************************\
149 Convertie une branche au format CNS vers le format stm_solver()
150 Les tensions sur les grilles sont initialisées à vdd.
151 \******************************************************************************/
152 tpiv
* tpiv_createbranch( link_list
*head
, char transtype
)
155 stm_solver_maillon
*stmm
;
156 mcc_trans_spice
*trsspice
;
157 mcc_trans_mcc
*trsmcc
;
169 /* Transforme la branche CNS en branche STM */
170 for( cnsm
= head
; cnsm
; cnsm
= cnsm
->NEXT
) {
171 if ((cnsm
->TYPE
& CNS_EXT
) == CNS_EXT
) break;
172 stmm
= stm_solver_new_maillon();
174 switch( transtype
) {
176 case TAS_TRMODEL_MCCRSAT
:
179 if( (cnsm
->TYPE
& CNS_SWITCH
)==CNS_SWITCH
) {
180 ptype
= getptype( cnsm
->ULINK
.LOTRS
->USER
, TAS_TRANS_SWITCH
);
182 trspair
= (lotrs_list
*)ptype
->DATA
;
186 tpiv_addtransmcc_switch( br
, stmm
, cnsm
, trspair
);
188 trsmcc
= tpiv_addtransmcc( br
, stmm
, cnsm
);
192 case TAS_TRMODEL_SPICE
:
194 vg
= tpiv_get_voltage_driving_lotrs( cnsm
->ULINK
.LOTRS
);
197 if( TAS_CONTEXT->TAS_LEVEL == 2 )
199 elp_lotrs_param_get( cnsm
->ULINK
.LOTRS
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &vbulk
,NULL
,NULL
,NULL
,NULL
);
202 if( MLO_IS_TRANSP(cnsm->ULINK.LOTRS->TYPE) )
203 vbulk = tas_getparam( cnsm->ULINK.LOTRS, TAS_CASE, TP_VDDmax );
209 trsspice
= mcc_create_trans_spice( cnsm
->ULINK
.LOTRS
,
210 tas_getparam ( cnsm
->ULINK
.LOTRS
,
217 br
->HEADTRSSPICE
= addchain( br
->HEADTRSSPICE
, trsspice
);
218 elpLotrsGetUnShrinkDim( cnsm
->ULINK
.LOTRS
,
219 TAS_GETLENGTH( cnsm
),
220 TAS_GETWIDTH( cnsm
),
225 rate
= tas_get_current_rate( cnsm
);
227 trsspice
->TRLENGTH
= ((float)l
)*1e-6 / ((float)SCALE_X
) ;
228 trsspice
->TRWIDTH
= ((float)w
)*1e-6 / ((float)SCALE_X
) ;
230 // Voir le deshrinkage
231 // trsspice->WIDTH = TAS_GETWIDTH( cnsm );
232 // trsspice->LENGTH = TAS_GETLENGTH( cnsm );
233 // Voir l'influence de WIDTH sur les aires.
235 trlist
= addchain( NULL
, trsspice
);
236 stm_solver_add_model( stmm
,
237 (char(*)(void*,float,float,float*))mcc_spice_ids_list
,
238 (char(*)(void*,float,float,float*))mcc_spice_vds_list
,
246 fprintf( stderr
, "Bad transistor model.\n" );
250 br
->HEAD
= stm_solver_maillon_addchain( br
->HEAD
, stmm
);
253 br
->HEAD
= stm_solver_maillon_reverse( br
->HEAD
);
258 /******************************************************************************\
259 Crée une branche pour le calcul du leakage dont le transistor activelink est bloque
260 \******************************************************************************/
261 tpiv
* tpiv_createbranch_leakage( link_list
*head
, link_list
*activelink
, char transtype
)
264 stm_solver_maillon
*stmm
;
265 mcc_trans_spice
*trsspice
;
266 mcc_trans_mcc
*trsmcc
;
278 /* Transforme la branche CNS en branche STM */
279 for( cnsm
= head
; cnsm
; cnsm
= cnsm
->NEXT
) {
280 if ((cnsm
->TYPE
& CNS_EXT
) == CNS_EXT
) break;
281 stmm
= stm_solver_new_maillon();
283 if((cnsm
== activelink
) || (TAS_PATH_TYPE
== 'm')){
284 vg
= tpiv_get_blocked_voltage_driving_lotrs( cnsm
->ULINK
.LOTRS
);
286 vg
= tpiv_get_voltage_driving_lotrs( cnsm
->ULINK
.LOTRS
);
289 elp_lotrs_param_get( cnsm
->ULINK
.LOTRS
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &vbulk
,NULL
,NULL
,NULL
,NULL
);
291 trsspice
= mcc_create_trans_spice( cnsm
->ULINK
.LOTRS
,
292 tas_getparam ( cnsm
->ULINK
.LOTRS
,
299 br
->HEADTRSSPICE
= addchain( br
->HEADTRSSPICE
, trsspice
);
300 elpLotrsGetUnShrinkDim( cnsm
->ULINK
.LOTRS
,
301 TAS_GETLENGTH( cnsm
),
302 TAS_GETWIDTH( cnsm
),
307 rate
= tas_get_current_rate( cnsm
);
309 trsspice
->TRLENGTH
= ((float)l
)*1e-6 / ((float)SCALE_X
) ;
310 trsspice
->TRWIDTH
= ((float)w
)*1e-6 / ((float)SCALE_X
) ;
312 trlist
= addchain( NULL
, trsspice
);
313 stm_solver_add_model( stmm
,
314 (char(*)(void*,float,float,float*))mcc_spice_ids_list
,
315 (char(*)(void*,float,float,float*))mcc_spice_vds_list
,
322 br
->HEAD
= stm_solver_maillon_addchain( br
->HEAD
, stmm
);
325 br
->HEAD
= stm_solver_maillon_reverse( br
->HEAD
);
330 tpiv
* tpiv_createbranch_leakage_2( link_list
*head
, link_list
*activelink
, char transtype
)
333 stm_solver_maillon
*stmm
;
334 mcc_trans_spice
*trsspice
;
335 mcc_trans_mcc
*trsmcc
;
344 chain_list
*chain
, *ptparachain
, *ptchain
;
345 lotrs_list
*ptparatrans
, *ptlotrs
;
351 /* Transforme la branche CNS en branche STM */
352 for( cnsm
= head
; cnsm
; cnsm
= cnsm
->NEXT
) {
353 if ((cnsm
->TYPE
& CNS_EXT
) == CNS_EXT
) break;
354 stmm
= stm_solver_new_maillon();
356 cone
= (cone_list
*)getptype( cnsm
->ULINK
.LOTRS
->USER
, CNS_DRIVINGCONE
)->DATA
;
357 if((((cone
->TECTYPE
& (CNS_STATE_ONE
|CNS_ONE
)) != 0) && MLO_IS_TRANSN(cnsm
->ULINK
.LOTRS
->TYPE
))
358 || (((cone
->TECTYPE
& (CNS_STATE_ZERO
|CNS_ZERO
)) != 0) && MLO_IS_TRANSP(cnsm
->ULINK
.LOTRS
->TYPE
))){
359 vg
= tpiv_get_voltage_driving_lotrs( cnsm
->ULINK
.LOTRS
);
361 vg
= tpiv_get_blocked_voltage_driving_lotrs( cnsm
->ULINK
.LOTRS
);
364 elp_lotrs_param_get( cnsm
->ULINK
.LOTRS
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &vbulk
,NULL
,NULL
,NULL
,NULL
);
366 trsspice
= mcc_create_trans_spice( cnsm
->ULINK
.LOTRS
,
367 tas_getparam ( cnsm
->ULINK
.LOTRS
,
374 br
->HEADTRSSPICE
= addchain( br
->HEADTRSSPICE
, trsspice
);
375 ptlotrs
= cnsm
->ULINK
.LOTRS
;
376 if ((ptuser
= getptype(ptlotrs
->USER
, MBK_TRANS_PARALLEL
)) != NULL
) {
377 ptparachain
= (chain_list
*)ptuser
->DATA
;
380 for (ptchain
= ptparachain
; ptchain
; ptchain
= ptchain
->NEXT
) {
381 ptparatrans
= (lotrs_list
*)ptchain
->DATA
;
382 w
+= ptparatrans
->WIDTH
* (l
/ ptparatrans
->LENGTH
);
389 rate
= tas_get_current_rate( cnsm
);
391 trsspice
->TRLENGTH
= ((float)l
)*1e-6 / ((float)SCALE_X
) ;
392 trsspice
->TRWIDTH
= ((float)w
)*1e-6 / ((float)SCALE_X
) ;
394 trlist
= addchain( NULL
, trsspice
);
395 stm_solver_add_model( stmm
,
396 (char(*)(void*,float,float,float*))mcc_spice_ids_list
,
397 (char(*)(void*,float,float,float*))mcc_spice_vds_list
,
404 br
->HEAD
= stm_solver_maillon_addchain( br
->HEAD
, stmm
);
407 br
->HEAD
= stm_solver_maillon_reverse( br
->HEAD
);
411 /******************************************************************************\
413 \******************************************************************************/
414 void tpiv_freebranch( tpiv
*br
)
416 chain_list
*scantrsmcc
;
417 chain_list
*scantrsspice
;
418 mcc_trans_mcc
*trsmcc
;
419 mcc_trans_spice
*trsspice
;
421 stm_solver_maillon_freechain( br
->HEAD
);
423 for( scantrsmcc
= br
->HEADTRSMCC
;
425 scantrsmcc
= scantrsmcc
->NEXT
427 trsmcc
= (mcc_trans_mcc
*)scantrsmcc
->DATA
;
428 mcc_delete_trans_mcc( trsmcc
);
430 freechain( br
->HEADTRSMCC
);
432 for( scantrsspice
= br
->HEADTRSSPICE
;
434 scantrsspice
= scantrsspice
->NEXT
437 trsspice
= (mcc_trans_spice
*)scantrsspice
->DATA
;
438 mcc_delete_trans_spice( trsspice
);
440 freechain( br
->HEADTRSSPICE
);
445 /******************************************************************************\
446 Crée un modèle timing_iv de la branche CNS passée en paramètre.
447 Pour l'instant, le conflit modélisé par une capacité calculée avec MCC.
448 head Premier maillon de la branche
449 active Maillon qui commute
450 vref Polarisation de la branche (vdd ou vss)
451 pconf0 Paramètre pour le calcul de la capacité
452 pconf1 Paramètre pour le calcul de la capacité
453 fin_vi Entrée : tension initiale
454 fin_vf Entrée : tension finale
455 fin_vs Entrée : seuil logique
456 vouti Sortie : tension initiale
457 \******************************************************************************/
458 timing_iv
*tpiv_dualmodel( cone_list
*cone
,
471 timing_iv
*iv
= NULL
;
473 stm_solver_maillon_list
*maillon
;
479 double AX
, BX
, rtx
, rx
, VT
, QX
, QY
, thr
, vddmax
, vddin
, imax
;
482 tas_getmcc( branch
->LINK
,
500 imax
= tas_get_current ( branch
, branch
->LINK
, 1.0, NO
);
501 pconf0
= pconf0
+ tas_getcapaparams (cone
, branch
, active
, imax
, QX
, QY
, &capai
, &irap
, &temps
,TAS_UNKNOWN_EVENT
,0);
503 switch( TAS_CONTEXT
->TAS_LEVEL
) {
505 trtype
= TAS_TRMODEL_MCCRSAT
;
508 trtype
= TAS_TRMODEL_SPICE
;
511 trtype
= TAS_TRMODEL_MCCRSAT
;
514 br
= tpiv_createbranch( branch
->LINK
, trtype
);
520 for( link
=branch
->LINK
, maillon
=br
->HEAD
;
521 link
&& link
!= active
;
522 link
= link
->NEXT
, maillon
= maillon
->NEXT
);
526 d
.TRS
= link
->ULINK
.LOTRS
;
528 // Polarise le dernier élément
529 for( maillon
= br
->HEAD
; maillon
->NEXT
; maillon
= maillon
->NEXT
);
530 maillon
->MAILLON
->VS
=vref
;
532 vdd
= tas_getparam( branch
->LINK
->ULINK
.LOTRS
, TAS_CASE
, TP_VDDmax
);
533 iv
= stm_modiv_create( 10,
537 (char(*)(void*,float,float,float*))tpiv_calc_i
,
541 stm_modiv_set_cf( iv
, capai
, pconf0
, pconf1
, irap
);
542 stm_modiv_set_in( iv
, VT
, fin_vi
, fin_vf
, fin_vs
);
543 stm_modiv_set_ti( iv
, vouti
);
546 tpiv_freebranch( br
);
551 char tpiv_calc_i( tpiv_i
*model
, float ve
, float vs
, float *is
)
554 mcc_trans_mcc
*trsmcc
;
555 mcc_trans_spice
*trsspi
;
559 for( chtrs
= model
->ACTIVE
->MAILLON
->MODEL_VDS
; chtrs
; chtrs
= chtrs
->NEXT
) {
560 if( model
->TRTYPE
== TAS_TRMODEL_MCCRSAT
) {
561 trsmcc
= (mcc_trans_mcc
*)chtrs
->DATA
;
562 if( trsmcc
->TYPE
== model
->TRS
->TYPE
)
565 vg
= model
->VDDMAX
- ve
;
569 trsspi
= (mcc_trans_spice
*)chtrs
->DATA
;
570 if( ( trsspi
->TRANSTYPE
== MCC_NMOS
&& MLO_IS_TRANSN( model
->TRS
->TYPE
) ) ||
571 ( trsspi
->TRANSTYPE
== MCC_PMOS
&& MLO_IS_TRANSP( model
->TRS
->TYPE
) ) )
574 vg
= model
->VDDMAX
- ve
;
578 ret
= stm_solver_i( model
->HEAD
, vs
, is
);
582 void tpiv_set_voltage_driving_lotrs( lotrs_list
*lotrs
, float voltage
)
586 ptl
= getptype( lotrs
->GRID
->SIG
->USER
, TAS_SIG_VOLTAGE
);
588 lotrs
->GRID
->SIG
->USER
= addptype( lotrs
->GRID
->SIG
->USER
, TAS_SIG_VOLTAGE
, 0l );
589 ptl
= lotrs
->GRID
->SIG
->USER
;
592 ptl
->DATA
= (void*)((long)(voltage
*1000.0));
595 void tpiv_clean_voltage_driving_lotrs( lotrs_list
*lotrs
)
597 lotrs
->GRID
->SIG
->USER
= testanddelptype( lotrs
->GRID
->SIG
->USER
, TAS_SIG_VOLTAGE
);
600 float tpiv_get_voltage_driving_lotrs( lotrs_list
*lotrs
)
602 cone_list
*cone_avant
;
607 ptype_list
*ptl
, *ptype
;
609 ptl
= getptype( lotrs
->GRID
->SIG
->USER
, TAS_SIG_VOLTAGE
);
611 return ((float)((long)(ptl
->DATA
)))/1000.0 ;
615 cone_avant
= (cone_list
*)getptype( lotrs
->USER
, CNS_DRIVINGCONE
)->DATA
;
619 power
= cns_get_multivoltage( cone_avant
);
625 if( ( lotrs
->TYPE
& CNS_TN
) == CNS_TN
) {
626 if( TAS_PATH_TYPE
== 'M' )
627 voltage
= power
->VDDMIN
;
629 voltage
= power
->VDDMAX
;
632 if( TAS_PATH_TYPE
== 'M' )
633 voltage
= power
->VSSMAX
;
635 voltage
= power
->VSSMIN
;
639 /* solution provisoire : ici, on prend la dégradation du maillon courant,
640 pas celle du cone d'entrée. */
642 if( MLO_IS_TRANSN( lotrs
->TYPE
) &&
643 ((cone_avant
->TECTYPE
& CNS_VDD_DEGRADED
) == CNS_VDD_DEGRADED
) ) {
644 vdeg
= tas_getparam( lotrs
, TAS_CASE
, TP_deg
);
645 if((ptype
= getptype(cone_avant
->USER
, TAS_VDD_NOTDEG
)) != NULL
){
646 vdeg
+= *(float*)(&ptype
->DATA
);
648 vdeg
-= tas_getparam ( lotrs
, TAS_CASE
, TP_VDDmax
);
652 if( MLO_IS_TRANSP( lotrs
->TYPE
) &&
653 ((cone_avant
->TECTYPE
& CNS_VSS_DEGRADED
) == CNS_VSS_DEGRADED
) ) {
654 vdeg
= tas_getparam( lotrs
, TAS_CASE
, TP_deg
);
659 /* prise en compte si degradation des inputs */
661 if( usedefault
== 1 ) {
662 if( ( lotrs
->TYPE
& CNS_TN
) == CNS_TN
)
663 voltage
= tas_getparam ( lotrs
, TAS_CASE
, TP_VDDmax
);
668 voltage
= voltage
+ vdeg
;
673 /******************************************************************************\
674 Renvoie la tension de blocage d'un transistor pour le calcul du leakage
675 \******************************************************************************/
676 float tpiv_get_blocked_voltage_driving_lotrs( lotrs_list
*lotrs
)
678 cone_list
*cone_avant
;
686 cone_avant
= (cone_list
*)getptype( lotrs
->USER
, CNS_DRIVINGCONE
)->DATA
;
690 power
= cns_get_multivoltage( cone_avant
);
693 /* tasLeakageRatio Calcul du delta voltage sur la tension de grille pour le leakage */
694 if (V_FLOAT_TAB
[__AVT_LEAKAGE_RATIO
].SET
){
695 if( TAS_PATH_TYPE
== 'M' )
696 delta
= power
->VDDMIN
* V_FLOAT_TAB
[__AVT_LEAKAGE_RATIO
].VALUE
;
698 delta
= power
->VDDMAX
* V_FLOAT_TAB
[__AVT_LEAKAGE_RATIO
].VALUE
;
703 /* Si TN alors on la tension de blocage n'est pas tout a fait 0v si delta!=0 */
704 if( ( lotrs
->TYPE
& CNS_TN
) == CNS_TN
) {
705 if( TAS_PATH_TYPE
== 'M' )
706 voltage
= power
->VSSMAX
+ delta
;
708 voltage
= power
->VSSMIN
+ delta
;
711 /* Si TP alors on la tension de blocage n'est pas tout a fait VDD si delta!=0 */
712 if( TAS_PATH_TYPE
== 'M' )
713 voltage
= power
->VDDMIN
- delta
;
715 voltage
= power
->VDDMAX
- delta
;
720 if( usedefault
== 1 ) {
721 if (V_FLOAT_TAB
[__AVT_LEAKAGE_RATIO
].SET
){
722 delta
= tas_getparam ( lotrs
, TAS_CASE
, TP_VDDmax
) * V_FLOAT_TAB
[__AVT_LEAKAGE_RATIO
].VALUE
;
724 if( ( lotrs
->TYPE
& CNS_TP
) == CNS_TP
)
725 voltage
= tas_getparam ( lotrs
, TAS_CASE
, TP_VDDmax
) - delta
;
727 voltage
= 0.0 + delta
;
734 /******************************************************************************\
735 Calcul le courant maximum dans une branche en utilisant stm_solver.
736 \******************************************************************************/
737 char tpiv_i_brdual( head
, vout
, valim
, imax
, savepol
)
747 stm_solver_maillon_list
*maillon
;
750 if( ( head
->TYPE
& (CNS_IN
| CNS_INOUT
) ) != 0 )
753 for( link
= head
->NEXT
; link
; link
= link
->NEXT
) {
754 if ((link
->TYPE
& CNS_EXT
) == CNS_EXT
) break;
755 if( !V_BOOL_TAB
[ __AVT_NEW_SWITCH_MODEL
].VALUE
) {
756 if( link
->ULINK
.LOTRS
->TYPE
!= head
->ULINK
.LOTRS
->TYPE
)
761 switch( TAS_CONTEXT
->TAS_LEVEL
) {
764 brtype
= TAS_TRMODEL_MCCRSAT
;
768 brtype
= TAS_TRMODEL_SPICE
;
771 brtype
= TAS_TRMODEL_MCCRSAT
;
775 br
= tpiv_createbranch( head
, brtype
);
776 for( maillon
= br
->HEAD
; maillon
->NEXT
; maillon
= maillon
->NEXT
);
777 maillon
->MAILLON
->VS
=valim
;
779 r
= stm_solver_i( br
->HEAD
, vout
, imax
);
781 if( savepol
== YES
) {
782 for( maillon
= br
->HEAD
, link
= head
;
784 maillon
= maillon
->NEXT
, link
= link
->NEXT
) {
786 // old: if(link->ULINK.LOTRS->TYPE==TRANSP)
787 if(MLO_IS_TRANSP(link
->ULINK
.LOTRS
->TYPE
))
788 tas_set_vpol( link
, valim
- maillon
->MAILLON
->VD
);
790 tas_set_vpol( link
, maillon
->MAILLON
->VD
);
794 tpiv_freebranch( br
);
796 if( TPIV_DEBUG_IBR
&&
797 ( V_BOOL_TAB
[ __TAS_CHECK_IMAX
].VALUE
|| V_BOOL_TAB
[ __TAS_USE_BSIM_CURRENT
].VALUE
)
801 static FILE *file
=NULL
;
804 for( link
= head
; link
; link
= link
->NEXT
) {
805 if( ( link
->TYPE
& CNS_EXT
) == CNS_EXT
)
807 if( getptype( link
->ULINK
.LOTRS
->USER
, MBK_TRANS_PARALLEL
) )
809 if( getptype( link
->ULINK
.LOTRS
->USER
, TAS_TRANS_SWITCH
) )
814 if( V_BOOL_TAB
[ __TAS_CHECK_IMAX
].VALUE
) {
816 file
= mbkfopen( "current", "dat", "w" );
818 brtype
= TAS_TRMODEL_SPICE
;
819 br
= tpiv_createbranch( head
, brtype
);
820 for( maillon
= br
->HEAD
; maillon
->NEXT
; maillon
= maillon
->NEXT
);
821 maillon
->MAILLON
->VS
=valim
;
822 stm_solver_i( br
->HEAD
, vout
, &imcc
);
823 d
= (*imax
-imcc
)*100.0/imcc
;
824 if( V_BOOL_TAB
[ __TAS_CHECK_IMAX
].VALUE
) {
825 fprintf( file
, "error=%f\n",d
);
827 tpiv_freebranch( br
);
828 if( V_BOOL_TAB
[ __TAS_USE_BSIM_CURRENT
].VALUE
)
836 /******************************************************************************\
837 Calcul du courant leakage d'une branche dont le transistor activelink est bloque
838 \******************************************************************************/
839 char tpiv_i_brdual_leakage( head
, activelink
, vout
, valim
, imax
)
841 link_list
*activelink
;
849 stm_solver_maillon_list
*maillon
;
852 if( ( head
->TYPE
& (CNS_IN
| CNS_INOUT
) ) != 0 )
855 for( link
= head
->NEXT
; link
; link
= link
->NEXT
) {
856 if ((link
->TYPE
& CNS_EXT
) == CNS_EXT
) break;
857 if( !V_BOOL_TAB
[ __AVT_NEW_SWITCH_MODEL
].VALUE
) {
858 if( link
->ULINK
.LOTRS
->TYPE
!= head
->ULINK
.LOTRS
->TYPE
)
863 brtype
= TAS_TRMODEL_SPICE
;
865 br
= tpiv_createbranch_leakage( head
, activelink
, brtype
);
866 for( maillon
= br
->HEAD
; maillon
->NEXT
; maillon
= maillon
->NEXT
);
867 maillon
->MAILLON
->VS
=valim
;
869 r
= stm_solver_i( br
->HEAD
, vout
, imax
);
871 tpiv_freebranch( br
);
877 char tpiv_i_brdual_leakage_2( head
, activelink
, vout
, valim
, imax
)
879 link_list
*activelink
;
887 stm_solver_maillon_list
*maillon
;
890 if( ( head
->TYPE
& (CNS_IN
| CNS_INOUT
) ) != 0 )
893 for( link
= head
->NEXT
; link
; link
= link
->NEXT
) {
894 if ((link
->TYPE
& CNS_EXT
) == CNS_EXT
) break;
895 if( !V_BOOL_TAB
[ __AVT_NEW_SWITCH_MODEL
].VALUE
) {
896 if( link
->ULINK
.LOTRS
->TYPE
!= head
->ULINK
.LOTRS
->TYPE
)
901 brtype
= TAS_TRMODEL_SPICE
;
903 br
= tpiv_createbranch_leakage_2( head
, activelink
, brtype
);
904 for( maillon
= br
->HEAD
; maillon
->NEXT
; maillon
= maillon
->NEXT
);
905 maillon
->MAILLON
->VS
=valim
;
907 r
= stm_solver_i( br
->HEAD
, vout
, imax
);
909 tpiv_freebranch( br
);
914 /******************************************************************************\
915 Renvoie le courant d'une branche lorsque tous les maillons commandés par le même
916 signal que celui qui controle activelink valent vin. Les autres sont drivés par
917 les tensions des cones d'avant.
918 \******************************************************************************/
919 int tpiv_get_i_multi_input( link0
, activelink
, vout
, valim
, vin
, vinopp
, trmodel
, imax
)
921 link_list
*activelink
;
931 stm_solver_maillon_list
*maillon
;
934 br
= tpiv_createbranch( link0
, trmodel
);
935 for( maillon
= br
->HEAD
; maillon
->NEXT
; maillon
= maillon
->NEXT
);
936 maillon
->MAILLON
->VS
=valim
;
938 for( maillon
= br
->HEAD
, link
= link0
;
940 maillon
= maillon
->NEXT
, link
= link
->NEXT
) {
942 if( link
->ULINK
.LOTRS
->GRID
->SIG
== activelink
->ULINK
.LOTRS
->GRID
->SIG
) {
943 tas_tpiv_set_vg_for_switch( maillon
->MAILLON
,
945 MLO_IS_TRANSN(activelink
->ULINK
.LOTRS
->TYPE
) ? 'N' : 'P',
952 r
= stm_solver_i( br
->HEAD
, vout
, imax
);
954 tpiv_freebranch( br
);
959 /******************************************************************************\
960 Trace dans un fichier le courant d'un branche lorsque le maillon 'actif' varie
961 de 'vin_d' a 'vin_f', et lorsque la la tension de sortie varie de 'vout_d' à 'vout_f'
962 Calcul le courant maximum dans une branche en utilisant stm_solver.
963 \******************************************************************************/
964 void tpiv_i_trace_brdual( filename
, head
, actif
, brtype
, vin_d
, vin_f
, vout_d
, vout_f
, valim
, vdd
)
978 stm_solver_maillon_list
*maillon
;
986 float timax
[3], vin
[3] ;
989 br
= tpiv_createbranch( head
, brtype
);
990 for( maillon
= br
->HEAD
; maillon
->NEXT
; maillon
= maillon
->NEXT
);
991 maillon
->MAILLON
->VS
=valim
;
995 /**** variation de vin ****/
996 sprintf( buffer
, "%s_vin.dat", filename
);
997 ptf
= fopen( buffer
, "w" );
998 step
= (vin_f
-vin_d
)/((float)k
) ;
1000 for( l
=0 , v
=vin_d
; l
<=k
; l
++, v
=v
+step
) {
1001 for( maillon
= br
->HEAD
, lnk
= head
; maillon
&& lnk
; maillon
= maillon
->NEXT
, lnk
= lnk
->NEXT
) {
1002 if( lnk
->ULINK
.LOTRS
->GRID
->SIG
== actif
->ULINK
.LOTRS
->GRID
->SIG
) {
1003 tas_tpiv_set_vg_for_switch( maillon
->MAILLON
,
1005 MLO_IS_TRANSN(actif
->ULINK
.LOTRS
->TYPE
) ? 'N' : 'P',
1012 r
= stm_solver_i( br
->HEAD
, vout_f
, &imax
);
1013 fprintf( ptf
, "%g %g\n", v
, -imax
);
1018 /**** variation de vout ****/
1019 sprintf( buffer
, "%s_vout.dat", filename
);
1020 ptf
= fopen( buffer
, "w" );
1021 vt
= tas_getparam( actif
->ULINK
.LOTRS
, TAS_CASE
, TP_VT
);
1022 step
= (vout_f
-vout_d
)/((float)k
) ;
1024 if( MLO_IS_TRANSN(actif
->ULINK
.LOTRS
->TYPE
) ) {
1025 vin
[0] = 3.0 * (vin_f
-vt
)/3.0 + vt
;
1026 vin
[1] = 2.0 * (vin_f
-vt
)/3.0 + vt
;
1027 vin
[2] = 1.0 * (vin_f
-vt
)/3.0 + vt
;
1030 vin
[0] = 0.0*(vdd
-vt
-vin_f
)/3.0 + vin_f
;
1031 vin
[1] = 1.0*(vdd
-vt
-vin_f
)/3.0 + vin_f
;
1032 vin
[2] = 2.0*(vdd
-vt
-vin_f
)/3.0 + vin_f
;
1035 fprintf( ptf
, "#vin %g %g %g\n", vin
[0], vin
[1], vin
[2] );
1036 for( l
=0 , v
=vout_d
; l
<=k
; l
++, v
=v
+step
) {
1038 for( i
=0; i
<=2 ; i
++ ) {
1039 for( maillon
= br
->HEAD
, lnk
= head
; maillon
&& lnk
; maillon
= maillon
->NEXT
, lnk
= lnk
->NEXT
) {
1040 if( lnk
->ULINK
.LOTRS
->GRID
->SIG
== actif
->ULINK
.LOTRS
->GRID
->SIG
) {
1041 tas_tpiv_set_vg_for_switch( maillon
->MAILLON
,
1043 MLO_IS_TRANSN(actif
->ULINK
.LOTRS
->TYPE
) ? 'N' : 'P',
1050 r
= stm_solver_i( br
->HEAD
, v
, &timax
[i
] );
1052 fprintf( ptf
, "%g %g %g %g\n", v
, -timax
[0], -timax
[1], -timax
[2] );
1057 tpiv_freebranch( br
);
1060 /******************************************************************************\
1061 Alloue une structure tpiv
1062 \******************************************************************************/
1063 tpiv
* tpiv_alloc( void )
1066 s
= (tpiv
*)addptype( NULL
, 0l, NULL
);
1068 s
->HEADTRSSPICE
=NULL
;
1074 /******************************************************************************\
1075 Libère une structure tpiv
1076 \******************************************************************************/
1077 void tpiv_free( tpiv
*s
)
1080 ptl
= (ptype_list
*)s
;
1085 /******************************************************************************\
1086 Trace la tension de sortie d'un inverseur.
1087 \******************************************************************************/
1089 void tpiv_inverter( char *fname
,
1100 dualparams
*scmmodel
,
1105 stm_solver_maillon
*stmp
;
1106 stm_solver_maillon
*stmn
;
1107 mcc_trans_mcc
*trsmccn
;
1108 mcc_trans_spice
*trsspicen
;
1109 mcc_trans_mcc
*trsmccp
;
1110 mcc_trans_spice
*trsspicep
;
1114 double ve
, vs
, lve
, lvs
, v2
, lv2
;
1117 float in
, ip
, lin
, lip
;
1121 double qsatn
,qsatp
, qsat
, qsatx
;
1122 double qovrn
,qovrp
, qovr
;
1123 double qconfn
,qconfp
, qconf
;
1124 float isatn
, isatp
, lisatn
, lisatp
;
1125 double seuil1
, seuil2
, ts1
, ts2
, fth
;
1127 chain_list
*trslist
;
1137 stm_dual_param_timing paramtiming
;
1138 double vt
, vdd
, ci
, capaie
[4], vcap
[3], vt0
, vt0c
, dtpwl
, load
;
1140 vt
= scmmodel
->DP
[STM_VT
];
1141 vt0
= scmmodel
->DP
[STM_VT0
];
1142 vt0c
= scmmodel
->DP
[STM_VT0C
];
1143 vdd
= scmmodel
->DP
[STM_VDDMAX
];
1144 ci
= scmmodel
->DP
[STM_CAPAI
];
1145 capaie
[0] = scmmodel
->DP
[STM_CAPAI0
] ;
1146 capaie
[1] = scmmodel
->DP
[STM_CAPAI1
] ;
1147 capaie
[2] = scmmodel
->DP
[STM_CAPAI2
] ;
1148 capaie
[3] = scmmodel
->DP
[STM_CAPAI3
] ;
1154 load
= stm_modscm_dual_capaeq (scmmodel
, NULL
, f
, r
, c1
, c2
, scmmodel
->DP
[STM_THRESHOLD
], NULL
);
1157 stm_modscm_dual_fill_param( scmmodel
, f
, NULL
, driver
, load
, ¶mtiming
) ;
1159 reverse
=tpiv_inverter_config_reverse
;
1160 if (sens
=='U') t0
=tpiv_inverter_config_t0r
; else t0
=tpiv_inverter_config_t0f
;
1166 printf( " f=%.1f r=%.3g c1=%.3gfF c2=%.3gfF ci=%.3gfF\n", f
, r
, c1
, c2
, ci
);
1168 file
= fopen( fname
, "w" );
1170 perror( "can't open file " );
1177 switch( transtype
) {
1179 if( tn
->BULK
&& tn
->BULK
->SIG
) {
1180 if( ! getlosigalim( tn
->BULK
->SIG
, &vbn
) )
1183 if( tp
->BULK
&& tp
->BULK
->SIG
) {
1184 if( ! getlosigalim( tp
->BULK
->SIG
, &vbp
) )
1193 seuil1
= vdd
* SIM_VTH_HIGH
;
1194 seuil2
= vdd
* SIM_VTH_LOW
;
1197 seuil1
= vdd
* SIM_VTH_LOW
;
1198 seuil2
= vdd
* SIM_VTH_HIGH
;
1203 if( c2
>0.0 ) c2
= c2
/ 1000.0 ;
1205 stmp
= stm_solver_new_maillon();
1206 stmn
= stm_solver_new_maillon();
1208 switch( transtype
) {
1211 trtype
= TAS_TRMODEL_MCCRSAT
;
1212 trsmccn
= mcc_create_trans_mcc( tn
, vdd
, TAS_CASE
, NULL
, 0.0, 0.0 );
1213 elpLotrsGetShrinkDim( tn
, &l
, &w
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, TAS_CASE
);
1214 trsmccn
->TRWIDTH
= w
;
1215 trsmccn
->TRLENGTH
= l
;
1216 trslist
= addchain( NULL
,trsmccn
);
1217 ptl
= getptype( tn
->USER
, MBK_TRANS_PARALLEL
);
1219 for( chain
= (chain_list
*)ptl
->DATA
; chain
; chain
= chain
->NEXT
) {
1220 lotrs
= (lotrs_list
*)chain
->DATA
;
1221 if( lotrs
==tn
) continue ;
1222 trsmccn
= mcc_create_trans_mcc( lotrs
, vdd
, TAS_CASE
, NULL
, 0.0, 0.0 );
1223 elpLotrsGetShrinkDim( lotrs
, &l
, &w
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, TAS_CASE
);
1224 trsmccn
->TRWIDTH
= w
;
1225 trsmccn
->TRLENGTH
= l
;
1226 trslist
= addchain( trslist
,trsmccn
);
1229 stm_solver_add_model( stmn
,
1230 (char(*)(void*,float,float,float*))mcc_mcc_ids_list
,
1231 (char(*)(void*,float,float,float*))mcc_mcc_vds_list
,
1235 freechain( trslist
);
1237 trsmccp
= mcc_create_trans_mcc( tp
, vdd
, TAS_CASE
, NULL
, 0.0, 0.0 );
1238 elpLotrsGetShrinkDim( tp
, &l
, &w
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, TAS_CASE
);
1239 trsmccp
->TRWIDTH
= w
;
1240 trsmccp
->TRLENGTH
= l
;
1241 trslist
= addchain( NULL
, trsmccp
);
1242 ptl
= getptype( tp
->USER
, MBK_TRANS_PARALLEL
);
1244 for( chain
= (chain_list
*)ptl
->DATA
; chain
; chain
= chain
->NEXT
) {
1245 lotrs
= (lotrs_list
*)chain
->DATA
;
1246 if( lotrs
==tp
) continue ;
1247 trsmccp
= mcc_create_trans_mcc( lotrs
, vdd
, TAS_CASE
, NULL
, 0.0, 0.0 );
1248 elpLotrsGetShrinkDim( lotrs
, &l
, &w
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, TAS_CASE
);
1249 trsmccp
->TRWIDTH
= w
;
1250 trsmccp
->TRLENGTH
= l
;
1251 trslist
= addchain( trslist
,trsmccp
);
1254 stm_solver_add_model( stmp
,
1255 (char(*)(void*,float,float,float*))mcc_mcc_ids_list
,
1256 (char(*)(void*,float,float,float*))mcc_mcc_vds_list
,
1260 freechain( trslist
);
1264 trtype
= TAS_TRMODEL_SPICE
;
1265 trsspicen
= mcc_create_trans_spice( tn
, vdd
, NULL
, 0.0, 0.0 );
1266 trslist
= addchain( NULL
, trsspicen
);
1267 ptl
= getptype( tn
->USER
, MBK_TRANS_PARALLEL
);
1269 for( chain
= (chain_list
*)ptl
->DATA
; chain
; chain
= chain
->NEXT
) {
1270 lotrs
= (lotrs_list
*)chain
->DATA
;
1271 if( lotrs
==tn
) continue ;
1272 trsspicen
= mcc_create_trans_spice( lotrs
, vdd
, NULL
, 0.0, 0.0 );
1273 trslist
= addchain( trslist
, trsspicen
);
1276 stm_solver_add_model( stmn
,
1277 (char(*)(void*,float,float,float*))mcc_spice_ids_list
,
1278 (char(*)(void*,float,float,float*))mcc_spice_vds
,
1282 freechain( trslist
);
1284 trsspicep
= mcc_create_trans_spice( tp
, vdd
, NULL
, 0.0, 0.0 );
1285 trslist
= addchain( NULL
, trsspicep
);
1286 ptl
= getptype( tp
->USER
, MBK_TRANS_PARALLEL
);
1288 for( chain
= (chain_list
*)ptl
->DATA
; chain
; chain
= chain
->NEXT
) {
1289 lotrs
= (lotrs_list
*)chain
->DATA
;
1290 if( lotrs
==tp
) continue ;
1291 trsspicep
= mcc_create_trans_spice( lotrs
, vdd
, NULL
, 0.0, 0.0 );
1292 trslist
= addchain( trslist
, trsspicep
);
1295 stm_solver_add_model( stmp
,
1296 (char(*)(void*,float,float,float*))mcc_spice_ids_list
,
1297 (char(*)(void*,float,float,float*))mcc_spice_vds_list
,
1301 freechain( trslist
);
1305 fprintf( stderr
, "Bad transistor model.\n" );
1320 te
= 1e-12 * ( stm_modscm_dual_calte (vdd
-vt
, vt
, vdd
/2.0, f
) - stm_modscm_dual_calte (vdd
-vt
, vt
, 0, f
) );
1341 fprintf( file
, "# tas time origin : vt=%g, tsim=%g\n\n", vt
, dt0
+ 1e-12 * ( stm_modscm_dual_calte (vdd
-vt
, vt
, vt
, f
) - stm_modscm_dual_calte (vdd
-vt
, vt
, 0, f
) ) );
1342 fprintf( file
, "# %12s %12s %12s %12s %12s %12s %12s %12s\n\n",
1343 "T", "ve", "vs", "in", "ip", "qn", "qp", "qsat"
1350 if( paramtiming
.NTHSHRK
) {
1351 dtpwl
= stm_get_t_pwth( paramtiming
.VDDIN
, vt
, 0.0, paramtiming
.PWTHSHRK
);
1354 while( ts
< 0.0 || te
< 0.0 || ts1
< 0.0 || ts2
< 0.0 || encore
) {
1362 if( paramtiming
.NTHSHRK
)
1363 ve
= stm_get_v_pwth( t
+dtpwl
, vt
, vdd
, STM_UP
, paramtiming
.PWTHSHRK
);
1365 ve
= stm_get_v (t
, vt
, 0.0, vdd
, f
);
1367 if( ve
> vdd
/2.0 ) {
1371 while( k
<3 && ve
>= vcap
[k
] )
1376 if( paramtiming
.NTHSHRK
)
1377 ve
= stm_get_v_pwth( t
+dtpwl
, vt
, vdd
, STM_DN
, paramtiming
.PWTHSHRK
);
1379 ve
= stm_get_v (t
, vdd
-vt
, vdd
, 0.0, f
);
1381 if( ve
< vdd
/2.0 ) {
1385 while( k
<3 && ve
< vcap
[2-k
] )
1389 //ci = capaie[k]/1000.0;
1391 tas_tpiv_solver_calc_ids( stmn
, ve
, vbn
, vdd
, &isatn
, trtype
);
1392 tas_tpiv_solver_calc_ids( stmp
, (ve
-vdd
), vbp
, -vdd
, &isatp
, trtype
);
1394 rn
= tas_tpiv_solver_calc_ids( stmn
, ve
, vbn
, vs
, &in
, trtype
);
1395 rp
= tas_tpiv_solver_calc_ids( stmp
, (ve
-vdd
), vbp
, (vs
-vdd
), &ip
, trtype
);
1405 if( r
>=0.0 && c2
>= 0.0 ) {
1406 vs
= ( (-ip
)-in
+ ci
*(ve
-lve
)/dt
+ c1
*lvs
/dt
- r
*c2
*c2
*lv2
/(dt
+r
*c2
)/dt
+ c2
*lv2
/dt
) / ( c1
/dt
+ c2
/(dt
+r
*c2
));
1407 v2
= dt
/(dt
+r
*c2
)*(vs
+r
*c2
*lv2
/dt
);
1410 vs
= ( dt
* ( (-in
) - ip
) + c1
* lvs
+ ci
* ( ve
- lve
) ) / c1
;
1413 printf( "error : ve=%g vs=%g vbn=%g vbp=%g rn=%d rp=%d\n",
1414 ve
, vs
, vbn
, vbp
, rn
, rp
1422 qn
= qn
+ ( in
+ lin
) * (dt
*1.0e-12) / 2.0 ;
1423 qsatn
= qsatn
+ ( (isatn
-in
) + (lisatn
-lin
) ) * (dt
*1.0e-12) / 2.0 ;
1426 qovrn
= qovrn
+ ( in
+ lin
) * (dt
*1.0e-12) / 2.0 ;
1430 qp
= qp
+ ( ip
+ lip
) * (dt
*1.0e-12) / 2.0 ;
1431 qsatp
= qsatp
+ ( (isatp
-ip
) + (lisatp
-lip
) ) * (dt
*1.0e-12) / 2.0 ;
1434 qovrp
= qovrp
+ ( ip
+ lip
) * (dt
*1.0e-12) / 2.0 ;
1447 fprintf( file
, "%12g %12g %12g %12g %12g %12g %12g %12g\n",
1448 t
*1e-12+dt0
, ve
, vs
, in
, ip
, qn
, qp
, qsatx
1452 if ( vs
< vdd
/2.0 ) {
1469 qovr
= fabs(qovrp
) ;
1473 if ( vs
> vdd
/2.0 ) {
1490 qovr
= fabs(qovrn
) ;
1502 if( sens
=='U' ) { /* ud */
1514 fth
= stm_thr2scm( ts2
-ts1
, seuil2
/vdd
, seuil1
/vdd
, vt
, 0.0, vdd
, STM_DN
);
1516 fth
= stm_thr2scm( ts2
-ts1
, seuil1
/vdd
, seuil2
/vdd
, vt
, vdd
, vdd
, STM_UP
);
1518 printf( " -> te=%g ts=%g tp=%g\n", te
, ts
, ts
-te
);
1519 printf( " t1=%g t2=%g f=%g (fshrk=%.2f)\n", ts1
, ts2
, ts2
-ts1
, fth
);
1520 printf( " qsat = %.3gfC (%.3gfF)\n",
1521 qsat
*1.0e15
, qsat
/(vdd
/2.0)*1.0e15
);
1522 printf( " qconf = %.3gfC (%.3gfF)\n",
1523 qconf
*1.0e15
, qconf
/(vdd
/2.0)*1.0e15
);
1524 printf( " qovr(vt) = %.3gfC (%.3gfF)\n",
1525 qovr
*1.0e15
, qovr
/(vdd
/2.0)*1.0e15
1531 /************** Calcul du conflit en statique ***********/
1533 /* seuil statique */
1535 seuil
= tpiv_getseuil( stmn
, stmp
, vdd
, vbn
, vbp
, 1, trtype
);
1536 printf( " Static threshold (vin where vout=vdd/2.0) (satured) : %.3gV\n", seuil
);
1537 qn
= tpiv_getconflict( stmn
, stmp
, vdd
, vbn
, vbp
, vt
, f
, seuil
, sens
, dt
, 1, trtype
);
1538 printf( " -> Satured Qconf=%.3gfF (Cconf=%.3gfF)\n", qn
*1e15
, qn
*1e15
/(vdd
/2.0) );
1539 qn
= tpiv_getconflict( stmn
, stmp
, vdd
, vbn
, vbp
, vt
, f
, seuil
, sens
, dt
, 0, trtype
);
1540 printf( " -> Real Qconf=%.3gfF (Cconf=%.3gfF)\n", qn
*1e15
, qn
*1e15
/(vdd
/2.0) );
1542 seuil
= tpiv_getseuil( stmn
, stmp
, vdd
, vbn
, vbp
, 0, trtype
);
1543 printf( " Static threshold (vin where vout=vdd/2.0) (real) : %.3gV\n", seuil
);
1544 qn
= tpiv_getconflict( stmn
, stmp
, vdd
, vbn
, vbp
, vt
, f
, seuil
, sens
, dt
, 1, trtype
);
1545 printf( " -> Satured Qconf=%.3gfF (Cconf=%.3gfF)\n", qn
*1e15
, qn
*1e15
/(vdd
/2.0) );
1546 qn
= tpiv_getconflict( stmn
, stmp
, vdd
, vbn
, vbp
, vt
, f
, seuil
, sens
, dt
, 0, trtype
);
1547 printf( " -> Real Qconf=%.3gfF (Cconf=%.3gfF)\n", qn
*1e15
, qn
*1e15
/(vdd
/2.0) );
1551 double tpiv_getconflict( stm_solver_maillon
*stmn
, stm_solver_maillon
*stmp
, double vdd
, double vbn
, double vbp
, double vt
, double f
, double seuil
, char sens
, double dt
, char satured
, char brtype
)
1568 for( t
= 0.0 ; ( sens
== 'U' && ve
< seuil
) || ( sens
== 'D' && ve
> seuil
) ; t
= t
+ dt
) {
1571 ve
= stm_get_v( t
, vt
, 0.0, vdd
, f
);
1573 ve
= stm_get_v (t
, vt
, vdd
, 0.0, f
);
1582 vs
= tpiv_getvs( stmn
, stmp
, ve
, vbn
, vbp
, vdd
, brtype
);
1586 r
= tas_tpiv_solver_calc_ids( stmn
, ve
, vbn
, vs
, &i
, brtype
);
1588 r
= tas_tpiv_solver_calc_ids( stmp
, (ve
-vdd
), vbp
, vs
-vdd
, &i
, brtype
);
1594 q
= q
+ ( i
+ li
) * (dt
*1.0e-12) / 2.0 ;
1601 double tpiv_getvs( stm_solver_maillon
*stmn
, stm_solver_maillon
*stmp
, double ve
, double vbn
, double vbp
, double vdd
, char brtype
)
1618 vs
= (vmax
+vmin
)/2.0;
1620 rn
= tas_tpiv_solver_calc_ids( stmn
, ve
, vbn
, vs
, &in
, brtype
);
1621 rp
= tas_tpiv_solver_calc_ids( stmp
, (ve
-vdd
), vbp
, vs
-vdd
, &ip
, brtype
);
1635 if( fabs(ip
-in
)/ip
< 1e-8 )
1638 while( !stop
&& iter
);
1643 return (vmax
+vmin
)/2.0 ;
1646 double tpiv_getseuil( stm_solver_maillon
*stmn
, stm_solver_maillon
*stmp
, double vdd
, double vbn
, double vbp
, char satured
, char brtype
)
1665 ve
= (vmax
+vmin
)/2.0;
1668 rn
= tas_tpiv_solver_calc_ids( stmn
, ve
, vbn
, vdd
, &in
, brtype
);
1669 rp
= tas_tpiv_solver_calc_ids( stmp
, (ve
-vdd
), vbp
, -vdd
, &ip
, brtype
);
1672 rn
= tas_tpiv_solver_calc_ids( stmn
, ve
, vbn
, vs
, &in
, brtype
);
1673 rp
= tas_tpiv_solver_calc_ids( stmp
, (ve
-vdd
), vbp
, vs
-vdd
, &ip
, brtype
);
1688 if( fabs(ip
-in
)/ip
< 1e-8 )
1691 while( !stop
&& iter
);
1696 return (vmax
+vmin
)/2.0 ;
1699 void tpiv_carac_static( lotrs_list
*lotrs
,
1703 float vb
, /* uniquement pris en compte pour modèle spice */
1708 mcc_trans_mcc
*trsmcc
;
1709 mcc_trans_spice
*trsspi
;
1722 if( MLO_IS_TRANSP(lotrs
->TYPE
) )
1723 vbulk
= tas_getparam( lotrs
, TAS_CASE
, TP_VDDmax
);
1727 trsmcc
= mcc_create_trans_mcc( lotrs
, vdd
, TAS_CASE
, NULL
, 0.0, vbulk
);
1728 elpLotrsGetShrinkDim( lotrs
, &l
, &w
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, TAS_CASE
);
1729 trsmcc
->TRWIDTH
= w
;
1730 trsmcc
->TRLENGTH
= l
;
1732 trsspi
= mcc_create_trans_spice( lotrs
, vdd
, NULL
, 0.0, 0.0 );
1734 if (SIMUINV_PREFIX
==NULL
)
1735 sprintf( bname
, "static_%c_w=%ld_l=%ld",
1736 MLO_IS_TRANSN(lotrs
->TYPE
) ? 'n' : 'p',
1741 sprintf( bname
, "%s.%s.static_%c_w=%ld_l=%ld", SIMUINV_PREFIX
,env_SIMUINV
=='T'?"tas":"mcc",
1742 MLO_IS_TRANSN(lotrs
->TYPE
) ? 'n' : 'p',
1747 sprintf( fname
, "%s_ids=f(vds)", bname
);
1749 ptf
= mbkfopen( fname
, "dat", WRITE_TEXT
);
1757 for( j
=1 ; j
<=nj
; j
++ ) {
1759 vj
= ((float)j
)/((float)nj
) * (vgsmax
-vt
)+vt
;
1760 fprintf( ptf
, "# vgs = %g\n\n", vj
);
1762 fprintf( ptf
, "# vds imcc ispi\n\n" );
1764 for( i
=0 ; i
<=ni
; i
++ ) {
1766 vi
= ((float)i
)/((float)ni
) * vdsmax
;
1768 if( MLO_IS_TRANSN(lotrs
->TYPE
) ) {
1769 trsmcc
->VG
= vs
+vj
;
1770 //trsmcc->VB = 0.0 ;
1771 mcc_mcc_ids( trsmcc
, vs
, vs
+vi
, &imcc
);
1772 mcc_spice_ids( trsspi
, vj
, vbs
, vi
, &ispi
);
1775 trsmcc
->VG
= vs
-vj
;
1776 //trsmcc->VB = vdd ;
1777 mcc_mcc_ids( trsmcc
, vs
, vs
-vi
, &imcc
);
1778 mcc_spice_ids( trsspi
, -vj
, vbs
, -vi
, &ispi
);
1781 fprintf( ptf
, "%g %g %g\n", vi
, imcc
, ispi
);
1783 fprintf( ptf
, "\n" );
1788 sprintf( fname
, "%s_ids=f(vgs)", bname
);
1790 ptf
= mbkfopen( fname
, "dat", WRITE_TEXT
);
1797 for( j
=1 ; j
<=nj
; j
++ ) {
1799 vj
= ((float)j
)/((float)nj
) * vdsmax
;
1800 fprintf( ptf
, "# vds = %g\n\n", vj
);
1802 fprintf( ptf
, "# vgs imcc ispi\n\n" );
1804 for( i
=0 ; i
<=ni
; i
++ ) {
1806 vi
= ((float)i
)/((float)ni
)*vgsmax
;
1808 if( MLO_IS_TRANSN(lotrs
->TYPE
) ) {
1809 trsmcc
->VG
= vs
+vi
;
1810 mcc_mcc_ids( trsmcc
, vs
, vs
+vj
, &imcc
);
1811 mcc_spice_ids( trsspi
, vi
, vbs
, vj
, &ispi
);
1814 trsmcc
->VG
= vs
-vi
;
1815 mcc_mcc_ids( trsmcc
, vs
, vs
-vj
, &imcc
);
1816 mcc_spice_ids( trsspi
, -vi
, vbs
, -vj
, &ispi
);
1819 fprintf( ptf
, "%g %g %g\n", vi
, imcc
, ispi
);
1821 fprintf( ptf
, "\n" );
1826 ptf
= mbkfopen( bname
, "plt", WRITE_TEXT
);
1828 fprintf( ptf
, "set grid\n");
1829 fprintf( ptf
, "set title \"%s\"\n",MLO_IS_TRANSN(lotrs
->TYPE
)?"NMOS":"PMOS");
1830 fprintf( ptf
, "plot '%s_ids=f(vds).dat' using 1:2 title \"TAS\" with lines, '%s_ids=f(vds).dat' using 1:3 title \"MCC\" with lines\n", bname
, bname
);
1831 fprintf( ptf
, "pause -1\n" );
1832 fprintf( ptf
, "plot '%s_ids=f(vgs).dat' using 1:2 title \"TAS\" with lines, '%s_ids=f(vgs).dat' using 1:3 title \"MCC\" with lines\n", bname
, bname
);
1833 fprintf( ptf
, "pause -1\n" );
1839 void tas_tpiv_set_vg_for_switch( stm_solver_maillon
*maillon
, char brtype
, char typeactive
, float vgactive
, float vgswitch
)
1842 mcc_trans_mcc
*trsmcc
;
1843 mcc_trans_spice
*trsspi
;
1845 for( chtrs
= (chain_list
*)maillon
->MODEL_VDS
; chtrs
; chtrs
= chtrs
->NEXT
) {
1846 if( brtype
== TAS_TRMODEL_MCCRSAT
) {
1847 trsmcc
= (mcc_trans_mcc
*)chtrs
->DATA
;
1848 if( ( typeactive
== 'N' && MLO_IS_TRANSN(trsmcc
->TYPE
) ) || ( typeactive
== 'P' && MLO_IS_TRANSP(trsmcc
->TYPE
) ) )
1849 trsmcc
->VG
= vgactive
;
1851 trsmcc
->VG
= vgswitch
;
1854 trsspi
= (mcc_trans_spice
*)chtrs
->DATA
;
1855 if( ( typeactive
== 'N' && trsspi
->TRANSTYPE
== MCC_NMOS
) || ( typeactive
== 'P' && trsspi
->TRANSTYPE
== MCC_PMOS
) )
1856 trsspi
->VG
= vgactive
;
1858 trsspi
->VG
= vgswitch
;
1864 void tas_tpiv_set_vg( stm_solver_maillon
*maillon
, char brtype
, float vg
)
1867 mcc_trans_mcc
*trsmcc
;
1868 mcc_trans_spice
*trsspi
;
1870 for( chtrs
= (chain_list
*)maillon
->MODEL_VDS
; chtrs
; chtrs
= chtrs
->NEXT
) {
1871 if( brtype
== TAS_TRMODEL_MCCRSAT
) {
1872 trsmcc
= (mcc_trans_mcc
*)chtrs
->DATA
;
1876 trsspi
= (mcc_trans_spice
*)chtrs
->DATA
;
1882 void tas_tpiv_set_vb( stm_solver_maillon
*maillon
, char brtype
, float vb
)
1885 mcc_trans_mcc
*trsmcc
;
1886 mcc_trans_spice
*trsspi
;
1888 for( chtrs
= (chain_list
*)maillon
->MODEL_VDS
; chtrs
; chtrs
= chtrs
->NEXT
) {
1889 if( brtype
== TAS_TRMODEL_MCCRSAT
) {
1890 trsmcc
= (mcc_trans_mcc
*)chtrs
->DATA
;
1894 trsspi
= (mcc_trans_spice
*)chtrs
->DATA
;
1900 char tas_tpiv_solver_calc_ids( stm_solver_maillon
*maillon
, float vgs
, float vbs
, float vds
, float *ids
, char brtype
)
1902 tas_tpiv_set_vg( maillon
, brtype
, vgs
);
1903 tas_tpiv_set_vb( maillon
, brtype
, vbs
);
1904 return stm_solver_calc_ids( maillon
, 0.0, vds
, ids
);