2
* Electric(tm) VLSI Design System
5
* Input/output tool: LEF (Library Exchange Format) reader
6
* Written by: Steven M. Rubin, Static Free Software
8
* Copyright (c) 2000 Static Free Software.
10
* Electric(tm) is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* Electric(tm) is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with Electric(tm); see the file COPYING. If not, write to
22
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23
* Boston, Mass 02111-1307, USA.
25
* Static Free Software
27
* Portola Valley, California 94028
28
* info@staticfreesoft.com
32
* Note that this reader was built by examining LEF files and reverse-engineering them.
33
* It does not claim to be compliant with the LEF specification, but it also does not
34
* claim to define a new specification. It is merely incomplete.
41
#include "egraphics.h"
42
#include "efunction.h"
50
/*************** LEF PATHS ***************/
52
#define NOLEFPATH ((LEFPATH *)-1)
54
typedef struct Ilefpath
60
struct Ilefpath *nextlefpath;
63
LEFPATH *io_leffreepath = NOLEFPATH;
65
/*************** MISCELLANEOUS ***************/
69
static INTBIG io_leffilesize;
70
static INTBIG io_leflineno;
71
static char io_lefline[MAXLINE];
72
static INTBIG io_leflinepos;
73
VIADEF *io_leffirstviadef = NOVIADEF;
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 *facet, 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 *facet);
90
static BOOLEAN io_lefreadpin(FILE *f, NODEPROTO *facet);
91
static BOOLEAN io_lefreadport(FILE *f, NODEPROTO *facet, char *portname, INTBIG portbits);
92
static void io_leffreevias(void);
95
* Routine to free all memory associated with this module.
97
void io_freelefimemory(void)
102
BOOLEAN io_readleflibrary(LIBRARY *lib)
105
REGISTER BOOLEAN ret;
107
extern DIALOG us_progressdialog;
110
fp = xopen(lib->libfile, io_filetypelef, "", &filename);
113
ttyputerr(_("File %s not found"), lib->libfile);
117
/* remove any vias in the globals */
120
/* prepare for input */
121
io_leffilesize = filesize(fp);
122
if (DiaInitDialog(&us_progressdialog))
128
DiaSetText(2, _("Reading LEF file..."));
134
ret = io_lefreadfile(fp, lib);
139
if (!ret) ttyputmsg(_("LEF file %s is read"), lib->libfile); else
140
ttyputmsg(_("Error reading LEF file %s"), lib->libfile);
144
void io_leffreevias(void)
148
while (io_leffirstviadef != NOVIADEF)
150
vd = io_leffirstviadef;
151
io_leffirstviadef = io_leffirstviadef->nextviadef;
152
efree((char *)vd->vianame);
158
* Routine to read the LEF file in "f".
160
BOOLEAN io_lefreadfile(FILE *f, LIBRARY *lib)
166
/* get the next keyword */
167
key = io_lefgetkeyword(f);
169
if (namesame(key, "LAYER") == 0)
171
if (io_lefreadlayer(f, lib)) return(TRUE);
173
if (namesame(key, "MACRO") == 0)
175
if (io_lefreadmacro(f, lib)) return(TRUE);
177
if (namesame(key, "VIA") == 0)
179
if (io_lefreadvia(f, lib)) return(TRUE);
185
void io_lefparselayer(char *layername, INTBIG *arcfunc, INTBIG *layerfunc)
187
REGISTER INTBIG laynum;
189
*arcfunc = APUNKNOWN;
190
*layerfunc = LFUNKNOWN;
192
if (namesamen(layername, "METAL", 5) == 0)
194
laynum = atoi(&layername[5]);
197
case 1: *arcfunc = APMETAL1; *layerfunc = LFMETAL1; break;
198
case 2: *arcfunc = APMETAL2; *layerfunc = LFMETAL2; break;
199
case 3: *arcfunc = APMETAL3; *layerfunc = LFMETAL3; break;
200
case 4: *arcfunc = APMETAL4; *layerfunc = LFMETAL4; break;
201
case 5: *arcfunc = APMETAL5; *layerfunc = LFMETAL5; break;
202
case 6: *arcfunc = APMETAL6; *layerfunc = LFMETAL6; break;
203
case 7: *arcfunc = APMETAL7; *layerfunc = LFMETAL7; break;
204
case 8: *arcfunc = APMETAL8; *layerfunc = LFMETAL8; break;
209
if (namesamen(layername, "POLY", 4) == 0)
211
laynum = atoi(&layername[4]);
214
case 1: *arcfunc = APPOLY1; *layerfunc = LFPOLY1; break;
215
case 2: *arcfunc = APPOLY2; *layerfunc = LFPOLY2; break;
216
case 3: *arcfunc = APPOLY3; *layerfunc = LFPOLY3; break;
221
if (namesame(layername, "PDIFF") == 0)
224
*layerfunc = LFDIFF | LFPTYPE;
227
if (namesame(layername, "NDIFF") == 0)
230
*layerfunc = LFDIFF | LFNTYPE;
233
if (namesame(layername, "DIFF") == 0)
240
if (namesame(layername, "CONT") == 0)
242
*layerfunc = LFCONTACT1;
245
if (namesamen(layername, "VIA", 3) == 0)
247
laynum = atoi(&layername[3]);
251
case 12: *layerfunc = LFCONTACT2; break;
254
case 23: *layerfunc = LFCONTACT3; break;
257
case 34: *layerfunc = LFCONTACT4; break;
260
case 45: *layerfunc = LFCONTACT5; break;
263
case 56: *layerfunc = LFCONTACT6; break;
268
BOOLEAN io_lefreadlayer(FILE *f, LIBRARY *lib)
270
REGISTER char *layername, *key;
272
REGISTER INTBIG defwidth;
273
INTBIG afunc, layerfunc;
274
REGISTER ARCPROTO *ap;
277
layername = io_lefgetkeyword(f);
280
ttyputerr(_("EOF parsing LAYER header"));
283
io_lefparselayer(layername, &afunc, &layerfunc);
284
if (afunc == APUNKNOWN) ap = NOARCPROTO; else
286
for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
287
if (((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH)) == afunc) break;
292
/* get the next keyword */
293
key = io_lefgetkeyword(f);
296
ttyputerr(_("EOF parsing LAYER"));
300
if (namesame(key, "END") == 0)
302
key = io_lefgetkeyword(f);
306
if (namesame(key, "WIDTH") == 0)
308
key = io_lefgetkeyword(f);
311
ttyputerr(_("EOF reading WIDTH"));
314
v = (float)atof(key);
315
defwidth = scalefromdispunit(v, DISPUNITMIC);
316
if (ap != NOARCPROTO)
318
setval((INTBIG)ap, VARCPROTO, "IO_lef_width", defwidth, VINTEGER);
320
if (io_lefignoretosemicolon(f, "WIDTH")) return(TRUE);
324
if (namesame(key, "TYPE") == 0 || namesame(key, "SPACING") == 0 ||
325
namesame(key, "PITCH") == 0 || namesame(key, "DIRECTION") == 0 ||
326
namesame(key, "CAPACITANCE") == 0 || namesame(key, "RESISTANCE") == 0)
329
if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
336
BOOLEAN io_lefreadmacro(FILE *f, LIBRARY *lib)
338
REGISTER char *cellname, *key;
339
REGISTER INTBIG ox, oy, blx, bhx, bly, bhy;
342
REGISTER NODEPROTO *facet;
343
REGISTER NODEINST *ni;
346
cellname = io_lefgetkeyword(f);
349
ttyputerr(_("EOF parsing MACRO header"));
353
(void)addstringtoinfstr(cellname);
354
(void)addstringtoinfstr("{sk}");
355
cellname = returninfstr();
356
facet = us_newnodeproto(cellname, lib);
357
if (facet == NONODEPROTO)
359
ttyputerr(_("Cannot create facet '%s'"), cellname);
365
/* get the next keyword */
366
key = io_lefgetkeyword(f);
369
ttyputerr(_("EOF parsing MACRO"));
373
if (namesame(key, "END") == 0)
375
key = io_lefgetkeyword(f);
379
if (namesame(key, "SOURCE") == 0 || namesame(key, "FOREIGN") == 0 ||
380
namesame(key, "SYMMETRY") == 0 || namesame(key, "SITE") == 0 ||
381
namesame(key, "CLASS") == 0 || namesame(key, "LEQ") == 0)
384
if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
388
if (namesame(key, "ORIGIN") == 0)
390
key = io_lefgetkeyword(f);
393
ttyputerr(_("EOF reading ORIGIN X"));
396
x = (float)atof(key);
397
ox = scalefromdispunit(x, DISPUNITMIC);
399
key = io_lefgetkeyword(f);
402
ttyputerr(_("EOF reading ORIGIN Y"));
405
y = (float)atof(key);
406
oy = scalefromdispunit(y, DISPUNITMIC);
407
if (io_lefignoretosemicolon(f, "ORIGIN")) return(TRUE);
409
/* create the facet-center node */
410
defaultnodesize(gen_facetcenterprim, &sx, &sy);
411
blx = ox - sx/2; bhx = blx + sx;
412
bly = oy - sy/2; bhy = bly + sy;
413
ni = newnodeinst(gen_facetcenterprim, blx, bhx, bly, bhy, 0, 0, facet);
414
if (ni == NONODEINST)
416
ttyputerr(_("Line %ld: Cannot create facet center node"), io_leflineno);
419
ni->userbits |= HARDSELECTN|NVISIBLEINSIDE;
420
endobjectchange((INTBIG)ni, VNODEINST);
424
if (namesame(key, "SIZE") == 0)
426
key = io_lefgetkeyword(f);
429
ttyputerr(_("EOF reading SIZE X"));
432
x = (float)atof(key);
433
sx = scalefromdispunit(x, DISPUNITMIC);
435
key = io_lefgetkeyword(f);
438
ttyputerr(_("EOF reading SIZE 'BY'"));
441
if (namesame(key, "BY") != 0)
443
ttyputerr(_("Line %ld: Expected 'by' in SIZE"), io_leflineno);
447
key = io_lefgetkeyword(f);
450
ttyputerr(_("EOF reading SIZE Y"));
453
y = (float)atof(key);
454
sy = scalefromdispunit(y, DISPUNITMIC);
455
if (io_lefignoretosemicolon(f, "SIZE")) return(TRUE);
459
if (namesame(key, "PIN") == 0)
461
if (io_lefreadpin(f, facet)) return(TRUE);
465
if (namesame(key, "OBS") == 0)
467
if (io_lefreadobs(f, facet)) return(TRUE);
471
ttyputerr(_("Line %ld: Unknown MACRO keyword (%s)"), io_leflineno, key);
477
BOOLEAN io_lefreadvia(FILE *f, LIBRARY *lib)
479
REGISTER char *vianame, *key;
480
REGISTER INTBIG lx, hx, ly, hy, i, lay1found, lay2found;
481
INTBIG afunc, layerfunc;
485
REGISTER PORTPROTO *pp;
488
/* get the via name */
489
vianame = io_lefgetkeyword(f);
490
if (vianame == 0) return(TRUE);
492
/* create a new via definition */
493
vd = (VIADEF *)emalloc(sizeof (VIADEF), io_tool->cluster);
494
if (vd == 0) return(TRUE);
495
(void)allocstring(&vd->vianame, vianame, io_tool->cluster);
497
vd->via = NONODEPROTO;
498
vd->lay1 = vd->lay2 = NOARCPROTO;
499
vd->nextviadef = io_leffirstviadef;
500
io_leffirstviadef = vd;
502
/* ignore the "DEFAULT" keyword */
503
key = io_lefgetkeyword(f);
504
if (key == 0) return(TRUE);
505
if (namesame(key, "DEFAULT") != 0)
507
ttyputerr(_("Expected 'DEFAULT' after VIA name"));
513
/* get the next keyword */
514
key = io_lefgetkeyword(f);
515
if (key == 0) return(TRUE);
516
if (namesame(key, "END") == 0)
518
key = io_lefgetkeyword(f);
521
if (namesame(key, "RESISTANCE") == 0)
523
if (io_lefignoretosemicolon(f, key)) return(TRUE);
526
if (namesame(key, "LAYER") == 0)
528
key = io_lefgetkeyword(f);
529
if (key == 0) return(TRUE);
530
io_lefparselayer(key, &afunc, &layerfunc);
531
if (afunc == APUNKNOWN) ap = NOARCPROTO; else
533
for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
534
if (((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH)) == afunc) break;
536
if (ap != NOARCPROTO)
538
if (vd->lay1 == NOARCPROTO) vd->lay1 = ap; else
541
if (io_lefignoretosemicolon(f, "LAYER")) return(TRUE);
544
if (namesame(key, "RECT") == 0)
546
/* handle definition of a via rectangle */
547
key = io_lefgetkeyword(f);
548
if (key == 0) return(TRUE);
549
v = (float)atof(key);
550
lx = scalefromdispunit(v, DISPUNITMIC);
552
key = io_lefgetkeyword(f);
553
if (key == 0) return(TRUE);
554
v = (float)atof(key);
555
ly = scalefromdispunit(v, DISPUNITMIC);
557
key = io_lefgetkeyword(f);
558
if (key == 0) return(TRUE);
559
v = (float)atof(key);
560
hx = scalefromdispunit(v, DISPUNITMIC);
562
key = io_lefgetkeyword(f);
563
if (key == 0) return(TRUE);
564
v = (float)atof(key);
565
hy = scalefromdispunit(v, DISPUNITMIC);
567
/* accumulate largest layer size */
568
if (hx-lx > vd->sx) vd->sx = hx - lx;
569
if (hy-ly > vd->sy) vd->sy = hy - ly;
571
if (io_lefignoretosemicolon(f, "RECT")) return(TRUE);
575
if (vd->lay1 != NOARCPROTO && vd->lay2 != NOARCPROTO)
577
for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
579
if (((np->userbits&NFUNCTION)>>NFUNCTIONSH) != NPCONTACT) continue;
580
pp = np->firstportproto;
581
lay1found = lay2found = 0;
582
for(i=0; pp->connects[i] != NOARCPROTO; i++)
584
if (pp->connects[i] == vd->lay1) lay1found = 1;
585
if (pp->connects[i] == vd->lay2) lay2found = 1;
587
if (lay1found != 0 && lay2found != 0) break;
594
BOOLEAN io_lefreadpin(FILE *f, NODEPROTO *facet)
597
REGISTER INTBIG portbits, usebits;
598
char curkey[200], pinname[200];
600
/* get the pin name */
601
key = io_lefgetkeyword(f);
604
ttyputerr(_("EOF parsing PIN name"));
607
strcpy(pinname, key);
609
portbits = usebits = 0;
612
key = io_lefgetkeyword(f);
615
ttyputerr(_("EOF parsing PIN"));
619
if (namesame(key, "END") == 0)
621
key = io_lefgetkeyword(f);
625
if (namesame(key, "SHAPE") == 0 || namesame(key, "CAPACITANCE") == 0 ||
626
namesame(key, "ANTENNASIZE") == 0)
629
if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
633
if (namesame(key, "USE") == 0)
635
key = io_lefgetkeyword(f);
638
ttyputerr(_("EOF reading USE clause"));
641
if (namesame(key, "POWER") == 0) usebits = PWRPORT; else
642
if (namesame(key, "GROUND") == 0) usebits = GNDPORT; else
643
if (namesame(key, "CLOCK") == 0) usebits = CLKPORT; else
645
ttyputerr(_("Line %ld: Unknown USE keyword (%s)"),
648
if (io_lefignoretosemicolon(f, "USE")) return(TRUE);
652
if (namesame(key, "DIRECTION") == 0)
654
key = io_lefgetkeyword(f);
657
ttyputerr(_("EOF reading DIRECTION clause"));
660
if (namesame(key, "INPUT") == 0) portbits = INPORT; else
661
if (namesame(key, "OUTPUT") == 0) portbits = OUTPORT; else
662
if (namesame(key, "INOUT") == 0) portbits = BIDIRPORT; else
664
ttyputerr(_("Line %ld: Unknown DIRECTION keyword (%s)"),
667
if (io_lefignoretosemicolon(f, "DIRECTION")) return(TRUE);
671
if (namesame(key, "PORT") == 0)
673
if (usebits != 0) portbits = usebits;
674
if (io_lefreadport(f, facet, pinname, portbits))
679
ttyputerr(_("Line %ld: Unknown PIN keyword (%s)"), io_leflineno, key);
685
BOOLEAN io_lefreadport(FILE *f, NODEPROTO *facet, char *portname, INTBIG portbits)
688
REGISTER INTBIG i, j, lx, hx, ly, hy, intx, inty, first,
689
intwidth, lastintx, lastinty, sea, cx, cy;
690
INTBIG afunc, layerfunc, sx, sy;
691
REGISTER INTBIG afunc1, afunc2, found1, found2;
692
REGISTER ARCPROTO *ap, *ap1, *ap2;
693
REGISTER NODEPROTO *pin, *plnp;
694
REGISTER ARCINST *ai;
695
REGISTER NODEINST *ni;
696
REGISTER PORTPROTO *pp;
699
REGISTER LEFPATH *lefpaths, *lp, *olp;
703
lefpaths = NOLEFPATH;
707
key = io_lefgetkeyword(f);
710
ttyputerr(_("EOF parsing PORT"));
714
if (namesame(key, "END") == 0)
719
if (namesame(key, "LAYER") == 0)
721
key = io_lefgetkeyword(f);
724
ttyputerr(_("EOF reading LAYER clause"));
727
io_lefparselayer(key, &afunc, &layerfunc);
728
if (afunc == APUNKNOWN) ap = NOARCPROTO; else
729
ap = io_lefgetarc(afunc);
730
plnp = io_lefgetnode(layerfunc);
731
if (io_lefignoretosemicolon(f, "LAYER")) return(TRUE);
735
if (namesame(key, "WIDTH") == 0)
737
key = io_lefgetkeyword(f);
740
ttyputerr(_("EOF reading WIDTH clause"));
743
width = (float)atof(key);
744
intwidth = scalefromdispunit(width, DISPUNITMIC);
745
if (io_lefignoretosemicolon(f, "WIDTH")) return(TRUE);
749
if (namesame(key, "RECT") == 0)
751
if (plnp == NONODEPROTO)
753
ttyputerr(_("Line %ld: No layers for RECT"), io_leflineno);
756
key = io_lefgetkeyword(f);
759
ttyputerr(_("EOF reading RECT low X"));
762
x = (float)atof(key);
763
lx = scalefromdispunit(x, DISPUNITMIC);
765
key = io_lefgetkeyword(f);
768
ttyputerr(_("EOF reading RECT low Y"));
771
y = (float)atof(key);
772
ly = scalefromdispunit(y, DISPUNITMIC);
774
key = io_lefgetkeyword(f);
777
ttyputerr(_("EOF reading RECT high X"));
780
x = (float)atof(key);
781
hx = scalefromdispunit(x, DISPUNITMIC);
783
key = io_lefgetkeyword(f);
786
ttyputerr(_("EOF reading RECT high Y"));
789
y = (float)atof(key);
790
hy = scalefromdispunit(y, DISPUNITMIC);
792
if (io_lefignoretosemicolon(f, "RECT")) return(TRUE);
795
if (hx < lx) { j = hx; hx = lx; lx = j; }
796
if (hy < ly) { j = hy; hy = ly; ly = j; }
797
ni = newnodeinst(plnp, lx, hx, ly, hy, 0, 0, facet);
798
if (ni == NONODEINST)
800
ttyputerr(_("Line %ld: Cannot create pin for RECT"), io_leflineno);
803
endobjectchange((INTBIG)ni, VNODEINST);
807
/* create the port on the first pin */
809
pp = io_lefnewport(facet, ni, plnp->firstportproto, portname);
810
pp->userbits = (pp->userbits & ~STATEBITS) | portbits;
815
if (namesame(key, "PATH") == 0)
817
if (ap == NOARCPROTO)
819
ttyputerr(_("Line %ld: No layers for PATH"), io_leflineno);
824
key = io_lefgetkeyword(f);
827
ttyputerr(_("EOF reading PATH clause"));
830
if (strcmp(key, ";") == 0) break;
831
x = (float)atof(key);
833
key = io_lefgetkeyword(f);
836
ttyputerr(_("EOF reading PATH clause"));
839
y = (float)atof(key);
841
/* plot this point */
842
intx = scalefromdispunit(x, DISPUNITMIC);
843
inty = scalefromdispunit(y, DISPUNITMIC);
847
lp = io_lefnewpath();
848
if (lp == NOLEFPATH) return(TRUE);
850
/* LINTED "lastintx" used in proper order */
851
lp->x[0] = lastintx; lp->x[1] = intx;
853
/* LINTED "lastinty" used in proper order */
854
lp->y[0] = lastinty; lp->y[1] = inty;
855
lp->ni[0] = NONODEINST; lp->ni[1] = NONODEINST;
856
lp->width = intwidth;
858
lp->nextlefpath = lefpaths;
861
lastintx = intx; lastinty = inty;
866
if (namesame(key, "VIA") == 0)
868
/* get the coordinates */
869
key = io_lefgetkeyword(f);
872
ttyputerr(_("EOF reading VIA clause"));
875
x = (float)atof(key);
876
intx = scalefromdispunit(x, DISPUNITMIC);
878
key = io_lefgetkeyword(f);
881
ttyputerr(_("EOF reading VIA clause"));
884
y = (float)atof(key);
885
inty = scalefromdispunit(y, DISPUNITMIC);
887
/* find the proper via */
888
key = io_lefgetkeyword(f);
889
afunc1 = afunc2 = APUNKNOWN;
890
if (namesame(key, "via1") == 0)
894
} else if (namesame(key, "via2") == 0)
898
} else if (namesame(key, "via3") == 0)
902
} else if (namesame(key, "via4") == 0)
908
ttyputerr(_("Line %ld: Unknown VIA type (%s)"), io_leflineno, key);
911
ap1 = io_lefgetarc(afunc1);
912
if (ap1 == NOARCPROTO) return(TRUE);
913
ap2 = io_lefgetarc(afunc2);
914
if (ap2 == NOARCPROTO) return(TRUE);
915
for(pin = el_curtech->firstnodeproto; pin != NONODEPROTO; pin = pin->nextnodeproto)
917
if (((pin->userbits&NFUNCTION)>>NFUNCTIONSH) != NPCONTACT) continue;
918
pp = pin->firstportproto;
920
for(i=0; pp->connects[i] != NOARCPROTO; i++)
922
if (pp->connects[i] == ap1) found1 = 1;
923
if (pp->connects[i] == ap2) found2 = 1;
925
if (found1 != 0 && found2 != 0) break;
927
if (pin == NONODEPROTO)
929
ttyputerr(_("Line %ld: No Via in current technology connects %s to %s"),
930
io_leflineno, arcfunctionname(afunc1),
931
arcfunctionname(afunc2));
934
if (io_lefignoretosemicolon(f, "VIA")) return(TRUE);
937
defaultnodesize(pin, &sx, &sy);
938
lx = intx - sx / 2; hx = lx + sx;
939
ly = inty - sy / 2; hy = ly + sy;
940
ni = newnodeinst(pin, lx, hx, ly, hy, 0, 0, facet);
941
if (ni == NONODEINST)
943
ttyputerr(_("Line %ld: Cannot create VIA for PATH"), io_leflineno);
946
endobjectchange((INTBIG)ni, VNODEINST);
950
ttyputerr(_("Line %ld: Unknown PORT keyword (%s)"), io_leflineno, key);
954
/* look for paths that end at vias */
955
for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
959
if (lp->ni[i] != NONODEINST) continue;
960
sea = initsearch(lp->x[i], lp->x[i], lp->y[i], lp->y[i], facet);
963
geom = nextobject(sea);
964
if (geom == NOGEOM) break;
965
if (!geom->entryisnode) continue;
966
ni = geom->entryaddr.ni;
967
cx = (ni->lowx + ni->highx) / 2;
968
cy = (ni->lowy + ni->highy) / 2;
969
if (cx != lp->x[i] || cy != lp->y[i]) continue;
973
if (lp->ni[i] == NONODEINST) continue;
975
/* use this via at other paths which meet here */
976
for(olp = lefpaths; olp != NOLEFPATH; olp = olp->nextlefpath)
980
if (olp->ni[j] != NONODEINST) continue;
981
if (olp->x[j] != lp->x[i] || olp->y[j] != lp->y[i]) continue;
982
olp->ni[j] = lp->ni[i];
988
/* create pins at all other path ends */
989
for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
993
if (lp->ni[i] != NONODEINST) continue;
994
pin = getpinproto(lp->arc);
995
if (pin == NONODEPROTO) continue;
996
defaultnodesize(pin, &sx, &sy);
997
lx = lp->x[i] - sx / 2; hx = lx + sx;
998
ly = lp->y[i] - sy / 2; hy = ly + sy;
999
lp->ni[i] = newnodeinst(pin, lx, hx, ly, hy, 0, 0, facet);
1000
if (lp->ni[i] == NONODEINST)
1002
ttyputerr(_("Line %ld: Cannot create pin for PATH"), io_leflineno);
1005
endobjectchange((INTBIG)lp->ni[i], VNODEINST);
1007
/* use this pin at other paths which meet here */
1008
for(olp = lefpaths; olp != NOLEFPATH; olp = olp->nextlefpath)
1012
if (olp->ni[j] != NONODEINST) continue;
1013
if (olp->x[j] != lp->x[i] || olp->y[j] != lp->y[i]) continue;
1014
olp->ni[j] = lp->ni[i];
1020
/* now instantiate the paths */
1021
for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
1023
ai = newarcinst(lp->arc, lp->width, us_makearcuserbits(lp->arc),
1024
lp->ni[0], lp->ni[0]->proto->firstportproto, lp->x[0], lp->y[0],
1025
lp->ni[1], lp->ni[1]->proto->firstportproto, lp->x[1], lp->y[1], facet);
1026
if (ai == NOARCINST)
1028
ttyputerr(_("Line %ld: Cannot create arc for PATH"), io_leflineno);
1032
io_leffreepaths(lefpaths);
1038
* Routine to create a port called "thename" on port "pp" of node "ni" in facet "facet".
1039
* The name is modified if it already exists.
1041
PORTPROTO *io_lefnewport(NODEPROTO *facet, NODEINST *ni, PORTPROTO *pp, char *thename)
1043
REGISTER PORTPROTO *ppt;
1045
REGISTER char *newname, *portname;
1051
for(ppt = facet->firstportproto; ppt != NOPORTPROTO; ppt = ppt->nextportproto)
1052
if (namesame(portname, ppt->protoname) == 0) break;
1053
if (ppt == NOPORTPROTO)
1055
ppt = newportproto(facet, ni, pp, portname);
1059
/* make space for modified name */
1060
if (newname == 0) newname = (char *)emalloc(strlen(thename)+10, el_tempcluster);
1061
sprintf(newname, "%s-%ld", thename, i);
1064
if (newname != 0) efree(newname);
1068
BOOLEAN io_lefreadobs(FILE *f, NODEPROTO *facet)
1071
INTBIG lfunc, arcfunc;
1072
REGISTER INTBIG lx, hx, ly, hy, j;
1074
REGISTER NODEINST *ni;
1075
REGISTER NODEPROTO *np;
1080
key = io_lefgetkeyword(f);
1083
ttyputerr(_("EOF parsing OBS"));
1087
if (namesame(key, "END") == 0) break;
1089
if (namesame(key, "LAYER") == 0)
1091
key = io_lefgetkeyword(f);
1094
ttyputerr(_("EOF reading LAYER clause"));
1097
io_lefparselayer(key, &arcfunc, &lfunc);
1098
if (lfunc == LFUNKNOWN)
1100
ttyputerr(_("Line %ld: Unknown layer name (%s)"), io_leflineno, key);
1103
np = io_lefgetnode(lfunc);
1104
if (np == NONODEPROTO) return(TRUE);
1105
if (io_lefignoretosemicolon(f, "LAYER")) return(TRUE);
1109
if (namesame(key, "RECT") == 0)
1111
if (np == NONODEPROTO)
1113
ttyputerr(_("Line %ld: No layers for RECT"), io_leflineno);
1116
key = io_lefgetkeyword(f);
1119
ttyputerr(_("EOF reading RECT low X"));
1122
x = (float)atof(key);
1123
lx = scalefromdispunit(x, DISPUNITMIC);
1125
key = io_lefgetkeyword(f);
1128
ttyputerr(_("EOF reading RECT low Y"));
1131
y = (float)atof(key);
1132
ly = scalefromdispunit(y, DISPUNITMIC);
1134
key = io_lefgetkeyword(f);
1137
ttyputerr(_("EOF reading RECT high X"));
1140
x = (float)atof(key);
1141
hx = scalefromdispunit(x, DISPUNITMIC);
1143
key = io_lefgetkeyword(f);
1146
ttyputerr(_("EOF reading RECT high Y"));
1149
y = (float)atof(key);
1150
hy = scalefromdispunit(y, DISPUNITMIC);
1152
if (io_lefignoretosemicolon(f, "RECT")) return(TRUE);
1155
if (hx < lx) { j = hx; hx = lx; lx = j; }
1156
if (hy < ly) { j = hy; hy = ly; ly = j; }
1157
ni = newnodeinst(np, lx, hx, ly, hy, 0, 0, facet);
1158
if (ni == NONODEINST)
1160
ttyputerr(_("Line %ld: Cannot create node for RECT"), io_leflineno);
1163
endobjectchange((INTBIG)ni, VNODEINST);
1170
BOOLEAN io_lefignoretosemicolon(FILE *f, char *command)
1174
/* ignore up to the next semicolon */
1177
key = io_lefgetkeyword(f);
1180
ttyputerr(_("EOF parsing %s"), command);
1183
if (strcmp(key, ";") == 0) break;
1188
char *io_lefgetkeyword(FILE *f)
1191
REGISTER INTBIG filepos, i;
1193
/* keep reading from file until something is found on a line */
1194
while (io_lefline[io_leflinepos] == 0)
1196
/* read a line from the file, exit at EOF */
1197
if (xfgets(io_lefline, MAXLINE, f)) return(0);
1199
if ((io_leflineno%50) == 0)
1202
DiaPercent(1, filepos*100/io_leffilesize);
1205
/* remove comments from the line */
1206
for(i=0; io_lefline[i] != 0; i++)
1207
if (io_lefline[i] == '#')
1213
/* look for the first text on the line */
1215
while (io_lefline[io_leflinepos] == ' ' || io_lefline[io_leflinepos] == '\t')
1219
/* remember where the keyword begins */
1220
ret = &io_lefline[io_leflinepos];
1222
/* scan to the end of the keyword */
1223
while (io_lefline[io_leflinepos] != 0 && io_lefline[io_leflinepos] != ' ' &&
1224
io_lefline[io_leflinepos] != '\t') io_leflinepos++;
1225
if (io_lefline[io_leflinepos] != 0) io_lefline[io_leflinepos++] = 0;
1227
/* advance to the start of the next keyword */
1228
while (io_lefline[io_leflinepos] == ' ' || io_lefline[io_leflinepos] == '\t')
1233
NODEPROTO *io_lefgetnode(INTBIG lfunc)
1235
REGISTER NODEPROTO *np;
1237
np = getpurelayernode(el_curtech, -1, lfunc);
1238
if (np == NONODEPROTO)
1240
ttyputerr(_("Line %ld: Layer not in current technology"),
1242
return(NONODEPROTO);
1247
ARCPROTO *io_lefgetarc(INTBIG afunc)
1249
REGISTER ARCPROTO *ap;
1251
for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
1252
if ((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH) == afunc) break;
1253
if (ap == NOARCPROTO)
1255
ttyputerr(_("Line %ld: Layer %s not in current technology"),
1256
io_leflineno, arcfunctionname(afunc));
1262
LEFPATH *io_lefnewpath(void)
1266
if (io_leffreepath != NOLEFPATH)
1268
lp = io_leffreepath;
1269
io_leffreepath = lp->nextlefpath;
1272
lp = (LEFPATH *)emalloc(sizeof(LEFPATH), io_tool->cluster);
1273
if (lp == 0) lp = NOLEFPATH;
1278
void io_lefkillpath(LEFPATH *lp)
1280
lp->nextlefpath = io_leffreepath;
1281
io_leffreepath = lp;
1284
void io_leffreepaths(LEFPATH *firstlp)
1286
LEFPATH *lp, *nextlp;
1288
for(lp = firstlp; lp != NOLEFPATH; lp = nextlp)
1290
nextlp = lp->nextlefpath;
1295
#endif /* IOLEF - at top */