17 #include "spi_parse.h"
19 //#define CORRECT_CONNECT
21 //#define DELAY_DEBUG_STAT
22 extern float SPI_SCALE_RESIFACTOR
;
23 extern float SPI_SCALE_CAPAFACTOR
;
25 static HeapAlloc ha_item
;
26 static int freeitemspace
;
32 extern int spi_get_xy (chain_list
*ligne
, float *com_x
, float *com_y
, int *Tx
, int *Ty
, int *R
, int *A
);
34 void _spispef_setnodename(subckt
*cir
, __node_
* n
, char *ins
, char *con
)
38 CheckNodeSupInfo(cir
, n
);
40 p
=(__names_
*)AdvancedBlockAlloc(cir
->aba
, sizeof(ptype_list
));
43 p
->next
=n
->SUPINFO
->names
;
48 static int countchain(chain_list *cl)
51 while (cl!=NULL) { i++; cl=cl->NEXT;}
56 void _spispef_complete_node(subckt
*cir
, char *name
, __node_
*n
, int mark
, int justcreated
)
60 #ifndef __ALL_WARNING__
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
;
74 e
=AddHeapItem(&cir
->ha_equi
);
83 e
->firstline
=e
->lastline
=cir
->TOTAL_LINE_COUNTER
;
85 e
->firstline
=e
->lastline
=-1;
88 e
->next
=cir
->all_equi
;
89 if (cir
->all_equi
!=NULL
) cir
->all_equi
->a
.prev
=e
;
95 void _spispef_mergenodes(subckt
*cir
, __node_
*a
, __node_
*b
)
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
)
102 a
->signal
->nbelem
+=b
->signal
->nbelem
;
103 // a->signal->tag|=b->signal->tag;
105 a
->signal
->b
.nbnodes
+=b
->signal
->b
.nbnodes
;
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
;
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
);
123 while (n
!=NULL
) { n
->signal
=a
->signal
; n
=n
->SUIV
; }
127 b
->signal
->nbelem
+=a
->signal
->nbelem
;
128 // b->signal->tag|=a->signal->tag;
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
);
145 while (n
!=NULL
) { n
->signal
=b
->signal
; n
=n
->SUIV
; }
149 static char *vect(char *name
, char *buf
)
151 if (vectorindex(name
)==-1) return name
;
152 sprintf(buf
,"%s[%d]",vectorradical(name
),vectorindex(name
));
156 static void _ParasiticDriveHeader(subckt
*cir
, char *name
, chain_list
*interf
)
166 jours
= localtime( &secondes
);
169 "%d/%02d/%04d at %2d:%02d:%02d",
179 "*SPEF \"IEEE 1481, 1998\"\n"
182 "*VENDOR \"Avertec\"\n"
183 "*PROGRAM \"Parasitic Driver\"\n"
184 "*VERSION \"0.1b\"\n"
185 "*DESIGN_FLOW \"EXTERNAL LOADS\" \"EXTERNAL_SLEWS\"\n"
188 "*BUS_DELIMITER []\n"
192 "*L_UNIT 1.0 HENRY\n",
198 fprintf(cir
->of
, "\n*NAME_MAP\n");
199 for (e
=cir
->all_equi
; e
!=NULL
; e
=e
->next
)
201 if (e
->firstline
!=-1)
203 fprintf(cir
->of
, "*%d %s\n", e
->b
.nbnodes
, vect(e
->a
.nom
, tab
));
208 fprintf(cir
->of
, "\n*PORTS\n");
209 for (cl
=interf
; cl
!=NULL
; cl
=cl
->NEXT
)
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
)
215 n0
=ajoutenoeud( cir
, (char *)ch
->DATA
, 0 );
216 if (n
->signal
->a
.nom
==n0
->signal
->a
.nom
) break;
220 n
=ajoutenoeud( cir
, (char *)cl
->DATA
, 0 );
221 fprintf(cir
->of
,"%s I\n", vect(n
->signal
->a
.nom
, tab
));
224 fprintf(cir
->of
,"\n");
228 static void namenode(__node_
*n
, __names_
*name
, char *buf
)
233 sprintf(buf
, "*%d", n
->signal
->b
.nbnodes
);
236 sprintf(buf
, "%s:%s", name
->ins
, name
->con
);
240 sprintf(buf
, "*%d:%d", n
->signal
->b
.nbnodes
,n
->index
);
243 static void _ParasiticDriveNet(subckt
*cir
, __equi_
*e
)
248 int num
, done
=0, hascon
=0;
249 char buf
[1024], buf0
[1024];
252 // printf("ending %s\n",e->a.nom);
253 for (i
=e
->items
, totcapa
=0; i
!=NULL
; i
=i
->next
)
255 if (i
->type
=='c') totcapa
+=i
->value
;
258 for (n
=e
->nodes
; n
!=NULL
; n
=n
->SUIV
)
259 if (n
->SUPINFO
!=NULL
&& n
->SUPINFO
->names
!=NULL
) break;
261 if (n
!=NULL
) hascon
=1;
265 fprintf(cir
->of
, "\n*D_NET *%d %f\n",e
->b
.nbnodes
,totcapa
*1e15
);
267 fprintf(cir
->of
, "\n*D_NET *%d %.3g\n",e
->b
.nbnodes
,totcapa
*1e15
);
271 fprintf(cir
->of
, "*CONN\n");
273 // for (n=e->nodes, num=0; n!=NULL; n=n->SUIV) n->index=num++;
275 for (n
=e
->nodes
; n
!=NULL
; n
=n
->SUIV
)
277 for (nam
=n
->SUPINFO
!=NULL
?n
->SUPINFO
->names
:NULL
; nam
!=NULL
; nam
=nam
->next
)
279 namenode(n
, nam
, buf
);
281 fprintf(cir
->of
, "*P %s I\n", buf
);
283 fprintf(cir
->of
, "*I %s I\n", buf
);
287 for (i
=e
->items
; i
!=NULL
; i
=i
->next
)
289 if (i
->type
=='c') break;
293 fprintf(cir
->of
, "\n*CAP\n");
295 for (i
=e
->items
, num
=1; i
!=NULL
; i
=i
->next
)
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
);
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
);
307 fprintf(cir
->of
, "%d %s %s %f\n", num
++, buf
, buf0
, i
->value
*1e15
);
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
);
314 fprintf(cir
->of
, "%d %s %s %.3f\n", num
++, buf
, buf0
, i
->value
*1e15
);
321 for (i
=e
->items
; i
!=NULL
; i
=i
->next
)
323 if (i
->type
=='r') break;
329 fprintf(cir
->of
, "\n*RES\n");
331 for (i
=e
->items
; i
!=NULL
; i
=i
->next
)
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
);
338 fprintf(cir
->of
, "%d %s %s %f\n", num
++, buf
, buf0
, i
->value
);
340 fprintf(cir
->of
, "%d %s %s %g\n", num
++, buf
, buf0
, i
->value
);
347 #ifdef CORRECT_CONNECT
348 for (n
=e
->nodes
; n
!=NULL
; n
=n
->SUIV
)
350 if (n
->SUPINFO
!=NULL
&& n
->SUPINFO
->names
!=NULL
&& n
->SUPINFO
->names
->next
!=NULL
)
355 fprintf(cir
->of
, "\n*RES\n");
358 namenode(n
, n
->SUPINFO
->names
, buf0
);
359 for (nam
=n
->SUPINFO
->names
->next
; nam
!=NULL
; nam
=nam
->next
)
361 namenode(n
, nam
, buf
);
362 fprintf(cir
->of
, "%d %s %s 0\n", num
++, buf0
, buf
);
368 for (i
=e
->items
; i
!=NULL
; i
=nexti
)
371 DelHeapItem(&ha_item
, i
);
373 freeitemspace
+=e
->nbelem
;
376 fprintf(cir
->of
, "*END\n\n");
379 static void checkstart(__equi_
*e
, int line
)
381 if ((e
->tag
& TAG_MASK
)!=0) return;
382 if (e
->firstline
==line
&& freeitemspace
>=e
->nbelem
)
386 freeitemspace
-=e
->nbelem
;
388 // printf("starting %s , %d, f=%d\n",e->a.nom,e->nbelem, freeitemspace);
389 if (e
->tag
& TAG_ALIM
) EXIT(6);
391 /* else if (e->firstline==line && freeitemspace<e->nbelem)
392 printf("[NOT STARTING] %s , %d, f=%d\n",e->a.nom,e->nbelem, freeitemspace);*/
395 static int checkend(__equi_
*e
, int line
)
397 if ((e
->tag
& TAG_MASK
)!=1) return 0;
398 if (e
->lastline
==line
)
406 static void CreateSpeforAnyOther(spifile
*sf
, chain_list
*cl
)
408 chain_list
*l
, *e
, *ch
;
415 chain_list
*fifodf
=NULL
, *elem
;
419 long df_time
=time(NULL
), df_starttime
=df_time
;
424 l
=lireligne(sf
, cir
);
426 if (!spi_get_xy (l
, &com_x
, &com_y
, &Tx
, &Ty
, &R
, &A
)) l
= NULL
;
427 while (l
!=NULL
&& forcedexit
==0)
432 if ((df_temp0
=time(NULL
))!=df_time
)
437 if (avt_terminal(stdout
))
439 sprintf(temp
,"[¤+%08d¤.]",sf
->msl_line
);
440 avt_fprintf(stdout
,temp
);
442 avt_back_fprintf(stdout
, strlen(temp
)-4);
448 if( strcasecmp( (char*)l
->DATA
, ".SUBCKT" ) == 0 )
451 avt_errmsg (SPI_ERRMSG
, "015", AVT_FATAL
, sf
->filename
, sf
->msl_line
);
454 tmp
=namealloc((char *)e
->DATA
);
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;
464 if ((where
=filepath(cir
->NOM
, "spef"))!=NULL
)
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);
472 for (ch
=cl
; ch
!=NULL
; ch
=ch
->NEXT
)
474 cir
=(subckt
*)ch
->DATA
;
475 if (((subckt
*)ch
->DATA
)->nbequi
!=0) break;
477 if (ch
==NULL
) // no more circuit to complete
482 if ((cir
->of
=mbkfopen(cir
->NOM
, "spef", WRITE_TEXT
))==NULL
)
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
++;
487 _ParasiticDriveHeader(cir
, cir
->NOM
, e
->NEXT
);
492 if (cir
->of
!=NULL
) printf("%s pass %d\n",cir
->NOM
, cir
->pass
);
495 else if (strcasecmp( (char*)(l
->DATA
), ".ENDS" ) == 0 )
504 // printf("closed %s\n",cir->NOM);
508 printf("%s, %d equi remaining\n-----------------\n",cir
->NOM
,cir
->nbequi
);
513 else if (cir
!=NULL
&& cir
->of
!=NULL
&& (*(char*)l
->DATA
=='R' || *(char*)l
->DATA
=='r'))
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
522 checkstart(a
->signal
, cir
->TOTAL_LINE_COUNTER
/*sf->msl_line*/);
523 if ((a
->signal
->tag
& TAG_MASK
)==1)
525 i
=AddHeapItem(&ha_item
);
526 i
->next
=a
->signal
->items
; a
->signal
->items
=i
;
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
);
533 if (checkend(a
->signal
, cir
->TOTAL_LINE_COUNTER
/*sf->msl_line*/))
535 _ParasiticDriveNet(cir
, a
->signal
);
539 else if (cir
!=NULL
&& cir
->of
!=NULL
&& (*(char*)l
->DATA
=='C' || *(char*)l
->DATA
=='c'))
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
548 checkstart(a
->signal
, cir
->TOTAL_LINE_COUNTER
/*sf->msl_line*/);
549 if ((a
->signal
->tag
& TAG_MASK
)==1)
551 i
=AddHeapItem(&ha_item
);
552 i
->next
=a
->signal
->items
; a
->signal
->items
=i
;
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
);
559 if (checkend(a
->signal
, cir
->TOTAL_LINE_COUNTER
/*sf->msl_line*/))
561 _ParasiticDriveNet(cir
, a
->signal
);
566 if (b
->signal
!=a
->signal
)
568 checkstart(b
->signal
, cir
->TOTAL_LINE_COUNTER
/*sf->msl_line*/);
569 if ((b
->signal
->tag
& TAG_MASK
)==1)
571 i
=AddHeapItem(&ha_item
);
572 i
->next
=b
->signal
->items
; b
->signal
->items
=i
;
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
);
579 if (checkend(b
->signal
, cir
->TOTAL_LINE_COUNTER
/*sf->msl_line*/))
581 _ParasiticDriveNet(cir
, b
->signal
);
586 else if (strcasecmp ((char *)l
->DATA
, ".INCLUDE") == 0 || strcasecmp ((char *)l
->DATA
, ".INC") == 0 || strcasecmp ((char *)l
->DATA
, ".INCL") == 0)
589 tmp
= (char *)elem
->DATA
;
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 );
599 if ((l
=lireligne(sf
, cir
))==NULL
)
601 while (fifodf
!=NULL
&& l
==NULL
)
605 sf
=(spifile
*)fifodf
->DATA
;
609 l
=lireligne(sf
, cir
);
612 if (!spi_get_xy (l
, &com_x
, &com_y
, &Tx
, &Ty
, &R
, &A
)) l
= NULL
;
614 if (l
!=NULL
) freechain(l
);
618 static void ParseAndReparseUntilTheEnd(char *name
, char *ext
, chain_list
*cl
)
624 for (ch
=cl
, cnt
=0; ch
!=NULL
; cnt
+=((subckt
*)ch
->DATA
)->nbequi
, ch
=ch
->NEXT
) ;
627 sf
=spifileopen(name
, ext
, ( SPI_PARSE_FIRSTLINE
== PARSEFIRSTLINE_YES
) ? 1 : 0 );
629 CreateSpeforAnyOther(sf
, cl
);
632 for (ch
=cl
, cnt
=0; ch
!=NULL
; cnt
+=((subckt
*)ch
->DATA
)->nbequi
, ch
=ch
->NEXT
) ;
637 void SpiceToSpef(char *name
, char *ext
, chain_list
*cirs
, long freespace
)
645 unsigned long freespaceUL
;
647 freespaceUL
=((unsigned long )freespace
)*1024*1024;
649 for (cl
=cirs
; cl
!=NULL
; cl
=cl
->NEXT
)
651 cir
=(subckt
*)cl
->DATA
;
652 for (e
=cir
->all_equi
, cnt0
=0, cnt
=0; e
!=NULL
; e
=e
->next
, cnt
++)
654 if (isvss(e
->a
.nom
) || isglobalvss(e
->a
.nom
) || isvdd(e
->a
.nom
) || isglobalvdd(e
->a
.nom
))
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
;
661 for (n
=e
->nodes
, num
=1; n
!=NULL
; n
=n
->SUIV
) n
->index
=num
++;
663 // printf("[%d %d] %d elem, %s\n",e->firstline,e->lastline,e->nbelem, nom);
665 cir
->nbequi
=cnt
-cnt0
;
668 printf("%d nodes, %d equis (%d sans RC, max=%d)\n", cir
->nbnodes
, cnt
,cnt0
,maxelem
);
672 freeitemspace
=freespaceUL
/sizeof(__item_
);
674 if (maxelem
>freeitemspace
)
676 fprintf(stderr
,"Can not drive spef with the current space restriction (maximum: %d rc), needed %d\n",freeitemspace
,maxelem
);
681 CreateHeap(sizeof(__item_
), 8192, &ha_item
);
684 printf("tempspace=%ldKo, %d rc elems\n",freespaceUL
/1024,freeitemspace
);
686 ParseAndReparseUntilTheEnd(name
, ext
, cirs
);
687 DeleteHeap(&ha_item
);