Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / mbkspice / spi_drive.c
1 /*
2 * This file is part of the Alliance CAD System
3 * Copyright (C) Laboratoire LIP6 - Département ASIM
4 * Universite Pierre et Marie Curie
5 *
6 * Home page : http://www-asim.lip6.fr/alliance/
7 * E-mail support : mailto:alliance-support@asim.lip6.fr
8 *
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.
13 *
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.
18 *
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.
22 */
23
24
25 /*******************************************************************************
26 * *
27 * Tool : Spice parser / driver v 7.00 *
28 * Author(s) : Gregoire AVOT *
29 * Updates : August, 17th 1998 *
30 * *
31 *******************************************************************************/
32
33 #define SPI_MAX_COL 80
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include <stdarg.h>
43 #include <time.h>
44 #include <ctype.h>
45 #include AVT_H
46 #include MUT_H
47 #include MLO_H
48 #include RCN_H
49 #include EQT_H
50 #include MSL_H
51 #include MCC_H
52 #include "spi_drive.h"
53 #include "spi_int.h"
54
55 /*static chain_list *TNMOS ;
56 static chain_list *TPMOS ;*/
57 extern char *SPI_NETNAME;
58 int SPI_DRV_TRSPARAM=1;
59 char SPI_NAMENODES;
60 char SPI_COMPOSE_NAME_SEPAR;
61 char SPI_INS_SEPAR='.';
62 char SPI_REPLACE_INS_SEPAR='_';
63 int SPI_LOWRESISTANCE_AS_TENSION=0;
64
65 float CAPAMINI = 0;
66 float RESIMINI = 0.001;
67
68 #define SPI_NONODES (-1l)
69 #define SPI_MAXSTATICNAME 16
70
71
72 chain_list *UNIT_LIST=NULL;
73
74 #define SPI_FULL_DRIVE 1
75 #define SPI_DRIVE_ALL 2
76 static int SPI_FLAGS=0;
77
78 static mbk_options_pack_struct spice_opack[]=
79 {
80 {"DriveInstanceParameters", SPI_FULL_DRIVE},
81 {"IgnoreGlobalParameters", SPI_DRIVE_ALL}
82 };
83
84 void (*SPI_LOCON_INODE_FUNC)( FILE *ptf, lofig_list *lofig, void *data ) = NULL;
85 void *SPI_LOCON_INODE_DATA = NULL;
86
87 void spi_cleanextlocon( lofig_list *lofig )
88 {
89 locon_list *locon ;
90 ptype_list *ptl ;
91 losig_list *losig ;
92
93 for( locon = lofig->LOCON ; locon ; locon = locon->NEXT ) {
94 losig = locon->SIG ;
95 ptl = getptype( losig->USER, SPI_EXTLOCON );
96 if( ptl )
97 losig->USER = delptype( losig->USER, SPI_EXTLOCON );
98 }
99 }
100
101 locon_list* spi_getextlocon( losig_list *losig )
102 {
103 ptype_list *ptl ;
104 chain_list *scan;
105 locon_list *locon;
106
107 if( losig->TYPE != 'E' )
108 return NULL;
109
110 ptl = getptype( losig->USER, SPI_EXTLOCON );
111 if( ptl )
112 return (locon_list*)ptl->DATA;
113
114 ptl = getptype( losig->USER, LOFIGCHAIN );
115 if( !ptl )
116 return NULL;
117
118 for( scan = (chain_list*) ptl->DATA ; scan ; scan = scan->NEXT ) {
119 locon = (locon_list*) scan->DATA ;
120 if( locon->TYPE == 'E' )
121 break;
122 }
123
124 if( !scan )
125 locon = NULL;
126
127 losig->USER = addptype( losig->USER, SPI_EXTLOCON, (void*)locon );
128 return locon;
129 }
130
131 /******************************************************************************\
132 spi_makename()
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 )
137 {
138 int i;
139 int l;
140 static char spi_name[1024];
141
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;
146 else
147 spi_name[i] = alc_name[i];
148 }
149 spi_name[l]='\0';
150
151 return spi_name;
152 }
153
154 char* spinamenode( losig, node )
155 losig_list *losig;
156 long node;
157 {
158 return spinamenodedetail( losig, node, 0 );
159 }
160
161 char* spinamenodedetail( losig, node, force )
162 losig_list *losig;
163 long node;
164 char force;
165 {
166 char tmp[1024];
167 static char names[SPI_MAXSTATICNAME][1024];
168 static int curnames = 0;
169 locon_list *locon;
170 ptype_list *ptptype;
171 convindex *cvx;
172
173 spi_env();
174
175 curnames++;
176 if( curnames == SPI_MAXSTATICNAME )
177 curnames=0;
178
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) ));
183 spi_vect( tmp );
184 sprintf( names[curnames], "%s", tmp );
185 }
186 else
187 sprintf( names[curnames], "sig%ld", losig->INDEX );
188 }
189 else {
190 strcpy( tmp, spi_makename( getsigname(losig) ) );
191 spi_vect( tmp );
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 );
198 else {
199 sprintf( names[curnames],
200 "%s%c%ld",
201 tmp,
202 SPI_COMPOSE_NAME_SEPAR,
203 node
204 );
205 }
206 }
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 );
211 }
212 else {
213 sprintf( names[curnames],
214 "%s%c%ld",
215 tmp,
216 SPI_COMPOSE_NAME_SEPAR,
217 node
218 );
219 }
220 }
221 }
222 }
223 else {
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 );
228 else
229 sprintf( names[curnames], "%ld", cvx->premier + node - 1 );
230 }
231
232 return( names[curnames] );
233 }
234
235 char *spi_gettransname(type)
236 char type ;
237 {
238 chain_list *chain ;
239
240 if(MLO_IS_TRANSN(type))
241 chain = TNMOS ;
242 else if (MLO_IS_TRANSP(type))
243 chain = TPMOS ;
244 else
245 chain = TNMOS ;
246
247 if (!chain) avt_errmsg(SPI_ERRMSG, "081", AVT_FATAL);
248
249 return((char *)chain->DATA) ;
250 }
251
252 int getanode(losig_list *signal)
253 {
254 if (signal->PRCN==NULL) return 0;
255 if (signal->PRCN->PWIRE!=NULL) return signal->PRCN->PWIRE->NODE1;
256 if (signal->PRCN->PCTC!=NULL)
257 {
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;
261 }
262 return 0;
263 }
264
265 void cherche_alim( ptfig, vdd, vss )
266 lofig_list *ptfig;
267 char **vdd;
268 char **vss;
269 {
270 locon_list *scancon;
271 losig_list *signal;
272 int node;
273 static char stvss[1024], stvdd[1024];
274
275 *vdd = NULL;
276 *vss = NULL;
277
278 for( scancon = ptfig->LOCON ;
279 scancon && !(*vdd && *vss) ;
280 scancon = scancon->NEXT
281 )
282 {
283 if( mbk_LosigIsVDD( scancon->SIG ) )
284 {
285 signal = scancon->SIG;
286
287 if( scancon->PNODE )
288 strcpy( stvdd, spinamenode( signal, scancon->PNODE->DATA ) );
289 else
290 strcpy( stvdd, spinamenode( signal, SPI_NONODES ) );
291
292 *vdd = stvdd;
293 }
294
295 if( mbk_LosigIsVSS( scancon->SIG ) )
296 {
297 signal = scancon->SIG;
298
299 if( scancon->PNODE )
300 strcpy( stvss, spinamenode( signal, scancon->PNODE->DATA ) );
301 else
302 strcpy( stvss, spinamenode( signal, SPI_NONODES ) );
303
304 *vss = stvss;
305 }
306 }
307
308 // zinaps le 20/8/2002
309 for( signal = ptfig->LOSIG ;
310 signal && !(*vdd && *vss) ;
311 signal = signal->NEXT
312 )
313 {
314 if(mbk_LosigIsVDD(signal))
315 {
316 if((node=getanode(signal))!=0)
317 strcpy( stvdd, spinamenode( signal, node ) );
318 else
319 strcpy( stvdd, spinamenode( signal, SPI_NONODES ) );
320 *vdd = stvdd;
321 }
322
323 if(mbk_LosigIsVSS(signal))
324 {
325 if((node=getanode(signal))!=0)
326 strcpy( stvss, spinamenode( signal, node ) );
327 else
328 strcpy( stvss, spinamenode( signal, SPI_NONODES ) );
329 *vss = stvss;
330 }
331 }
332 }
333
334 void sortrcn( ptfig, df, vss )
335 lofig_list *ptfig;
336 FILE *df;
337 char *vss;
338 {
339 losig_list *scanlosig;
340 int nbr;
341 lowire_list *scanlowire;
342 int nbctc, cnt;
343 // chain_list *scanchain;
344 chain_list *headctc;
345 loctc_list *ptctc;
346 char *name1, *name2;
347 float resival;
348 lonode_list *ptnode1;
349 lonode_list *ptnode2;
350 static char drivewirenotconnected='u';
351 char *env;
352 ptype_list *pt;
353 char siname[1024];
354 int cachemode;
355
356 if( drivewirenotconnected=='u' ) {
357
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. */
362
363 env = NULL; //getenv("MBK_SPI_DRIVE_WIRE_NOT_CONNECTED");
364 if( env ) {
365 if( strcasecmp( env, "yes" )==0 )
366 drivewirenotconnected = 'y';
367 if( strcasecmp( env, "no" )==0 )
368 drivewirenotconnected = 'n';
369 }
370 if( drivewirenotconnected == 'u' )
371 drivewirenotconnected = 'y' ; // défaut.
372 }
373
374 nbctc = 0;
375 cachemode=rcn_hascache(ptfig);
376
377 for( scanlosig = ptfig->LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT )
378 {
379 if( !scanlosig->PRCN )
380 continue;
381
382 if (cachemode && (mbk_LosigIsVDD(scanlosig) || mbk_LosigIsVSS(scanlosig))) continue;
383
384 rcn_lock_signal(ptfig, scanlosig);
385
386 if( scanlosig->PRCN->PWIRE || scanlosig->PRCN->PCTC )
387 {
388 nbr = 1;
389
390
391 for( scanlowire = scanlosig->PRCN->PWIRE ;
392 scanlowire ;
393 scanlowire = scanlowire->NEXT )
394 {
395 resival=scanlowire->RESI;
396
397 if( drivewirenotconnected == 'n' ) {
398 ptnode1 = getlonode( scanlosig, scanlowire->NODE1 );
399 ptnode2 = getlonode( scanlosig, scanlowire->NODE2 );
400
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 &&
405 !ptnode1->CTCLIST
406 )
407 continue ;
408 if( RCN_GETFLAG( ptnode2->FLAG, RCN_FLAG_ONE ) &&
409 !RCN_GETFLAG( ptnode2->FLAG, RCN_FLAG_LOCON ) &&
410 scanlowire->CAPA == 0.0 &&
411 !ptnode2->CTCLIST
412 )
413 continue ;
414 }
415
416 if (resival<RESIMINI) resival=RESIMINI;
417 if (SPI_LOWRESISTANCE_AS_TENSION==0)
418 {
419 if ((pt=getptype(scanlowire->USER, RESINAME))!=NULL)
420 strcpy(siname, spi_makename((char *)pt->DATA));
421 else
422 sprintf(siname, "%ld_%d",scanlosig->INDEX, nbr);
423 spi_print( df,
424 "R%s %s %s %g\n",
425 siname,
426 spinamenode( scanlosig, scanlowire->NODE1 ),
427 spinamenode( scanlosig, scanlowire->NODE2 ),
428 resival
429 );
430 }
431 else
432 {
433 spi_print( df,
434 "V%d_%d %s %s 0\n",
435 scanlosig->INDEX,
436 nbr,
437 spinamenode( scanlosig, scanlowire->NODE1 ),
438 spinamenode( scanlosig, scanlowire->NODE2 )
439 );
440 }
441
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. */
444
445 if( scanlowire->CAPA!=0 && scanlowire->CAPA / 2.0 >= CAPAMINI )
446 {
447 spi_print( df,
448 "C%d_%d1 %s %s %g\n",
449 scanlosig->INDEX,
450 nbr,
451 spinamenode( scanlosig, scanlowire->NODE1 ),
452 "0"/*vss*/,
453 (scanlowire->CAPA / 2.0) * 1e-12
454 );
455
456 spi_print( df,
457 "C%d_%d2 %s %s %g\n",
458 scanlosig->INDEX,
459 nbr,
460 spinamenode( scanlosig, scanlowire->NODE2 ),
461 "0"/*vss*/,
462 (scanlowire->CAPA / 2.0) * 1e-12
463 );
464 }
465
466 nbr++;
467 }
468 if (nbr > 1)
469 spi_print( df, "\n" );
470
471 for (headctc=scanlosig->PRCN->PCTC, cnt=0; headctc!=NULL; headctc=headctc->NEXT)
472 {
473 ptctc=(loctc_list *)headctc->DATA;
474 if (rcn_capacitancetooutput(cachemode, scanlosig, ptctc))
475 {
476 if( ptctc->CAPA >= CAPAMINI )
477 {
478 name1 = spinamenode( ptctc->SIG1, ptctc->NODE1 > 0 ? ptctc->NODE1 : SPI_NONODES );
479 name2 = spinamenode( ptctc->SIG2, ptctc->NODE2 > 0 ? ptctc->NODE2 : SPI_NONODES );
480
481 if (mbk_LosigIsVSS( ptctc->SIG1 ) || mbk_LosigIsVSS( ptctc->SIG2 ) )
482 {
483 if ((pt=getptype(ptctc->USER, MSL_CAPANAME))!=NULL)
484 strcpy(siname, spi_makename((char *)pt->DATA));
485 else
486 sprintf(siname, "%d",nbctc);
487 spi_print( df, "C%s %s %s %g\n", siname, name1, name2, ptctc->CAPA * 1e-12);
488 }
489 else
490 {
491 if ((pt=getptype(ptctc->USER, MSL_CAPANAME))!=NULL)
492 strcpy(siname, spi_makename((char *)pt->DATA));
493 else
494 sprintf(siname, "_ctc_%d",nbctc);
495 spi_print( df, "C%s %s %s %g\n", siname, name1, name2, ptctc->CAPA * 1e-12 );
496 }
497 cnt++;
498 nbctc++;
499 }
500 }
501
502 }
503
504 if (cnt !=0)
505 spi_print( df, "\n" );
506 }
507
508 /* On ne sort la capa totale que si on a ni RCN, ni CTC */
509
510 if( !scanlosig->PRCN->PWIRE && !scanlosig->PRCN->PCTC )
511 {
512 if( rcn_getcapa( ptfig,scanlosig ) >= CAPAMINI )
513 {
514 spi_print( df,
515 "Ct%d %s %s %g\n",
516 scanlosig->INDEX,
517 spinamenode( scanlosig, SPI_NONODES ),
518 "0"/*vss*/,
519 rcn_getcapa( ptfig,scanlosig ) * 1e-12
520 );
521 }
522 }
523 //spi_print( df, "\n" );
524 rcn_unlock_signal(ptfig, scanlosig);
525 }
526 #if 0
527 headctc = getallctc( ptfig );
528
529 for( scanchain = headctc ; scanchain ; scanchain = scanchain->NEXT )
530 {
531 ptctc = (loctc_list*)scanchain->DATA ;
532
533 if( ptctc->CAPA >= CAPAMINI )
534 {
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 );
539 else
540 spi_print( df, "C_ctc_%d %s %s %g\n", nbctc, name1, name2, ptctc->CAPA * 1e-12 );
541 }
542
543 nbctc++;
544 }
545
546 freechain( headctc );
547 #endif
548 }
549
550 void signalnoeud( ptfig )
551 lofig_list *ptfig;
552 {
553 losig_list *scanlosig;
554 convindex *nouveau;
555 int dernier;
556
557 dernier = 1;
558
559 for( scanlosig = ptfig -> LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT )
560 {
561 nouveau = ( convindex* ) mbkalloc( sizeof( convindex ) );
562 nouveau->sig = scanlosig;
563 nouveau->premier = dernier;
564
565 /* Evaluation de gauche à droite */
566 if( scanlosig->PRCN && scanlosig->PRCN->NBNODE > 0 )
567 dernier += scanlosig->PRCN->NBNODE ;
568 else
569 dernier++;
570
571 scanlosig->USER = addptype( scanlosig->USER, SPI_DRIVER_PTYPE, nouveau );
572 }
573 }
574
575 void freesignalnoeud( lofig_list *ptfig )
576 {
577 losig_list *scanlosig;
578 ptype_list *pt;
579
580 for( scanlosig = ptfig -> LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT )
581 {
582 if ((pt=getptype(scanlosig->USER, SPI_DRIVER_PTYPE))!=NULL)
583 {
584 mbkfree(pt->DATA);
585 scanlosig->USER = delptype( scanlosig->USER, SPI_DRIVER_PTYPE);
586 }
587 }
588 }
589
590
591
592 void sortconnecteur( df, c )
593 FILE *df;
594 locon_list *c;
595 {
596 losig_list *signal;
597 num_list *tetenum,*scannum;
598 char force;
599
600 signal = c->SIG;
601
602 if( c->PNODE )
603 {
604 tetenum = spi_getinode( c );
605 if( !tetenum ) {
606 tetenum = c->PNODE;
607 force = 0;
608 }
609 else
610 force = 1;
611
612 for( scannum = tetenum ; scannum ; scannum = scannum->NEXT )
613 spi_print( df, "%s ", spinamenodedetail( signal, scannum->DATA, force) );
614 }
615 else
616 {
617 tetenum = spi_getinode( c );
618 if( !tetenum )
619 spi_print( df, "%s ", spinamenode( signal, SPI_NONODES ) );
620 else {
621 for( scannum = tetenum ; scannum ; scannum = scannum->NEXT )
622 {
623 spi_print( df, "%s ", spinamenodedetail( signal, scannum->DATA, 1) );
624 }
625 }
626 }
627 }
628
629 void sortconnecteur_ordre( df, ordre, liste )
630 FILE *df;
631 chain_list *ordre;
632 locon_list *liste;
633 {
634 chain_list *scanordre;
635 locon_list *scanlocon;
636 int num;
637 int n;
638 chain_list *cpteordre;
639 losig_list *signal;
640 ptype_list *pt;
641 convindex *noeudbase;
642 num_list *scannum;
643 num_list *tetenum;
644 char force;
645
646 for( scanordre = ordre ; scanordre ; scanordre = scanordre->NEXT )
647 {
648 for( scanlocon = liste ; scanlocon ; scanlocon = scanlocon->NEXT )
649 if( scanlocon->NAME == ((char*)(scanordre->DATA)) )
650 break;
651
652 if( !scanlocon ) avt_errmsg (SPI_ERRMSG, "005", AVT_FATAL);
653
654 num = 0;
655 for( cpteordre = ordre ;
656 cpteordre != scanordre ;
657 cpteordre = cpteordre->NEXT
658 )
659 if( ((char*)(cpteordre->DATA)) == scanlocon->NAME )
660 num++;
661
662 signal = scanlocon->SIG;
663 pt = getptype( signal->USER, SPI_DRIVER_PTYPE );
664 noeudbase = (convindex*)(pt->DATA);
665
666 if( scanlocon->PNODE )
667 {
668 tetenum = spi_getinode( scanlocon );
669 if( !tetenum ) {
670 tetenum = scanlocon->PNODE;
671 force = 0;
672 }
673 else
674 force = 1;
675
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 ) );
681
682 }
683 else
684 spi_print( df, "%s ", spinamenode( signal, SPI_NONODES ) );
685 }
686 }
687
688 void sortnet( ptfig, df )
689 lofig_list *ptfig;
690 FILE *df;
691 {
692 losig_list *scanlosig;
693 locon_list *scanlocon;
694 chain_list *scanchain;
695 ptype_list *ptl;
696 convindex *conv;
697 tableint *noeudunique;
698 num_list *scannum;
699 lowire_list *scanlowire;
700 loctc_list *ptctc;
701 int i;
702 char v[1024];
703
704 for( scanlosig = ptfig->LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT )
705 {
706 if ( ( scanlosig->NAMECHAIN ) ||
707 ( scanlosig->TYPE == EXTERNAL ) )
708 {
709 ptl = getptype(scanlosig->USER,SPI_DRIVER_PTYPE);
710 conv = (convindex*)(ptl->DATA);
711
712 spi_print( df, "* %s ", SPI_NETNAME );
713
714 /* Evaluation de gauche à droite */
715 if( scanlosig->PRCN && scanlosig->PRCN->NBNODE > 1 )
716 {
717 noeudunique = creattableint();
718
719 for( scanlowire = scanlosig->PRCN->PWIRE ;
720 scanlowire ;
721 scanlowire = scanlowire->NEXT
722 )
723 {
724 settableint( noeudunique, scanlowire->NODE1, (void*)1 );
725 settableint( noeudunique, scanlowire->NODE2, (void*)1 );
726 }
727
728 for( scanchain = scanlosig->PRCN->PCTC ;
729 scanchain ;
730 scanchain = scanchain->NEXT
731 )
732 {
733 ptctc = (loctc_list*)scanchain->DATA;
734 if( ptctc->NODE1 )
735 settableint( noeudunique, ptctc->NODE1, (void*)1 );
736 if( ptctc->NODE2 )
737 settableint( noeudunique, ptctc->NODE2, (void*)1 );
738 }
739
740 ptl = getptype( scanlosig->USER, LOFIGCHAIN );
741 if( !ptl )
742 {
743 fflush( stdout );
744 fprintf( stderr, "*** spi error *** : LOFIGCHAIN missing.\n" );
745 EXIT(1);
746 }
747
748 for( scanchain = (chain_list*)(ptl->DATA) ;
749 scanchain ;
750 scanchain = scanchain->NEXT
751 )
752 {
753 for( scannum = ((locon_list*)(scanchain->DATA))->PNODE ;
754 scannum ;
755 scannum = scannum->NEXT
756 )
757 settableint( noeudunique, scannum->DATA, (void*)1 );
758 }
759
760 i = 0 ;
761 /*
762 while( (i = scanint( noeudunique, i ) ) )
763 tooutput( df, "%d ", i + conv->premier - 1 );
764 */
765 /* On ne sort qu'un seul noeud */
766 i = scanint( noeudunique, i );
767 spi_print( df, "%d ", i + conv->premier - 1 );
768
769 freetableint( noeudunique );
770 }
771 else
772 spi_print( df, "%d ", conv->premier);
773
774 spi_print( df, "= " );
775
776 /*
777 for( scanchain = scanlosig->NAMECHAIN ;
778 scanchain ;
779 scanchain=scanchain->NEXT
780 )
781 */
782
783 if(scanlosig->TYPE == EXTERNAL)
784 {
785 for(scanlocon = ptfig->LOCON ; scanlocon != NULL &&
786 scanlocon->SIG != scanlosig ;
787 scanlocon = scanlocon->NEXT)
788
789 if(scanlocon == NULL)
790 {
791 fflush( stdout );
792 fprintf( stderr, "*** spi error *** : LOFIGCHAIN missing.\n" );
793 EXIT(1);
794 }
795
796 strcpy( v, scanlocon->NAME);
797 spi_vect( v );
798 spi_print( df, "%s ", v);
799 }
800 else
801 {
802 scanchain = scanlosig->NAMECHAIN;
803 {
804 strcpy( v, (char*)(scanchain->DATA) );
805 spi_vect( v );
806 spi_print( df, "%s ", v );
807 }
808 }
809
810 spi_print( df, "\n" );
811 }
812 }
813
814 }
815
816 void sort_unlinked_net( lofig_list *ptfig, FILE *df )
817 {
818 losig_list *scanlosig;
819 ptype_list *ptl;
820 chain_list *cl;
821
822 for( scanlosig = ptfig->LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT )
823 {
824 ptl=getptype(scanlosig->USER, LOFIGCHAIN);
825 cl=(chain_list *)ptl->DATA;
826 if ( cl==NULL && scanlosig->NAMECHAIN)
827 {
828 spi_print( df, "* |UNCONNECTED_NET %s\n", spinamenode( scanlosig, SPI_NONODES ));
829 }
830 }
831 }
832
833 void sortinstance( ptfig, df )
834 lofig_list *ptfig;
835 FILE *df;
836 {
837 loins_list *scanloins;
838 locon_list *scanloconins;
839 ptype_list *pt;
840 eqt_param *ep;
841 int i;
842 ht *globparam;
843
844 if (SPI_FLAGS & SPI_FULL_DRIVE)
845 {
846 globparam=addht(2048);
847 if (MBK_GLOBALPARAMS!=NULL)
848 {
849 for (i=0; i<MBK_GLOBALPARAMS->NUMBER; i++)
850 addhtitem(globparam, MBK_GLOBALPARAMS->EBI[i].NAME, 0);
851 }
852 }
853
854 for( scanloins = ptfig->LOINS ; scanloins ; scanloins = scanloins->NEXT )
855 {
856 spi_print( df, "x%s ", scanloins->INSNAME );
857
858 /* L'ordre des connecteurs entre la lofig et sa version instanciée n'est
859 pas le meme */
860
861 pt = getptype( scanloins->USER, PH_INTERF );
862 if( pt )
863 sortconnecteur_ordre( df,
864 (chain_list*)(pt->DATA),
865 scanloins->LOCON
866 );
867 else
868 for( scanloconins = scanloins->LOCON ;
869 scanloconins ;
870 scanloconins = scanloconins->NEXT
871 )
872 sortconnecteur( df, scanloconins );
873
874 spi_print( df, "%s", scanloins->FIGNAME );
875
876
877 if (SPI_FLAGS & SPI_FULL_DRIVE)
878 {
879 optparam_list *optparams, *ptopt;
880 // drive les parametres des instances
881 if ((pt = getptype (scanloins->USER, PARAM_CONTEXT))!=NULL)
882 {
883 ep=(eqt_param *)pt->DATA;
884 for (i=0; i<ep->NUMBER; i++)
885 {
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 );
888 }
889 }
890
891 if ((pt = getptype (scanloins->USER, OPT_PARAMS))) {
892 optparams = (optparam_list *) pt->DATA;
893
894 for (ptopt = optparams; ptopt; ptopt = ptopt->NEXT) {
895 if (ptopt->TAG == '$') {
896 spi_print( df, " %s='%s'", ptopt->UNAME.SPECIAL, ptopt->UDATA.EXPR );
897 }
898 else {
899 spi_print( df, " %s=%g", ptopt->UNAME.SPECIAL, ptopt->UDATA.VALUE );
900 }
901 }
902 }
903 }
904
905 spi_print( df, "\n");
906
907 }
908 if (SPI_FLAGS & SPI_FULL_DRIVE) delht(globparam);
909 }
910
911 /* param doit etre en minuscule */
912 static float getbaseunit(lofig_list *lf, char *param)
913 {
914 char temp[100], *c;
915 chain_list *cl;
916 sprintf(temp," %s ",param);
917 for (cl=UNIT_LIST; cl!=NULL; cl=cl->NEXT)
918 {
919 c=(char *)cl->DATA;
920 if (strstr(c,temp)!=NULL && (c=strchr(c,':'))!=NULL)
921 return atof(&c[1]);
922 }
923 return 0;
924
925 lf = NULL;
926 }
927
928
929
930 static char *modelname(lotrs_list *tr, int in_SPI_TRANSISTOR_AS_INSTANCE)
931 {
932 char *subcktname=NULL, *modelname;
933 ptype_list *ptype;
934
935 if(tr->MODINDEX < 0)
936 return spi_gettransname(tr->TYPE);
937
938 modelname=getlotrsmodel(tr);
939
940 if ( in_SPI_TRANSISTOR_AS_INSTANCE )
941 {
942 if (( ptype = getptype ( tr->USER, TRANS_FIGURE )))
943 subcktname = (char*)ptype->DATA;
944 else
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);
949 }
950
951 if (subcktname==NULL) return modelname;
952 return subcktname;
953 }
954
955
956
957 // zinaps: le 27/9/2002
958 static char *strip(char *name)
959 {
960 static char temp[1024];
961 int i,j;
962 for (i=0, j=0;name[i]!='\0';i++)
963 {
964 if (name[i]!='*') temp[j++]=name[i];
965 }
966 temp[j]='\0';
967 return temp;
968 }
969
970 static float bestunit(float val, char **unit)
971 {
972 if (val<1e3) { *unit="U"; return val; }
973 // if (val<1e6) { *unit='m'; return val*1e-6; }
974 *unit=""; return val*1e-6;
975 }
976
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
1003
1004 void sorttransistormos(lofig_list *ptfig, FILE *df, char *vss, char *vdd )
1005 {
1006 lotrs_list *scantrs;
1007 int nb;
1008 ht *trname;
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;
1014 double sa,sb,sd;
1015 double sca,scb,scc,sc;
1016 double nrs,nrd,m;
1017 double nf,nfing;
1018 double geomod;
1019 double absource, lssource, lgsource ;
1020 double abdrain, lsdrain, lgdrain ;
1021 int status, done, in_SPI_TRANSISTOR_AS_INSTANCE ;
1022 ptype_list *pt;
1023
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;
1030
1031 for( scantrs = ptfig->LOTRS, nb=1 ; scantrs ; scantrs = scantrs->NEXT, nb++ );
1032
1033 trname = addht(nb);
1034
1035 nb = 0;
1036
1037 for( scantrs = ptfig->LOTRS; scantrs; scantrs = scantrs->NEXT )
1038 {
1039 done=0;
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)
1044 {
1045 ptype_list *ptype;
1046 if (( ptype = getptype ( scantrs->USER, TRANS_FIGURE ))!=NULL)
1047 in_SPI_TRANSISTOR_AS_INSTANCE=1;
1048 else
1049 in_SPI_TRANSISTOR_AS_INSTANCE=0;
1050 }
1051 else in_SPI_TRANSISTOR_AS_INSTANCE=V_INT_TAB[__SIM_TRANSISTOR_AS_INSTANCE].VALUE;
1052
1053 if( scantrs->TRNAME )
1054 {
1055 if( gethtitem( trname, scantrs->TRNAME ) != EMPTYHT )
1056 {
1057 do
1058 {
1059 nb++;
1060 sprintf( name, "%s_%d", scantrs->TRNAME, nb );
1061 ptr = namealloc( name );
1062 }
1063 while( gethtitem( trname, ptr ) != EMPTYHT );
1064 addhtitem( trname, ptr, 1 );
1065 if (isdiode)
1066 spi_print( df, "D%s ", spi_makename(name) );
1067 else if (isjfet)
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) );
1071 else
1072 spi_print( df, "XM%s ", spi_makename(name) );
1073 }
1074 else
1075 {
1076 if (isdiode)
1077 spi_print( df, "D%s ", spi_makename(scantrs->TRNAME) );
1078 else if (isjfet)
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) );
1082 else
1083 spi_print( df, "XM%s ", spi_makename(scantrs->TRNAME) );
1084 addhtitem( trname, scantrs->TRNAME, 1 );
1085 }
1086 }
1087 else
1088 {
1089 do
1090 {
1091 nb++;
1092 sprintf( name, "%d", nb );
1093 ptr = namealloc( name );
1094 }
1095 while( gethtitem( trname, ptr ) != EMPTYHT );
1096 if (isdiode)
1097 spi_print( df, "D%s ", spi_makename(name) );
1098 else if (isjfet)
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) );
1102 else
1103 spi_print( df, "XM%s ", spi_makename(name) );
1104 addhtitem( trname, ptr, 1 );
1105 }
1106 if (isdiode)
1107 {
1108 if (mbk_isdioden(modname))
1109 {
1110 sortconnecteur( df, scantrs->GRID );
1111 sortconnecteur( df, scantrs->DRAIN );
1112 }
1113 else
1114 {
1115 sortconnecteur( df, scantrs->DRAIN );
1116 sortconnecteur( df, scantrs->GRID );
1117 }
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 );
1123 }
1124 else if (isjfet)
1125 {
1126 sortconnecteur( df, scantrs->DRAIN );
1127 sortconnecteur( df, scantrs->GRID );
1128 sortconnecteur( df, scantrs->SOURCE );
1129 spi_print( df, "%s ", modname);
1130 }
1131 else
1132 {
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 )
1138 {
1139 sortconnecteur( df, scantrs->BULK );
1140 modname=modelname(scantrs, in_SPI_TRANSISTOR_AS_INSTANCE);
1141 spi_print( df, "%s ", modname);
1142 }
1143 else
1144 {
1145 if (MLO_IS_TRANSN(scantrs->TYPE))
1146 {
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);
1150 }
1151 else
1152 {
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);
1156 }
1157 }
1158 if (!in_SPI_TRANSISTOR_AS_INSTANCE)
1159 {
1160 if(scantrs->LENGTH!=0)
1161 {
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 );
1164 else
1165 {
1166 val=bestunit((float)scantrs->LENGTH/SCALE_X, &ptr);
1167 spi_print( df, "L=%g%s ", val, ptr );
1168 }
1169 done|=DONE_L;
1170 }
1171
1172 if(scantrs->WIDTH!=0)
1173 {
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 );
1176 else
1177 {
1178 val=bestunit((float)scantrs->WIDTH/SCALE_X, &ptr);
1179 spi_print( df, "W=%g%s ", val, ptr);
1180 }
1181 done|=DONE_W;
1182 }
1183
1184 if( scantrs->XS >= 0 )
1185 {
1186 if (as_unit!=1 || !V_BOOL_TAB[__SPI_DRIVE_USE_UNITS].VALUE)
1187 spi_print( df,
1188 "AS=%g ",
1189 ((float) scantrs->XS * scantrs->WIDTH / ( SCALE_X * SCALE_X ))*1e-12/as_unit
1190 );
1191 else
1192 spi_print( df,
1193 "AS=%gP ",
1194 (float) scantrs->XS * scantrs->WIDTH / ( SCALE_X * SCALE_X )
1195 );
1196 done|=DONE_AS;
1197 }
1198
1199 if( scantrs->XD >= 0 )
1200 {
1201 if (ad_unit!=1 || !V_BOOL_TAB[__SPI_DRIVE_USE_UNITS].VALUE)
1202 spi_print( df,
1203 "AD=%g ",
1204 ((float) scantrs->XD * scantrs->WIDTH / ( SCALE_X * SCALE_X ))*1e-12/ad_unit
1205 );
1206 else
1207 spi_print( df,
1208 "AD=%gP ",
1209 (float) scantrs->XD * scantrs->WIDTH / ( SCALE_X * SCALE_X )
1210 );
1211 done|=DONE_AD;
1212 }
1213 if( scantrs->PS >= 0 )
1214 {
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 );
1217 else
1218 spi_print( df, "PS=%gU ", (float)scantrs->PS/SCALE_X );
1219 done|=DONE_PS;
1220 }
1221
1222 if( scantrs->PD >= 0 )
1223 {
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 );
1226 else
1227 spi_print( df, "PD=%gU ", (float)scantrs->PD/SCALE_X );
1228 done|=DONE_PD;
1229 }
1230
1231 if ( SPI_DRV_TRSPARAM )
1232 {
1233 nrs = getlotrsparam (scantrs,MBK_NRS,NULL,&status);
1234 if(status == 1) {
1235 spi_print( df, "nrs=%g ",nrs);
1236 done = done | DONE_NRS ;
1237 }
1238
1239 nrd = getlotrsparam (scantrs,MBK_NRD,NULL,&status);
1240 if(status == 1) {
1241 spi_print( df, "nrd=%g ",nrd);
1242 done = done | DONE_NRD ;
1243 }
1244
1245 mulu0 = getlotrsparam (scantrs,MBK_MULU0,NULL,&status);
1246 if(status == 1) {
1247 spi_print( df, "mulu0=%g ",mulu0);
1248 done = done | DONE_MULUO ;
1249 }
1250
1251 delvt0 = getlotrsparam (scantrs,MBK_DELVT0,NULL,&status);
1252 if(status == 1) {
1253 spi_print( df, "delvto=%g ",delvt0);
1254 done = done | DONE_DELVTO ;
1255 }
1256
1257 sa = getlotrsparam (scantrs,MBK_SA,NULL,&status);
1258 if(status == 1) {
1259 spi_print( df, "sa=%g ",sa);
1260 done = done | DONE_SA ;
1261 }
1262
1263 sb = getlotrsparam (scantrs,MBK_SB,NULL,&status);
1264 if(status == 1) {
1265 spi_print( df, "sb=%g ",sb);
1266 done = done | DONE_SB ;
1267 }
1268
1269 sd = getlotrsparam (scantrs,MBK_SD,NULL,&status);
1270 if(status == 1) {
1271 spi_print( df, "sd=%g ",sd);
1272 done = done | DONE_SD ;
1273 }
1274
1275 nf = getlotrsparam (scantrs,MBK_NF,NULL,&status);
1276 if(status == 1) {
1277 spi_print( df, "nf=%g ",nf);
1278 done = done | DONE_NF ;
1279 }
1280
1281 nfing = getlotrsparam (scantrs,MBK_NFING,NULL,&status);
1282 if(status == 1) {
1283 spi_print( df, "nfing=%g ",nfing);
1284 done = done | DONE_NF ;
1285 }
1286
1287 m = getlotrsparam (scantrs,MBK_M,NULL,&status);
1288 if(status == 1) {
1289 spi_print( df, "m=%g ",m);
1290 done = done | DONE_M ;
1291 }
1292
1293 geomod = getlotrsparam (scantrs,MBK_GEOMOD,NULL,&status);
1294 if(status == 1) {
1295 spi_print( df, "geomod=%g ",geomod);
1296 done = done | DONE_GEOMOD ;
1297 }
1298
1299 sc = getlotrsparam (scantrs,MBK_SC,NULL,&status);
1300 if(status == 1) {
1301 spi_print( df, "sc=%g ",sc);
1302 done = done | DONE_SC ;
1303 }
1304
1305 sca = getlotrsparam (scantrs,MBK_SCA,NULL,&status);
1306 if(status == 1) {
1307 spi_print( df, "sca=%g ",sca);
1308 done = done | DONE_SCA ;
1309 }
1310
1311 scb = getlotrsparam (scantrs,MBK_SCB,NULL,&status);
1312 if(status == 1) {
1313 spi_print( df, "scb=%g ",scb);
1314 done = done | DONE_SCB ;
1315 }
1316
1317 scc = getlotrsparam (scantrs,MBK_SCC,NULL,&status);
1318 if(status == 1) {
1319 spi_print( df, "scc=%g ",scc);
1320 done = done | DONE_SCC ;
1321 }
1322
1323 absource = getlotrsparam (scantrs,MBK_ABSOURCE,NULL,&status);
1324 if(status == 1) {
1325 spi_print( df, "absource=%g ",absource);
1326 done = done | DONE_ABSOURCE ;
1327 }
1328
1329 lssource = getlotrsparam (scantrs,MBK_LSSOURCE,NULL,&status);
1330 if(status == 1) {
1331 spi_print( df, "lssource=%g ",lssource);
1332 done = done | DONE_LSSOURCE ;
1333 }
1334
1335 lgsource = getlotrsparam (scantrs,MBK_LGSOURCE,NULL,&status);
1336 if(status == 1) {
1337 spi_print( df, "lgsource=%g ",lgsource);
1338 done = done | DONE_LGSOURCE ;
1339 }
1340
1341 abdrain = getlotrsparam (scantrs,MBK_ABDRAIN,NULL,&status);
1342 if(status == 1) {
1343 spi_print( df, "abdrain=%g ",abdrain);
1344 done = done | DONE_ABDRAIN ;
1345 }
1346
1347 lsdrain = getlotrsparam (scantrs,MBK_LSDRAIN,NULL,&status);
1348 if(status == 1) {
1349 spi_print( df, "lsdrain=%g ",lsdrain);
1350 done = done | DONE_LSDRAIN ;
1351 }
1352
1353 lgdrain = getlotrsparam (scantrs,MBK_LGDRAIN,NULL,&status);
1354 if(status == 1) {
1355 spi_print( df, "lgdrain=%g ",lgdrain);
1356 done = done | DONE_LGDRAIN ;
1357 }
1358 }
1359 if (done==0 || (SPI_FLAGS & SPI_FULL_DRIVE)!=0)
1360 {
1361 optparam_list *optparams, *ptopt;
1362 if ((pt = getptype (scantrs->USER, OPT_PARAMS))) {
1363 optparams = (optparam_list *) pt->DATA;
1364
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;
1372
1373 if (isknowntrsparam (ptopt->UNAME.STANDARD)) { paramname=*ptopt->UNAME.STANDARD; tag=paramname[0]; }
1374 else { paramname=ptopt->UNAME.SPECIAL; tag=ptopt->TAG; }
1375 if (tag == '$') {
1376 spi_print( df, " %s='%s'", *paramname=='$'?paramname+1:paramname, ptopt->UDATA.EXPR );
1377 }
1378 else {
1379 spi_print( df, " %s=%g", paramname, ptopt->UDATA.VALUE );
1380 }
1381 }
1382 }
1383 }
1384 }
1385 else
1386 {
1387 pt = getptype( scantrs->USER, PARAM_CONTEXT );
1388 if( pt ) {
1389 eqt_param *param ;
1390 int i ;
1391
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" ) ) )
1415 continue ;
1416 spi_print( df, " %s=%g", param->EBI[i].NAME, param->EBI[i].VAL );
1417 }
1418 }
1419 }
1420 }
1421 spi_print( df, "\n" );
1422 }
1423
1424 delht( trname );
1425 }
1426
1427 void sortcircuit( ptfig, df )
1428 lofig_list *ptfig;
1429 FILE *df;
1430 {
1431 char *vdd, *vss;
1432 locon_list *scancon;
1433 ptype_list *pt;
1434 char temp[1024];
1435
1436 cherche_alim( ptfig, &vdd, &vss );
1437
1438 /* Sortie des instances et des transistors */
1439
1440 spi_print( df, "\n.subckt %s ", ptfig->NAME );
1441
1442 pt = getptype( ptfig->USER, PH_INTERF );
1443 if( pt )
1444 sortconnecteur_ordre( df, (chain_list*)(pt->DATA), ptfig->LOCON );
1445 else
1446 for( scancon = ptfig->LOCON ; scancon ; scancon = scancon->NEXT )
1447 sortconnecteur( df, scancon );
1448
1449 spi_print( df,"\n" );
1450
1451 {
1452 int count=0;
1453 for (scancon=ptfig->LOCON; scancon!=NULL; scancon=scancon->NEXT)
1454 {
1455 if (scancon->DIRECTION!=UNKNOWN)
1456 {
1457 strcpy(temp,scancon->NAME); spi_vect(temp);
1458 if (count==0) fprintf( df, "* |CONDIR ");
1459 else fprintf( df, ", ");
1460 fprintf( df, temp);
1461 switch (scancon->DIRECTION)
1462 {
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;
1469 }
1470 count++;
1471 if (count==5)
1472 {
1473 fprintf( df, "\n");
1474 count=0;
1475 }
1476 }
1477 }
1478 if (count!=0) fprintf( df, "\n");
1479 }
1480
1481 if( SPI_NAMENODES == FALSE )
1482 sortnet( ptfig, df );
1483
1484 sortinstance( ptfig, df );
1485 sorttransistormos( ptfig, df, vss, vdd);
1486 sortrcn( ptfig, df, vss );
1487 sort_unlinked_net(ptfig, df );
1488
1489 if( spi_getfuncinode() ) {
1490 (spi_getfuncinode())( df, ptfig, spi_getdatainode() );
1491 spi_setfuncinode( NULL, NULL );
1492 }
1493
1494 spi_print( df, ".ends %s\n\n", ptfig->NAME );
1495 }
1496
1497
1498
1499 void spi_env()
1500 {
1501 char *env;
1502
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;
1508
1509 env = V_STR_TAB[__MBK_SPI_COMPOSE_NAME_SEPAR].VALUE;
1510 if( env )
1511 {
1512 switch( strlen( env ) )
1513 {
1514 case 0:
1515 SPI_COMPOSE_NAME_SEPAR = 0;
1516 break;
1517 case 1:
1518 SPI_COMPOSE_NAME_SEPAR = *env;
1519 break;
1520 default :
1521 avt_errmsg (SPI_ERRMSG, "007", AVT_FATAL);
1522 break;
1523 }
1524 }
1525 else {
1526 SPI_COMPOSE_NAME_SEPAR = '_';
1527 }
1528
1529 if (UNIT_LIST==NULL)
1530 {
1531 env = V_STR_TAB[__MBK_DRIVE_DEFAULT_UNITS].VALUE;
1532 if (env!=NULL)
1533 {
1534 char *start=env;
1535 int i=1, tag=0;
1536 char temp[1000];
1537 strcpy(temp," ");
1538
1539 while (*start!='\0')
1540 {
1541 if (*start==';')
1542 {
1543 if (tag!=1)
1544 fprintf(stderr,"error parsing env '%s=%s'\n","MBK_DRIVE_DEFAULT_UNITS",env);
1545 temp[i]='\0';
1546 UNIT_LIST=addchain(UNIT_LIST, strdup(temp));
1547 i=1;
1548 tag=0;
1549 start++;
1550 }
1551 if (*start==',') { temp[i++]=' '; start++; }
1552 else if (*start==':') { temp[i++]=' '; tag++; }
1553 if (*start!=' ') temp[i++]=tolower(*start);
1554 start++;
1555 }
1556 if (i!=1)
1557 {
1558 if (tag!=1)
1559 fprintf(stderr,"error parsing env '%s=%s'\n","MBK_DRIVE_DEFAULT_UNITS",env);
1560 temp[i]='\0';
1561 UNIT_LIST=addchain(UNIT_LIST, strdup(temp));
1562 }
1563 }
1564 }
1565
1566 SPI_FLAGS=mbk_ReadFlags(__MBK_SPICE_DRIVER_FLAGS, spice_opack, sizeof(spice_opack)/sizeof(*spice_opack), 0, 0);
1567
1568 }
1569
1570 void spicesavelofiginfile( lofig_list *ptfig, FILE *df, int driveincludes )
1571 {
1572 chain_list *scanchain;
1573 locon_list *scancon;
1574 num_list *scannum;
1575 char v[1024];
1576 ptype_list *pt;
1577 char *nom;
1578 int colonne;
1579 int lgmot;
1580
1581 spi_env();
1582
1583 // Zinaps: coherence entre les formats mbk
1584 {
1585 loins_list *ls;
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);
1590 }
1591 // Zinaps: c'est tout
1592
1593 /* On va travailler sur les fonctions RCN : */
1594 lofigchain( ptfig );
1595
1596 signalnoeud( ptfig ); /* Calcule les noeuds Spice */
1597
1598 /* Sort la ligne *interf */
1599
1600 if( SPI_NAMENODES == FALSE ) {
1601 colonne = strlen( "* INTERF " );
1602 tooutput( df, "* INTERF " );
1603
1604 pt = getptype( ptfig->USER, PH_INTERF );
1605 if( pt )
1606 {
1607 for( scanchain = (chain_list*)(pt->DATA) ;
1608 scanchain ;
1609 scanchain = scanchain->NEXT
1610 )
1611 {
1612 nom = ((char*)(scanchain->DATA));
1613 strcpy( v, nom );
1614 spi_vect( v );
1615
1616 lgmot = strlen(v)+1;
1617 if( colonne+lgmot >= SPI_MAX_COL-2 )
1618 {
1619 colonne = strlen( "* INTERF " );
1620 tooutput( df, "\n* INTERF " );
1621 }
1622 colonne = colonne + lgmot;
1623
1624 tooutput( df, "%s ", v );
1625
1626 }
1627 }
1628 else
1629 {
1630 for( scancon = ptfig->LOCON ; scancon ; scancon = scancon->NEXT )
1631 {
1632 if( scancon->PNODE )
1633 {
1634 for( scannum = scancon->PNODE ; scannum ; scannum = scannum->NEXT )
1635 {
1636 strcpy( v, scancon->NAME );
1637 spi_vect( v );
1638
1639 lgmot = strlen(v)+1;
1640 if( colonne+lgmot >= SPI_MAX_COL-2 )
1641 {
1642 colonne = strlen( "* INTERF " );
1643 tooutput( df, "\n* INTERF " );
1644 }
1645 colonne = colonne + lgmot;
1646
1647 tooutput( df, "%s ", v );
1648
1649 }
1650 }
1651 else
1652 {
1653 strcpy( v, scancon->NAME );
1654 spi_vect( v );
1655
1656 lgmot = strlen(v)+1;
1657 if( colonne+lgmot >= SPI_MAX_COL-2 )
1658 {
1659 colonne = strlen( "* INTERF " );
1660 tooutput( df, "\n* INTERF " );
1661 }
1662 colonne = colonne + lgmot;
1663
1664 tooutput( df, "%s ", v );
1665 }
1666 }
1667 }
1668
1669 tooutput( df, "\n\n" );
1670 }
1671
1672 /* Sort les .include */
1673
1674 if (driveincludes)
1675 {
1676 for( scanchain = ptfig->MODELCHAIN; scanchain; scanchain = scanchain->NEXT )
1677 {
1678 spi_print( df, ".INCLUDE \"%s.%s\"\n", (char*)scanchain->DATA, OUT_LO );
1679 }
1680 }
1681 sortcircuit( ptfig, df );
1682
1683 // Zinaps: coherence entre les formats mbk, retour a la normal
1684 {
1685 loins_list *ls;
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);
1690 }
1691 // Zinaps: c'est tout
1692
1693 spi_cleanextlocon(ptfig);
1694 freesignalnoeud(ptfig );
1695
1696 }
1697
1698 void spicesavelofig( ptfig )
1699 lofig_list *ptfig;
1700 {
1701 FILE *df; /* descripteur de fichier de sortie */
1702
1703 spi_env();
1704
1705 /* Ouverture du fichier de sortie */
1706 df = mbkfopen( ptfig->NAME, OUT_LO, WRITE_TEXT );
1707 if( !df )
1708 {
1709 fflush( stdout );
1710 fprintf( stderr, "*** mbk error : savelofig impossible.\n" );
1711 fprintf( stderr,
1712 "Can't open file %s.%s for writing.\n",
1713 ptfig->NAME,
1714 OUT_LO
1715 );
1716 EXIT(1);
1717 }
1718
1719 /* header */
1720 spiceprintdate( ptfig->NAME, df );
1721
1722
1723 //---------->
1724 spicesavelofiginfile( ptfig, df, 1);
1725
1726 if( fclose(df) == -1 )
1727 {
1728 fflush( stdout );
1729 fprintf( stderr,
1730 "*** mbk error *** : Can't close file %s.\n,",
1731 ptfig->NAME
1732 );
1733 EXIT(1);
1734 }
1735 }
1736
1737 void spicesavelofigsinfile( chain_list *cl, FILE *df)
1738 {
1739 time_t secondes;
1740 struct tm *jours;
1741 lofig_list *ptfig;
1742
1743 spi_env();
1744
1745 /* Ouverture du fichier de sortie */
1746
1747 time( &secondes );
1748 jours = localtime( &secondes );
1749
1750 while (cl!=NULL)
1751 {
1752 ptfig=(lofig_list *)cl->DATA;
1753 spicesavelofiginfile( ptfig, df, 0);
1754 cl=cl->NEXT;
1755 }
1756 }
1757
1758
1759 void spiceprintdate( char *circuit, FILE *df )
1760 {
1761 char buf[1024];
1762
1763 sprintf(buf,"Spice description of %s\n", circuit );
1764 avt_printExecInfo(df, "*", buf, "");
1765 }
1766
1767
1768
1769 void tooutput( FILE *fd, ...)
1770 {
1771 va_list index;
1772 char *fmt;
1773
1774 va_start( index, fd );
1775
1776 fmt = va_arg( index, char* );
1777
1778 if( vfprintf( fd, fmt, index ) < 0 )
1779 {
1780 fflush( stdout );
1781 fprintf( stderr, "*** spi error *** : Error while writing file.\n" );
1782 perror( "System say " );
1783 EXIT( 1 );
1784 }
1785 }
1786
1787
1788
1789
1790
1791 void spi_vect( s )
1792 char *s;
1793 {
1794 int i,p1;
1795
1796 // if (!MBK_DEVECT) return;
1797
1798 if( s == NULL )
1799 return;
1800 if( s[0] == '\0' )
1801 return;
1802
1803
1804 /* Positionne i sur le premier caractere non espace a la fin de la chaine */
1805 i = strlen( s ) ;
1806 do
1807 i--;
1808 while( s[i] == ' ' && i >0 );
1809
1810 /* passe un eventuel paquet de nombres */
1811 if( i )
1812 {
1813 p1 = i;
1814 while( isdigit( (int)s[i] ) && i >0 )
1815 i--;
1816 if( p1 != i && s[i] == ' ' )
1817 {
1818 if (!strcmp (SPI_VECTOR, "[]"))
1819 {
1820 s[i] = '[';
1821 s[p1+1] = ']';
1822 s[p1+2] = '\0' ;
1823 }
1824 else if (!strcmp (SPI_VECTOR, "()"))
1825 {
1826 s[i] = '(';
1827 s[p1+1] = ')';
1828 s[p1+2] = '\0' ;
1829 }
1830 else if (!strcmp (SPI_VECTOR, "<>"))
1831 {
1832 s[i] = '<';
1833 s[p1+1] = '>';
1834 s[p1+2] = '\0' ;
1835 }
1836 else if (!strcmp (SPI_VECTOR, "_"))
1837 {
1838 s[i] = '_';
1839 s[p1+1] = '\0' ;
1840 }
1841 }
1842 }
1843 }
1844
1845 void spi_print( FILE *fd, ...)
1846 {
1847 va_list index;
1848 char *fmt;
1849 static int lgcurrent=0;
1850 char buf[1000];
1851 int l;
1852
1853 va_start( index, fd );
1854
1855 fmt = va_arg( index, char* );
1856
1857 vsprintf( buf, fmt, index ) ;
1858 l = strlen(buf);
1859
1860 if( lgcurrent==0 || l + lgcurrent < 80 ) {
1861 fputs( buf, fd );
1862 lgcurrent = lgcurrent + l ;
1863 }
1864 else {
1865 fputs( "\n+ ", fd );
1866 fputs( buf, fd );
1867 lgcurrent = l + 2;
1868 }
1869
1870 if( buf[l-1] == '\n' )
1871 lgcurrent = 0;
1872 }
1873
1874 /* Fonctions d'accès pour insérer des mesures dans le fichier de sortie sur les
1875 locons sans avoir à modifier la lofig.
1876
1877 locon->PNODE = 1 2 3
1878 INODE = 12 13 14
1879
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 :
1883
1884 exemple pour des mesures de courant :
1885
1886 Vmeas1 1 12 dc 0v
1887 Vmeas2 2 13 dc 0v
1888 Vmeas3 3 14 dc 0v
1889 */
1890
1891 void spi_setfuncinode( void (*fn)( FILE*, lofig_list*, void* ), void *data )
1892 {
1893 SPI_LOCON_INODE_FUNC = fn;
1894 SPI_LOCON_INODE_DATA = data;
1895 }
1896
1897 void *spi_getdatainode(void)
1898 {
1899 return SPI_LOCON_INODE_DATA;
1900 }
1901
1902 void (*spi_getfuncinode(void))( FILE*, lofig_list*, void* )
1903 {
1904 return SPI_LOCON_INODE_FUNC;
1905 }
1906
1907 num_list* spi_getinode( locon_list *locon )
1908 {
1909 ptype_list *ptl;
1910
1911 ptl = getptype( locon->USER, SPI_LOCON_INODE );
1912 if( !ptl ) return NULL;
1913 return (num_list*)ptl->DATA;
1914 }
1915
1916 void spi_setinode( locon_list *locon, num_list *head )
1917 {
1918 ptype_list *ptl;
1919
1920 if( !locon->SIG )
1921 return;
1922
1923 ptl = getptype( locon->USER, SPI_LOCON_INODE );
1924 if( ptl ) {
1925 freenum( ptl->DATA );
1926 }
1927 else {
1928 locon->USER = addptype( locon->USER, SPI_LOCON_INODE, NULL );
1929 ptl = locon->USER;
1930 }
1931
1932 ptl->DATA = head;
1933
1934 ptl = getptype( locon->SIG->USER, SPI_SIG_INODE );
1935 if( !ptl )
1936 locon->SIG->USER = addptype( locon->SIG->USER,
1937 SPI_SIG_INODE,
1938 (void*)1l
1939 );
1940 else
1941 (*(long *)&ptl->DATA)++;
1942 }
1943
1944 void spi_clearinode( locon_list *locon )
1945 {
1946 ptype_list *ptl;
1947
1948 ptl = getptype( locon->USER, SPI_LOCON_INODE );
1949 if( ptl ) {
1950 freenum( ptl->DATA );
1951 locon->USER = delptype( locon->USER, SPI_LOCON_INODE );
1952 }
1953
1954 if( locon->SIG ) {
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 );
1960 }
1961 }
1962 }
1963
1964 /* renvoie un locon sur le signal pour la détermination d'un nom de
1965 signal représentatif. renvoie NULL pas de solution. */
1966
1967 static char *nameofdevice(locon_list *lc)
1968 {
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;
1971 return "";
1972 }
1973
1974 locon_list* spichooseonelocon( losig_list *losig )
1975 {
1976 ptype_list *ptype ;
1977 locon_list *minlocon = NULL ;
1978 locon_list *locon ;
1979 chain_list *chain ;
1980 int ret;
1981
1982 ptype = getptype( losig->USER, SPI_CHOOSEN_LOCON );
1983 if( ptype )
1984 return (locon_list*)ptype->DATA ;
1985
1986 ptype = getptype( losig->USER, LOFIGCHAIN );
1987 if( ptype ) {
1988
1989 for( chain = ptype->DATA ; chain ; chain = chain->NEXT ) {
1990 locon = (locon_list*)chain->DATA ;
1991 if( locon->PNODE &&
1992 ( !minlocon ||
1993 (ret=strcmp(locon->NAME, minlocon->NAME))<0 ||
1994 (ret==0 && strcmp(nameofdevice(locon), nameofdevice(minlocon))<0))
1995 )
1996 minlocon = locon ;
1997 }
1998
1999 losig->USER = addptype( losig->USER, SPI_CHOOSEN_LOCON, minlocon );
2000 }
2001
2002 return minlocon ;
2003 }