2 * This file is part of the Alliance CAD System
3 * Copyright (C) Laboratoire LIP6 - Département ASIM
4 * Universite Pierre et Marie Curie
6 * Home page : http://www-asim.lip6.fr/alliance/
7 * E-mail support : mailto:alliance-support@asim.lip6.fr
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Library General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
14 * Alliance VLSI CAD System is distributed in the hope that it will be
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with the GNU C Library; see the file COPYING. If not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /*******************************************************************************
27 * Tool : Spice parser / driver v 7.00 *
28 * Author(s) : Gregoire AVOT *
29 * Updates : August, 17th 1998 *
31 *******************************************************************************/
33 #define SPI_MAX_COL 80
39 #include <sys/types.h>
52 #include "spi_drive.h"
55 /*static chain_list *TNMOS ;
56 static chain_list *TPMOS ;*/
57 extern char *SPI_NETNAME
;
58 int SPI_DRV_TRSPARAM
=1;
60 char SPI_COMPOSE_NAME_SEPAR
;
61 char SPI_INS_SEPAR
='.';
62 char SPI_REPLACE_INS_SEPAR
='_';
63 int SPI_LOWRESISTANCE_AS_TENSION
=0;
66 float RESIMINI
= 0.001;
68 #define SPI_NONODES (-1l)
69 #define SPI_MAXSTATICNAME 16
72 chain_list
*UNIT_LIST
=NULL
;
74 #define SPI_FULL_DRIVE 1
75 #define SPI_DRIVE_ALL 2
76 static int SPI_FLAGS
=0;
78 static mbk_options_pack_struct spice_opack
[]=
80 {"DriveInstanceParameters", SPI_FULL_DRIVE
},
81 {"IgnoreGlobalParameters", SPI_DRIVE_ALL
}
84 void (*SPI_LOCON_INODE_FUNC
)( FILE *ptf
, lofig_list
*lofig
, void *data
) = NULL
;
85 void *SPI_LOCON_INODE_DATA
= NULL
;
87 void spi_cleanextlocon( lofig_list
*lofig
)
93 for( locon
= lofig
->LOCON
; locon
; locon
= locon
->NEXT
) {
95 ptl
= getptype( losig
->USER
, SPI_EXTLOCON
);
97 losig
->USER
= delptype( losig
->USER
, SPI_EXTLOCON
);
101 locon_list
* spi_getextlocon( losig_list
*losig
)
107 if( losig
->TYPE
!= 'E' )
110 ptl
= getptype( losig
->USER
, SPI_EXTLOCON
);
112 return (locon_list
*)ptl
->DATA
;
114 ptl
= getptype( losig
->USER
, LOFIGCHAIN
);
118 for( scan
= (chain_list
*) ptl
->DATA
; scan
; scan
= scan
->NEXT
) {
119 locon
= (locon_list
*) scan
->DATA
;
120 if( locon
->TYPE
== 'E' )
127 losig
->USER
= addptype( losig
->USER
, SPI_EXTLOCON
, (void*)locon
);
131 /******************************************************************************\
133 Renvoie un pointeur sur un buffer statique contenant un nom compatible avec
134 Spice, c'est à dire sans caractère séparateur.
135 \******************************************************************************/
136 char* spi_makename( char *alc_name
)
140 static char spi_name
[1024];
142 l
= strlen( alc_name
);
143 for( i
=0 ; i
< l
; i
++ ) {
144 if( alc_name
[i
] == SEPAR
)
145 spi_name
[i
] = SPI_REPLACE_INS_SEPAR
;
147 spi_name
[i
] = alc_name
[i
];
154 char* spinamenode( losig
, node
)
158 return spinamenodedetail( losig
, node
, 0 );
161 char* spinamenodedetail( losig
, node
, force
)
167 static char names
[SPI_MAXSTATICNAME
][1024];
168 static int curnames
= 0;
176 if( curnames
== SPI_MAXSTATICNAME
)
179 if( SPI_NAMENODES
== TRUE
) {
180 if( ( node
== SPI_NONODES
|| losig
->PRCN
->NBNODE
<=2 ) && force
==0 ) {
181 if( losig
->NAMECHAIN
) {
182 strcpy( tmp
, spi_makename( getsigname(losig
) ));
184 sprintf( names
[curnames
], "%s", tmp
);
187 sprintf( names
[curnames
], "sig%ld", losig
->INDEX
);
190 strcpy( tmp
, spi_makename( getsigname(losig
) ) );
192 if( losig
->TYPE
!= 'E' ) {
193 // On choisi un noeud pour driver un nom "court". On en prend un sur
194 // sur le premier connecteur sur le signal.
195 locon
=spichooseonelocon( losig
);
196 if( locon
&& locon
->PNODE
->DATA
== node
)
197 sprintf( names
[curnames
], "%s", tmp
);
199 sprintf( names
[curnames
],
202 SPI_COMPOSE_NAME_SEPAR
,
207 else { // signal externe : on ne change pas le noeud sur l'interface.
208 locon
= spi_getextlocon( losig
);
209 if( locon
&& locon
->PNODE
&& locon
->PNODE
->DATA
==node
) {
210 sprintf( names
[curnames
], "%s", tmp
);
213 sprintf( names
[curnames
],
216 SPI_COMPOSE_NAME_SEPAR
,
224 ptptype
= getptype( losig
->USER
, SPI_DRIVER_PTYPE
);
225 cvx
= (convindex
*)(ptptype
->DATA
);
226 if( node
== SPI_NONODES
)
227 sprintf( names
[curnames
], "%d", cvx
->premier
);
229 sprintf( names
[curnames
], "%ld", cvx
->premier
+ node
- 1 );
232 return( names
[curnames
] );
235 char *spi_gettransname(type
)
240 if(MLO_IS_TRANSN(type
))
242 else if (MLO_IS_TRANSP(type
))
247 if (!chain
) avt_errmsg(SPI_ERRMSG
, "081", AVT_FATAL
);
249 return((char *)chain
->DATA
) ;
252 int getanode(losig_list
*signal
)
254 if (signal
->PRCN
==NULL
) return 0;
255 if (signal
->PRCN
->PWIRE
!=NULL
) return signal
->PRCN
->PWIRE
->NODE1
;
256 if (signal
->PRCN
->PCTC
!=NULL
)
258 loctc_list
*tmp
=(loctc_list
*)signal
->PRCN
->PCTC
->DATA
;
259 if (tmp
->SIG1
==signal
) return tmp
->NODE1
;
260 if (tmp
->SIG2
==signal
) return tmp
->NODE2
;
265 void cherche_alim( ptfig
, vdd
, vss
)
273 static char stvss
[1024], stvdd
[1024];
278 for( scancon
= ptfig
->LOCON
;
279 scancon
&& !(*vdd
&& *vss
) ;
280 scancon
= scancon
->NEXT
283 if( mbk_LosigIsVDD( scancon
->SIG
) )
285 signal
= scancon
->SIG
;
288 strcpy( stvdd
, spinamenode( signal
, scancon
->PNODE
->DATA
) );
290 strcpy( stvdd
, spinamenode( signal
, SPI_NONODES
) );
295 if( mbk_LosigIsVSS( scancon
->SIG
) )
297 signal
= scancon
->SIG
;
300 strcpy( stvss
, spinamenode( signal
, scancon
->PNODE
->DATA
) );
302 strcpy( stvss
, spinamenode( signal
, SPI_NONODES
) );
308 // zinaps le 20/8/2002
309 for( signal
= ptfig
->LOSIG
;
310 signal
&& !(*vdd
&& *vss
) ;
311 signal
= signal
->NEXT
314 if(mbk_LosigIsVDD(signal
))
316 if((node
=getanode(signal
))!=0)
317 strcpy( stvdd
, spinamenode( signal
, node
) );
319 strcpy( stvdd
, spinamenode( signal
, SPI_NONODES
) );
323 if(mbk_LosigIsVSS(signal
))
325 if((node
=getanode(signal
))!=0)
326 strcpy( stvss
, spinamenode( signal
, node
) );
328 strcpy( stvss
, spinamenode( signal
, SPI_NONODES
) );
334 void sortrcn( ptfig
, df
, vss
)
339 losig_list
*scanlosig
;
341 lowire_list
*scanlowire
;
343 // chain_list *scanchain;
348 lonode_list
*ptnode1
;
349 lonode_list
*ptnode2
;
350 static char drivewirenotconnected
='u';
356 if( drivewirenotconnected
=='u' ) {
358 /* variable temporaire permettant de contourner le bug de sim qui
359 drive des netlists avec des noeuds connectés à un seul wire, ce
360 qui n'est pas supporté par titan. solution bourrin car ca ne prend
361 pas en compte un ensemble de résistances arrivant nul part. */
363 env
= NULL
; //getenv("MBK_SPI_DRIVE_WIRE_NOT_CONNECTED");
365 if( strcasecmp( env
, "yes" )==0 )
366 drivewirenotconnected
= 'y';
367 if( strcasecmp( env
, "no" )==0 )
368 drivewirenotconnected
= 'n';
370 if( drivewirenotconnected
== 'u' )
371 drivewirenotconnected
= 'y' ; // défaut.
375 cachemode
=rcn_hascache(ptfig
);
377 for( scanlosig
= ptfig
->LOSIG
; scanlosig
; scanlosig
= scanlosig
->NEXT
)
379 if( !scanlosig
->PRCN
)
382 if (cachemode
&& (mbk_LosigIsVDD(scanlosig
) || mbk_LosigIsVSS(scanlosig
))) continue;
384 rcn_lock_signal(ptfig
, scanlosig
);
386 if( scanlosig
->PRCN
->PWIRE
|| scanlosig
->PRCN
->PCTC
)
391 for( scanlowire
= scanlosig
->PRCN
->PWIRE
;
393 scanlowire
= scanlowire
->NEXT
)
395 resival
=scanlowire
->RESI
;
397 if( drivewirenotconnected
== 'n' ) {
398 ptnode1
= getlonode( scanlosig
, scanlowire
->NODE1
);
399 ptnode2
= getlonode( scanlosig
, scanlowire
->NODE2
);
401 /* Teste si cette resistance est connectée à quelque chose. */
402 if( RCN_GETFLAG( ptnode1
->FLAG
, RCN_FLAG_ONE
) &&
403 !RCN_GETFLAG( ptnode1
->FLAG
, RCN_FLAG_LOCON
) &&
404 scanlowire
->CAPA
== 0.0 &&
408 if( RCN_GETFLAG( ptnode2
->FLAG
, RCN_FLAG_ONE
) &&
409 !RCN_GETFLAG( ptnode2
->FLAG
, RCN_FLAG_LOCON
) &&
410 scanlowire
->CAPA
== 0.0 &&
416 if (resival
<RESIMINI
) resival
=RESIMINI
;
417 if (SPI_LOWRESISTANCE_AS_TENSION
==0)
419 if ((pt
=getptype(scanlowire
->USER
, RESINAME
))!=NULL
)
420 strcpy(siname
, spi_makename((char *)pt
->DATA
));
422 sprintf(siname
, "%ld_%d",scanlosig
->INDEX
, nbr
);
426 spinamenode( scanlosig
, scanlowire
->NODE1
),
427 spinamenode( scanlosig
, scanlowire
->NODE2
),
437 spinamenode( scanlosig
, scanlowire
->NODE1
),
438 spinamenode( scanlosig
, scanlowire
->NODE2
)
442 /* HSpice ne supporte pas 1e-6P : Il ne prendra pas en compte le P, et
443 * on aura 1 micron au lieu de 1e-18. */
445 if( scanlowire
->CAPA
!=0 && scanlowire
->CAPA
/ 2.0 >= CAPAMINI
)
448 "C%d_%d1 %s %s %g\n",
451 spinamenode( scanlosig
, scanlowire
->NODE1
),
453 (scanlowire
->CAPA
/ 2.0) * 1e-12
457 "C%d_%d2 %s %s %g\n",
460 spinamenode( scanlosig
, scanlowire
->NODE2
),
462 (scanlowire
->CAPA
/ 2.0) * 1e-12
469 spi_print( df
, "\n" );
471 for (headctc
=scanlosig
->PRCN
->PCTC
, cnt
=0; headctc
!=NULL
; headctc
=headctc
->NEXT
)
473 ptctc
=(loctc_list
*)headctc
->DATA
;
474 if (rcn_capacitancetooutput(cachemode
, scanlosig
, ptctc
))
476 if( ptctc
->CAPA
>= CAPAMINI
)
478 name1
= spinamenode( ptctc
->SIG1
, ptctc
->NODE1
> 0 ? ptctc
->NODE1
: SPI_NONODES
);
479 name2
= spinamenode( ptctc
->SIG2
, ptctc
->NODE2
> 0 ? ptctc
->NODE2
: SPI_NONODES
);
481 if (mbk_LosigIsVSS( ptctc
->SIG1
) || mbk_LosigIsVSS( ptctc
->SIG2
) )
483 if ((pt
=getptype(ptctc
->USER
, MSL_CAPANAME
))!=NULL
)
484 strcpy(siname
, spi_makename((char *)pt
->DATA
));
486 sprintf(siname
, "%d",nbctc
);
487 spi_print( df
, "C%s %s %s %g\n", siname
, name1
, name2
, ptctc
->CAPA
* 1e-12);
491 if ((pt
=getptype(ptctc
->USER
, MSL_CAPANAME
))!=NULL
)
492 strcpy(siname
, spi_makename((char *)pt
->DATA
));
494 sprintf(siname
, "_ctc_%d",nbctc
);
495 spi_print( df
, "C%s %s %s %g\n", siname
, name1
, name2
, ptctc
->CAPA
* 1e-12 );
505 spi_print( df
, "\n" );
508 /* On ne sort la capa totale que si on a ni RCN, ni CTC */
510 if( !scanlosig
->PRCN
->PWIRE
&& !scanlosig
->PRCN
->PCTC
)
512 if( rcn_getcapa( ptfig
,scanlosig
) >= CAPAMINI
)
517 spinamenode( scanlosig
, SPI_NONODES
),
519 rcn_getcapa( ptfig
,scanlosig
) * 1e-12
523 //spi_print( df, "\n" );
524 rcn_unlock_signal(ptfig
, scanlosig
);
527 headctc
= getallctc( ptfig
);
529 for( scanchain
= headctc
; scanchain
; scanchain
= scanchain
->NEXT
)
531 ptctc
= (loctc_list
*)scanchain
->DATA
;
533 if( ptctc
->CAPA
>= CAPAMINI
)
535 name1
= spinamenode( ptctc
->SIG1
, ptctc
->NODE1
> 0 ? ptctc
->NODE1
: SPI_NONODES
);
536 name2
= spinamenode( ptctc
->SIG2
, ptctc
->NODE2
> 0 ? ptctc
->NODE2
: SPI_NONODES
);
537 if (mbk_LosigIsVSS( ptctc
->SIG1
) || mbk_LosigIsVSS( ptctc
->SIG2
) )
538 spi_print( df
, "C%d %s %s %g\n", nbctc
, name1
, name2
, ptctc
->CAPA
* 1e-12 );
540 spi_print( df
, "C_ctc_%d %s %s %g\n", nbctc
, name1
, name2
, ptctc
->CAPA
* 1e-12 );
546 freechain( headctc
);
550 void signalnoeud( ptfig
)
553 losig_list
*scanlosig
;
559 for( scanlosig
= ptfig
-> LOSIG
; scanlosig
; scanlosig
= scanlosig
->NEXT
)
561 nouveau
= ( convindex
* ) mbkalloc( sizeof( convindex
) );
562 nouveau
->sig
= scanlosig
;
563 nouveau
->premier
= dernier
;
565 /* Evaluation de gauche à droite */
566 if( scanlosig
->PRCN
&& scanlosig
->PRCN
->NBNODE
> 0 )
567 dernier
+= scanlosig
->PRCN
->NBNODE
;
571 scanlosig
->USER
= addptype( scanlosig
->USER
, SPI_DRIVER_PTYPE
, nouveau
);
575 void freesignalnoeud( lofig_list
*ptfig
)
577 losig_list
*scanlosig
;
580 for( scanlosig
= ptfig
-> LOSIG
; scanlosig
; scanlosig
= scanlosig
->NEXT
)
582 if ((pt
=getptype(scanlosig
->USER
, SPI_DRIVER_PTYPE
))!=NULL
)
585 scanlosig
->USER
= delptype( scanlosig
->USER
, SPI_DRIVER_PTYPE
);
592 void sortconnecteur( df
, c
)
597 num_list
*tetenum
,*scannum
;
604 tetenum
= spi_getinode( c
);
612 for( scannum
= tetenum
; scannum
; scannum
= scannum
->NEXT
)
613 spi_print( df
, "%s ", spinamenodedetail( signal
, scannum
->DATA
, force
) );
617 tetenum
= spi_getinode( c
);
619 spi_print( df
, "%s ", spinamenode( signal
, SPI_NONODES
) );
621 for( scannum
= tetenum
; scannum
; scannum
= scannum
->NEXT
)
623 spi_print( df
, "%s ", spinamenodedetail( signal
, scannum
->DATA
, 1) );
629 void sortconnecteur_ordre( df
, ordre
, liste
)
634 chain_list
*scanordre
;
635 locon_list
*scanlocon
;
638 chain_list
*cpteordre
;
641 convindex
*noeudbase
;
646 for( scanordre
= ordre
; scanordre
; scanordre
= scanordre
->NEXT
)
648 for( scanlocon
= liste
; scanlocon
; scanlocon
= scanlocon
->NEXT
)
649 if( scanlocon
->NAME
== ((char*)(scanordre
->DATA
)) )
652 if( !scanlocon
) avt_errmsg (SPI_ERRMSG
, "005", AVT_FATAL
);
655 for( cpteordre
= ordre
;
656 cpteordre
!= scanordre
;
657 cpteordre
= cpteordre
->NEXT
659 if( ((char*)(cpteordre
->DATA
)) == scanlocon
->NAME
)
662 signal
= scanlocon
->SIG
;
663 pt
= getptype( signal
->USER
, SPI_DRIVER_PTYPE
);
664 noeudbase
= (convindex
*)(pt
->DATA
);
666 if( scanlocon
->PNODE
)
668 tetenum
= spi_getinode( scanlocon
);
670 tetenum
= scanlocon
->PNODE
;
676 for( scannum
= tetenum
, n
=0 ; n
<num
&& scannum
!=NULL
; scannum
= scannum
->NEXT
, n
++ );
677 if (scannum
!=NULL
&& n
<=num
)
678 spi_print( df
, "%s ", spinamenodedetail( signal
, scannum
->DATA
, force
) );
679 else // zinaps : 25/4/2003
680 spi_print( df
, "%s ", spinamenode( signal
, SPI_NONODES
) );
684 spi_print( df
, "%s ", spinamenode( signal
, SPI_NONODES
) );
688 void sortnet( ptfig
, df
)
692 losig_list
*scanlosig
;
693 locon_list
*scanlocon
;
694 chain_list
*scanchain
;
697 tableint
*noeudunique
;
699 lowire_list
*scanlowire
;
704 for( scanlosig
= ptfig
->LOSIG
; scanlosig
; scanlosig
= scanlosig
->NEXT
)
706 if ( ( scanlosig
->NAMECHAIN
) ||
707 ( scanlosig
->TYPE
== EXTERNAL
) )
709 ptl
= getptype(scanlosig
->USER
,SPI_DRIVER_PTYPE
);
710 conv
= (convindex
*)(ptl
->DATA
);
712 spi_print( df
, "* %s ", SPI_NETNAME
);
714 /* Evaluation de gauche à droite */
715 if( scanlosig
->PRCN
&& scanlosig
->PRCN
->NBNODE
> 1 )
717 noeudunique
= creattableint();
719 for( scanlowire
= scanlosig
->PRCN
->PWIRE
;
721 scanlowire
= scanlowire
->NEXT
724 settableint( noeudunique
, scanlowire
->NODE1
, (void*)1 );
725 settableint( noeudunique
, scanlowire
->NODE2
, (void*)1 );
728 for( scanchain
= scanlosig
->PRCN
->PCTC
;
730 scanchain
= scanchain
->NEXT
733 ptctc
= (loctc_list
*)scanchain
->DATA
;
735 settableint( noeudunique
, ptctc
->NODE1
, (void*)1 );
737 settableint( noeudunique
, ptctc
->NODE2
, (void*)1 );
740 ptl
= getptype( scanlosig
->USER
, LOFIGCHAIN
);
744 fprintf( stderr
, "*** spi error *** : LOFIGCHAIN missing.\n" );
748 for( scanchain
= (chain_list
*)(ptl
->DATA
) ;
750 scanchain
= scanchain
->NEXT
753 for( scannum
= ((locon_list
*)(scanchain
->DATA
))->PNODE
;
755 scannum
= scannum
->NEXT
757 settableint( noeudunique
, scannum
->DATA
, (void*)1 );
762 while( (i = scanint( noeudunique, i ) ) )
763 tooutput( df, "%d ", i + conv->premier - 1 );
765 /* On ne sort qu'un seul noeud */
766 i
= scanint( noeudunique
, i
);
767 spi_print( df
, "%d ", i
+ conv
->premier
- 1 );
769 freetableint( noeudunique
);
772 spi_print( df
, "%d ", conv
->premier
);
774 spi_print( df
, "= " );
777 for( scanchain = scanlosig->NAMECHAIN ;
779 scanchain=scanchain->NEXT
783 if(scanlosig
->TYPE
== EXTERNAL
)
785 for(scanlocon
= ptfig
->LOCON
; scanlocon
!= NULL
&&
786 scanlocon
->SIG
!= scanlosig
;
787 scanlocon
= scanlocon
->NEXT
)
789 if(scanlocon
== NULL
)
792 fprintf( stderr
, "*** spi error *** : LOFIGCHAIN missing.\n" );
796 strcpy( v
, scanlocon
->NAME
);
798 spi_print( df
, "%s ", v
);
802 scanchain
= scanlosig
->NAMECHAIN
;
804 strcpy( v
, (char*)(scanchain
->DATA
) );
806 spi_print( df
, "%s ", v
);
810 spi_print( df
, "\n" );
816 void sort_unlinked_net( lofig_list
*ptfig
, FILE *df
)
818 losig_list
*scanlosig
;
822 for( scanlosig
= ptfig
->LOSIG
; scanlosig
; scanlosig
= scanlosig
->NEXT
)
824 ptl
=getptype(scanlosig
->USER
, LOFIGCHAIN
);
825 cl
=(chain_list
*)ptl
->DATA
;
826 if ( cl
==NULL
&& scanlosig
->NAMECHAIN
)
828 spi_print( df
, "* |UNCONNECTED_NET %s\n", spinamenode( scanlosig
, SPI_NONODES
));
833 void sortinstance( ptfig
, df
)
837 loins_list
*scanloins
;
838 locon_list
*scanloconins
;
844 if (SPI_FLAGS
& SPI_FULL_DRIVE
)
846 globparam
=addht(2048);
847 if (MBK_GLOBALPARAMS
!=NULL
)
849 for (i
=0; i
<MBK_GLOBALPARAMS
->NUMBER
; i
++)
850 addhtitem(globparam
, MBK_GLOBALPARAMS
->EBI
[i
].NAME
, 0);
854 for( scanloins
= ptfig
->LOINS
; scanloins
; scanloins
= scanloins
->NEXT
)
856 spi_print( df
, "x%s ", scanloins
->INSNAME
);
858 /* L'ordre des connecteurs entre la lofig et sa version instanciée n'est
861 pt
= getptype( scanloins
->USER
, PH_INTERF
);
863 sortconnecteur_ordre( df
,
864 (chain_list
*)(pt
->DATA
),
868 for( scanloconins
= scanloins
->LOCON
;
870 scanloconins
= scanloconins
->NEXT
872 sortconnecteur( df
, scanloconins
);
874 spi_print( df
, "%s", scanloins
->FIGNAME
);
877 if (SPI_FLAGS
& SPI_FULL_DRIVE
)
879 optparam_list
*optparams
, *ptopt
;
880 // drive les parametres des instances
881 if ((pt
= getptype (scanloins
->USER
, PARAM_CONTEXT
))!=NULL
)
883 ep
=(eqt_param
*)pt
->DATA
;
884 for (i
=0; i
<ep
->NUMBER
; i
++)
886 if ((SPI_FLAGS
& SPI_DRIVE_ALL
)!=0 || ((SPI_FLAGS
& SPI_DRIVE_ALL
)==0 && gethtitem(globparam
, ep
->EBI
[i
].NAME
)==EMPTYHT
))
887 spi_print( df
, " %s=%g", ep
->EBI
[i
].NAME
, ep
->EBI
[i
].VAL
);
891 if ((pt
= getptype (scanloins
->USER
, OPT_PARAMS
))) {
892 optparams
= (optparam_list
*) pt
->DATA
;
894 for (ptopt
= optparams
; ptopt
; ptopt
= ptopt
->NEXT
) {
895 if (ptopt
->TAG
== '$') {
896 spi_print( df
, " %s='%s'", ptopt
->UNAME
.SPECIAL
, ptopt
->UDATA
.EXPR
);
899 spi_print( df
, " %s=%g", ptopt
->UNAME
.SPECIAL
, ptopt
->UDATA
.VALUE
);
905 spi_print( df
, "\n");
908 if (SPI_FLAGS
& SPI_FULL_DRIVE
) delht(globparam
);
911 /* param doit etre en minuscule */
912 static float getbaseunit(lofig_list
*lf
, char *param
)
916 sprintf(temp
," %s ",param
);
917 for (cl
=UNIT_LIST
; cl
!=NULL
; cl
=cl
->NEXT
)
920 if (strstr(c
,temp
)!=NULL
&& (c
=strchr(c
,':'))!=NULL
)
930 static char *modelname(lotrs_list
*tr
, int in_SPI_TRANSISTOR_AS_INSTANCE
)
932 char *subcktname
=NULL
, *modelname
;
936 return spi_gettransname(tr
->TYPE
);
938 modelname
=getlotrsmodel(tr
);
940 if ( in_SPI_TRANSISTOR_AS_INSTANCE
)
942 if (( ptype
= getptype ( tr
->USER
, TRANS_FIGURE
)))
943 subcktname
= (char*)ptype
->DATA
;
945 subcktname
= mcc_getsubckt( MCC_MODELFILE
, modelname
,
946 MLO_IS_TRANSN(tr
->TYPE
)?MCC_NMOS
:MCC_PMOS
,
947 MCC_TYPICAL
, ((float)tr
->LENGTH
/SCALE_X
)*1.0e-6,
948 ((float)tr
->WIDTH
/SCALE_X
)*1.0e-6);
951 if (subcktname
==NULL
) return modelname
;
957 // zinaps: le 27/9/2002
958 static char *strip(char *name
)
960 static char temp
[1024];
962 for (i
=0, j
=0;name
[i
]!='\0';i
++)
964 if (name
[i
]!='*') temp
[j
++]=name
[i
];
970 static float bestunit(float val
, char **unit
)
972 if (val
<1e3
) { *unit
="U"; return val
; }
973 // if (val<1e6) { *unit='m'; return val*1e-6; }
974 *unit
=""; return val
*1e-6;
977 #define DONE_W 0x00000001
978 #define DONE_L 0x00000002
979 #define DONE_AS 0x00000004
980 #define DONE_AD 0x00000008
981 #define DONE_PS 0x00000010
982 #define DONE_PD 0x00000020
983 #define DONE_NRS 0x00000040
984 #define DONE_NRD 0x00000080
985 #define DONE_DELVTO 0x00000100
986 #define DONE_SA 0x00000200
987 #define DONE_SB 0x00000400
988 #define DONE_SD 0x00000800
989 #define DONE_NF 0x00001000
990 #define DONE_GEOMOD 0x00002000
991 #define DONE_MULUO 0x00004000
992 #define DONE_M 0x00008000
993 #define DONE_SC 0x00010000
994 #define DONE_SCA 0x00020000
995 #define DONE_SCB 0x00040000
996 #define DONE_SCC 0x00080000
997 #define DONE_ABSOURCE 0x00100000
998 #define DONE_LSSOURCE 0x00200000
999 #define DONE_LGSOURCE 0x00400000
1000 #define DONE_ABDRAIN 0x00800000
1001 #define DONE_LSDRAIN 0x01000000
1002 #define DONE_LGDRAIN 0x02000000
1004 void sorttransistormos(lofig_list
*ptfig
, FILE *df
, char *vss
, char *vdd
)
1006 lotrs_list
*scantrs
;
1009 char name
[1024], *ptr
, tag
;
1010 char *alim
, *modname
, *paramname
;
1011 int isdiode
, isjfet
;
1012 float w_unit
, l_unit
, as_unit
, ad_unit
, ps_unit
, pd_unit
, val
;
1013 double delvt0
,mulu0
;
1015 double sca
,scb
,scc
,sc
;
1019 double absource
, lssource
, lgsource
;
1020 double abdrain
, lsdrain
, lgdrain
;
1021 int status
, done
, in_SPI_TRANSISTOR_AS_INSTANCE
;
1024 if ((w_unit
=getbaseunit(ptfig
, "w"))==0) w_unit
=1;
1025 if ((l_unit
=getbaseunit(ptfig
, "l"))==0) l_unit
=1;
1026 if ((as_unit
=getbaseunit(ptfig
, "as"))==0) as_unit
=1;
1027 if ((ad_unit
=getbaseunit(ptfig
, "ad"))==0) ad_unit
=1;
1028 if ((ps_unit
=getbaseunit(ptfig
, "ps"))==0) ps_unit
=1;
1029 if ((pd_unit
=getbaseunit(ptfig
, "pd"))==0) pd_unit
=1;
1031 for( scantrs
= ptfig
->LOTRS
, nb
=1 ; scantrs
; scantrs
= scantrs
->NEXT
, nb
++ );
1037 for( scantrs
= ptfig
->LOTRS
; scantrs
; scantrs
= scantrs
->NEXT
)
1040 modname
= getlotrsmodel(scantrs
);
1041 isdiode
= 0; //(mbk_isdioden(modname) || mbk_isdiodep(modname));
1042 isjfet
= (mbk_isjfetn(modname
) || mbk_isjfetp(modname
));
1043 if (V_INT_TAB
[__SIM_TRANSISTOR_AS_INSTANCE
].VALUE
==2)
1046 if (( ptype
= getptype ( scantrs
->USER
, TRANS_FIGURE
))!=NULL
)
1047 in_SPI_TRANSISTOR_AS_INSTANCE
=1;
1049 in_SPI_TRANSISTOR_AS_INSTANCE
=0;
1051 else in_SPI_TRANSISTOR_AS_INSTANCE
=V_INT_TAB
[__SIM_TRANSISTOR_AS_INSTANCE
].VALUE
;
1053 if( scantrs
->TRNAME
)
1055 if( gethtitem( trname
, scantrs
->TRNAME
) != EMPTYHT
)
1060 sprintf( name
, "%s_%d", scantrs
->TRNAME
, nb
);
1061 ptr
= namealloc( name
);
1063 while( gethtitem( trname
, ptr
) != EMPTYHT
);
1064 addhtitem( trname
, ptr
, 1 );
1066 spi_print( df
, "D%s ", spi_makename(name
) );
1068 spi_print( df
, "J%s ", spi_makename(name
) );
1069 else if (!in_SPI_TRANSISTOR_AS_INSTANCE
)
1070 spi_print( df
, "M%s ", spi_makename(name
) );
1072 spi_print( df
, "XM%s ", spi_makename(name
) );
1077 spi_print( df
, "D%s ", spi_makename(scantrs
->TRNAME
) );
1079 spi_print( df
, "J%s ", spi_makename(scantrs
->TRNAME
) );
1080 else if (!in_SPI_TRANSISTOR_AS_INSTANCE
)
1081 spi_print( df
, "M%s ", spi_makename(scantrs
->TRNAME
) );
1083 spi_print( df
, "XM%s ", spi_makename(scantrs
->TRNAME
) );
1084 addhtitem( trname
, scantrs
->TRNAME
, 1 );
1092 sprintf( name
, "%d", nb
);
1093 ptr
= namealloc( name
);
1095 while( gethtitem( trname
, ptr
) != EMPTYHT
);
1097 spi_print( df
, "D%s ", spi_makename(name
) );
1099 spi_print( df
, "J%s ", spi_makename(name
) );
1100 else if (!in_SPI_TRANSISTOR_AS_INSTANCE
)
1101 spi_print( df
, "M%s ", spi_makename(name
) );
1103 spi_print( df
, "XM%s ", spi_makename(name
) );
1104 addhtitem( trname
, ptr
, 1 );
1108 if (mbk_isdioden(modname
))
1110 sortconnecteur( df
, scantrs
->GRID
);
1111 sortconnecteur( df
, scantrs
->DRAIN
);
1115 sortconnecteur( df
, scantrs
->DRAIN
);
1116 sortconnecteur( df
, scantrs
->GRID
);
1118 spi_print( df
, "%s ", modname
);
1119 if( scantrs
->XD
!= 0 && scantrs
->PD
!= 0 )
1120 spi_print( df
, "AREA=%gP ", (float) scantrs
->XD
* scantrs
->PD
/ ( 4 * SCALE_X
* SCALE_X
) );
1121 if( scantrs
->PD
!= 0 )
1122 spi_print( df
, "PERI=%gU ", (float)scantrs
->PD
/SCALE_X
);
1126 sortconnecteur( df
, scantrs
->DRAIN
);
1127 sortconnecteur( df
, scantrs
->GRID
);
1128 sortconnecteur( df
, scantrs
->SOURCE
);
1129 spi_print( df
, "%s ", modname
);
1133 sortconnecteur( df
, scantrs
->DRAIN
);
1134 sortconnecteur( df
, scantrs
->GRID
);
1135 sortconnecteur( df
, scantrs
->SOURCE
);
1136 // zinaps le 20/8/2002
1137 if( scantrs
->BULK
&& scantrs
->BULK
->SIG
)
1139 sortconnecteur( df
, scantrs
->BULK
);
1140 modname
=modelname(scantrs
, in_SPI_TRANSISTOR_AS_INSTANCE
);
1141 spi_print( df
, "%s ", modname
);
1145 if (MLO_IS_TRANSN(scantrs
->TYPE
))
1147 if( !vss
) alim
=strip(VSS
); else alim
=vss
;
1148 modname
=modelname(scantrs
, in_SPI_TRANSISTOR_AS_INSTANCE
);
1149 spi_print( df
, "%s %s ", alim
, modname
);
1153 if( !vdd
) alim
=strip(VDD
); else alim
=vdd
;
1154 modname
=modelname(scantrs
, in_SPI_TRANSISTOR_AS_INSTANCE
);
1155 spi_print( df
, "%s %s ", alim
, modname
);
1158 if (!in_SPI_TRANSISTOR_AS_INSTANCE
)
1160 if(scantrs
->LENGTH
!=0)
1162 if (l_unit
!=1 || !V_BOOL_TAB
[__SPI_DRIVE_USE_UNITS
].VALUE
)
1163 spi_print( df
, "L=%g ", ((float)scantrs
->LENGTH
/SCALE_X
)*1e-6/l_unit
);
1166 val
=bestunit((float)scantrs
->LENGTH
/SCALE_X
, &ptr
);
1167 spi_print( df
, "L=%g%s ", val
, ptr
);
1172 if(scantrs
->WIDTH
!=0)
1174 if (w_unit
!=1 || !V_BOOL_TAB
[__SPI_DRIVE_USE_UNITS
].VALUE
)
1175 spi_print( df
, "W=%g ", ((float)scantrs
->WIDTH
/SCALE_X
)*1e-6/w_unit
);
1178 val
=bestunit((float)scantrs
->WIDTH
/SCALE_X
, &ptr
);
1179 spi_print( df
, "W=%g%s ", val
, ptr
);
1184 if( scantrs
->XS
>= 0 )
1186 if (as_unit
!=1 || !V_BOOL_TAB
[__SPI_DRIVE_USE_UNITS
].VALUE
)
1189 ((float) scantrs
->XS
* scantrs
->WIDTH
/ ( SCALE_X
* SCALE_X
))*1e-12/as_unit
1194 (float) scantrs
->XS
* scantrs
->WIDTH
/ ( SCALE_X
* SCALE_X
)
1199 if( scantrs
->XD
>= 0 )
1201 if (ad_unit
!=1 || !V_BOOL_TAB
[__SPI_DRIVE_USE_UNITS
].VALUE
)
1204 ((float) scantrs
->XD
* scantrs
->WIDTH
/ ( SCALE_X
* SCALE_X
))*1e-12/ad_unit
1209 (float) scantrs
->XD
* scantrs
->WIDTH
/ ( SCALE_X
* SCALE_X
)
1213 if( scantrs
->PS
>= 0 )
1215 if (ps_unit
!=1 || !V_BOOL_TAB
[__SPI_DRIVE_USE_UNITS
].VALUE
)
1216 spi_print( df
, "PS=%g ", ((float)scantrs
->PS
/SCALE_X
)*1e-6/ps_unit
);
1218 spi_print( df
, "PS=%gU ", (float)scantrs
->PS
/SCALE_X
);
1222 if( scantrs
->PD
>= 0 )
1224 if (pd_unit
!=1 || !V_BOOL_TAB
[__SPI_DRIVE_USE_UNITS
].VALUE
)
1225 spi_print( df
, "PD=%g ", ((float)scantrs
->PD
/SCALE_X
)*1e-6/pd_unit
);
1227 spi_print( df
, "PD=%gU ", (float)scantrs
->PD
/SCALE_X
);
1231 if ( SPI_DRV_TRSPARAM
)
1233 nrs
= getlotrsparam (scantrs
,MBK_NRS
,NULL
,&status
);
1235 spi_print( df
, "nrs=%g ",nrs
);
1236 done
= done
| DONE_NRS
;
1239 nrd
= getlotrsparam (scantrs
,MBK_NRD
,NULL
,&status
);
1241 spi_print( df
, "nrd=%g ",nrd
);
1242 done
= done
| DONE_NRD
;
1245 mulu0
= getlotrsparam (scantrs
,MBK_MULU0
,NULL
,&status
);
1247 spi_print( df
, "mulu0=%g ",mulu0
);
1248 done
= done
| DONE_MULUO
;
1251 delvt0
= getlotrsparam (scantrs
,MBK_DELVT0
,NULL
,&status
);
1253 spi_print( df
, "delvto=%g ",delvt0
);
1254 done
= done
| DONE_DELVTO
;
1257 sa
= getlotrsparam (scantrs
,MBK_SA
,NULL
,&status
);
1259 spi_print( df
, "sa=%g ",sa
);
1260 done
= done
| DONE_SA
;
1263 sb
= getlotrsparam (scantrs
,MBK_SB
,NULL
,&status
);
1265 spi_print( df
, "sb=%g ",sb
);
1266 done
= done
| DONE_SB
;
1269 sd
= getlotrsparam (scantrs
,MBK_SD
,NULL
,&status
);
1271 spi_print( df
, "sd=%g ",sd
);
1272 done
= done
| DONE_SD
;
1275 nf
= getlotrsparam (scantrs
,MBK_NF
,NULL
,&status
);
1277 spi_print( df
, "nf=%g ",nf
);
1278 done
= done
| DONE_NF
;
1281 nfing
= getlotrsparam (scantrs
,MBK_NFING
,NULL
,&status
);
1283 spi_print( df
, "nfing=%g ",nfing
);
1284 done
= done
| DONE_NF
;
1287 m
= getlotrsparam (scantrs
,MBK_M
,NULL
,&status
);
1289 spi_print( df
, "m=%g ",m
);
1290 done
= done
| DONE_M
;
1293 geomod
= getlotrsparam (scantrs
,MBK_GEOMOD
,NULL
,&status
);
1295 spi_print( df
, "geomod=%g ",geomod
);
1296 done
= done
| DONE_GEOMOD
;
1299 sc
= getlotrsparam (scantrs
,MBK_SC
,NULL
,&status
);
1301 spi_print( df
, "sc=%g ",sc
);
1302 done
= done
| DONE_SC
;
1305 sca
= getlotrsparam (scantrs
,MBK_SCA
,NULL
,&status
);
1307 spi_print( df
, "sca=%g ",sca
);
1308 done
= done
| DONE_SCA
;
1311 scb
= getlotrsparam (scantrs
,MBK_SCB
,NULL
,&status
);
1313 spi_print( df
, "scb=%g ",scb
);
1314 done
= done
| DONE_SCB
;
1317 scc
= getlotrsparam (scantrs
,MBK_SCC
,NULL
,&status
);
1319 spi_print( df
, "scc=%g ",scc
);
1320 done
= done
| DONE_SCC
;
1323 absource
= getlotrsparam (scantrs
,MBK_ABSOURCE
,NULL
,&status
);
1325 spi_print( df
, "absource=%g ",absource
);
1326 done
= done
| DONE_ABSOURCE
;
1329 lssource
= getlotrsparam (scantrs
,MBK_LSSOURCE
,NULL
,&status
);
1331 spi_print( df
, "lssource=%g ",lssource
);
1332 done
= done
| DONE_LSSOURCE
;
1335 lgsource
= getlotrsparam (scantrs
,MBK_LGSOURCE
,NULL
,&status
);
1337 spi_print( df
, "lgsource=%g ",lgsource
);
1338 done
= done
| DONE_LGSOURCE
;
1341 abdrain
= getlotrsparam (scantrs
,MBK_ABDRAIN
,NULL
,&status
);
1343 spi_print( df
, "abdrain=%g ",abdrain
);
1344 done
= done
| DONE_ABDRAIN
;
1347 lsdrain
= getlotrsparam (scantrs
,MBK_LSDRAIN
,NULL
,&status
);
1349 spi_print( df
, "lsdrain=%g ",lsdrain
);
1350 done
= done
| DONE_LSDRAIN
;
1353 lgdrain
= getlotrsparam (scantrs
,MBK_LGDRAIN
,NULL
,&status
);
1355 spi_print( df
, "lgdrain=%g ",lgdrain
);
1356 done
= done
| DONE_LGDRAIN
;
1359 if (done
==0 || (SPI_FLAGS
& SPI_FULL_DRIVE
)!=0)
1361 optparam_list
*optparams
, *ptopt
;
1362 if ((pt
= getptype (scantrs
->USER
, OPT_PARAMS
))) {
1363 optparams
= (optparam_list
*) pt
->DATA
;
1365 for (ptopt
= optparams
; ptopt
; ptopt
= ptopt
->NEXT
) {
1366 if (((done
& DONE_L
)!=0 && strcasecmp(ptopt
->UNAME
.SPECIAL
, "l")==0)
1367 || ((done
& DONE_W
)!=0 && strcasecmp(ptopt
->UNAME
.SPECIAL
, "w")==0)
1368 || ((done
& DONE_AS
)!=0 && strcasecmp(ptopt
->UNAME
.SPECIAL
, "as")==0)
1369 || ((done
& DONE_AD
)!=0 && strcasecmp(ptopt
->UNAME
.SPECIAL
, "ad")==0)
1370 || ((done
& DONE_PS
)!=0 && strcasecmp(ptopt
->UNAME
.SPECIAL
, "ps")==0)
1371 || ((done
& DONE_PD
)!=0 && strcasecmp(ptopt
->UNAME
.SPECIAL
, "pd")==0)) continue;
1373 if (isknowntrsparam (ptopt
->UNAME
.STANDARD
)) { paramname
=*ptopt
->UNAME
.STANDARD
; tag
=paramname
[0]; }
1374 else { paramname
=ptopt
->UNAME
.SPECIAL
; tag
=ptopt
->TAG
; }
1376 spi_print( df
, " %s='%s'", *paramname
=='$'?paramname
+1:paramname
, ptopt
->UDATA
.EXPR
);
1379 spi_print( df
, " %s=%g", paramname
, ptopt
->UDATA
.VALUE
);
1387 pt
= getptype( scantrs
->USER
, PARAM_CONTEXT
);
1392 param
= (eqt_param
*)pt
->DATA
;
1393 for( i
= 0 ; i
< param
->NUMBER
; i
++ ) {
1394 if( ( ( done
& DONE_W
) && !strcasecmp( param
->EBI
[i
].NAME
, "W" ) ) ||
1395 ( ( done
& DONE_L
) && !strcasecmp( param
->EBI
[i
].NAME
, "L" ) ) ||
1396 ( ( done
& DONE_AS
) && !strcasecmp( param
->EBI
[i
].NAME
, "AS" ) ) ||
1397 ( ( done
& DONE_AD
) && !strcasecmp( param
->EBI
[i
].NAME
, "AD" ) ) ||
1398 ( ( done
& DONE_PS
) && !strcasecmp( param
->EBI
[i
].NAME
, "PS" ) ) ||
1399 ( ( done
& DONE_PD
) && !strcasecmp( param
->EBI
[i
].NAME
, "PD" ) ) ||
1400 ( ( done
& DONE_DELVTO
) && !strcasecmp( param
->EBI
[i
].NAME
, "DELVT0" ) ) ||
1401 ( ( done
& DONE_MULUO
) && !strcasecmp( param
->EBI
[i
].NAME
, "MULU0" ) ) ||
1402 ( ( done
& DONE_SA
) && !strcasecmp( param
->EBI
[i
].NAME
, "SA" ) ) ||
1403 ( ( done
& DONE_SB
) && !strcasecmp( param
->EBI
[i
].NAME
, "SB" ) ) ||
1404 ( ( done
& DONE_SD
) && !strcasecmp( param
->EBI
[i
].NAME
, "SD" ) ) ||
1405 ( ( done
& DONE_GEOMOD
) && !strcasecmp( param
->EBI
[i
].NAME
, "GEOMOD" ) ) ||
1406 ( ( done
& DONE_M
) && !strcasecmp( param
->EBI
[i
].NAME
, "M" ) ) ||
1407 ( ( done
& DONE_NF
) && !strcasecmp( param
->EBI
[i
].NAME
, "NF" ) ) ||
1408 ( ( done
& DONE_NF
) && !strcasecmp( param
->EBI
[i
].NAME
, "NFING" ) ) ||
1409 ( ( done
& DONE_NRS
) && !strcasecmp( param
->EBI
[i
].NAME
, "NRS" ) ) ||
1410 ( ( done
& DONE_NRD
) && !strcasecmp( param
->EBI
[i
].NAME
, "NRD" ) ) ||
1411 ( ( done
& DONE_SC
) && !strcasecmp( param
->EBI
[i
].NAME
, "SC" ) ) ||
1412 ( ( done
& DONE_SCA
) && !strcasecmp( param
->EBI
[i
].NAME
, "SCA" ) ) ||
1413 ( ( done
& DONE_SCB
) && !strcasecmp( param
->EBI
[i
].NAME
, "SCB" ) ) ||
1414 ( ( done
& DONE_SCC
) && !strcasecmp( param
->EBI
[i
].NAME
, "SCC" ) ) )
1416 spi_print( df
, " %s=%g", param
->EBI
[i
].NAME
, param
->EBI
[i
].VAL
);
1421 spi_print( df
, "\n" );
1427 void sortcircuit( ptfig
, df
)
1432 locon_list
*scancon
;
1436 cherche_alim( ptfig
, &vdd
, &vss
);
1438 /* Sortie des instances et des transistors */
1440 spi_print( df
, "\n.subckt %s ", ptfig
->NAME
);
1442 pt
= getptype( ptfig
->USER
, PH_INTERF
);
1444 sortconnecteur_ordre( df
, (chain_list
*)(pt
->DATA
), ptfig
->LOCON
);
1446 for( scancon
= ptfig
->LOCON
; scancon
; scancon
= scancon
->NEXT
)
1447 sortconnecteur( df
, scancon
);
1449 spi_print( df
,"\n" );
1453 for (scancon
=ptfig
->LOCON
; scancon
!=NULL
; scancon
=scancon
->NEXT
)
1455 if (scancon
->DIRECTION
!=UNKNOWN
)
1457 strcpy(temp
,scancon
->NAME
); spi_vect(temp
);
1458 if (count
==0) fprintf( df
, "* |CONDIR ");
1459 else fprintf( df
, ", ");
1461 switch (scancon
->DIRECTION
)
1463 case IN
: fprintf( df
, " IN"); break;
1464 case OUT
: fprintf( df
, " OUT"); break;
1465 case INOUT
: fprintf( df
, " INOUT"); break;
1466 case TRANSCV
: fprintf( df
, " TRANSCV"); break;
1467 case TRISTATE
: fprintf( df
, " TRISTATE"); break;
1468 default: fprintf( df
, " IN"); break;
1478 if (count
!=0) fprintf( df
, "\n");
1481 if( SPI_NAMENODES
== FALSE
)
1482 sortnet( ptfig
, df
);
1484 sortinstance( ptfig
, df
);
1485 sorttransistormos( ptfig
, df
, vss
, vdd
);
1486 sortrcn( ptfig
, df
, vss
);
1487 sort_unlinked_net(ptfig
, df
);
1489 if( spi_getfuncinode() ) {
1490 (spi_getfuncinode())( df
, ptfig
, spi_getdatainode() );
1491 spi_setfuncinode( NULL
, NULL
);
1494 spi_print( df
, ".ends %s\n\n", ptfig
->NAME
);
1503 RESIMINI
= V_FLOAT_TAB
[__MBK_SPI_DRIVE_RESI_MINI
].VALUE
;
1504 CAPAMINI
= V_FLOAT_TAB
[__MBK_SPI_DRIVE_CAPA_MINI
].VALUE
;
1505 SPI_DRV_TRSPARAM
= V_BOOL_TAB
[__MBK_SPI_DRV_TRSPARAM
].VALUE
;
1506 SPI_NETNAME
= V_STR_TAB
[__MBK_SPI_NETNAME
].VALUE
;
1507 SPI_NAMENODES
= V_BOOL_TAB
[__MBK_SPI_NAMENODES
].VALUE
;
1509 env
= V_STR_TAB
[__MBK_SPI_COMPOSE_NAME_SEPAR
].VALUE
;
1512 switch( strlen( env
) )
1515 SPI_COMPOSE_NAME_SEPAR
= 0;
1518 SPI_COMPOSE_NAME_SEPAR
= *env
;
1521 avt_errmsg (SPI_ERRMSG
, "007", AVT_FATAL
);
1526 SPI_COMPOSE_NAME_SEPAR
= '_';
1529 if (UNIT_LIST
==NULL
)
1531 env
= V_STR_TAB
[__MBK_DRIVE_DEFAULT_UNITS
].VALUE
;
1539 while (*start
!='\0')
1544 fprintf(stderr
,"error parsing env '%s=%s'\n","MBK_DRIVE_DEFAULT_UNITS",env
);
1546 UNIT_LIST
=addchain(UNIT_LIST
, strdup(temp
));
1551 if (*start
==',') { temp
[i
++]=' '; start
++; }
1552 else if (*start
==':') { temp
[i
++]=' '; tag
++; }
1553 if (*start
!=' ') temp
[i
++]=tolower(*start
);
1559 fprintf(stderr
,"error parsing env '%s=%s'\n","MBK_DRIVE_DEFAULT_UNITS",env
);
1561 UNIT_LIST
=addchain(UNIT_LIST
, strdup(temp
));
1566 SPI_FLAGS
=mbk_ReadFlags(__MBK_SPICE_DRIVER_FLAGS
, spice_opack
, sizeof(spice_opack
)/sizeof(*spice_opack
), 0, 0);
1570 void spicesavelofiginfile( lofig_list
*ptfig
, FILE *df
, int driveincludes
)
1572 chain_list
*scanchain
;
1573 locon_list
*scancon
;
1583 // Zinaps: coherence entre les formats mbk
1586 // connecteurs primaux
1587 ptfig
->LOCON
=(locon_list
*)reverse((chain_list
*)ptfig
->LOCON
);
1588 for (ls
=ptfig
->LOINS
;ls
!=NULL
;ls
=ls
->NEXT
)
1589 ls
->LOCON
=(locon_list
*)reverse((chain_list
*)ls
->LOCON
);
1591 // Zinaps: c'est tout
1593 /* On va travailler sur les fonctions RCN : */
1594 lofigchain( ptfig
);
1596 signalnoeud( ptfig
); /* Calcule les noeuds Spice */
1598 /* Sort la ligne *interf */
1600 if( SPI_NAMENODES
== FALSE
) {
1601 colonne
= strlen( "* INTERF " );
1602 tooutput( df
, "* INTERF " );
1604 pt
= getptype( ptfig
->USER
, PH_INTERF
);
1607 for( scanchain
= (chain_list
*)(pt
->DATA
) ;
1609 scanchain
= scanchain
->NEXT
1612 nom
= ((char*)(scanchain
->DATA
));
1616 lgmot
= strlen(v
)+1;
1617 if( colonne
+lgmot
>= SPI_MAX_COL
-2 )
1619 colonne
= strlen( "* INTERF " );
1620 tooutput( df
, "\n* INTERF " );
1622 colonne
= colonne
+ lgmot
;
1624 tooutput( df
, "%s ", v
);
1630 for( scancon
= ptfig
->LOCON
; scancon
; scancon
= scancon
->NEXT
)
1632 if( scancon
->PNODE
)
1634 for( scannum
= scancon
->PNODE
; scannum
; scannum
= scannum
->NEXT
)
1636 strcpy( v
, scancon
->NAME
);
1639 lgmot
= strlen(v
)+1;
1640 if( colonne
+lgmot
>= SPI_MAX_COL
-2 )
1642 colonne
= strlen( "* INTERF " );
1643 tooutput( df
, "\n* INTERF " );
1645 colonne
= colonne
+ lgmot
;
1647 tooutput( df
, "%s ", v
);
1653 strcpy( v
, scancon
->NAME
);
1656 lgmot
= strlen(v
)+1;
1657 if( colonne
+lgmot
>= SPI_MAX_COL
-2 )
1659 colonne
= strlen( "* INTERF " );
1660 tooutput( df
, "\n* INTERF " );
1662 colonne
= colonne
+ lgmot
;
1664 tooutput( df
, "%s ", v
);
1669 tooutput( df
, "\n\n" );
1672 /* Sort les .include */
1676 for( scanchain
= ptfig
->MODELCHAIN
; scanchain
; scanchain
= scanchain
->NEXT
)
1678 spi_print( df
, ".INCLUDE \"%s.%s\"\n", (char*)scanchain
->DATA
, OUT_LO
);
1681 sortcircuit( ptfig
, df
);
1683 // Zinaps: coherence entre les formats mbk, retour a la normal
1686 // connecteurs primaux
1687 ptfig
->LOCON
=(locon_list
*)reverse((chain_list
*)ptfig
->LOCON
);
1688 for (ls
=ptfig
->LOINS
;ls
!=NULL
;ls
=ls
->NEXT
)
1689 ls
->LOCON
=(locon_list
*)reverse((chain_list
*)ls
->LOCON
);
1691 // Zinaps: c'est tout
1693 spi_cleanextlocon(ptfig
);
1694 freesignalnoeud(ptfig
);
1698 void spicesavelofig( ptfig
)
1701 FILE *df
; /* descripteur de fichier de sortie */
1705 /* Ouverture du fichier de sortie */
1706 df
= mbkfopen( ptfig
->NAME
, OUT_LO
, WRITE_TEXT
);
1710 fprintf( stderr
, "*** mbk error : savelofig impossible.\n" );
1712 "Can't open file %s.%s for writing.\n",
1720 spiceprintdate( ptfig
->NAME
, df
);
1724 spicesavelofiginfile( ptfig
, df
, 1);
1726 if( fclose(df
) == -1 )
1730 "*** mbk error *** : Can't close file %s.\n,",
1737 void spicesavelofigsinfile( chain_list
*cl
, FILE *df
)
1745 /* Ouverture du fichier de sortie */
1748 jours
= localtime( &secondes
);
1752 ptfig
=(lofig_list
*)cl
->DATA
;
1753 spicesavelofiginfile( ptfig
, df
, 0);
1759 void spiceprintdate( char *circuit
, FILE *df
)
1763 sprintf(buf
,"Spice description of %s\n", circuit
);
1764 avt_printExecInfo(df
, "*", buf
, "");
1769 void tooutput( FILE *fd
, ...)
1774 va_start( index
, fd
);
1776 fmt
= va_arg( index
, char* );
1778 if( vfprintf( fd
, fmt
, index
) < 0 )
1781 fprintf( stderr
, "*** spi error *** : Error while writing file.\n" );
1782 perror( "System say " );
1796 // if (!MBK_DEVECT) return;
1804 /* Positionne i sur le premier caractere non espace a la fin de la chaine */
1808 while( s
[i
] == ' ' && i
>0 );
1810 /* passe un eventuel paquet de nombres */
1814 while( isdigit( (int)s
[i
] ) && i
>0 )
1816 if( p1
!= i
&& s
[i
] == ' ' )
1818 if (!strcmp (SPI_VECTOR
, "[]"))
1824 else if (!strcmp (SPI_VECTOR
, "()"))
1830 else if (!strcmp (SPI_VECTOR
, "<>"))
1836 else if (!strcmp (SPI_VECTOR
, "_"))
1845 void spi_print( FILE *fd
, ...)
1849 static int lgcurrent
=0;
1853 va_start( index
, fd
);
1855 fmt
= va_arg( index
, char* );
1857 vsprintf( buf
, fmt
, index
) ;
1860 if( lgcurrent
==0 || l
+ lgcurrent
< 80 ) {
1862 lgcurrent
= lgcurrent
+ l
;
1865 fputs( "\n+ ", fd
);
1870 if( buf
[l
-1] == '\n' )
1874 /* Fonctions d'accès pour insérer des mesures dans le fichier de sortie sur les
1875 locons sans avoir à modifier la lofig.
1877 locon->PNODE = 1 2 3
1880 Les inodes sont drivés en priorités par rapport aux pnodes. Ensuite, la
1881 fonction utilisateur est appellés avant le .ends. C'est l'utilisateur qui
1882 doit placer les mesures entre chaque paire de noeud pnode/inode :
1884 exemple pour des mesures de courant :
1891 void spi_setfuncinode( void (*fn
)( FILE*, lofig_list
*, void* ), void *data
)
1893 SPI_LOCON_INODE_FUNC
= fn
;
1894 SPI_LOCON_INODE_DATA
= data
;
1897 void *spi_getdatainode(void)
1899 return SPI_LOCON_INODE_DATA
;
1902 void (*spi_getfuncinode(void))( FILE*, lofig_list
*, void* )
1904 return SPI_LOCON_INODE_FUNC
;
1907 num_list
* spi_getinode( locon_list
*locon
)
1911 ptl
= getptype( locon
->USER
, SPI_LOCON_INODE
);
1912 if( !ptl
) return NULL
;
1913 return (num_list
*)ptl
->DATA
;
1916 void spi_setinode( locon_list
*locon
, num_list
*head
)
1923 ptl
= getptype( locon
->USER
, SPI_LOCON_INODE
);
1925 freenum( ptl
->DATA
);
1928 locon
->USER
= addptype( locon
->USER
, SPI_LOCON_INODE
, NULL
);
1934 ptl
= getptype( locon
->SIG
->USER
, SPI_SIG_INODE
);
1936 locon
->SIG
->USER
= addptype( locon
->SIG
->USER
,
1941 (*(long *)&ptl
->DATA
)++;
1944 void spi_clearinode( locon_list
*locon
)
1948 ptl
= getptype( locon
->USER
, SPI_LOCON_INODE
);
1950 freenum( ptl
->DATA
);
1951 locon
->USER
= delptype( locon
->USER
, SPI_LOCON_INODE
);
1955 ptl
= getptype( locon
->SIG
->USER
, SPI_SIG_INODE
);
1956 if( ptl
) { // C'est obligé...
1957 (*(long *)&ptl
->DATA
)--;
1958 if( ((long)ptl
->DATA
)==0 )
1959 locon
->SIG
->USER
= delptype( locon
->SIG
->USER
, SPI_SIG_INODE
);
1964 /* renvoie un locon sur le signal pour la détermination d'un nom de
1965 signal représentatif. renvoie NULL pas de solution. */
1967 static char *nameofdevice(locon_list
*lc
)
1969 if (lc
->TYPE
=='T' && ((lotrs_list
*)lc
->ROOT
)->TRNAME
!=NULL
) return ((lotrs_list
*)lc
->ROOT
)->TRNAME
;
1970 if (lc
->TYPE
=='I' && ((loins_list
*)lc
->ROOT
)->INSNAME
!=NULL
) return ((loins_list
*)lc
->ROOT
)->INSNAME
;
1974 locon_list
* spichooseonelocon( losig_list
*losig
)
1977 locon_list
*minlocon
= NULL
;
1982 ptype
= getptype( losig
->USER
, SPI_CHOOSEN_LOCON
);
1984 return (locon_list
*)ptype
->DATA
;
1986 ptype
= getptype( losig
->USER
, LOFIGCHAIN
);
1989 for( chain
= ptype
->DATA
; chain
; chain
= chain
->NEXT
) {
1990 locon
= (locon_list
*)chain
->DATA
;
1993 (ret
=strcmp(locon
->NAME
, minlocon
->NAME
))<0 ||
1994 (ret
==0 && strcmp(nameofdevice(locon
), nameofdevice(minlocon
))<0))
1999 losig
->USER
= addptype( losig
->USER
, SPI_CHOOSEN_LOCON
, minlocon
);