1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: iolefi.c
6 * Input/output tool: LEF (Library Exchange Format) reader
7 * Written by: Steven M. Rubin, Static Free Software
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 /*
33 * Note that this reader was built by examining LEF files and reverse-engineering them.
34 * It does not claim to be compliant with the LEF specification, but it also does not
35 * claim to define a new specification. It is merely incomplete.
36 */
37
38 #include "config.h"
39 #include "global.h"
40 #include "egraphics.h"
41 #include "efunction.h"
42 #include "edialogs.h"
43 #include "iolefdef.h"
44 #include "tecart.h"
45 #include "tecgen.h"
46 #include "eio.h"
47 #include "usr.h"
48
49 /*************** LEF PATHS ***************/
50
51 #define NOLEFPATH ((LEFPATH *)-1)
52
53 typedef struct Ilefpath
54 {
55 INTBIG x[2], y[2];
56 NODEINST *ni[2];
57 INTBIG width;
58 ARCPROTO *arc;
59 struct Ilefpath *nextlefpath;
60 } LEFPATH;
61
62 LEFPATH *io_leffreepath = NOLEFPATH;
63
64 /*************** MISCELLANEOUS ***************/
65
66 #define MAXLINE 2500
67
68 static INTBIG io_leffilesize;
69 static INTBIG io_leflineno;
70 static CHAR io_lefline[MAXLINE];
71 static INTBIG io_leflinepos;
72 VIADEF *io_leffirstviadef = NOVIADEF;
73 static void *io_lefprogressdialog;
74
75 /* prototypes for local routines */
76 static void io_leffreepaths(LEFPATH *firstlp);
77 static ARCPROTO *io_lefgetarc(INTBIG afunc);
78 static CHAR *io_lefgetkeyword(FILE *f);
79 static NODEPROTO *io_lefgetnode(INTBIG lfunc);
80 static BOOLEAN io_lefignoretosemicolon(FILE *f, CHAR *command);
81 static void io_lefkillpath(LEFPATH *lp);
82 static LEFPATH *io_lefnewpath(void);
83 static PORTPROTO *io_lefnewport(NODEPROTO *cell, NODEINST *ni, PORTPROTO *pp, CHAR *thename);
84 static void io_lefparselayer(CHAR *layername, INTBIG *arcfunc, INTBIG *layerfunc);
85 static BOOLEAN io_lefreadfile(FILE *f, LIBRARY *lib);
86 static BOOLEAN io_lefreadlayer(FILE *f, LIBRARY *lib);
87 static BOOLEAN io_lefreadmacro(FILE *f, LIBRARY *lib);
88 static BOOLEAN io_lefreadvia(FILE *f, LIBRARY *lib);
89 static BOOLEAN io_lefreadobs(FILE *f, NODEPROTO *cell);
90 static BOOLEAN io_lefreadpin(FILE *f, NODEPROTO *cell);
91 static BOOLEAN io_lefreadport(FILE *f, NODEPROTO *cell, CHAR *portname, INTBIG portbits);
92 static void io_leffreevias(void);
93
94 /*
95 * Routine to free all memory associated with this module.
96 */
io_freelefimemory(void)97 void io_freelefimemory(void)
98 {
99 io_leffreevias();
100 }
101
io_readleflibrary(LIBRARY * lib)102 BOOLEAN io_readleflibrary(LIBRARY *lib)
103 {
104 FILE *fp;
105 REGISTER BOOLEAN ret;
106 CHAR *filename;
107
108 /* open the file */
109 fp = xopen(lib->libfile, io_filetypelef, x_(""), &filename);
110 if (fp == NULL)
111 {
112 ttyputerr(_("File %s not found"), lib->libfile);
113 return(TRUE);
114 }
115
116 /* remove any vias in the globals */
117 io_leffreevias();
118
119 /* prepare for input */
120 io_leffilesize = filesize(fp);
121 io_lefprogressdialog = DiaInitProgress(_("Reading LEF file..."), 0);
122 if (io_lefprogressdialog == 0)
123 {
124 xclose(fp);
125 return(TRUE);
126 }
127 DiaSetProgress(io_lefprogressdialog, 0, io_leffilesize);
128 io_leflineno = 0;
129 io_leflinepos = 0;
130 io_lefline[0] = 0;
131
132 /* read the file */
133 ret = io_lefreadfile(fp, lib);
134
135 /* clean up */
136 DiaDoneProgress(io_lefprogressdialog);
137 xclose(fp);
138 if (!ret) ttyputmsg(_("LEF file %s is read"), lib->libfile); else
139 ttyputmsg(_("Error reading LEF file %s"), lib->libfile);
140 return(FALSE);
141 }
142
io_leffreevias(void)143 void io_leffreevias(void)
144 {
145 VIADEF *vd;
146
147 while (io_leffirstviadef != NOVIADEF)
148 {
149 vd = io_leffirstviadef;
150 io_leffirstviadef = io_leffirstviadef->nextviadef;
151 efree((CHAR *)vd->vianame);
152 efree((CHAR *)vd);
153 }
154 }
155
156 /*
157 * Routine to read the LEF file in "f".
158 */
io_lefreadfile(FILE * f,LIBRARY * lib)159 BOOLEAN io_lefreadfile(FILE *f, LIBRARY *lib)
160 {
161 REGISTER CHAR *key;
162
163 for(;;)
164 {
165 /* get the next keyword */
166 key = io_lefgetkeyword(f);
167 if (key == 0) break;
168 if (namesame(key, x_("LAYER")) == 0)
169 {
170 if (io_lefreadlayer(f, lib)) return(TRUE);
171 }
172 if (namesame(key, x_("MACRO")) == 0)
173 {
174 if (io_lefreadmacro(f, lib)) return(TRUE);
175 }
176 if (namesame(key, x_("VIA")) == 0)
177 {
178 if (io_lefreadvia(f, lib)) return(TRUE);
179 }
180 }
181 return(FALSE);
182 }
183
io_lefparselayer(CHAR * layername,INTBIG * arcfunc,INTBIG * layerfunc)184 void io_lefparselayer(CHAR *layername, INTBIG *arcfunc, INTBIG *layerfunc)
185 {
186 REGISTER INTBIG laynum, j;
187
188 *arcfunc = APUNKNOWN;
189 *layerfunc = LFUNKNOWN;
190
191 j = 0;
192 if (namesamen(layername, x_("METAL"), 5) == 0) j = 5; else
193 if (namesamen(layername, x_("MET"), 3) == 0) j = 3;
194 if (j != 0)
195 {
196 laynum = eatoi(&layername[j]);
197 switch (laynum)
198 {
199 case 1: *arcfunc = APMETAL1; *layerfunc = LFMETAL1; break;
200 case 2: *arcfunc = APMETAL2; *layerfunc = LFMETAL2; break;
201 case 3: *arcfunc = APMETAL3; *layerfunc = LFMETAL3; break;
202 case 4: *arcfunc = APMETAL4; *layerfunc = LFMETAL4; break;
203 case 5: *arcfunc = APMETAL5; *layerfunc = LFMETAL5; break;
204 case 6: *arcfunc = APMETAL6; *layerfunc = LFMETAL6; break;
205 case 7: *arcfunc = APMETAL7; *layerfunc = LFMETAL7; break;
206 case 8: *arcfunc = APMETAL8; *layerfunc = LFMETAL8; break;
207 case 9: *arcfunc = APMETAL9; *layerfunc = LFMETAL9; break;
208 case 10: *arcfunc = APMETAL10; *layerfunc = LFMETAL10; break;
209 case 11: *arcfunc = APMETAL11; *layerfunc = LFMETAL11; break;
210 case 12: *arcfunc = APMETAL12; *layerfunc = LFMETAL12; break;
211 }
212 return;
213 }
214
215 if (namesamen(layername, x_("POLY"), 4) == 0)
216 {
217 laynum = eatoi(&layername[4]);
218 switch (laynum)
219 {
220 case 1: *arcfunc = APPOLY1; *layerfunc = LFPOLY1; break;
221 case 2: *arcfunc = APPOLY2; *layerfunc = LFPOLY2; break;
222 case 3: *arcfunc = APPOLY3; *layerfunc = LFPOLY3; break;
223 }
224 return;
225 }
226
227 if (namesame(layername, x_("PDIFF")) == 0)
228 {
229 *arcfunc = APDIFFP;
230 *layerfunc = LFDIFF | LFPTYPE;
231 return;
232 }
233 if (namesame(layername, x_("NDIFF")) == 0)
234 {
235 *arcfunc = APDIFFN;
236 *layerfunc = LFDIFF | LFNTYPE;
237 return;
238 }
239 if (namesame(layername, x_("DIFF")) == 0)
240 {
241 *arcfunc = APDIFF;
242 *layerfunc = LFDIFF;
243 return;
244 }
245
246 if (namesame(layername, x_("CONT")) == 0)
247 {
248 *layerfunc = LFCONTACT1;
249 return;
250 }
251 if (namesamen(layername, x_("VIA"), 3) == 0)
252 {
253 laynum = eatoi(&layername[3]);
254 switch (laynum)
255 {
256 case 0:
257 case 1:
258 case 12: *layerfunc = LFCONTACT2; break;
259
260 case 2:
261 case 23: *layerfunc = LFCONTACT3; break;
262
263 case 3:
264 case 34: *layerfunc = LFCONTACT4; break;
265
266 case 4:
267 case 45: *layerfunc = LFCONTACT5; break;
268
269 case 5:
270 case 56: *layerfunc = LFCONTACT6; break;
271
272 case 6:
273 case 67: *layerfunc = LFCONTACT7; break;
274
275 case 7:
276 case 78: *layerfunc = LFCONTACT8; break;
277
278 case 8:
279 case 89: *layerfunc = LFCONTACT9; break;
280
281 case 9: *layerfunc = LFCONTACT10; break;
282
283 case 10: *layerfunc = LFCONTACT11; break;
284
285 case 11: *layerfunc = LFCONTACT12; break;
286 }
287 }
288 }
289
io_lefreadlayer(FILE * f,LIBRARY * lib)290 BOOLEAN io_lefreadlayer(FILE *f, LIBRARY *lib)
291 {
292 REGISTER CHAR *layername, *key;
293 CHAR curkey[200];
294 REGISTER INTBIG defwidth;
295 INTBIG afunc, layerfunc;
296 REGISTER ARCPROTO *ap;
297 float v;
298
299 layername = io_lefgetkeyword(f);
300 if (layername == 0)
301 {
302 ttyputerr(_("EOF parsing LAYER header"));
303 return(TRUE);
304 }
305 io_lefparselayer(layername, &afunc, &layerfunc);
306 if (afunc == APUNKNOWN) ap = NOARCPROTO; else
307 {
308 for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
309 if (((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH)) == afunc) break;
310 }
311
312 for(;;)
313 {
314 /* get the next keyword */
315 key = io_lefgetkeyword(f);
316 if (key == 0)
317 {
318 ttyputerr(_("EOF parsing LAYER"));
319 return(TRUE);
320 }
321
322 if (namesame(key, x_("END")) == 0)
323 {
324 key = io_lefgetkeyword(f);
325 break;
326 }
327
328 if (namesame(key, x_("WIDTH")) == 0)
329 {
330 key = io_lefgetkeyword(f);
331 if (key == 0)
332 {
333 ttyputerr(_("EOF reading WIDTH"));
334 return(TRUE);
335 }
336 v = (float)eatof(key);
337 defwidth = scalefromdispunit(v, DISPUNITMIC);
338 if (ap != NOARCPROTO)
339 {
340 setval((INTBIG)ap, VARCPROTO, x_("IO_lef_width"), defwidth, VINTEGER);
341 }
342 if (io_lefignoretosemicolon(f, x_("WIDTH"))) return(TRUE);
343 continue;
344 }
345
346 if (namesame(key, x_("TYPE")) == 0 || namesame(key, x_("SPACING")) == 0 ||
347 namesame(key, x_("PITCH")) == 0 || namesame(key, x_("DIRECTION")) == 0 ||
348 namesame(key, x_("CAPACITANCE")) == 0 || namesame(key, x_("RESISTANCE")) == 0)
349 {
350 estrcpy(curkey, key);
351 if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
352 continue;
353 }
354 }
355 return(FALSE);
356 }
357
io_lefreadmacro(FILE * f,LIBRARY * lib)358 BOOLEAN io_lefreadmacro(FILE *f, LIBRARY *lib)
359 {
360 REGISTER CHAR *cellname, *key;
361 REGISTER INTBIG ox, oy, blx, bhx, bly, bhy, dx, dy;
362 INTBIG sx, sy;
363 float x, y;
364 REGISTER NODEPROTO *cell;
365 REGISTER NODEINST *ni;
366 CHAR curkey[200];
367 REGISTER void *infstr;
368
369 cellname = io_lefgetkeyword(f);
370 if (cellname == 0)
371 {
372 ttyputerr(_("EOF parsing MACRO header"));
373 return(TRUE);
374 }
375 infstr = initinfstr();
376 addstringtoinfstr(infstr, cellname);
377 addstringtoinfstr(infstr, x_("{sk}"));
378 cellname = returninfstr(infstr);
379 cell = us_newnodeproto(cellname, lib);
380 if (cell == NONODEPROTO)
381 {
382 ttyputerr(_("Cannot create cell '%s'"), cellname);
383 return(TRUE);
384 }
385
386 for(;;)
387 {
388 /* get the next keyword */
389 key = io_lefgetkeyword(f);
390 if (key == 0)
391 {
392 ttyputerr(_("EOF parsing MACRO"));
393 return(TRUE);
394 }
395
396 if (namesame(key, x_("END")) == 0)
397 {
398 key = io_lefgetkeyword(f);
399 break;
400 }
401
402 if (namesame(key, x_("SOURCE")) == 0 || namesame(key, x_("FOREIGN")) == 0 ||
403 namesame(key, x_("SYMMETRY")) == 0 || namesame(key, x_("SITE")) == 0 ||
404 namesame(key, x_("CLASS")) == 0 || namesame(key, x_("LEQ")) == 0 ||
405 namesame(key, x_("POWER")) == 0)
406 {
407 estrcpy(curkey, key);
408 if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
409 continue;
410 }
411
412 if (namesame(key, x_("ORIGIN")) == 0)
413 {
414 key = io_lefgetkeyword(f);
415 if (key == 0)
416 {
417 ttyputerr(_("EOF reading ORIGIN X"));
418 return(TRUE);
419 }
420 x = (float)eatof(key);
421 ox = scalefromdispunit(x, DISPUNITMIC);
422
423 key = io_lefgetkeyword(f);
424 if (key == 0)
425 {
426 ttyputerr(_("EOF reading ORIGIN Y"));
427 return(TRUE);
428 }
429 y = (float)eatof(key);
430 oy = scalefromdispunit(y, DISPUNITMIC);
431 if (io_lefignoretosemicolon(f, x_("ORIGIN"))) return(TRUE);
432
433 /* create or move the cell-center node */
434 for(ni = cell->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
435 if (ni->proto == gen_cellcenterprim) break;
436 if (ni == NONODEINST)
437 {
438 defaultnodesize(gen_cellcenterprim, &sx, &sy);
439 blx = ox - sx/2; bhx = blx + sx;
440 bly = oy - sy/2; bhy = bly + sy;
441 ni = newnodeinst(gen_cellcenterprim, blx, bhx, bly, bhy, 0, 0, cell);
442 if (ni == NONODEINST)
443 {
444 ttyputerr(_("Line %ld: Cannot create cell center node"), io_leflineno);
445 return(TRUE);
446 }
447 ni->userbits |= HARDSELECTN|NVISIBLEINSIDE;
448 } else
449 {
450 startobjectchange((INTBIG)ni, VNODEINST);
451 dx = ox - (ni->lowx + ni->highx) / 2;
452 dy = oy - (ni->lowy + ni->highy) / 2;
453 modifynodeinst(ni, dx, dy, dx, dy, 0, 0);
454 }
455 endobjectchange((INTBIG)ni, VNODEINST);
456 continue;
457 }
458
459 if (namesame(key, x_("SIZE")) == 0)
460 {
461 key = io_lefgetkeyword(f);
462 if (key == 0)
463 {
464 ttyputerr(_("EOF reading SIZE X"));
465 return(TRUE);
466 }
467 x = (float)eatof(key);
468 sx = scalefromdispunit(x, DISPUNITMIC);
469
470 key = io_lefgetkeyword(f);
471 if (key == 0)
472 {
473 ttyputerr(_("EOF reading SIZE 'BY'"));
474 return(TRUE);
475 }
476 if (namesame(key, x_("BY")) != 0)
477 {
478 ttyputerr(_("Line %ld: Expected 'by' in SIZE"), io_leflineno);
479 return(TRUE);
480 }
481
482 key = io_lefgetkeyword(f);
483 if (key == 0)
484 {
485 ttyputerr(_("EOF reading SIZE Y"));
486 return(TRUE);
487 }
488 y = (float)eatof(key);
489 sy = scalefromdispunit(y, DISPUNITMIC);
490 if (io_lefignoretosemicolon(f, x_("SIZE"))) return(TRUE);
491 continue;
492 }
493
494 if (namesame(key, x_("PIN")) == 0)
495 {
496 if (io_lefreadpin(f, cell)) return(TRUE);
497 continue;
498 }
499
500 if (namesame(key, x_("OBS")) == 0)
501 {
502 if (io_lefreadobs(f, cell)) return(TRUE);
503 continue;
504 }
505
506 ttyputerr(_("Line %ld: Unknown MACRO keyword (%s)"), io_leflineno, key);
507 return(TRUE);
508 }
509 return(FALSE);
510 }
511
io_lefreadvia(FILE * f,LIBRARY * lib)512 BOOLEAN io_lefreadvia(FILE *f, LIBRARY *lib)
513 {
514 REGISTER CHAR *vianame, *key;
515 REGISTER INTBIG lx, hx, ly, hy, i, lay1found, lay2found;
516 INTBIG afunc, layerfunc;
517 NODEPROTO *np;
518 ARCPROTO *ap;
519 float v;
520 BOOLEAN ignoredefault;
521 REGISTER PORTPROTO *pp;
522 REGISTER VIADEF *vd;
523
524 /* get the via name */
525 vianame = io_lefgetkeyword(f);
526 if (vianame == 0) return(TRUE);
527
528 /* create a new via definition */
529 vd = (VIADEF *)emalloc(sizeof (VIADEF), io_tool->cluster);
530 if (vd == 0) return(TRUE);
531 (void)allocstring(&vd->vianame, vianame, io_tool->cluster);
532 vd->sx = vd->sy = 0;
533 vd->via = NONODEPROTO;
534 vd->lay1 = vd->lay2 = NOARCPROTO;
535 vd->nextviadef = io_leffirstviadef;
536 io_leffirstviadef = vd;
537
538 ignoredefault = TRUE;
539 for(;;)
540 {
541 /* get the next keyword */
542 key = io_lefgetkeyword(f);
543 if (key == 0) return(TRUE);
544 if (ignoredefault)
545 {
546 ignoredefault = FALSE;
547 if (namesame(key, x_("DEFAULT")) == 0) continue;
548 }
549 if (namesame(key, x_("END")) == 0)
550 {
551 key = io_lefgetkeyword(f);
552 break;
553 }
554 if (namesame(key, x_("RESISTANCE")) == 0)
555 {
556 if (io_lefignoretosemicolon(f, key)) return(TRUE);
557 continue;
558 }
559 if (namesame(key, x_("LAYER")) == 0)
560 {
561 key = io_lefgetkeyword(f);
562 if (key == 0) return(TRUE);
563 io_lefparselayer(key, &afunc, &layerfunc);
564 if (afunc == APUNKNOWN) ap = NOARCPROTO; else
565 {
566 for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
567 if (((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH)) == afunc) break;
568 }
569 if (ap != NOARCPROTO)
570 {
571 if (vd->lay1 == NOARCPROTO) vd->lay1 = ap; else
572 vd->lay2 = ap;
573 }
574 if (io_lefignoretosemicolon(f, x_("LAYER"))) return(TRUE);
575 continue;
576 }
577 if (namesame(key, x_("RECT")) == 0)
578 {
579 /* handle definition of a via rectangle */
580 key = io_lefgetkeyword(f);
581 if (key == 0) return(TRUE);
582 v = (float)eatof(key);
583 lx = scalefromdispunit(v, DISPUNITMIC);
584
585 key = io_lefgetkeyword(f);
586 if (key == 0) return(TRUE);
587 v = (float)eatof(key);
588 ly = scalefromdispunit(v, DISPUNITMIC);
589
590 key = io_lefgetkeyword(f);
591 if (key == 0) return(TRUE);
592 v = (float)eatof(key);
593 hx = scalefromdispunit(v, DISPUNITMIC);
594
595 key = io_lefgetkeyword(f);
596 if (key == 0) return(TRUE);
597 v = (float)eatof(key);
598 hy = scalefromdispunit(v, DISPUNITMIC);
599
600 /* accumulate largest layer size */
601 if (hx-lx > vd->sx) vd->sx = hx - lx;
602 if (hy-ly > vd->sy) vd->sy = hy - ly;
603
604 if (io_lefignoretosemicolon(f, x_("RECT"))) return(TRUE);
605 continue;
606 }
607 }
608 if (vd->lay1 != NOARCPROTO && vd->lay2 != NOARCPROTO)
609 {
610 for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
611 {
612 if (((np->userbits&NFUNCTION)>>NFUNCTIONSH) != NPCONTACT) continue;
613 pp = np->firstportproto;
614 lay1found = lay2found = 0;
615 for(i=0; pp->connects[i] != NOARCPROTO; i++)
616 {
617 if (pp->connects[i] == vd->lay1) lay1found = 1;
618 if (pp->connects[i] == vd->lay2) lay2found = 1;
619 }
620 if (lay1found != 0 && lay2found != 0) break;
621 }
622 vd->via = np;
623 }
624 return(FALSE);
625 }
626
io_lefreadpin(FILE * f,NODEPROTO * cell)627 BOOLEAN io_lefreadpin(FILE *f, NODEPROTO *cell)
628 {
629 REGISTER CHAR *key;
630 REGISTER INTBIG portbits, usebits;
631 CHAR curkey[200], pinname[200];
632
633 /* get the pin name */
634 key = io_lefgetkeyword(f);
635 if (key == 0)
636 {
637 ttyputerr(_("EOF parsing PIN name"));
638 return(TRUE);
639 }
640 estrcpy(pinname, key);
641
642 portbits = usebits = 0;
643 for(;;)
644 {
645 key = io_lefgetkeyword(f);
646 if (key == 0)
647 {
648 ttyputerr(_("EOF parsing PIN"));
649 return(TRUE);
650 }
651
652 if (namesame(key, x_("END")) == 0)
653 {
654 key = io_lefgetkeyword(f);
655 break;
656 }
657
658 if (namesame(key, x_("SHAPE")) == 0 || namesame(key, x_("CAPACITANCE")) == 0 ||
659 namesame(key, x_("ANTENNASIZE")) == 0)
660 {
661 estrcpy(curkey, key);
662 if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
663 continue;
664 }
665
666 if (namesame(key, x_("USE")) == 0)
667 {
668 key = io_lefgetkeyword(f);
669 if (key == 0)
670 {
671 ttyputerr(_("EOF reading USE clause"));
672 return(TRUE);
673 }
674 if (namesame(key, x_("POWER")) == 0) usebits = PWRPORT; else
675 if (namesame(key, x_("GROUND")) == 0) usebits = GNDPORT; else
676 if (namesame(key, x_("CLOCK")) == 0) usebits = CLKPORT; else
677 {
678 ttyputerr(_("Line %ld: Unknown USE keyword (%s)"),
679 io_leflineno, key);
680 }
681 if (io_lefignoretosemicolon(f, x_("USE"))) return(TRUE);
682 continue;
683 }
684
685 if (namesame(key, x_("DIRECTION")) == 0)
686 {
687 key = io_lefgetkeyword(f);
688 if (key == 0)
689 {
690 ttyputerr(_("EOF reading DIRECTION clause"));
691 return(TRUE);
692 }
693 if (namesame(key, x_("INPUT")) == 0) portbits = INPORT; else
694 if (namesame(key, x_("OUTPUT")) == 0) portbits = OUTPORT; else
695 if (namesame(key, x_("INOUT")) == 0) portbits = BIDIRPORT; else
696 {
697 ttyputerr(_("Line %ld: Unknown DIRECTION keyword (%s)"),
698 io_leflineno, key);
699 }
700 if (io_lefignoretosemicolon(f, x_("DIRECTION"))) return(TRUE);
701 continue;
702 }
703
704 if (namesame(key, x_("PORT")) == 0)
705 {
706 if (usebits != 0) portbits = usebits;
707 if (io_lefreadport(f, cell, pinname, portbits))
708 return(TRUE);
709 continue;
710 }
711
712 ttyputerr(_("Line %ld: Unknown PIN keyword (%s)"), io_leflineno, key);
713 return(TRUE);
714 }
715 return(FALSE);
716 }
717
io_lefreadport(FILE * f,NODEPROTO * cell,CHAR * portname,INTBIG portbits)718 BOOLEAN io_lefreadport(FILE *f, NODEPROTO *cell, CHAR *portname, INTBIG portbits)
719 {
720 REGISTER CHAR *key;
721 REGISTER INTBIG i, j, lx, hx, ly, hy, intx, inty, first,
722 intwidth, lastintx, lastinty, sea, cx, cy;
723 INTBIG afunc, layerfunc, sx, sy;
724 REGISTER INTBIG afunc1, afunc2, found1, found2;
725 REGISTER ARCPROTO *ap, *ap1, *ap2;
726 REGISTER NODEPROTO *pin, *plnp;
727 REGISTER ARCINST *ai;
728 REGISTER NODEINST *ni;
729 REGISTER PORTPROTO *pp;
730 REGISTER GEOM *geom;
731 float width, x, y;
732 REGISTER LEFPATH *lefpaths, *lp, *olp;
733
734 ap = NOARCPROTO;
735 plnp = NONODEPROTO;
736 lefpaths = NOLEFPATH;
737 first = 1;
738 for(;;)
739 {
740 key = io_lefgetkeyword(f);
741 if (key == 0)
742 {
743 ttyputerr(_("EOF parsing PORT"));
744 return(TRUE);
745 }
746
747 if (namesame(key, x_("END")) == 0)
748 {
749 break;
750 }
751
752 if (namesame(key, x_("LAYER")) == 0)
753 {
754 key = io_lefgetkeyword(f);
755 if (key == 0)
756 {
757 ttyputerr(_("EOF reading LAYER clause"));
758 return(TRUE);
759 }
760 io_lefparselayer(key, &afunc, &layerfunc);
761 if (afunc == APUNKNOWN) ap = NOARCPROTO; else
762 ap = io_lefgetarc(afunc);
763 plnp = io_lefgetnode(layerfunc);
764 if (io_lefignoretosemicolon(f, x_("LAYER"))) return(TRUE);
765 continue;
766 }
767
768 if (namesame(key, x_("WIDTH")) == 0)
769 {
770 key = io_lefgetkeyword(f);
771 if (key == 0)
772 {
773 ttyputerr(_("EOF reading WIDTH clause"));
774 return(TRUE);
775 }
776 width = (float)eatof(key);
777 intwidth = scalefromdispunit(width, DISPUNITMIC);
778 if (io_lefignoretosemicolon(f, x_("WIDTH"))) return(TRUE);
779 continue;
780 }
781
782 if (namesame(key, x_("RECT")) == 0)
783 {
784 if (plnp == NONODEPROTO)
785 {
786 ttyputerr(_("Line %ld: No layers for RECT"), io_leflineno);
787 return(TRUE);
788 }
789 key = io_lefgetkeyword(f);
790 if (key == 0)
791 {
792 ttyputerr(_("EOF reading RECT low X"));
793 return(TRUE);
794 }
795 x = (float)eatof(key);
796 lx = scalefromdispunit(x, DISPUNITMIC);
797
798 key = io_lefgetkeyword(f);
799 if (key == 0)
800 {
801 ttyputerr(_("EOF reading RECT low Y"));
802 return(TRUE);
803 }
804 y = (float)eatof(key);
805 ly = scalefromdispunit(y, DISPUNITMIC);
806
807 key = io_lefgetkeyword(f);
808 if (key == 0)
809 {
810 ttyputerr(_("EOF reading RECT high X"));
811 return(TRUE);
812 }
813 x = (float)eatof(key);
814 hx = scalefromdispunit(x, DISPUNITMIC);
815
816 key = io_lefgetkeyword(f);
817 if (key == 0)
818 {
819 ttyputerr(_("EOF reading RECT high Y"));
820 return(TRUE);
821 }
822 y = (float)eatof(key);
823 hy = scalefromdispunit(y, DISPUNITMIC);
824
825 if (io_lefignoretosemicolon(f, x_("RECT"))) return(TRUE);
826
827 /* make the pin */
828 if (hx < lx) { j = hx; hx = lx; lx = j; }
829 if (hy < ly) { j = hy; hy = ly; ly = j; }
830 ni = newnodeinst(plnp, lx, hx, ly, hy, 0, 0, cell);
831 if (ni == NONODEINST)
832 {
833 ttyputerr(_("Line %ld: Cannot create pin for RECT"), io_leflineno);
834 return(TRUE);
835 }
836 endobjectchange((INTBIG)ni, VNODEINST);
837
838 if (first != 0)
839 {
840 /* create the port on the first pin */
841 first = 0;
842 pp = io_lefnewport(cell, ni, plnp->firstportproto, portname);
843 pp->userbits = (pp->userbits & ~STATEBITS) | portbits;
844 }
845 continue;
846 }
847
848 if (namesame(key, x_("PATH")) == 0)
849 {
850 if (ap == NOARCPROTO)
851 {
852 ttyputerr(_("Line %ld: No layers for PATH"), io_leflineno);
853 return(TRUE);
854 }
855 for(i=0; ; i++)
856 {
857 key = io_lefgetkeyword(f);
858 if (key == 0)
859 {
860 ttyputerr(_("EOF reading PATH clause"));
861 return(TRUE);
862 }
863 if (estrcmp(key, x_(";")) == 0) break;
864 x = (float)eatof(key);
865
866 key = io_lefgetkeyword(f);
867 if (key == 0)
868 {
869 ttyputerr(_("EOF reading PATH clause"));
870 return(TRUE);
871 }
872 y = (float)eatof(key);
873
874 /* plot this point */
875 intx = scalefromdispunit(x, DISPUNITMIC);
876 inty = scalefromdispunit(y, DISPUNITMIC);
877 if (i != 0)
878 {
879 /* queue path */
880 lp = io_lefnewpath();
881 if (lp == NOLEFPATH) return(TRUE);
882
883 /* LINTED "lastintx" used in proper order */
884 lp->x[0] = lastintx; lp->x[1] = intx;
885
886 /* LINTED "lastinty" used in proper order */
887 lp->y[0] = lastinty; lp->y[1] = inty;
888 lp->ni[0] = NONODEINST; lp->ni[1] = NONODEINST;
889 lp->width = intwidth;
890 lp->arc = ap;
891 lp->nextlefpath = lefpaths;
892 lefpaths = lp;
893 }
894 lastintx = intx; lastinty = inty;
895 }
896 continue;
897 }
898
899 if (namesame(key, x_("VIA")) == 0)
900 {
901 /* get the coordinates */
902 key = io_lefgetkeyword(f);
903 if (key == 0)
904 {
905 ttyputerr(_("EOF reading VIA clause"));
906 return(TRUE);
907 }
908 x = (float)eatof(key);
909 intx = scalefromdispunit(x, DISPUNITMIC);
910
911 key = io_lefgetkeyword(f);
912 if (key == 0)
913 {
914 ttyputerr(_("EOF reading VIA clause"));
915 return(TRUE);
916 }
917 y = (float)eatof(key);
918 inty = scalefromdispunit(y, DISPUNITMIC);
919
920 /* find the proper via */
921 key = io_lefgetkeyword(f);
922 afunc1 = afunc2 = APUNKNOWN;
923 if (namesame(key, x_("via1")) == 0)
924 {
925 afunc1 = APMETAL1;
926 afunc2 = APMETAL2;
927 } else if (namesame(key, x_("via2")) == 0)
928 {
929 afunc1 = APMETAL2;
930 afunc2 = APMETAL3;
931 } else if (namesame(key, x_("via3")) == 0)
932 {
933 afunc1 = APMETAL3;
934 afunc2 = APMETAL4;
935 } else if (namesame(key, x_("via4")) == 0)
936 {
937 afunc1 = APMETAL4;
938 afunc2 = APMETAL5;
939 } else
940 {
941 ttyputerr(_("Line %ld: Unknown VIA type (%s)"), io_leflineno, key);
942 return(TRUE);
943 }
944 ap1 = io_lefgetarc(afunc1);
945 if (ap1 == NOARCPROTO) return(TRUE);
946 ap2 = io_lefgetarc(afunc2);
947 if (ap2 == NOARCPROTO) return(TRUE);
948 for(pin = el_curtech->firstnodeproto; pin != NONODEPROTO; pin = pin->nextnodeproto)
949 {
950 if (((pin->userbits&NFUNCTION)>>NFUNCTIONSH) != NPCONTACT) continue;
951 pp = pin->firstportproto;
952 found1 = found2 = 0;
953 for(i=0; pp->connects[i] != NOARCPROTO; i++)
954 {
955 if (pp->connects[i] == ap1) found1 = 1;
956 if (pp->connects[i] == ap2) found2 = 1;
957 }
958 if (found1 != 0 && found2 != 0) break;
959 }
960 if (pin == NONODEPROTO)
961 {
962 ttyputerr(_("Line %ld: No Via in current technology connects %s to %s"),
963 io_leflineno, arcfunctionname(afunc1),
964 arcfunctionname(afunc2));
965 return(TRUE);
966 }
967 if (io_lefignoretosemicolon(f, x_("VIA"))) return(TRUE);
968
969 /* create the via */
970 defaultnodesize(pin, &sx, &sy);
971 lx = intx - sx / 2; hx = lx + sx;
972 ly = inty - sy / 2; hy = ly + sy;
973 ni = newnodeinst(pin, lx, hx, ly, hy, 0, 0, cell);
974 if (ni == NONODEINST)
975 {
976 ttyputerr(_("Line %ld: Cannot create VIA for PATH"), io_leflineno);
977 return(TRUE);
978 }
979 endobjectchange((INTBIG)ni, VNODEINST);
980 continue;
981 }
982
983 ttyputerr(_("Line %ld: Unknown PORT keyword (%s)"), io_leflineno, key);
984 return(TRUE);
985 }
986
987 /* look for paths that end at vias */
988 for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
989 {
990 for(i=0; i<2; i++)
991 {
992 if (lp->ni[i] != NONODEINST) continue;
993 sea = initsearch(lp->x[i], lp->x[i], lp->y[i], lp->y[i], cell);
994 for(;;)
995 {
996 geom = nextobject(sea);
997 if (geom == NOGEOM) break;
998 if (!geom->entryisnode) continue;
999 ni = geom->entryaddr.ni;
1000 cx = (ni->lowx + ni->highx) / 2;
1001 cy = (ni->lowy + ni->highy) / 2;
1002 if (cx != lp->x[i] || cy != lp->y[i]) continue;
1003 lp->ni[i] = ni;
1004 break;
1005 }
1006 if (lp->ni[i] == NONODEINST) continue;
1007
1008 /* use this via at other paths which meet here */
1009 for(olp = lefpaths; olp != NOLEFPATH; olp = olp->nextlefpath)
1010 {
1011 for(j=0; j<2; j++)
1012 {
1013 if (olp->ni[j] != NONODEINST) continue;
1014 if (olp->x[j] != lp->x[i] || olp->y[j] != lp->y[i]) continue;
1015 olp->ni[j] = lp->ni[i];
1016 }
1017 }
1018 }
1019 }
1020
1021 /* create pins at all other path ends */
1022 for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
1023 {
1024 for(i=0; i<2; i++)
1025 {
1026 if (lp->ni[i] != NONODEINST) continue;
1027 pin = getpinproto(lp->arc);
1028 if (pin == NONODEPROTO) continue;
1029 defaultnodesize(pin, &sx, &sy);
1030 lx = lp->x[i] - sx / 2; hx = lx + sx;
1031 ly = lp->y[i] - sy / 2; hy = ly + sy;
1032 lp->ni[i] = newnodeinst(pin, lx, hx, ly, hy, 0, 0, cell);
1033 if (lp->ni[i] == NONODEINST)
1034 {
1035 ttyputerr(_("Line %ld: Cannot create pin for PATH"), io_leflineno);
1036 return(TRUE);
1037 }
1038 endobjectchange((INTBIG)lp->ni[i], VNODEINST);
1039
1040 /* use this pin at other paths which meet here */
1041 for(olp = lefpaths; olp != NOLEFPATH; olp = olp->nextlefpath)
1042 {
1043 for(j=0; j<2; j++)
1044 {
1045 if (olp->ni[j] != NONODEINST) continue;
1046 if (olp->x[j] != lp->x[i] || olp->y[j] != lp->y[i]) continue;
1047 olp->ni[j] = lp->ni[i];
1048 }
1049 }
1050 }
1051 }
1052
1053 /* now instantiate the paths */
1054 for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
1055 {
1056 ai = newarcinst(lp->arc, lp->width, us_makearcuserbits(lp->arc),
1057 lp->ni[0], lp->ni[0]->proto->firstportproto, lp->x[0], lp->y[0],
1058 lp->ni[1], lp->ni[1]->proto->firstportproto, lp->x[1], lp->y[1], cell);
1059 if (ai == NOARCINST)
1060 {
1061 ttyputerr(_("Line %ld: Cannot create arc for PATH"), io_leflineno);
1062 return(TRUE);
1063 }
1064 }
1065 io_leffreepaths(lefpaths);
1066
1067 return(FALSE);
1068 }
1069
1070 /*
1071 * Routine to create a port called "thename" on port "pp" of node "ni" in cell "cell".
1072 * The name is modified if it already exists.
1073 */
io_lefnewport(NODEPROTO * cell,NODEINST * ni,PORTPROTO * pp,CHAR * thename)1074 PORTPROTO *io_lefnewport(NODEPROTO *cell, NODEINST *ni, PORTPROTO *pp, CHAR *thename)
1075 {
1076 REGISTER PORTPROTO *ppt;
1077 REGISTER INTBIG i, leng;
1078 REGISTER CHAR *newname, *portname;
1079
1080 portname = thename;
1081 newname = 0;
1082 for(i=0; ; i++)
1083 {
1084 ppt = getportproto(cell, portname);
1085 if (ppt == NOPORTPROTO)
1086 {
1087 ppt = newportproto(cell, ni, pp, portname);
1088 break;
1089 }
1090
1091 /* make space for modified name */
1092 if (newname == 0)
1093 {
1094 leng = estrlen(thename)+10;
1095 newname = (CHAR *)emalloc(leng * SIZEOFCHAR, el_tempcluster);
1096 }
1097 esnprintf(newname, leng, x_("%s-%ld"), thename, i);
1098 portname = newname;
1099 }
1100 if (newname != 0) efree(newname);
1101 return(ppt);
1102 }
1103
io_lefreadobs(FILE * f,NODEPROTO * cell)1104 BOOLEAN io_lefreadobs(FILE *f, NODEPROTO *cell)
1105 {
1106 REGISTER CHAR *key;
1107 INTBIG lfunc, arcfunc;
1108 REGISTER INTBIG lx, hx, ly, hy, j;
1109 float x, y;
1110 REGISTER NODEINST *ni;
1111 REGISTER NODEPROTO *np;
1112
1113 np = NONODEPROTO;
1114 for(;;)
1115 {
1116 key = io_lefgetkeyword(f);
1117 if (key == 0)
1118 {
1119 ttyputerr(_("EOF parsing OBS"));
1120 return(TRUE);
1121 }
1122
1123 if (namesame(key, x_("END")) == 0) break;
1124
1125 if (namesame(key, x_("LAYER")) == 0)
1126 {
1127 key = io_lefgetkeyword(f);
1128 if (key == 0)
1129 {
1130 ttyputerr(_("EOF reading LAYER clause"));
1131 return(TRUE);
1132 }
1133 io_lefparselayer(key, &arcfunc, &lfunc);
1134 if (lfunc == LFUNKNOWN)
1135 {
1136 ttyputerr(_("Line %ld: Unknown layer name (%s)"), io_leflineno, key);
1137 return(TRUE);
1138 }
1139 np = io_lefgetnode(lfunc);
1140 if (np == NONODEPROTO) return(TRUE);
1141 if (io_lefignoretosemicolon(f, x_("LAYER"))) return(TRUE);
1142 continue;
1143 }
1144
1145 if (namesame(key, x_("RECT")) == 0)
1146 {
1147 if (np == NONODEPROTO)
1148 {
1149 ttyputerr(_("Line %ld: No layers for RECT"), io_leflineno);
1150 return(TRUE);
1151 }
1152 key = io_lefgetkeyword(f);
1153 if (key == 0)
1154 {
1155 ttyputerr(_("EOF reading RECT low X"));
1156 return(TRUE);
1157 }
1158 x = (float)eatof(key);
1159 lx = scalefromdispunit(x, DISPUNITMIC);
1160
1161 key = io_lefgetkeyword(f);
1162 if (key == 0)
1163 {
1164 ttyputerr(_("EOF reading RECT low Y"));
1165 return(TRUE);
1166 }
1167 y = (float)eatof(key);
1168 ly = scalefromdispunit(y, DISPUNITMIC);
1169
1170 key = io_lefgetkeyword(f);
1171 if (key == 0)
1172 {
1173 ttyputerr(_("EOF reading RECT high X"));
1174 return(TRUE);
1175 }
1176 x = (float)eatof(key);
1177 hx = scalefromdispunit(x, DISPUNITMIC);
1178
1179 key = io_lefgetkeyword(f);
1180 if (key == 0)
1181 {
1182 ttyputerr(_("EOF reading RECT high Y"));
1183 return(TRUE);
1184 }
1185 y = (float)eatof(key);
1186 hy = scalefromdispunit(y, DISPUNITMIC);
1187
1188 if (io_lefignoretosemicolon(f, x_("RECT"))) return(TRUE);
1189
1190 /* make the pin */
1191 if (hx < lx) { j = hx; hx = lx; lx = j; }
1192 if (hy < ly) { j = hy; hy = ly; ly = j; }
1193 ni = newnodeinst(np, lx, hx, ly, hy, 0, 0, cell);
1194 if (ni == NONODEINST)
1195 {
1196 ttyputerr(_("Line %ld: Cannot create node for RECT"), io_leflineno);
1197 return(TRUE);
1198 }
1199 endobjectchange((INTBIG)ni, VNODEINST);
1200 continue;
1201 }
1202 }
1203 return(FALSE);
1204 }
1205
io_lefignoretosemicolon(FILE * f,CHAR * command)1206 BOOLEAN io_lefignoretosemicolon(FILE *f, CHAR *command)
1207 {
1208 REGISTER CHAR *key;
1209
1210 /* ignore up to the next semicolon */
1211 for(;;)
1212 {
1213 key = io_lefgetkeyword(f);
1214 if (key == 0)
1215 {
1216 ttyputerr(_("EOF parsing %s"), command);
1217 return(TRUE);
1218 }
1219 if (estrcmp(key, x_(";")) == 0) break;
1220 }
1221 return(FALSE);
1222 }
1223
io_lefgetkeyword(FILE * f)1224 CHAR *io_lefgetkeyword(FILE *f)
1225 {
1226 REGISTER CHAR *ret;
1227 REGISTER INTBIG filepos, i;
1228
1229 /* keep reading from file until something is found on a line */
1230 while (io_lefline[io_leflinepos] == 0)
1231 {
1232 /* read a line from the file, exit at EOF */
1233 if (xfgets(io_lefline, MAXLINE, f)) return(0);
1234 io_leflineno++;
1235 if ((io_leflineno%50) == 0)
1236 {
1237 filepos = xtell(f);
1238 DiaSetProgress(io_lefprogressdialog, filepos, io_leffilesize);
1239 }
1240
1241 /* remove comments from the line */
1242 for(i=0; io_lefline[i] != 0; i++)
1243 if (io_lefline[i] == '#')
1244 {
1245 io_lefline[i] = 0;
1246 break;
1247 }
1248
1249 /* look for the first text on the line */
1250 io_leflinepos = 0;
1251 while (io_lefline[io_leflinepos] == ' ' || io_lefline[io_leflinepos] == '\t')
1252 io_leflinepos++;
1253 }
1254
1255 /* remember where the keyword begins */
1256 ret = &io_lefline[io_leflinepos];
1257
1258 /* scan to the end of the keyword */
1259 while (io_lefline[io_leflinepos] != 0 && io_lefline[io_leflinepos] != ' ' &&
1260 io_lefline[io_leflinepos] != '\t') io_leflinepos++;
1261 if (io_lefline[io_leflinepos] != 0) io_lefline[io_leflinepos++] = 0;
1262
1263 /* advance to the start of the next keyword */
1264 while (io_lefline[io_leflinepos] == ' ' || io_lefline[io_leflinepos] == '\t')
1265 io_leflinepos++;
1266 return(ret);
1267 }
1268
io_lefgetnode(INTBIG lfunc)1269 NODEPROTO *io_lefgetnode(INTBIG lfunc)
1270 {
1271 REGISTER NODEPROTO *np;
1272
1273 np = getpurelayernode(el_curtech, -1, lfunc);
1274 if (np == NONODEPROTO)
1275 {
1276 ttyputerr(_("Line %ld: Layer not in current technology"),
1277 io_leflineno);
1278 return(NONODEPROTO);
1279 }
1280 return(np);
1281 }
1282
io_lefgetarc(INTBIG afunc)1283 ARCPROTO *io_lefgetarc(INTBIG afunc)
1284 {
1285 REGISTER ARCPROTO *ap;
1286
1287 for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
1288 if ((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH) == afunc) break;
1289 if (ap == NOARCPROTO)
1290 {
1291 ttyputerr(_("Line %ld: Layer %s not in current technology"),
1292 io_leflineno, arcfunctionname(afunc));
1293 return(NOARCPROTO);
1294 }
1295 return(ap);
1296 }
1297
io_lefnewpath(void)1298 LEFPATH *io_lefnewpath(void)
1299 {
1300 LEFPATH *lp;
1301
1302 if (io_leffreepath != NOLEFPATH)
1303 {
1304 lp = io_leffreepath;
1305 io_leffreepath = lp->nextlefpath;
1306 } else
1307 {
1308 lp = (LEFPATH *)emalloc(sizeof(LEFPATH), io_tool->cluster);
1309 if (lp == 0) lp = NOLEFPATH;
1310 }
1311 return(lp);
1312 }
1313
io_lefkillpath(LEFPATH * lp)1314 void io_lefkillpath(LEFPATH *lp)
1315 {
1316 lp->nextlefpath = io_leffreepath;
1317 io_leffreepath = lp;
1318 }
1319
io_leffreepaths(LEFPATH * firstlp)1320 void io_leffreepaths(LEFPATH *firstlp)
1321 {
1322 LEFPATH *lp, *nextlp;
1323
1324 for(lp = firstlp; lp != NOLEFPATH; lp = nextlp)
1325 {
1326 nextlp = lp->nextlefpath;
1327 io_lefkillpath(lp);
1328 }
1329 }
1330