Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / mbkspice / spi2spef.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <math.h>
5 #include <ctype.h>
6 #include <time.h>
7
8 #include MUT_H
9 #include MLO_H
10 #include MLU_H
11 #include RCN_H
12 #include EQT_H
13 #include MSL_H
14 #include AVT_H
15 #include "spi_int.h"
16 #include "spi_hash.h"
17 #include "spi_parse.h"
18
19 //#define CORRECT_CONNECT
20 //#define FULLVALUE
21 //#define DELAY_DEBUG_STAT
22 extern float SPI_SCALE_RESIFACTOR ;
23 extern float SPI_SCALE_CAPAFACTOR ;
24
25 static HeapAlloc ha_item;
26 static int freeitemspace;
27
28 #ifdef ENABLE_STATS
29 long ____nbequi=0;
30 #endif
31
32 extern int spi_get_xy (chain_list *ligne, float *com_x, float *com_y, int *Tx, int *Ty, int *R, int *A);
33
34 void _spispef_setnodename(subckt *cir, __node_ * n, char *ins, char *con)
35 {
36 __names_ *p;
37
38 CheckNodeSupInfo(cir, n);
39
40 p=(__names_ *)AdvancedBlockAlloc(cir->aba, sizeof(ptype_list));
41 p->con=con;
42 p->ins=ins;
43 p->next=n->SUPINFO->names;
44 n->SUPINFO->names=p;
45 }
46
47 /*
48 static int countchain(chain_list *cl)
49 {
50 int i=0;
51 while (cl!=NULL) { i++; cl=cl->NEXT;}
52 return i;
53 }
54 */
55
56 void _spispef_complete_node(subckt *cir, char *name, __node_ *n, int mark, int justcreated)
57 {
58 __equi_ *e;
59
60 #ifndef __ALL_WARNING__
61 name = NULL;
62 #endif
63 if (!justcreated)
64 {
65 e=n->signal;
66 if (mark)
67 {
68 if (e->firstline==-1) e->firstline=cir->TOTAL_LINE_COUNTER;
69 if (e->lastline==-1 || e->lastline<cir->TOTAL_LINE_COUNTER) e->lastline=cir->TOTAL_LINE_COUNTER;
70 }
71 return;
72 }
73
74 e=AddHeapItem(&cir->ha_equi);
75 #ifdef ENABLE_STATS
76 ____nbequi++;
77 #endif
78 n->signal=e;
79 n->SUIV=NULL;
80 e->nodes=n;
81 e->lastnode=n;
82 if (mark)
83 e->firstline=e->lastline=cir->TOTAL_LINE_COUNTER;
84 else
85 e->firstline=e->lastline=-1;
86 e->b.nbnodes=1;
87 e->nbelem=0;
88 e->next=cir->all_equi;
89 if (cir->all_equi!=NULL) cir->all_equi->a.prev=e;
90 e->a.prev=NULL;
91 // e->tag=0;
92 cir->all_equi=e;
93 }
94
95 void _spispef_mergenodes(subckt *cir, __node_ *a, __node_ *b)
96 {
97 __node_ *n;
98 if (a->signal==b->signal) return;
99 // printf("merge %d %d\n",a->index,b->index);
100 if (a->signal->b.nbnodes>b->signal->b.nbnodes)
101 {
102 a->signal->nbelem+=b->signal->nbelem;
103 // a->signal->tag|=b->signal->tag;
104 n=b->signal->nodes;
105 a->signal->b.nbnodes+=b->signal->b.nbnodes;
106
107 a->signal->lastnode->SUIV=b->signal->nodes;
108 a->signal->lastnode=b->signal->lastnode;
109 // a->signal->nodes=(__node_ *)append((chain_list *)a->signal->nodes, (chain_list *)b->signal->nodes);
110 if (a->signal->firstline==-1 ||
111 b->signal->firstline<a->signal->firstline) a->signal->firstline=b->signal->firstline;
112 if (a->signal->lastline==-1 ||
113 b->signal->lastline>a->signal->lastline) a->signal->lastline=b->signal->lastline;
114
115 if (b->signal->a.prev==NULL) cir->all_equi=b->signal->next;
116 else b->signal->a.prev->next=b->signal->next;
117 if (b->signal->next!=NULL) b->signal->next->a.prev=b->signal->a.prev;
118 DelHeapItem(&cir->ha_equi, b->signal);
119 #ifdef ENABLE_STATS
120 ____nbequi--;
121
122 #endif
123 while (n!=NULL) { n->signal=a->signal; n=n->SUIV; }
124 }
125 else
126 {
127 b->signal->nbelem+=a->signal->nbelem;
128 // b->signal->tag|=a->signal->tag;
129 n=a->signal->nodes;
130 b->signal->b.nbnodes+=a->signal->b.nbnodes;
131 b->signal->lastnode->SUIV=a->signal->nodes;
132 b->signal->lastnode=a->signal->lastnode;
133 //b->signal->nodes=(__node_ *)append((chain_list *)b->signal->nodes, (chain_list *)a->signal->nodes);
134 if (b->signal->firstline==-1 ||
135 a->signal->firstline<b->signal->firstline) b->signal->firstline=a->signal->firstline;
136 if (b->signal->lastline==-1 ||
137 a->signal->lastline>b->signal->lastline) b->signal->lastline=a->signal->lastline;
138 if (a->signal->a.prev==NULL) cir->all_equi=a->signal->next;
139 else a->signal->a.prev->next=a->signal->next;
140 if (a->signal->next!=NULL) a->signal->next->a.prev=a->signal->a.prev;
141 DelHeapItem(&cir->ha_equi, a->signal);
142 #ifdef ENABLE_STATS
143 ____nbequi--;
144 #endif
145 while (n!=NULL) { n->signal=b->signal; n=n->SUIV; }
146 }
147 }
148
149 static char *vect(char *name, char *buf)
150 {
151 if (vectorindex(name)==-1) return name;
152 sprintf(buf,"%s[%d]",vectorradical(name),vectorindex(name));
153 return buf;
154 }
155
156 static void _ParasiticDriveHeader(subckt *cir, char *name, chain_list *interf)
157 {
158 time_t secondes;
159 struct tm *jours;
160 char tab[1024];
161 __equi_ *e;
162 chain_list *cl, *ch;
163 __node_ *n, *n0;
164
165 time( &secondes );
166 jours = localtime( &secondes );
167
168 sprintf( tab,
169 "%d/%02d/%04d at %2d:%02d:%02d",
170 jours->tm_mday,
171 jours->tm_mon+1,
172 jours->tm_year+1900,
173 jours->tm_hour,
174 jours->tm_min,
175 jours->tm_sec
176 );
177
178 fprintf(cir->of,
179 "*SPEF \"IEEE 1481, 1998\"\n"
180 "*DESIGN \"%s\"\n"
181 "*DATE \"%s\"\n"
182 "*VENDOR \"Avertec\"\n"
183 "*PROGRAM \"Parasitic Driver\"\n"
184 "*VERSION \"0.1b\"\n"
185 "*DESIGN_FLOW \"EXTERNAL LOADS\" \"EXTERNAL_SLEWS\"\n"
186 "*DIVIDER .\n"
187 "*DELIMITER :\n"
188 "*BUS_DELIMITER []\n"
189 "*T_UNIT 1 NS\n"
190 "*C_UNIT 1.0 FF\n"
191 "*R_UNIT 1.0 OHM\n"
192 "*L_UNIT 1.0 HENRY\n",
193 name, tab
194 );
195
196 if (cir->nbequi>0)
197 {
198 fprintf(cir->of, "\n*NAME_MAP\n");
199 for (e=cir->all_equi; e!=NULL; e=e->next)
200 {
201 if (e->firstline!=-1)
202 {
203 fprintf(cir->of, "*%d %s\n", e->b.nbnodes, vect(e->a.nom, tab));
204 }
205 }
206 }
207
208 fprintf(cir->of, "\n*PORTS\n");
209 for (cl=interf; cl!=NULL; cl=cl->NEXT)
210 {
211 if (cl->NEXT != NULL && strcmp ((char *)cl->NEXT->DATA, "=") == 0) break;
212 n=ajoutenoeud( cir, (char *)cl->DATA, 0 );
213 for (ch=interf; ch!=cl; ch=ch->NEXT)
214 {
215 n0=ajoutenoeud( cir, (char *)ch->DATA, 0 );
216 if (n->signal->a.nom==n0->signal->a.nom) break;
217 }
218 if (ch==cl)
219 {
220 n=ajoutenoeud( cir, (char *)cl->DATA, 0 );
221 fprintf(cir->of,"%s I\n", vect(n->signal->a.nom, tab));
222 }
223 }
224 fprintf(cir->of,"\n");
225 }
226
227
228 static void namenode(__node_ *n, __names_ *name, char *buf)
229 {
230 if (name!=NULL)
231 {
232 if (name->ins==NULL)
233 sprintf(buf, "*%d", n->signal->b.nbnodes);
234 else
235 {
236 sprintf(buf, "%s:%s", name->ins, name->con);
237 }
238 }
239 else
240 sprintf(buf, "*%d:%d", n->signal->b.nbnodes,n->index);
241 }
242
243 static void _ParasiticDriveNet(subckt *cir, __equi_ *e)
244 {
245 __node_ *n;
246 __item_ *i, *nexti;
247 float totcapa;
248 int num, done=0, hascon=0;
249 char buf[1024], buf0[1024];
250 __names_ *nam;
251
252 // printf("ending %s\n",e->a.nom);
253 for (i=e->items, totcapa=0; i!=NULL; i=i->next)
254 {
255 if (i->type=='c') totcapa+=i->value;
256 }
257
258 for (n=e->nodes; n!=NULL; n=n->SUIV)
259 if (n->SUPINFO!=NULL && n->SUPINFO->names!=NULL) break;
260
261 if (n!=NULL) hascon=1;
262
263 done=1;
264 #ifdef FULLVALUE
265 fprintf(cir->of, "\n*D_NET *%d %f\n",e->b.nbnodes,totcapa*1e15);
266 #else
267 fprintf(cir->of, "\n*D_NET *%d %.3g\n",e->b.nbnodes,totcapa*1e15);
268 #endif
269 if (hascon)
270 {
271 fprintf(cir->of, "*CONN\n");
272
273 // for (n=e->nodes, num=0; n!=NULL; n=n->SUIV) n->index=num++;
274
275 for (n=e->nodes; n!=NULL; n=n->SUIV)
276 {
277 for (nam=n->SUPINFO!=NULL?n->SUPINFO->names:NULL; nam!=NULL; nam=nam->next)
278 {
279 namenode(n, nam, buf);
280 if (nam->ins==NULL)
281 fprintf(cir->of, "*P %s I\n", buf);
282 else
283 fprintf(cir->of, "*I %s I\n", buf);
284 }
285 }
286 }
287 for (i=e->items; i!=NULL; i=i->next)
288 {
289 if (i->type=='c') break;
290 }
291 if (i!=NULL)
292 {
293 fprintf(cir->of, "\n*CAP\n");
294
295 for (i=e->items, num=1; i!=NULL; i=i->next)
296 {
297 if (i->type=='c')
298 {
299 namenode(i->a, i->a->SUPINFO!=NULL?i->a->SUPINFO->names:NULL, buf);
300 namenode(i->b, i->b->SUPINFO!=NULL?i->b->SUPINFO->names:NULL, buf0);
301 #ifdef FULLVALUE
302 if (i->a->signal->tag & TAG_ALIM)
303 fprintf(cir->of, "%d %s %f\n", num++, buf0, i->value*1e15);
304 else if (i->b->signal->tag & TAG_ALIM)
305 fprintf(cir->of, "%d %s %f\n", num++, buf, i->value*1e15);
306 else
307 fprintf(cir->of, "%d %s %s %f\n", num++, buf, buf0, i->value*1e15);
308 #else
309 if (i->a->signal->tag & TAG_ALIM)
310 fprintf(cir->of, "%d %s %.3f\n", num++, buf0, i->value*1e15);
311 else if (i->b->signal->tag & TAG_ALIM)
312 fprintf(cir->of, "%d %s %.3f\n", num++, buf, i->value*1e15);
313 else
314 fprintf(cir->of, "%d %s %s %.3f\n", num++, buf, buf0, i->value*1e15);
315 #endif
316
317 }
318 }
319 }
320
321 for (i=e->items; i!=NULL; i=i->next)
322 {
323 if (i->type=='r') break;
324 }
325
326 num=1;
327 if (i!=NULL)
328 {
329 fprintf(cir->of, "\n*RES\n");
330
331 for (i=e->items; i!=NULL; i=i->next)
332 {
333 if (i->type=='r')
334 {
335 namenode(i->a, i->a->SUPINFO!=NULL?i->a->SUPINFO->names:NULL, buf);
336 namenode(i->b, i->b->SUPINFO!=NULL?i->b->SUPINFO->names:NULL, buf0);
337 #ifdef FULLVALUE
338 fprintf(cir->of, "%d %s %s %f\n", num++, buf, buf0, i->value);
339 #else
340 fprintf(cir->of, "%d %s %s %g\n", num++, buf, buf0, i->value);
341 #endif
342 }
343 }
344 i++;
345 }
346
347 #ifdef CORRECT_CONNECT
348 for (n=e->nodes; n!=NULL; n=n->SUIV)
349 {
350 if (n->SUPINFO!=NULL && n->SUPINFO->names!=NULL && n->SUPINFO->names->next!=NULL)
351 {
352 if (i==NULL)
353 {
354 i++;
355 fprintf(cir->of, "\n*RES\n");
356 }
357
358 namenode(n, n->SUPINFO->names, buf0);
359 for (nam=n->SUPINFO->names->next; nam!=NULL; nam=nam->next)
360 {
361 namenode(n, nam, buf);
362 fprintf(cir->of, "%d %s %s 0\n", num++, buf0, buf);
363 }
364 }
365 }
366 #endif
367
368 for (i=e->items; i!=NULL; i=nexti)
369 {
370 nexti=i->next;
371 DelHeapItem(&ha_item, i);
372 }
373 freeitemspace+=e->nbelem;
374
375 if (done)
376 fprintf(cir->of, "*END\n\n");
377 }
378
379 static void checkstart(__equi_ *e, int line)
380 {
381 if ((e->tag & TAG_MASK)!=0) return;
382 if (e->firstline==line && freeitemspace>=e->nbelem)
383 {
384 e->tag|=1;
385 e->items=NULL;
386 freeitemspace-=e->nbelem;
387
388 // printf("starting %s , %d, f=%d\n",e->a.nom,e->nbelem, freeitemspace);
389 if (e->tag & TAG_ALIM) EXIT(6);
390 }
391 /* else if (e->firstline==line && freeitemspace<e->nbelem)
392 printf("[NOT STARTING] %s , %d, f=%d\n",e->a.nom,e->nbelem, freeitemspace);*/
393 }
394
395 static int checkend(__equi_ *e, int line)
396 {
397 if ((e->tag & TAG_MASK)!=1) return 0;
398 if (e->lastline==line)
399 {
400 e->tag|=2;
401 return 1;
402 }
403 return 0;
404 }
405
406 static void CreateSpeforAnyOther(spifile *sf, chain_list *cl)
407 {
408 chain_list *l, *e, *ch;
409 subckt *cir=NULL;
410 char *tmp;
411 __equi_ *run_equi;
412 int forcedexit=0;
413 float com_x, com_y;
414 int Tx, Ty, R, A;
415 chain_list *fifodf=NULL, *elem;
416 #ifdef ENABLE_STATS
417 // -----
418 long df_temp0;
419 long df_time=time(NULL), df_starttime=df_time;
420 long df_temp=0;
421 // -----
422 #endif
423
424 l=lireligne(sf, cir);
425
426 if (!spi_get_xy (l, &com_x, &com_y, &Tx, &Ty, &R, &A)) l = NULL;
427 while (l!=NULL && forcedexit==0)
428 {
429 #ifdef ENABLE_STATS
430 if (++df_temp>=1024)
431 {
432 if ((df_temp0=time(NULL))!=df_time)
433 {
434 char temp[20];
435 df_time=df_temp0;
436 df_temp=0;
437 if (avt_terminal(stdout))
438 {
439 sprintf(temp,"[¤+%08d¤.]",sf->msl_line);
440 avt_fprintf(stdout,temp);
441 fflush(stdout);
442 avt_back_fprintf(stdout, strlen(temp)-4);
443 }
444 }
445 df_temp=0;
446 }
447 #endif
448 if( strcasecmp( (char*)l->DATA, ".SUBCKT" ) == 0 )
449 {
450 if(cir)
451 avt_errmsg (SPI_ERRMSG, "015", AVT_FATAL, sf->filename, sf->msl_line );
452
453 e=l->NEXT;
454 tmp=namealloc((char *)e->DATA);
455
456 for (ch=cl; ch!=NULL && strcasecmp(((subckt *)ch->DATA)->NOM,tmp)!=0; ch=ch->NEXT) /*printf(">>%s\n",((subckt *)ch->DATA)->NOM);*/;
457 if (ch==NULL) EXIT(124);
458 cir=(subckt *)ch->DATA;
459 cir->TOTAL_LINE_COUNTER=0;
460 if (cir->pass==0)
461 {
462 int i=1;
463 char *where;
464 if ((where=filepath(cir->NOM, "spef"))!=NULL)
465 {
466 avt_log(-1, 0, "File '%s.spef' already exists, no spef generation done\n",where);
467 // printf("[info] using existing parasitic file '%s.spef'\n",cir->NOM);
468 // fclose(cir->of);
469 cir->of=NULL;
470 cir->nbequi=0;
471
472 for (ch=cl; ch!=NULL; ch=ch->NEXT)
473 {
474 cir=(subckt *)ch->DATA;
475 if (((subckt *)ch->DATA)->nbequi!=0) break;
476 }
477 if (ch==NULL) // no more circuit to complete
478 forcedexit=1;
479 }
480 else
481 {
482 if ((cir->of=mbkfopen(cir->NOM, "spef", WRITE_TEXT))==NULL)
483 EXIT(142);
484 for (run_equi=cir->all_equi; run_equi!=NULL; run_equi=run_equi->next)
485 if (run_equi->firstline!=-1) run_equi->b.nbnodes=i++;
486 // drive header
487 _ParasiticDriveHeader(cir, cir->NOM, e->NEXT);
488 }
489 }
490 cir->pass++;
491 #ifdef ENABLE_STATS
492 if (cir->of!=NULL) printf("%s pass %d\n",cir->NOM, cir->pass);
493 #endif
494 }
495 else if (strcasecmp( (char*)(l->DATA), ".ENDS" ) == 0 )
496 {
497 //-----------------
498 // cir->nbequi=0;
499 if (cir->of!=NULL)
500 {
501 if (cir->nbequi==0)
502 {
503 fclose(cir->of);
504 // printf("closed %s\n",cir->NOM);
505 }
506 #ifdef ENABLE_STATS
507 else
508 printf("%s, %d equi remaining\n-----------------\n",cir->NOM,cir->nbequi);
509 #endif
510 }
511 cir=NULL;
512 }
513 else if (cir!=NULL && cir->of!=NULL && (*(char*)l->DATA=='R' || *(char*)l->DATA=='r'))
514 {
515 __node_ *a, *b;
516 __item_ *i;
517 if (countchain(l)<4)
518 avt_errmsg (SPI_ERRMSG, "036", AVT_FATAL, sf->filename, sf->msl_line );
519 a=ajoutenoeud( cir, (char *)l->NEXT->DATA, 0 ); //getnode(cir, (char *)l->NEXT->DATA, 0); // node0
520 b=ajoutenoeud( cir, (char *)l->NEXT->NEXT->DATA, 0 ); //b=getnode(cir, (char *)l->NEXT->NEXT->DATA, 0); // node1
521 // ---------
522 checkstart(a->signal, cir->TOTAL_LINE_COUNTER/*sf->msl_line*/);
523 if ((a->signal->tag & TAG_MASK)==1)
524 {
525 i=AddHeapItem(&ha_item);
526 i->next=a->signal->items; a->signal->items=i;
527 i->type='r';
528 i->a=a; i->b=b;
529 i->value = eqt_eval( GLOBAL_CTX, namealloc((char*)(l->NEXT->NEXT->NEXT->DATA)) ,EQTFAST ) * SPI_SCALE_RESIFACTOR ;
530 if( !eqt_resistrue(GLOBAL_CTX) )
531 avt_errmsg (SPI_ERRMSG, "034", AVT_FATAL, sf->filename, sf->msl_line );
532 }
533 if (checkend(a->signal, cir->TOTAL_LINE_COUNTER/*sf->msl_line*/))
534 {
535 _ParasiticDriveNet(cir, a->signal);
536 cir->nbequi--;
537 }
538 }
539 else if (cir!=NULL && cir->of!=NULL && (*(char*)l->DATA=='C' || *(char*)l->DATA=='c'))
540 {
541 __node_ *a, *b;
542 __item_ *i;
543 if (countchain(l)<4)
544 avt_errmsg (SPI_ERRMSG, "038", AVT_FATAL, sf->filename, sf->msl_line );
545 a=ajoutenoeud( cir, (char *)l->NEXT->DATA, 0 ); //a=getnode(cir, (char *)l->NEXT->DATA, 0); // node0
546 b=ajoutenoeud( cir, (char *)l->NEXT->NEXT->DATA, 0 ); //b=getnode(cir, (char *)l->NEXT->NEXT->DATA, 0); // node1
547 // ---------
548 checkstart(a->signal, cir->TOTAL_LINE_COUNTER/*sf->msl_line*/);
549 if ((a->signal->tag & TAG_MASK)==1)
550 {
551 i=AddHeapItem(&ha_item);
552 i->next=a->signal->items; a->signal->items=i;
553 i->type='c';
554 i->a=a; i->b=b;
555 i->value = eqt_eval( GLOBAL_CTX, namealloc((char*)(l->NEXT->NEXT->NEXT->DATA)) ,EQTFAST ) * SPI_SCALE_CAPAFACTOR ;
556 if( !eqt_resistrue(GLOBAL_CTX) )
557 avt_errmsg (SPI_ERRMSG, "034", AVT_FATAL, sf->filename, sf->msl_line );
558 }
559 if (checkend(a->signal, cir->TOTAL_LINE_COUNTER/*sf->msl_line*/))
560 {
561 _ParasiticDriveNet(cir, a->signal);
562 cir->nbequi--;
563 }
564
565 // ---------
566 if (b->signal!=a->signal)
567 {
568 checkstart(b->signal, cir->TOTAL_LINE_COUNTER/*sf->msl_line*/);
569 if ((b->signal->tag & TAG_MASK)==1)
570 {
571 i=AddHeapItem(&ha_item);
572 i->next=b->signal->items; b->signal->items=i;
573 i->type='c';
574 i->a=a; i->b=b;
575 i->value = eqt_eval( GLOBAL_CTX, namealloc((char*)(l->NEXT->NEXT->NEXT->DATA)) ,EQTFAST ) * SPI_SCALE_CAPAFACTOR ;
576 if( !eqt_resistrue(GLOBAL_CTX) )
577 avt_errmsg (SPI_ERRMSG, "034", AVT_FATAL, sf->filename, sf->msl_line );
578 }
579 if (checkend(b->signal, cir->TOTAL_LINE_COUNTER/*sf->msl_line*/))
580 {
581 _ParasiticDriveNet(cir, b->signal);
582 cir->nbequi--;
583 }
584 }
585 }
586 else if (strcasecmp ((char *)l->DATA, ".INCLUDE") == 0 || strcasecmp ((char *)l->DATA, ".INC") == 0 || strcasecmp ((char *)l->DATA, ".INCL") == 0)
587 {
588 elem = l->NEXT;
589 tmp = (char *)elem->DATA;
590 if (*tmp == '\'')
591 tmp++;
592 if (tmp[strlen (tmp) - 1] == '\'')
593 tmp[strlen (tmp) - 1] = 0;
594 fifodf = addchain( fifodf, sf );
595 sf = spifileopen(tmp,NULL,( SPI_PARSE_FIRSTLINE == PARSEFIRSTLINE_YES || SPI_PARSE_FIRSTLINE == PARSEFIRSTLINE_INC ) ? 1 : 0 );
596 }
597
598 freechain(l);
599 if ((l=lireligne(sf, cir))==NULL)
600 {
601 while (fifodf!=NULL && l==NULL)
602 {
603 spifileclose(sf) ;
604 elem = fifodf;
605 sf=(spifile*)fifodf->DATA;
606 fifodf=fifodf->NEXT;
607 elem->NEXT = NULL;
608 freechain( elem );
609 l=lireligne(sf, cir);
610 }
611 }
612 if (!spi_get_xy (l, &com_x, &com_y, &Tx, &Ty, &R, &A)) l = NULL;
613 }
614 if (l!=NULL) freechain(l);
615 }
616
617
618 static void ParseAndReparseUntilTheEnd(char *name, char *ext, chain_list *cl)
619 {
620 spifile *sf;
621 int cnt;
622 chain_list *ch;
623
624 for (ch=cl, cnt=0; ch!=NULL; cnt+=((subckt *)ch->DATA)->nbequi, ch=ch->NEXT) ;
625 while (cnt!=0)
626 {
627 sf=spifileopen(name, ext, ( SPI_PARSE_FIRSTLINE == PARSEFIRSTLINE_YES ) ? 1 : 0 );
628
629 CreateSpeforAnyOther(sf, cl);
630
631 spifileclose( sf );
632 for (ch=cl, cnt=0; ch!=NULL; cnt+=((subckt *)ch->DATA)->nbequi, ch=ch->NEXT) ;
633 }
634 }
635
636
637 void SpiceToSpef(char *name, char *ext, chain_list *cirs, long freespace)
638 {
639 chain_list *cl=NULL;
640 int maxelem=0;
641 subckt *cir;
642 __equi_ *e;
643 __node_ *n;
644 int cnt, cnt0, num;
645 unsigned long freespaceUL;
646
647 freespaceUL=((unsigned long )freespace)*1024*1024;
648
649 for (cl=cirs; cl!=NULL; cl=cl->NEXT)
650 {
651 cir=(subckt *)cl->DATA;
652 for (e=cir->all_equi, cnt0=0, cnt=0; e!=NULL; e=e->next, cnt++)
653 {
654 if (isvss(e->a.nom) || isglobalvss(e->a.nom) || isvdd(e->a.nom) || isglobalvdd(e->a.nom))
655 e->tag = TAG_ALIM;
656 else
657 e->tag = 0;
658 if (e->firstline==-1 || (e->tag & TAG_ALIM)!=0) { cnt0++; e->firstline=e->lastline=-1; }
659 else if (e->nbelem>maxelem) maxelem=e->nbelem;
660
661 for (n=e->nodes, num=1; n!=NULL; n=n->SUIV) n->index=num++;
662
663 // printf("[%d %d] %d elem, %s\n",e->firstline,e->lastline,e->nbelem, nom);
664 }
665 cir->nbequi=cnt-cnt0;
666 #ifdef ENABLE_STATS
667 if (cir->nbequi>0)
668 printf("%d nodes, %d equis (%d sans RC, max=%d)\n", cir->nbnodes, cnt,cnt0,maxelem);
669 #endif
670 }
671
672 freeitemspace=freespaceUL/sizeof(__item_);
673
674 if (maxelem>freeitemspace)
675 {
676 fprintf(stderr,"Can not drive spef with the current space restriction (maximum: %d rc), needed %d\n",freeitemspace,maxelem);
677 return; // free!!!
678 }
679
680
681 CreateHeap(sizeof(__item_), 8192, &ha_item);
682
683 #ifdef ENABLE_STATS
684 printf("tempspace=%ldKo, %d rc elems\n",freespaceUL/1024,freeitemspace);
685 #endif
686 ParseAndReparseUntilTheEnd(name, ext, cirs);
687 DeleteHeap(&ha_item);
688 }
689
690