Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / mbkspef / spef_drive.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI AVERTEC */
4 /* */
5 /* Produit : SPF Version 1.00 */
6 /* Fichier : spef_drive.c */
7 /* */
8 /* (c) copyright 2000 AVERTEC */
9 /* Tous droits reserves */
10 /* */
11 /* Auteur(s) : Olivier BICHAUT */
12 /* */
13 /****************************************************************************/
14
15 /****************************************************************************/
16 /* includes */
17 /****************************************************************************/
18
19 #include <ctype.h>
20 #include "spef_drive.h"
21 #include "spef_util.h"
22
23 #define SPEF_NAME_INDEX 0xfab60614
24
25 /****************************************************************************/
26 /* globals */
27 /****************************************************************************/
28 /****************************************************************************/
29 /* externs */
30 /****************************************************************************/
31
32 /****************************************************************************/
33 /* functions */
34 /****************************************************************************/
35
36 /****************************************************************************/
37 /* function spef_addslash() ajoute des backslash pour qu'un nom contenant */
38 /* des [ ] ne soit pas pris comme un vecteur */
39 /****************************************************************************/
40 static void addnameindex(ptype_list **user, long *val)
41 {
42 *user=addptype(*user, SPEF_NAME_INDEX, (void *)*val);
43 (*val)++;
44 }
45 static void removenameindex(ptype_list **user)
46 {
47 *user=testanddelptype(*user, SPEF_NAME_INDEX);
48 }
49
50 static char *spef_getitem(void *me, char type, char *buf)
51 {
52 ptype_list *pt;
53 switch(type)
54 {
55 case 'i': if ((pt=getptype(((loins_list *)me)->USER, SPEF_NAME_INDEX))!=NULL)
56 sprintf(buf, "*%ld", (long)pt->DATA);
57 else
58 strcpy(buf, ((loins_list *)me)->INSNAME);
59 break;
60 case 't': if ((pt=getptype(((lotrs_list *)me)->USER, SPEF_NAME_INDEX))!=NULL)
61 sprintf(buf, "*%ld", (long)pt->DATA);
62 else
63 strcpy(buf, ((lotrs_list *)me)->TRNAME!=NULL?((lotrs_list *)me)->TRNAME:"?");
64 break;
65 case 's': if ((pt=getptype(((losig_list *)me)->USER, SPEF_NAME_INDEX))!=NULL)
66 sprintf(buf, "*%ld", (long)pt->DATA);
67 else
68 exit(6);
69 break;
70 default:
71 strcpy(buf, "??");
72 }
73 return buf;
74 }
75
76 char *spef_addslash(char *str)
77 {
78 char ss[1024];
79 int i = 0, j = 0;
80
81 while (str[i] != '\0'){
82 if ((str[i] == SPEF_INFO->PREFIX_BUS_DELIMITER) || (str[i] == SPEF_INFO->SUFFIX_BUS_DELIMITER)){
83 ss[j] = '\\';
84 j++;
85 ss[j] = str[i];
86 j++;
87 i++;
88 }else{
89 ss[j] = str[i];
90 i++;
91 j++;
92 }
93 }
94 ss[j] = '\0';
95
96 return namealloc (ss);
97 }
98 /****************************************************************************/
99 /* function spef_printheader() ecrit l'entete du fichier spef */
100 /****************************************************************************/
101 void spef_printheader(FILE *file, lofig_list *ptfig)
102 {
103 chain_list *chain;
104 time_t counter;
105 char *date;
106 time (&counter) ;
107 date = ctime (&counter) ;
108 date[strlen (date) - 1] = '\0' ;
109 if(!SPEF_INFO){
110 spef_createinfo();
111 }
112 fprintf(file, "*SPEF %s\n", SPEF_INFO->SPEF);
113 fprintf(file, "*DESIGN \"%s\"\n", ptfig->NAME);
114 fprintf(file, "*DATE \"%s\"\n", date);
115 fprintf(file, "*VENDOR \"AVERTEC\"\n");
116 fprintf(file, "*PROGRAM \"spef_driver\"\n");
117 fprintf(file, "*VERSION \"1.0\"\n");
118
119 fprintf(file, "*DESIGN_FLOW ");
120 for(chain = SPEF_INFO->DESIGN_FLOW; chain; chain = chain->NEXT)
121 fprintf(file, "%s ", (char*)chain->DATA);
122 fprintf(file, "\n");
123
124 fprintf(file, "*DIVIDER %c\n", SPEF_INFO->DIVIDER);
125 fprintf(file, "*DELIMITER %c\n", SPEF_INFO->DELIMITER);
126 fprintf(file, "*BUS_DELIMITER %c%c\n", SPEF_INFO->PREFIX_BUS_DELIMITER, SPEF_INFO->SUFFIX_BUS_DELIMITER);
127 if(SPEF_INFO->SPEF_T_UNIT == 'N')
128 fprintf(file, "*T_UNIT %g NS\n", SPEF_INFO->SPEF_T_SCALE);
129 else if(SPEF_INFO->SPEF_T_UNIT == 'P')
130 fprintf(file, "*T_UNIT %g PS\n", SPEF_INFO->SPEF_T_SCALE);
131 if(SPEF_INFO->SPEF_CAP_UNIT == 'P')
132 fprintf(file, "*C_UNIT %g PF\n", SPEF_INFO->SPEF_CAP_SCALE);
133 else
134 fprintf(file, "*C_UNIT %g FF\n", SPEF_INFO->SPEF_CAP_SCALE * 1000.0);
135 if(SPEF_INFO->SPEF_RES_UNIT == 'O')
136 fprintf(file, "*R_UNIT %g OHM\n", SPEF_INFO->SPEF_RES_SCALE);
137 else
138 fprintf(file, "*R_UNIT %g KOHM\n", SPEF_INFO->SPEF_RES_SCALE / 1000.0);
139 if(SPEF_INFO->SPEF_L_UNIT == 'H')
140 fprintf(file, "*L_UNIT %g HENRY\n", SPEF_INFO->SPEF_L_SCALE);
141 else if(SPEF_INFO->SPEF_L_UNIT == 'M')
142 fprintf(file, "*L_UNIT %g MH\n", SPEF_INFO->SPEF_L_SCALE);
143 else if(SPEF_INFO->SPEF_L_UNIT == 'U')
144 fprintf(file, "*L_UNIT %g UH\n", SPEF_INFO->SPEF_L_SCALE);
145 }
146 /****************************************************************************/
147 /* function spef_printconn() ecrit les connecteurs d'un net */
148 /****************************************************************************/
149 static char *getpnode(locon_list *lc, char *buf, int incompmode)
150 {
151 if (incompmode && lc->PNODE!=NULL && lc->PNODE->NEXT==NULL) sprintf(buf," *x %ld", lc->PNODE->DATA);
152 else strcpy(buf,"");
153 return buf;
154
155 }
156 static char *convertname(char *name, char *buf)
157 {
158 if (strchr(name, ' '))
159 sprintf(buf, "%s%c%d%c", vectorradical(name), SPEF_INFO->PREFIX_BUS_DELIMITER,
160 vectorindex(name), SPEF_INFO->SUFFIX_BUS_DELIMITER);
161 else if (strchr(name, SPEF_INFO->PREFIX_BUS_DELIMITER))
162 strcpy(buf, spef_addslash(name));
163 else
164 strcpy(buf, name);
165
166 return buf;
167 }
168
169 void spef_printconn(FILE *file, losig_list *ptsig)
170 {
171 ptype_list *ptype;
172 chain_list *chain;
173 locon_list *ptcon;
174 num_list *num;
175 char direction;
176 char buf[1024], buf1[10], buf2[1024];
177 ht *modeht;
178 int incompmode=0;
179
180 fprintf(file, "\n*CONN\n");
181 ptype = getptype(ptsig->USER, LOFIGCHAIN);
182 if(ptype) {
183 modeht=addht(1000);
184 for(chain = (chain_list *)ptype->DATA; chain; chain = chain->NEXT) {
185 ptcon = (locon_list *)chain->DATA ;
186 if (ptcon->PNODE!=NULL) {
187 if (gethtitem(modeht, (void *)ptcon->PNODE->DATA)!=EMPTYHT) break;
188 else addhtitem(modeht, (void *)ptcon->PNODE->DATA, 0);
189 }
190 }
191 delht(modeht);
192 if (chain!=NULL) incompmode=1;
193 for(chain = (chain_list *)ptype->DATA; chain; chain = chain->NEXT) {
194 ptcon = (locon_list *)chain->DATA ;
195 if(ptcon->DIRECTION != 'X')
196 direction = ptcon->DIRECTION;
197 else
198 direction = 'I';
199 for(num = ptcon->PNODE; num; num = num->NEXT) {
200 if(ptcon->TYPE == 'I'){
201 fprintf(file, "*I %s%c%s %c *D %s%s\n", spef_getitem((loins_list*)ptcon->ROOT, 'i', buf), SPEF_INFO->DELIMITER, convertname(ptcon->NAME, buf2), direction, ((loins_list*)ptcon->ROOT)->FIGNAME, getpnode(ptcon, buf1, incompmode));
202 }
203 else // zinaps : 24/4/2003
204 if(ptcon->TYPE == 'T'){
205 fprintf(file, "*I %s%c%c %c *D %s%s\n", spef_getitem((lotrs_list*)ptcon->ROOT, 't', buf), SPEF_INFO->DELIMITER, tolower(ptcon->NAME[0]), direction, getlotrsmodel((lotrs_list*)ptcon->ROOT), getpnode(ptcon, buf1, incompmode));
206 } // end zinaps
207 else{
208 fprintf(file, "*P %s %c%s\n", convertname(ptcon->NAME, buf), direction, getpnode(ptcon, buf1, incompmode));
209 }
210 }
211 }
212 }
213 }
214 /****************************************************************************/
215 /* function spef_printnameorindex() ecrit un nom de net ou son index.node */
216 /****************************************************************************/
217 void spef_printnameorindex(FILE *file, losig_list *ptsig, long node)
218 {
219 ptype_list *ptype;
220 chain_list *chain;
221 locon_list *ptcon;
222 num_list *num;
223 char buf[2048];
224
225 ptype = getptype(ptsig->USER, LOFIGCHAIN);
226 if(ptype)
227 for(chain = (chain_list *)ptype->DATA; chain; chain = chain->NEXT) {
228 ptcon = (locon_list *)chain->DATA ;
229 for(num = ptcon->PNODE; num; num = num->NEXT) {
230 if(num->DATA == node){
231 if(ptcon->TYPE == 'I'){
232 if (strchr(ptcon->NAME, ' '))
233 fprintf(file, "%s%c%s%c%d%c ", spef_getitem((loins_list*)ptcon->ROOT, 'i', buf), SPEF_INFO->DELIMITER, vectorradical(ptcon->NAME),
234 SPEF_INFO->PREFIX_BUS_DELIMITER, vectorindex(ptcon->NAME), SPEF_INFO->SUFFIX_BUS_DELIMITER);
235 else if (strchr(ptcon->NAME, SPEF_INFO->PREFIX_BUS_DELIMITER))
236 fprintf(file, "%s%c%s ", spef_getitem((loins_list*)ptcon->ROOT, 'i', buf), SPEF_INFO->DELIMITER, spef_addslash(ptcon->NAME));
237 else
238 fprintf(file, "%s%c%s ", spef_getitem((loins_list*)ptcon->ROOT, 'i', buf), SPEF_INFO->DELIMITER, ptcon->NAME);
239 }
240 else // start zinaps
241 if(ptcon->TYPE == 'T'){
242 fprintf(file, "%s%c%c ", spef_getitem((lotrs_list*)ptcon->ROOT, 't', buf), SPEF_INFO->DELIMITER, tolower(ptcon->NAME[0]));
243 } // end zinaps
244 else{
245 if (strchr(ptcon->NAME, ' '))
246 fprintf(file, "%s%c%d%c ", vectorradical(ptcon->NAME), SPEF_INFO->PREFIX_BUS_DELIMITER,
247 vectorindex(ptcon->NAME), SPEF_INFO->SUFFIX_BUS_DELIMITER);
248 else if (strchr(ptcon->NAME, SPEF_INFO->PREFIX_BUS_DELIMITER))
249 fprintf(file, "%s ", spef_addslash(ptcon->NAME));
250 else
251 fprintf(file, "%s ", ptcon->NAME);
252 }
253 return ;
254 }
255 }
256 }
257 fprintf(file, "%s%c%ld ", spef_getitem(ptsig, 's', buf), SPEF_INFO->DELIMITER, node);
258 return ;
259 }
260 /****************************************************************************/
261 /* function spef_printnamemap() ecrit la table d'index des signaux */
262 /****************************************************************************/
263 static int spef_isalim(losig_list *losig)
264 {
265 return mbk_LosigIsVSS(losig) || mbk_LosigIsVDD(losig);
266 }
267
268 void spef_printnamemap(FILE *file, lofig_list *ptfig)
269 {
270 losig_list *losig;
271 lotrs_list *lt;
272 loins_list *li;
273 lorcnet_list *prcn;
274 long index = 1;
275
276 fprintf(file, "\n*NAME_MAP\n");
277 for(losig=ptfig->LOSIG;losig;losig=losig->NEXT){
278 if(spef_isalim(losig))
279 continue;
280 prcn = losig->PRCN;
281 /* if(prcn)
282 if(prcn->PCTC || prcn->PWIRE){*/
283 if (strchr(getsigname(losig), ' '))
284 fprintf(file, "*%ld %s%c%d%c\n", index, vectorradical(getsigname(losig)),
285 SPEF_INFO->PREFIX_BUS_DELIMITER, vectorindex(getsigname(losig)), SPEF_INFO->SUFFIX_BUS_DELIMITER);
286 else if (strchr(getsigname(losig), SPEF_INFO->PREFIX_BUS_DELIMITER))
287 fprintf(file, "*%ld %s\n", index, spef_addslash(getsigname(losig)));
288 else
289 fprintf(file, "*%ld %s\n", index, getsigname(losig));
290 addnameindex(&losig->USER, &index);
291 }
292 // }
293 for(lt=ptfig->LOTRS;lt!=NULL;lt=lt->NEXT)
294 {
295 if (lt->TRNAME!=NULL && strlen(lt->TRNAME)>7)
296 {
297 fprintf(file, "*%ld %s\n", index, lt->TRNAME);
298 addnameindex(&lt->USER, &index);
299 }
300 }
301 for(li=ptfig->LOINS;li!=NULL;li=li->NEXT)
302 {
303 if (strlen(li->INSNAME)>7)
304 {
305 fprintf(file, "*%ld %s\n", index, li->INSNAME);
306 addnameindex(&li->USER, &index);
307 }
308 }
309
310 }
311
312 static void spef_cleannamemap(lofig_list *ptfig)
313 {
314 losig_list *losig;
315 lotrs_list *lt;
316 loins_list *li;
317 lorcnet_list *prcn;
318
319 for(losig=ptfig->LOSIG;losig;losig=losig->NEXT){
320 removenameindex(&losig->USER);
321 }
322 for(lt=ptfig->LOTRS;lt!=NULL;lt=lt->NEXT)
323 {
324 removenameindex(&lt->USER);
325 }
326 for(li=ptfig->LOINS;li!=NULL;li=li->NEXT)
327 {
328 removenameindex(&li->USER);
329 }
330 }
331
332 /****************************************************************************/
333 /* function spef_printports() ecrit l'interface du circuit */
334 /****************************************************************************/
335 void spef_printports(FILE *file, lofig_list *ptfig)
336 {
337 locon_list *locon;
338
339 fprintf(file, "\n*PORTS\n");
340 for(locon=ptfig->LOCON;locon;locon=locon->NEXT){
341 if (strchr(locon->NAME, ' '))
342 fprintf(file, "%s%c%d%c %c\n", vectorradical(locon->NAME), SPEF_INFO->PREFIX_BUS_DELIMITER,
343 vectorindex(locon->NAME), SPEF_INFO->SUFFIX_BUS_DELIMITER, locon->DIRECTION);
344 else
345 fprintf(file, "%s %c\n", locon->NAME, locon->DIRECTION);
346 }
347 }
348 /****************************************************************************/
349 /* function spef_printdnets() drive les RC de tous les signaux */
350 /****************************************************************************/
351 void spef_printdnets(FILE *file, lofig_list *ptfig)
352 {
353 losig_list *losig;
354 lorcnet_list *prcn;
355 lowire_list *wire;
356 loctc_list *ctc;
357 chain_list *chain;
358 long nbcap = 0;
359 long nbres = 0;
360 char buf[2048];
361 int doneprintcapa;
362
363 for(losig=ptfig->LOSIG;losig;losig=losig->NEXT){
364 if(spef_isalim(losig))
365 continue;
366 rcn_refresh_signal(ptfig, losig);
367 prcn = losig->PRCN;
368 doneprintcapa=0;
369 if(prcn){
370 if(prcn->PCTC || prcn->PWIRE){
371 if(SPEF_INFO->SPEF_CAP_UNIT == 'P')
372 fprintf(file, "\n*D_NET %s %g\n", spef_getitem(losig, 's', buf), rcn_getcapa( ptfig, losig ));
373 else if(SPEF_INFO->SPEF_CAP_UNIT == 'F')
374 fprintf(file, "\n*D_NET %s %g\n", spef_getitem(losig, 's', buf), rcn_getcapa( ptfig,losig ) * 1000.0);
375 spef_printconn(file, losig);
376 if(prcn->PCTC){ /* drive la liste des capas */
377 fprintf(file, "*CAP\n");
378 doneprintcapa=1;
379 nbcap = 1;
380 for(chain=prcn->PCTC;chain;chain=chain->NEXT){
381 ctc=(loctc_list*)chain->DATA;
382 if (!spef_isalim(ctc->SIG1) || !spef_isalim(ctc->SIG2))
383 {
384 fprintf(file, "%ld ", nbcap);
385 nbcap++;
386 if(!spef_isalim(ctc->SIG1))
387 spef_printnameorindex(file, ctc->SIG1, ctc->NODE1);
388 if(!spef_isalim(ctc->SIG2))
389 spef_printnameorindex(file, ctc->SIG2, ctc->NODE2);
390 if(SPEF_INFO->SPEF_CAP_UNIT == 'P')
391 fprintf(file, "%g\n", ctc->CAPA);
392 else if(SPEF_INFO->SPEF_CAP_UNIT == 'F')
393 fprintf(file, "%g\n", ctc->CAPA * 1000.0);
394 }
395 }
396 }
397 if(prcn->PWIRE){ /* drive la liste des capas des resistances */
398 for(wire=prcn->PWIRE;wire;wire=wire->NEXT){
399 if(wire->CAPA > 0.0) {
400 if (!doneprintcapa) {
401 doneprintcapa=1;
402 fprintf(file, "*CAP\n");
403 nbcap = 1;
404 }
405 fprintf(file, "%ld ", nbcap);
406 nbcap++;
407 spef_printnameorindex(file, losig, wire->NODE1);
408 if(SPEF_INFO->SPEF_CAP_UNIT == 'P')
409 fprintf(file, "%g\n", wire->CAPA/2.0);
410 else if(SPEF_INFO->SPEF_CAP_UNIT == 'F')
411 fprintf(file, "%g\n", wire->CAPA * 500.0);
412 fprintf(file, "%ld ", nbcap);
413 nbcap++;
414 spef_printnameorindex(file, losig, wire->NODE2);
415 if(SPEF_INFO->SPEF_CAP_UNIT == 'P')
416 fprintf(file, "%g\n", wire->CAPA/2.0);
417 else if(SPEF_INFO->SPEF_CAP_UNIT == 'F')
418 fprintf(file, "%g\n", wire->CAPA * 500.0);
419 }
420 }
421 }
422 if(prcn->PWIRE){ /* drive la liste des resistances */
423 fprintf(file, "*RES\n");
424 nbres = 1;
425 for(wire=prcn->PWIRE;wire;wire=wire->NEXT){
426 fprintf(file, "%ld ", nbres);
427 nbres++;
428 spef_printnameorindex(file, losig, wire->NODE1);
429 spef_printnameorindex(file, losig, wire->NODE2);
430 if(SPEF_INFO->SPEF_RES_UNIT == 'O')
431 fprintf(file, "%g\n", wire->RESI);
432 if(SPEF_INFO->SPEF_RES_UNIT == 'K')
433 fprintf(file, "%g\n", wire->RESI / 1000.0);
434 }
435 }
436 fprintf(file, "\n*END\n");
437 }
438 }
439 }
440 }
441 /****************************************************************************/
442 void spef_drive(lofig_list *ptfig, FILE *outputfile)
443 {
444 FILE *file;
445 char buf[1024];
446
447 if (outputfile!=NULL) file=outputfile;
448 else
449 {
450 sprintf(buf,"%s.spef", ptfig->NAME);
451 file= fopen (buf, "w+");
452 }
453
454 spef_printheader(file, ptfig);
455 spef_printnamemap(file, ptfig);
456 spef_printports(file, ptfig);
457 spef_printdnets(file, ptfig);
458 spef_cleannamemap(ptfig);
459 if (outputfile==NULL) fclose(file);
460 }