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             : mailto:alliance-users@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 <unistd.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <stdarg.h>
42 #include <time.h>
43 #include <ctype.h>
44 #include <string.h>
45 #include <mut.h>
46 #include <mlo.h>
47 #include <rcn.h>
48 
49 #include "msl.h"
50 #include "spi_drive.h"
51 #include "spi_int.h"
52 #include "spi_msg.h"
53 #include "spi_global.h"
54 
55 
56 
57 void sort_locap(lofig_list *ptfig,FILE *df)  ;
58 void sort_lores(lofig_list *ptfig,FILE *df)  ;
59 void sort_loself(lofig_list *ptfig,FILE *df) ;
60 
61 
62 
63 
64 
65 static char    *TNMOS,
66                *TPMOS;
67 static char    *SPI_NETNAME;
68 char            SPI_NAMEDNODES;
69 
70 #define SPI_NONODES (-1l)
71 #define SPI_MAXSTATICNAME 16
72 
spivecname(char * name)73 char *spivecname( char *name )
74 {
75   char        *new_name;
76   char        *blank;
77   unsigned int length;
78   unsigned int pos_blank;
79 
80   if ( name != (char *)0 )
81   {
82     blank = strchr( name, ' ' );
83     if ( blank != (char *)0 )
84     {
85       length    = strlen( name );
86       pos_blank = blank - name;
87       new_name = (char *)mbkalloc( (length + 2) * sizeof(char) );
88       strcpy(new_name, name);
89       new_name[ pos_blank ] = '[';
90       new_name[ length    ] = ']';
91       new_name[ length + 1] = '\0';
92 
93       name = namealloc( new_name );
94       mbkfree( new_name );
95     }
96   }
97 
98   return( name );
99 }
100 
spinamednode(losig,node)101 char*           spinamednode( losig, node )
102 losig_list      *losig;
103 long            node;
104 {
105   static char    names[SPI_MAXSTATICNAME][255];
106   static int     curnames = 0;
107 
108   ptype_list    *ptptype;
109   convindex	*cvx;
110 
111   curnames++;
112   if( curnames == SPI_MAXSTATICNAME )
113     curnames=0;
114 
115   if( SPI_NAMEDNODES == TRUE ) {
116     if( node == SPI_NONODES ) {
117       if( losig->NAMECHAIN )
118         sprintf( names[curnames], "%s", spivecname( (char*)(losig->NAMECHAIN->DATA)));
119       else
120         sprintf( names[curnames], "sig%ld", losig->INDEX );
121     }
122     else {
123       if( losig->NAMECHAIN ) {
124         sprintf( names[curnames], "%s%c%ld", spivecname((char*)(losig->NAMECHAIN->DATA)),
125                                              SEPAR,
126                                              node
127                );
128       }
129       else {
130         sprintf( names[curnames], "sig%ld%c%ld", losig->INDEX,
131                                                  SEPAR,
132                                                  node
133                );
134       }
135     }
136   }
137   else {
138     ptptype = getptype( losig->USER, SPI_DRIVER_PTYPE );
139     cvx     = (convindex*)(ptptype->DATA);
140     if( node == SPI_NONODES )
141       sprintf( names[curnames], "%d", cvx->premier );
142     else
143       sprintf( names[curnames], "%ld", cvx->premier + node - 1 );
144   }
145 
146   return( names[curnames] );
147 }
148 
cherche_alim(ptfig,vdd,vss)149 void		cherche_alim( ptfig, vdd, vss )
150 lofig_list	*ptfig;
151 char		**vdd;
152 char		**vss;
153 {
154   locon_list	*scancon;
155   losig_list	*signal;
156   static char    stvss[255], stvdd[255];
157 
158   *vdd = 0;
159   *vss = 0;
160 
161   for( scancon = ptfig->LOCON ;
162        scancon && !(*vdd && *vss) ;
163        scancon = scancon->NEXT
164      )
165   {
166     if( isvdd( scancon->NAME ) )
167     {
168       signal  = scancon->SIG;
169       if( scancon->PNODE )
170         strcpy( stvdd, spinamednode( signal, scancon->PNODE->DATA ) );
171       else
172         strcpy( stvdd, spinamednode( signal, SPI_NONODES ) );
173 
174       *vdd = stvdd;
175     }
176 
177     if( isvss( scancon->NAME ) )
178     {
179       signal  = scancon->SIG;
180       if( scancon->PNODE )
181         strcpy( stvss, spinamednode( signal, scancon->PNODE->DATA ) );
182       else
183         strcpy( stvss, spinamednode( signal, SPI_NONODES ) );
184 
185       *vss = stvss;
186     }
187   }
188 }
189 
sortrcn(ptfig,df,vss)190 void            sortrcn( ptfig, df, vss )
191 lofig_list	*ptfig;
192 FILE		*df;
193 char            *vss;
194 {
195   losig_list	*scanlosig;
196   int		 nbr;
197   lowire_list	*scanlowire;
198   int            nbctc;
199   chain_list    *scanchain;
200   chain_list    *headctc;
201   loctc_list    *ptctc;
202 
203   nbctc = 0;
204 
205   for( scanlosig = ptfig->LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT )
206   {
207     if( !scanlosig->PRCN )
208       continue;
209 
210     if( scanlosig->PRCN->PWIRE || scanlosig->PRCN->PCTC )
211     {
212       nbr = 1;
213 
214 
215       for( scanlowire = scanlosig->PRCN->PWIRE ;
216            scanlowire ;
217            scanlowire = scanlowire->NEXT )
218       {
219         tooutput( df,
220                   "R%d_%d %s %s %g\n",
221                   scanlosig->INDEX,
222                   nbr,
223                   spinamednode( scanlosig, scanlowire->NODE1 ),
224                   spinamednode( scanlosig, scanlowire->NODE2 ),
225                   scanlowire->RESI < RESIMINI ? RESIMINI : scanlowire->RESI
226                 );
227 
228 	/* HSpice ne supporte pas 1e-6P : Il ne prendra pas en compte le P, et
229 	 * on aura 1 micron au lieu de 1e-18. */
230 
231         if( scanlowire->CAPA / 2.0 >= CAPAMINI )
232         {
233           tooutput( df,
234                     "C%d_%d1 %s %s %g\n",
235                     scanlosig->INDEX,
236                     nbr,
237                     spinamednode( scanlosig, scanlowire->NODE1 ),
238                     vss,
239                     scanlowire->CAPA / 2.0 * 1e-12
240                   );
241 
242           tooutput( df,
243                     "C%d_%d2 %s %s %g\n",
244                     scanlosig->INDEX,
245                     nbr,
246                     spinamednode( scanlosig, scanlowire->NODE2 ),
247                     vss,
248                     scanlowire->CAPA / 2.0 * 1e-12
249                   );
250         }
251 
252         nbr++;
253       }
254     }
255 
256     /* On ne sort la capa totale que si on a ni RCN, ni CTC */
257 
258     if( !scanlosig->PRCN->PWIRE && !scanlosig->PRCN->PCTC )
259     {
260       if( scanlosig->PRCN->CAPA >= CAPAMINI )
261       {
262         tooutput( df,
263                   "C%d %s %s %g\n",
264                   scanlosig->INDEX,
265                   spinamednode( scanlosig, SPI_NONODES ),
266                   vss,
267                   scanlosig->PRCN->CAPA * 1e-12
268                 );
269       }
270     }
271   }
272 
273   headctc = getallctc( ptfig );
274 
275   for( scanchain = headctc ; scanchain ; scanchain = scanchain->NEXT )
276   {
277     ptctc = (loctc_list*)scanchain->DATA ;
278 
279     if( ptctc->CAPA >= CAPAMINI )
280     {
281       tooutput( df,
282                 "C_ctc_%d %s %s %g\n",
283                 nbctc,
284                 spinamednode( ptctc->SIG1, ptctc->NODE1 > 0 ? ptctc->NODE1 :
285                                                               SPI_NONODES    ),
286                 spinamednode( ptctc->SIG2, ptctc->NODE2 > 0 ? ptctc->NODE2 :
287                                                               SPI_NONODES    ),
288                 ptctc->CAPA * 1e-12
289               );
290     }
291 
292     nbctc++;
293   }
294 
295   freechain( headctc );
296 }
297 
signalnoeud(ptfig)298 void		signalnoeud( ptfig )
299 lofig_list	*ptfig;
300 {
301   losig_list	*scanlosig;
302   convindex	*nouveau;
303   int		 dernier;
304 
305   dernier = 1;
306 
307   for( scanlosig = ptfig -> LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT )
308   {
309     nouveau          = ( convindex* ) mbkalloc( sizeof( convindex ) );
310     nouveau->sig     = scanlosig;
311     nouveau->premier = dernier;
312 
313     if( scanlosig->PRCN && scanlosig->PRCN->NBNODE > 0 )
314       dernier += scanlosig->PRCN->NBNODE ;
315     else
316       dernier++;
317 
318     scanlosig->USER = addptype( scanlosig->USER, SPI_DRIVER_PTYPE, nouveau );
319   }
320 }
321 
sortconnecteur(df,c,position)322 int		sortconnecteur( df, c, position )
323 FILE		*df;
324 locon_list	*c;
325 int             position;
326 {
327   losig_list	*signal;
328   num_list	*tetenum,*scannum;
329   char           v[1024] = "";
330   int            lgmot;
331 
332   signal    = c->SIG;
333 
334   if( c->PNODE )
335   {
336     tetenum = c->PNODE;
337     for( scannum = tetenum ; scannum ; scannum = scannum->NEXT )
338     {
339       sprintf( v,"%s ", spinamednode( signal, scannum->DATA) );
340       lgmot = strlen(v);
341       if( lgmot + position >= SPI_MAX_COL - 2 )
342       {
343         tooutput( df, "\n+ " );
344         position = lgmot+2;
345       }
346       else
347         position = position + lgmot;
348 
349       tooutput( df, v );
350     }
351   }
352   else
353   {
354     lgmot = strlen(v);
355     if( lgmot + position >= SPI_MAX_COL - 2 )
356     {
357       tooutput( df, "\n+ " );
358       position = lgmot+2;
359     }
360     else
361       position = position + lgmot;
362     sprintf( v, "%s ", spinamednode( signal, SPI_NONODES ) );
363     tooutput( df, v );
364   }
365 
366   return( position );
367 }
368 
sortconnecteur_ordre(df,ordre,liste,position)369 int             sortconnecteur_ordre( df, ordre, liste, position )
370 FILE            *df;
371 chain_list      *ordre;
372 locon_list      *liste;
373 int              position;
374 {
375   chain_list    *scanordre;
376   locon_list    *scanlocon;
377   int            num;
378   int            n;
379   chain_list    *cpteordre;
380   losig_list    *signal;
381   num_list      *scannum;
382   num_list      *tetenum;
383   char           v[1024];
384   int            lgmot;
385 
386   for( scanordre = ordre ; scanordre ; scanordre = scanordre->NEXT )
387   {
388     for( scanlocon = liste ; scanlocon ; scanlocon = scanlocon->NEXT )
389       if( scanlocon->NAME == ((char*)(scanordre->DATA)) )
390         break;
391 
392     if( !scanlocon )
393     {
394       fflush( stdout );
395       fprintf( stderr, "%s.\n", SPIMSG(5) );
396       EXIT(1);
397     }
398 
399     num = 0;
400     for( cpteordre = ordre ;
401          cpteordre != scanordre ;
402          cpteordre = cpteordre->NEXT
403        )
404       if( ((char*)(cpteordre->DATA)) == scanlocon->NAME )
405         num++;
406 
407     signal    = scanlocon->SIG;
408 
409     if( scanlocon->PNODE )
410     {
411       tetenum = scanlocon->PNODE;
412       for( scannum = tetenum, n=0 ; n<num ; scannum = scannum->NEXT, n++ );
413       sprintf( v, "%s ", spinamednode( signal, scannum->DATA ) );
414     }
415     else
416       sprintf( v, "%s ", spinamednode( signal, SPI_NONODES ) );
417 
418     lgmot = strlen(v);
419     if( lgmot + position >= SPI_MAX_COL )
420     {
421       tooutput( df, "\n+ " );
422       position = lgmot + 2;
423     }
424     else
425       position = position + lgmot;
426 
427     tooutput( df, v );
428   }
429 
430   return( position );
431 }
432 
sortnet(ptfig,df)433 void		sortnet( ptfig, df )
434 lofig_list	*ptfig;
435 FILE		*df;
436 {
437   losig_list	*scanlosig;
438   locon_list	*scanlocon;
439   chain_list	*scanchain;
440   ptype_list	*ptl;
441   convindex	*conv;
442   num_list	*scannum;
443   loctc_list	*ptctc;
444   int		 i;
445 
446   for( scanlosig = ptfig->LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT )
447   {
448     ptl  = getptype(scanlosig->USER,SPI_DRIVER_PTYPE);
449     conv = (convindex*)(ptl->DATA);
450     if( scanlosig->TYPE == EXTERNAL )
451     {
452 
453       if( scanlosig->TYPE == EXTERNAL )
454       {
455         ptl = getptype( scanlosig->USER, LOFIGCHAIN );
456 
457         if( !ptl )
458         {
459           fflush( stdout );
460           fprintf( stderr, "*** spi error *** : LOFIGCHAIN missing.\n" );
461           EXIT(1);
462         }
463 
464         for( scanchain = (chain_list*)(ptl->DATA) ;
465              scanchain ;
466              scanchain = scanchain->NEXT
467            )
468         {
469           scanlocon = (locon_list*)scanchain->DATA ;
470           if( scanlocon->ROOT == ptfig )
471           {
472             if( scanlocon->PNODE )
473             {
474               for( scannum = scanlocon->PNODE ;
475                    scannum ;
476                    scannum = scannum->NEXT
477                  )
478               {
479                 spi_vect( scanlocon->NAME );
480                 tooutput( df,
481                           "* %s %d = %s\n",
482                           SPI_NETNAME,
483                           scannum->DATA + conv->premier - 1 ,
484                           scanlocon->NAME
485                         );
486               }
487             }
488             else
489             {
490               spi_vect( scanlocon->NAME );
491               tooutput( df,
492                         "* %s %d = %s\n",
493                         SPI_NETNAME,
494                         conv->premier,
495                         scanlocon->NAME
496                       );
497             }
498           }
499         }
500       }
501     }
502     else
503     if( scanlosig->NAMECHAIN )
504     {
505       i = 0 ;
506       if( scanlosig->PRCN )
507       {
508         if( scanlosig->PRCN->PWIRE )
509           i = scanlosig->PRCN->PWIRE->NODE1 ;
510         else
511         if( scanlosig->PRCN->PCTC )
512         {
513           ptctc = (loctc_list*)scanlosig->PRCN->PCTC->DATA;
514           if( ptctc->SIG1 == scanlosig )
515             i = ptctc->NODE1;
516           else
517             i = ptctc->NODE2;
518         }
519 
520         if( i != 0 )
521           i = i + conv->premier - 1 ;
522       }
523 
524       if( i == 0 );
525         i = conv->premier ;
526 
527       spi_vect( (char*)scanlosig->NAMECHAIN->DATA );
528       tooutput( df,
529                 "* %s %d = %s\n",
530                 SPI_NETNAME,
531                 i,
532                 (char*)scanlosig->NAMECHAIN->DATA
533               ) ;
534     }
535   }
536 }
537 
sortinstance(ptfig,df)538 void		sortinstance( ptfig, df )
539 lofig_list	*ptfig;
540 FILE		*df;
541 {
542   loins_list	*scanloins;
543   locon_list	*scanloconins;
544   ptype_list    *pt;
545   char           v[1024];
546   int            lgmot;
547   int            colonne;
548 
549   for( scanloins = ptfig->LOINS ; scanloins ; scanloins = scanloins->NEXT )
550   {
551     sprintf( v, "x%s ", scanloins->INSNAME );
552     colonne = strlen( v );
553     tooutput( df, v );
554 
555     /* L'ordre des connecteurs entre la lofig et sa version instanci�e n'est
556        pas le meme */
557 
558     pt = getptype( scanloins->USER, PH_INTERF );
559     if( pt )
560       colonne = sortconnecteur_ordre( df,
561                                       (chain_list*)(pt->DATA),
562                                       scanloins->LOCON,
563                                       colonne
564                                     );
565     else
566       for( scanloconins = scanloins->LOCON ;
567            scanloconins ;
568            scanloconins = scanloconins->NEXT
569          )
570         colonne = sortconnecteur( df, scanloconins, colonne );
571 
572     sprintf( v, "%s\n", scanloins->FIGNAME );
573     lgmot = strlen(v);
574     if( lgmot+colonne >= SPI_MAX_COL -2 )
575       tooutput( df, "\n+" );
576     tooutput( df, v );
577   }
578 }
579 
sorttransistormos(ptfig,df,vss,vdd)580 void            sorttransistormos( ptfig, df, vss, vdd )
581 lofig_list      *ptfig;
582 FILE            *df;
583 char            *vss;
584 char            *vdd;
585 {
586   lotrs_list	*scantrs;
587   int		 nb;
588   ht            *trname;
589   char           name[1024], *ptr ;
590 
591   for( scantrs = ptfig->LOTRS, nb=1 ; scantrs ; scantrs = scantrs->NEXT, nb++ );
592 
593   trname = addht(nb);
594 
595   nb = 0;
596 
597   for( scantrs = ptfig->LOTRS; scantrs; scantrs = scantrs->NEXT )
598   {
599     if( scantrs->TRNAME )
600     {
601       if( gethtitem( trname, scantrs->TRNAME ) != EMPTYHT )
602       {
603         do
604         {
605           nb++;
606           sprintf( name, "%s_%d", scantrs->TRNAME, nb );
607           ptr = namealloc( name );
608         }
609         while( gethtitem( trname, ptr ) != EMPTYHT );
610         addhtitem( trname, ptr, 1 );
611         tooutput( df, "M%s ", name );
612       }
613       else
614       {
615         tooutput( df, "M%s ", scantrs->TRNAME );
616         addhtitem( trname, scantrs->TRNAME, 1 );
617       }
618     }
619     else
620     {
621       do
622       {
623         nb++;
624         sprintf( name, "%d", nb );
625         ptr = namealloc( name );
626       }
627       while( gethtitem( trname, ptr ) != EMPTYHT );
628       tooutput( df, "M%s ", name );
629       addhtitem( trname, ptr, 1 );
630     }
631 
632     sortconnecteur( df, scantrs->DRAIN,1  );
633     sortconnecteur( df, scantrs->GRID,1   );
634     sortconnecteur( df, scantrs->SOURCE,1 );
635     if( scantrs->BULK->SIG )
636     {
637       sortconnecteur( df, scantrs->BULK,1  );
638     }
639     else
640     {
641       if( IsTransN(scantrs->TYPE) )
642       {
643         if( !vss )
644         {
645           fflush( stdout );
646           fprintf( stderr,
647                    "*** spi error *** : Can't find signal VSS on figure %s.\n",
648                    ptfig->NAME
649                  );
650           EXIT(1);
651         }
652 
653         tooutput( df, "%s ", vss );
654       }
655       else
656       {
657         if( !vdd )
658         {
659           fflush( stdout );
660           fprintf( stderr,
661                    "*** spi error *** : Can't find signal VDD on figure %s.\n",
662                    ptfig->NAME
663                  );
664           EXIT(1);
665         }
666 
667         tooutput( df, "%s ", vdd );
668       }
669     }
670 
671     tooutput( df, "%s ", spitransmodel( scantrs->TYPE ) );
672 #define SCALED(x,y) (double)((double)(x)/(double)(y))
673 
674     if(scantrs->LENGTH!=0)
675       tooutput( df, "L=%gU ", SCALED(scantrs->LENGTH, SCALE_X));
676 
677     if(scantrs->WIDTH!=0)
678       tooutput( df, "W=%gU ", SCALED(scantrs->WIDTH, SCALE_X));
679 
680     if( scantrs->XS != 0 )
681       tooutput( df,
682                 "AS=%gP ",
683                 SCALED(scantrs->XS * scantrs->WIDTH,  SCALE_X * SCALE_X)
684               );
685 
686     if( scantrs->XD != 0 )
687       tooutput( df,
688                 "AD=%gP ",
689                 SCALED(scantrs->XD * scantrs->WIDTH,  SCALE_X * SCALE_X)
690               );
691 
692     if( scantrs->PS != 0 )
693       tooutput( df, "PS=%gU ", SCALED(scantrs->PS, SCALE_X));
694 
695     if( scantrs->PD != 0 )
696       tooutput( df, "PD=%gU ", SCALED(scantrs->PD, SCALE_X));
697 
698     tooutput( df, "\n" );
699   }
700 
701   delht( trname );
702 }
703 
sortcircuit(ptfig,df)704 void		sortcircuit( ptfig, df )
705 lofig_list	*ptfig;
706 FILE		*df;
707 {
708   char          *vdd, *vss;
709   locon_list	*scancon;
710   ptype_list    *pt;
711   int            colonne;
712   char           v[1024];
713 
714   cherche_alim( ptfig, &vdd, &vss );
715 
716   /* Sortie des instances et des transistors */
717 
718   sprintf( v, "\n.subckt %s ", ptfig->NAME );
719   colonne = strlen( v );
720 
721   tooutput( df, v );
722 
723   pt = getptype( ptfig->USER, PH_INTERF );
724   if( pt )
725     colonne = sortconnecteur_ordre( df,
726                                     (chain_list*)(pt->DATA),
727                                     ptfig->LOCON,
728                                     colonne
729                                   );
730   else
731     for( scancon = ptfig->LOCON ; scancon ; scancon = scancon->NEXT )
732       colonne = sortconnecteur( df, scancon, colonne );
733 
734   tooutput( df,"\n" );
735 
736   if( SPI_NAMEDNODES == FALSE ) {
737     sortnet( ptfig, df );
738   }
739 
740   sortinstance( ptfig, df );
741   sorttransistormos( ptfig, df, vss, vdd);
742 
743   sort_locap(ptfig,df)  ;
744   sort_lores(ptfig,df)  ;
745   sort_loself(ptfig,df) ;
746 
747   sortrcn( ptfig, df, vss );
748 
749   tooutput( df, ".ends %s\n\n", ptfig->NAME );
750 }
751 
spicesavelofig(ptfig)752 void		spicesavelofig( ptfig )
753 lofig_list	*ptfig;
754 {
755   FILE		*df;		/* descripteur de fichier de sortie */
756   chain_list    *scanchain;
757   locon_list    *scancon;
758   num_list      *scannum;
759   char		 v[1024];
760   ptype_list    *pt;
761   char          *nom;
762   time_t         secondes;
763   struct tm     *jours;
764   char          *env;
765   int            colonne;
766   int            lgmot;
767 
768   env = mbkgetenv( "MBK_SPI_TN" );
769 
770   if(env)
771     TNMOS = env;
772   else
773     TNMOS    = "TN";
774 
775   env = mbkgetenv( "MBK_SPI_TP" );
776 
777   if(env)
778     TPMOS = env;
779   else
780     TPMOS    = "TP";
781 
782   env = mbkgetenv( "MBK_SPI_NETNAME" );
783 
784   if( env )
785     SPI_NETNAME = env;
786   else
787     SPI_NETNAME = "NET";
788 
789   env = mbkgetenv( "MBK_SPI_NAMEDNODES" );
790 
791   if( env )
792     SPI_NAMEDNODES = TRUE ;
793   else
794     SPI_NAMEDNODES = FALSE ;
795 
796   spi_init_lang();
797 
798   /* Ouverture du fichier de sortie */
799   df = mbkfopen( ptfig->NAME, OUT_LO, WRITE_TEXT );
800   if( !df )
801   {
802     fflush( stdout );
803     fprintf( stderr, "*** mbk error : savelofig impossible.\n" );
804     fprintf( stderr,
805              "Can't open file %s.%s for writing.\n",
806              ptfig->NAME,
807              OUT_LO
808            );
809     EXIT(1);
810   }
811 
812 
813   time( &secondes );
814   jours = localtime( &secondes );
815 
816   tooutput( df, "* Spice description of %s\n", ptfig->NAME );
817   tooutput( df, "* Spice driver version %d\n",VERSION );
818   tooutput( df,
819            "* Date ( dd/mm/yyyy hh:mm:ss ): %2d/%02d/%04d at %2d:%02d:%02d\n\n",
820             jours->tm_mday,
821             jours->tm_mon+1,
822             jours->tm_year+1900,
823             jours->tm_hour,
824             jours->tm_min,
825             jours->tm_sec
826           );
827 
828   /* On va travailler sur les fonctions RCN : */
829   lofigchain( ptfig );
830 
831   signalnoeud( ptfig );		/* Calcule les noeuds Spice */
832 
833   /* Sort la ligne *interf */
834 
835   colonne = strlen( "* INTERF " );
836   tooutput( df, "* INTERF " );
837 
838   pt = getptype( ptfig->USER, PH_INTERF );
839   if( pt )
840   {
841     for( scanchain = (chain_list*)(pt->DATA) ;
842          scanchain ;
843          scanchain = scanchain->NEXT
844        )
845     {
846       nom = ((char*)(scanchain->DATA));
847       strcpy( v, nom );
848       spi_vect( v );
849 
850       lgmot = strlen(v)+1;
851       if( colonne+lgmot >= SPI_MAX_COL-2 )
852       {
853         colonne = strlen( "* INTERF " );
854         tooutput( df, "\n* INTERF " );
855       }
856       colonne = colonne + lgmot;
857 
858       tooutput( df, "%s ", v );
859 
860     }
861   }
862   else
863   {
864     for( scancon = ptfig->LOCON ; scancon ; scancon = scancon->NEXT )
865     {
866       if( scancon->PNODE )
867       {
868         for( scannum = scancon->PNODE ; scannum ; scannum = scannum->NEXT )
869         {
870           strcpy( v, scancon->NAME );
871           spi_vect( v );
872 
873           lgmot = strlen(v)+1;
874           if( colonne+lgmot >= SPI_MAX_COL-2 )
875           {
876             colonne = strlen( "* INTERF " );
877             tooutput( df, "\n* INTERF " );
878           }
879           colonne = colonne + lgmot;
880 
881           tooutput( df, "%s ", v );
882 
883         }
884       }
885       else
886       {
887         strcpy( v, scancon->NAME );
888         spi_vect( v );
889 
890         lgmot = strlen(v)+1;
891         if( colonne+lgmot >= SPI_MAX_COL-2 )
892         {
893           colonne = strlen( "* INTERF " );
894           tooutput( df, "\n* INTERF " );
895         }
896         colonne = colonne + lgmot;
897 
898         tooutput( df, "%s ", v );
899       }
900     }
901   }
902 
903   tooutput( df, "\n\n" );
904 
905   /* Sort les .include */
906 
907   for( scanchain = ptfig->MODELCHAIN; scanchain; scanchain = scanchain->NEXT )
908   {
909     tooutput( df, ".INCLUDE %s.%s\n", (char*)scanchain->DATA, OUT_LO );
910   }
911 
912   sortcircuit( ptfig, df );
913 
914   if( fclose(df) == -1 )
915   {
916     fflush( stdout );
917     fprintf( stderr,
918              "*** mbk error *** : Can't close file %s.\n,",
919              ptfig->NAME
920            );
921     EXIT(1);
922   }
923 }
924 
tooutput(FILE * fd,...)925 void            tooutput( FILE *fd, ... )
926 {
927   va_list       index;
928   char          *fmt;
929 
930   va_start( index, fd );
931 
932   fmt = va_arg( index, char* );
933 
934   if( vfprintf( fd, fmt, index ) < 0 )
935   {
936     fflush( stdout );
937     fprintf( stderr, "*** spi error *** : Error while writing file.\n" );
938     perror( "System say " );
939     EXIT( 1 );
940   }
941 
942   va_end( index );
943 }
944 
spi_vect(s)945 void spi_vect( s )
946 char *s;
947 {
948   int i,p1;
949 
950   if( s == NULL )
951     return;
952   if( s[0] == '\0' )
953     return;
954 
955 
956   /* Positionne i sur le premier caractere non espace a la fin de la chaine */
957   i = strlen( s ) ;
958   do
959     i--;
960   while( s[i] == ' ' && i >0 );
961 
962   /* passe un eventuel paquet de nombres */
963   if( i )
964   {
965     p1 = i;
966     while( isdigit( (int)s[i] ) && i >0 )
967       i--;
968     if( p1 != i && s[i] == ' ' )
969     {
970       s[i]    = '[';
971       s[p1+1] = ']';
972       s[p1+2] = '\0' ;
973     }
974   }
975 }
976 
977 
978 /****************************************************************************************************/
979 /************************************** locap, lores and loself *************************************/
980 /****************************************************************************************************/
981 
sort_locap(lofig_list * ptfig,FILE * df)982 void sort_locap(lofig_list *ptfig,FILE *df)
983 {
984   locap_list	*scancap   = NULL ;
985   int		nb         = 0    ;
986   ht            *capname   = NULL ;
987   char          name[1024]        ;
988   char          *ptr       = NULL ;
989 
990   for(scancap = ptfig -> LOCAP,nb = 1 ; scancap != NULL; scancap = scancap -> NEXT,nb++) ;
991 
992   capname = addht(nb) ;
993 
994   nb = 0 ;
995 
996   for(scancap = ptfig -> LOCAP ; scancap != NULL ; scancap = scancap -> NEXT)
997     {
998       if(scancap -> NAME != NULL)
999 	{
1000 	  if(gethtitem(capname,scancap -> NAME) != EMPTYHT)
1001 	    {
1002 	      do
1003 		{
1004 		  nb++ ;
1005 		  sprintf(name,"%s_%d",scancap -> NAME,nb) ;
1006 		  ptr = namealloc(name) ;
1007 		}
1008 
1009 	      while(gethtitem(capname,ptr) != EMPTYHT) ;
1010 
1011 	      addhtitem(capname,ptr,1) ;
1012 	      tooutput(df,"C%s ",name) ;
1013 	    }
1014 	  else
1015 	    {
1016 	      tooutput(df,"C%s ",scancap -> NAME) ;
1017 	      addhtitem(capname,scancap -> NAME,1) ;
1018 	    }
1019 	}
1020       else
1021 	{
1022 	  do
1023 	    {
1024 	      nb++ ;
1025 	      sprintf(name,"%d",nb) ;
1026 	      ptr = namealloc(name) ;
1027 	    }
1028 
1029 	  while(gethtitem(capname,ptr) != EMPTYHT) ;
1030 
1031 	  tooutput(df,"C%s ",name) ;
1032 	  addhtitem(capname,ptr,1) ;
1033 	}
1034 
1035       sortconnecteur(df,scancap -> TCON,1) ;
1036       sortconnecteur(df,scancap -> BCON,1) ;
1037 
1038       tooutput(df,"%g ",(float)scancap -> CAPA) ;
1039 
1040       tooutput(df,"\n") ;
1041     }
1042 
1043   delht(capname) ;
1044 }
1045 
1046 /****************************************************************************************************/
1047 
sort_lores(lofig_list * ptfig,FILE * df)1048 void sort_lores(lofig_list *ptfig,FILE *df)
1049 {
1050   lores_list	*scanres   = NULL ;
1051   int		nb         = 0    ;
1052   ht            *resname   = NULL ;
1053   char          name[1024]        ;
1054   char          *ptr       = NULL ;
1055 
1056   for(scanres = ptfig -> LORES,nb = 1 ; scanres != NULL; scanres = scanres -> NEXT,nb++) ;
1057 
1058   resname = addht(nb) ;
1059 
1060   nb = 0 ;
1061 
1062   for(scanres = ptfig -> LORES ; scanres != NULL ; scanres = scanres -> NEXT)
1063     {
1064       if(scanres -> NAME != NULL)
1065 	{
1066 	  if(gethtitem(resname,scanres -> NAME) != EMPTYHT)
1067 	    {
1068 	      do
1069 		{
1070 		  nb++ ;
1071 		  sprintf(name,"%s_%d",scanres -> NAME,nb) ;
1072 		  ptr = namealloc(name) ;
1073 		}
1074 
1075 	      while(gethtitem(resname,ptr) != EMPTYHT) ;
1076 
1077 	      addhtitem(resname,ptr,1) ;
1078 	      tooutput(df,"R%s ",name) ;
1079 	    }
1080 	  else
1081 	    {
1082 	      tooutput(df,"R%s ",scanres -> NAME) ;
1083 	      addhtitem(resname,scanres -> NAME,1) ;
1084 	    }
1085 	}
1086       else
1087 	{
1088 	  do
1089 	    {
1090 	      nb++ ;
1091 	      sprintf(name,"%d",nb) ;
1092 	      ptr = namealloc(name) ;
1093 	    }
1094 
1095 	  while(gethtitem(resname,ptr) != EMPTYHT) ;
1096 
1097 	  tooutput(df,"R%s ",name) ;
1098 	  addhtitem(resname,ptr,1) ;
1099 	}
1100 
1101       sortconnecteur(df,scanres -> RCON1,1) ;
1102       sortconnecteur(df,scanres -> RCON2,1) ;
1103 
1104       tooutput(df,"%g ",(float)scanres -> RESI) ;
1105 
1106       tooutput(df,"\n") ;
1107     }
1108 
1109   delht(resname) ;
1110 }
1111 
1112 /****************************************************************************************************/
1113 
sort_loself(lofig_list * ptfig,FILE * df)1114 void sort_loself(lofig_list *ptfig,FILE *df)
1115 {
1116   loself_list	*scanself   = NULL ;
1117   int		nb         = 0    ;
1118   ht            *selfname   = NULL ;
1119   char          name[1024]        ;
1120   char          *ptr       = NULL ;
1121 
1122   for(scanself = ptfig -> LOSELF,nb = 1 ; scanself != NULL; scanself = scanself -> NEXT,nb++) ;
1123 
1124   selfname = addht(nb) ;
1125 
1126   nb = 0 ;
1127 
1128   for(scanself = ptfig -> LOSELF ; scanself != NULL ; scanself = scanself -> NEXT)
1129     {
1130       if(scanself -> NAME != NULL)
1131 	{
1132 	  if(gethtitem(selfname,scanself -> NAME) != EMPTYHT)
1133 	    {
1134 	      do
1135 		{
1136 		  nb++ ;
1137 		  sprintf(name,"%s_%d",scanself -> NAME,nb) ;
1138 		  ptr = namealloc(name) ;
1139 		}
1140 
1141 	      while(gethtitem(selfname,ptr) != EMPTYHT) ;
1142 
1143 	      addhtitem(selfname,ptr,1) ;
1144 	      tooutput(df,"L%s ",name) ;
1145 	    }
1146 	  else
1147 	    {
1148 	      tooutput(df,"L%s ",scanself -> NAME) ;
1149 	      addhtitem(selfname,scanself -> NAME,1) ;
1150 	    }
1151 	}
1152       else
1153 	{
1154 	  do
1155 	    {
1156 	      nb++ ;
1157 	      sprintf(name,"%d",nb) ;
1158 	      ptr = namealloc(name) ;
1159 	    }
1160 
1161 	  while(gethtitem(selfname,ptr) != EMPTYHT) ;
1162 
1163 	  tooutput(df,"L%s ",name) ;
1164 	  addhtitem(selfname,ptr,1) ;
1165 	}
1166 
1167       sortconnecteur(df,scanself -> SCON1,1) ;
1168       sortconnecteur(df,scanself -> SCON2,1) ;
1169 
1170       tooutput(df,"%g ",(float)scanself -> SELF) ;
1171 
1172       tooutput(df,"\n") ;
1173     }
1174 
1175   delht(selfname) ;
1176 }
1177