~ubuntu-branches/ubuntu/jaunty/electric/jaunty

« back to all changes in this revision

Viewing changes to src/io/iolefi.c

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2009-01-08 02:05:08 UTC
  • mfrom: (1.3.1 upstream) (3.1.3 sid)
  • mto: (3.1.4 sid)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: james.westby@ubuntu.com-20090108020508-3e7e6241i7bkit2l
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Electric(tm) VLSI Design System
3
 
 *
4
 
 * File: iolefi.c
5
 
 * Input/output tool: LEF (Library Exchange Format) reader
6
 
 * Written by: Steven M. Rubin, Static Free Software
7
 
 *
8
 
 * Copyright (c) 2000 Static Free Software.
9
 
 *
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.
14
 
 *
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.
19
 
 *
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.
24
 
 *
25
 
 * Static Free Software
26
 
 * 4119 Alpine Road
27
 
 * Portola Valley, California 94028
28
 
 * info@staticfreesoft.com
29
 
 */
30
 
 
31
 
/*
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.
35
 
 */
36
 
 
37
 
#include "config.h"
38
 
#if IOLEF
39
 
 
40
 
#include "global.h"
41
 
#include "egraphics.h"
42
 
#include "efunction.h"
43
 
#include "edialogs.h"
44
 
#include "iolefdef.h"
45
 
#include "tecart.h"
46
 
#include "tecgen.h"
47
 
#include "eio.h"
48
 
#include "usr.h"
49
 
 
50
 
/*************** LEF PATHS ***************/
51
 
 
52
 
#define NOLEFPATH ((LEFPATH *)-1)
53
 
 
54
 
typedef struct Ilefpath
55
 
{
56
 
        INTBIG     x[2], y[2];
57
 
        NODEINST  *ni[2];
58
 
        INTBIG     width;
59
 
        ARCPROTO  *arc;
60
 
        struct Ilefpath *nextlefpath;
61
 
} LEFPATH;
62
 
 
63
 
LEFPATH *io_leffreepath = NOLEFPATH;
64
 
 
65
 
/*************** MISCELLANEOUS ***************/
66
 
 
67
 
#define MAXLINE 2500
68
 
 
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;
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 *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);
93
 
 
94
 
/*
95
 
 * Routine to free all memory associated with this module.
96
 
 */
97
 
void io_freelefimemory(void)
98
 
{
99
 
        io_leffreevias();
100
 
}
101
 
 
102
 
BOOLEAN io_readleflibrary(LIBRARY *lib)
103
 
{
104
 
        FILE *fp;
105
 
        REGISTER BOOLEAN ret;
106
 
        char *filename;
107
 
        extern DIALOG us_progressdialog;
108
 
 
109
 
        /* open the file */
110
 
        fp = xopen(lib->libfile, io_filetypelef, "", &filename);
111
 
        if (fp == NULL)
112
 
        {
113
 
                ttyputerr(_("File %s not found"), lib->libfile);
114
 
                return(TRUE);
115
 
        }
116
 
 
117
 
        /* remove any vias in the globals */
118
 
        io_leffreevias();
119
 
 
120
 
        /* prepare for input */
121
 
        io_leffilesize = filesize(fp);
122
 
        if (DiaInitDialog(&us_progressdialog))
123
 
        {
124
 
                xclose(fp);
125
 
                return(TRUE);
126
 
        }
127
 
        DiaPercent(1, 0);
128
 
        DiaSetText(2, _("Reading LEF file..."));
129
 
        io_leflineno = 0;
130
 
        io_leflinepos = 0;
131
 
        io_lefline[0] = 0;
132
 
 
133
 
        /* read the file */
134
 
        ret = io_lefreadfile(fp, lib);
135
 
 
136
 
        /* clean up */
137
 
        DiaDoneDialog();
138
 
        xclose(fp);
139
 
        if (!ret) ttyputmsg(_("LEF file %s is read"), lib->libfile); else
140
 
                ttyputmsg(_("Error reading LEF file %s"), lib->libfile);
141
 
        return(FALSE);
142
 
}
143
 
 
144
 
void io_leffreevias(void)
145
 
{
146
 
        VIADEF *vd;
147
 
 
148
 
        while (io_leffirstviadef != NOVIADEF)
149
 
        {
150
 
                vd = io_leffirstviadef;
151
 
                io_leffirstviadef = io_leffirstviadef->nextviadef;
152
 
                efree((char *)vd->vianame);
153
 
                efree((char *)vd);
154
 
        }
155
 
}
156
 
 
157
 
/*
158
 
 * Routine to read the LEF file in "f".
159
 
 */
160
 
BOOLEAN io_lefreadfile(FILE *f, LIBRARY *lib)
161
 
{
162
 
        REGISTER char *key;
163
 
 
164
 
        for(;;)
165
 
        {
166
 
                /* get the next keyword */
167
 
                key = io_lefgetkeyword(f);
168
 
                if (key == 0) break;
169
 
                if (namesame(key, "LAYER") == 0)
170
 
                {
171
 
                        if (io_lefreadlayer(f, lib)) return(TRUE);
172
 
                }
173
 
                if (namesame(key, "MACRO") == 0)
174
 
                {
175
 
                        if (io_lefreadmacro(f, lib)) return(TRUE);
176
 
                }
177
 
                if (namesame(key, "VIA") == 0)
178
 
                {
179
 
                        if (io_lefreadvia(f, lib)) return(TRUE);
180
 
                }
181
 
        }
182
 
        return(FALSE);
183
 
}
184
 
 
185
 
void io_lefparselayer(char *layername, INTBIG *arcfunc, INTBIG *layerfunc)
186
 
{
187
 
        REGISTER INTBIG laynum;
188
 
 
189
 
        *arcfunc = APUNKNOWN;
190
 
        *layerfunc = LFUNKNOWN;
191
 
 
192
 
        if (namesamen(layername, "METAL", 5) == 0)
193
 
        {
194
 
                laynum = atoi(&layername[5]);
195
 
                switch (laynum)
196
 
                {
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;
205
 
                }
206
 
                return;
207
 
        }
208
 
 
209
 
        if (namesamen(layername, "POLY", 4) == 0)
210
 
        {
211
 
                laynum = atoi(&layername[4]);
212
 
                switch (laynum)
213
 
                {
214
 
                        case 1: *arcfunc = APPOLY1;   *layerfunc = LFPOLY1;   break;
215
 
                        case 2: *arcfunc = APPOLY2;   *layerfunc = LFPOLY2;   break;
216
 
                        case 3: *arcfunc = APPOLY3;   *layerfunc = LFPOLY3;   break;
217
 
                }
218
 
                return;
219
 
        }
220
 
 
221
 
        if (namesame(layername, "PDIFF") == 0)
222
 
        {
223
 
                *arcfunc = APDIFFP;
224
 
                *layerfunc = LFDIFF | LFPTYPE;
225
 
                return;
226
 
        }
227
 
        if (namesame(layername, "NDIFF") == 0)
228
 
        {
229
 
                *arcfunc = APDIFFN;
230
 
                *layerfunc = LFDIFF | LFNTYPE;
231
 
                return;
232
 
        }
233
 
        if (namesame(layername, "DIFF") == 0)
234
 
        {
235
 
                *arcfunc = APDIFF;
236
 
                *layerfunc = LFDIFF;
237
 
                return;
238
 
        }
239
 
 
240
 
        if (namesame(layername, "CONT") == 0)
241
 
        {
242
 
                *layerfunc = LFCONTACT1;
243
 
                return;
244
 
        }
245
 
        if (namesamen(layername, "VIA", 3) == 0)
246
 
        {
247
 
                laynum = atoi(&layername[3]);
248
 
                switch (laynum)
249
 
                {
250
 
                        case 1:
251
 
                        case 12: *layerfunc = LFCONTACT2;   break;
252
 
 
253
 
                        case 2:
254
 
                        case 23: *layerfunc = LFCONTACT3;   break;
255
 
 
256
 
                        case 3:
257
 
                        case 34: *layerfunc = LFCONTACT4;   break;
258
 
 
259
 
                        case 4:
260
 
                        case 45: *layerfunc = LFCONTACT5;   break;
261
 
 
262
 
                        case 5:
263
 
                        case 56: *layerfunc = LFCONTACT6;   break;
264
 
                }
265
 
        }
266
 
}
267
 
 
268
 
BOOLEAN io_lefreadlayer(FILE *f, LIBRARY *lib)
269
 
{
270
 
        REGISTER char *layername, *key;
271
 
        char curkey[200];
272
 
        REGISTER INTBIG defwidth;
273
 
        INTBIG afunc, layerfunc;
274
 
        REGISTER ARCPROTO *ap;
275
 
        float v;
276
 
 
277
 
        layername = io_lefgetkeyword(f);
278
 
        if (layername == 0)
279
 
        {
280
 
                ttyputerr(_("EOF parsing LAYER header"));
281
 
                return(TRUE);
282
 
        }
283
 
        io_lefparselayer(layername, &afunc, &layerfunc);
284
 
        if (afunc == APUNKNOWN) ap = NOARCPROTO; else
285
 
        {
286
 
                for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
287
 
                        if (((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH)) == afunc) break;
288
 
        }
289
 
 
290
 
        for(;;)
291
 
        {
292
 
                /* get the next keyword */
293
 
                key = io_lefgetkeyword(f);
294
 
                if (key == 0)
295
 
                {
296
 
                        ttyputerr(_("EOF parsing LAYER"));
297
 
                        return(TRUE);
298
 
                }
299
 
 
300
 
                if (namesame(key, "END") == 0)
301
 
                {
302
 
                        key = io_lefgetkeyword(f);
303
 
                        break;
304
 
                }
305
 
 
306
 
                if (namesame(key, "WIDTH") == 0)
307
 
                {
308
 
                        key = io_lefgetkeyword(f);
309
 
                        if (key == 0)
310
 
                        {
311
 
                                ttyputerr(_("EOF reading WIDTH"));
312
 
                                return(TRUE);
313
 
                        }
314
 
                        v = (float)atof(key);
315
 
                        defwidth = scalefromdispunit(v, DISPUNITMIC);
316
 
                        if (ap != NOARCPROTO)
317
 
                        {
318
 
                                setval((INTBIG)ap, VARCPROTO, "IO_lef_width", defwidth, VINTEGER);
319
 
                        }
320
 
                        if (io_lefignoretosemicolon(f, "WIDTH")) return(TRUE);
321
 
                        continue;
322
 
                }
323
 
 
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)
327
 
                {
328
 
                        strcpy(curkey, key);
329
 
                        if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
330
 
                        continue;
331
 
                }
332
 
        }
333
 
        return(FALSE);
334
 
}
335
 
 
336
 
BOOLEAN io_lefreadmacro(FILE *f, LIBRARY *lib)
337
 
{
338
 
        REGISTER char *cellname, *key;
339
 
        REGISTER INTBIG ox, oy, blx, bhx, bly, bhy;
340
 
        INTBIG sx, sy;
341
 
        float x, y;
342
 
        REGISTER NODEPROTO *facet;
343
 
        REGISTER NODEINST *ni;
344
 
        char curkey[200];
345
 
 
346
 
        cellname = io_lefgetkeyword(f);
347
 
        if (cellname == 0)
348
 
        {
349
 
                ttyputerr(_("EOF parsing MACRO header"));
350
 
                return(TRUE);
351
 
        }
352
 
        (void)initinfstr();
353
 
        (void)addstringtoinfstr(cellname);
354
 
        (void)addstringtoinfstr("{sk}");
355
 
        cellname = returninfstr();
356
 
        facet = us_newnodeproto(cellname, lib);
357
 
        if (facet == NONODEPROTO)
358
 
        {
359
 
                ttyputerr(_("Cannot create facet '%s'"), cellname);
360
 
                return(TRUE);
361
 
        }
362
 
 
363
 
        for(;;)
364
 
        {
365
 
                /* get the next keyword */
366
 
                key = io_lefgetkeyword(f);
367
 
                if (key == 0)
368
 
                {
369
 
                        ttyputerr(_("EOF parsing MACRO"));
370
 
                        return(TRUE);
371
 
                }
372
 
 
373
 
                if (namesame(key, "END") == 0)
374
 
                {
375
 
                        key = io_lefgetkeyword(f);
376
 
                        break;
377
 
                }
378
 
 
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)
382
 
                {
383
 
                        strcpy(curkey, key);
384
 
                        if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
385
 
                        continue;
386
 
                }
387
 
 
388
 
                if (namesame(key, "ORIGIN") == 0)
389
 
                {
390
 
                        key = io_lefgetkeyword(f);
391
 
                        if (key == 0)
392
 
                        {
393
 
                                ttyputerr(_("EOF reading ORIGIN X"));
394
 
                                return(TRUE);
395
 
                        }
396
 
                        x = (float)atof(key);
397
 
                        ox = scalefromdispunit(x, DISPUNITMIC);
398
 
 
399
 
                        key = io_lefgetkeyword(f);
400
 
                        if (key == 0)
401
 
                        {
402
 
                                ttyputerr(_("EOF reading ORIGIN Y"));
403
 
                                return(TRUE);
404
 
                        }
405
 
                        y = (float)atof(key);
406
 
                        oy = scalefromdispunit(y, DISPUNITMIC);
407
 
                        if (io_lefignoretosemicolon(f, "ORIGIN")) return(TRUE);
408
 
 
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)
415
 
                        {
416
 
                                ttyputerr(_("Line %ld: Cannot create facet center node"), io_leflineno);
417
 
                                return(TRUE);
418
 
                        }
419
 
                        ni->userbits |= HARDSELECTN|NVISIBLEINSIDE;
420
 
                        endobjectchange((INTBIG)ni, VNODEINST);
421
 
                        continue;
422
 
                }
423
 
 
424
 
                if (namesame(key, "SIZE") == 0)
425
 
                {
426
 
                        key = io_lefgetkeyword(f);
427
 
                        if (key == 0)
428
 
                        {
429
 
                                ttyputerr(_("EOF reading SIZE X"));
430
 
                                return(TRUE);
431
 
                        }
432
 
                        x = (float)atof(key);
433
 
                        sx = scalefromdispunit(x, DISPUNITMIC);
434
 
 
435
 
                        key = io_lefgetkeyword(f);
436
 
                        if (key == 0)
437
 
                        {
438
 
                                ttyputerr(_("EOF reading SIZE 'BY'"));
439
 
                                return(TRUE);
440
 
                        }
441
 
                        if (namesame(key, "BY") != 0)
442
 
                        {
443
 
                                ttyputerr(_("Line %ld: Expected 'by' in SIZE"), io_leflineno);
444
 
                                return(TRUE);
445
 
                        }
446
 
 
447
 
                        key = io_lefgetkeyword(f);
448
 
                        if (key == 0)
449
 
                        {
450
 
                                ttyputerr(_("EOF reading SIZE Y"));
451
 
                                return(TRUE);
452
 
                        }
453
 
                        y = (float)atof(key);
454
 
                        sy = scalefromdispunit(y, DISPUNITMIC);
455
 
                        if (io_lefignoretosemicolon(f, "SIZE")) return(TRUE);
456
 
                        continue;
457
 
                }
458
 
 
459
 
                if (namesame(key, "PIN") == 0)
460
 
                {
461
 
                        if (io_lefreadpin(f, facet)) return(TRUE);
462
 
                        continue;
463
 
                }
464
 
 
465
 
                if (namesame(key, "OBS") == 0)
466
 
                {
467
 
                        if (io_lefreadobs(f, facet)) return(TRUE);
468
 
                        continue;
469
 
                }
470
 
 
471
 
                ttyputerr(_("Line %ld: Unknown MACRO keyword (%s)"), io_leflineno, key);
472
 
                return(TRUE);
473
 
        }
474
 
        return(FALSE);
475
 
}
476
 
 
477
 
BOOLEAN io_lefreadvia(FILE *f, LIBRARY *lib)
478
 
{
479
 
        REGISTER char *vianame, *key;
480
 
        REGISTER INTBIG lx, hx, ly, hy, i, lay1found, lay2found;
481
 
        INTBIG afunc, layerfunc;
482
 
        NODEPROTO *np;
483
 
        ARCPROTO *ap;
484
 
        float v;
485
 
        REGISTER PORTPROTO *pp;
486
 
        REGISTER VIADEF *vd;
487
 
 
488
 
        /* get the via name */
489
 
        vianame = io_lefgetkeyword(f);
490
 
        if (vianame == 0) return(TRUE);
491
 
 
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);
496
 
        vd->sx = vd->sy = 0;
497
 
        vd->via = NONODEPROTO;
498
 
        vd->lay1 = vd->lay2 = NOARCPROTO;
499
 
        vd->nextviadef = io_leffirstviadef;
500
 
        io_leffirstviadef = vd;
501
 
 
502
 
        /* ignore the "DEFAULT" keyword */
503
 
        key = io_lefgetkeyword(f);
504
 
        if (key == 0) return(TRUE);
505
 
        if (namesame(key, "DEFAULT") != 0)
506
 
        {
507
 
                ttyputerr(_("Expected 'DEFAULT' after VIA name"));
508
 
                return(TRUE);
509
 
        }
510
 
 
511
 
        for(;;)
512
 
        {
513
 
                /* get the next keyword */
514
 
                key = io_lefgetkeyword(f);
515
 
                if (key == 0) return(TRUE);
516
 
                if (namesame(key, "END") == 0)
517
 
                {
518
 
                        key = io_lefgetkeyword(f);
519
 
                        break;
520
 
                }
521
 
                if (namesame(key, "RESISTANCE") == 0)
522
 
                {
523
 
                        if (io_lefignoretosemicolon(f, key)) return(TRUE);
524
 
                        continue;
525
 
                }
526
 
                if (namesame(key, "LAYER") == 0)
527
 
                {
528
 
                        key = io_lefgetkeyword(f);
529
 
                        if (key == 0) return(TRUE);
530
 
                        io_lefparselayer(key, &afunc, &layerfunc);
531
 
                        if (afunc == APUNKNOWN) ap = NOARCPROTO; else
532
 
                        {
533
 
                                for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
534
 
                                        if (((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH)) == afunc) break;
535
 
                        }
536
 
                        if (ap != NOARCPROTO)
537
 
                        {
538
 
                                if (vd->lay1 == NOARCPROTO) vd->lay1 = ap; else
539
 
                                        vd->lay2 = ap;
540
 
                        }
541
 
                        if (io_lefignoretosemicolon(f, "LAYER")) return(TRUE);
542
 
                        continue;
543
 
                }
544
 
                if (namesame(key, "RECT") == 0)
545
 
                {
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);
551
 
 
552
 
                        key = io_lefgetkeyword(f);
553
 
                        if (key == 0) return(TRUE);
554
 
                        v = (float)atof(key);
555
 
                        ly = scalefromdispunit(v, DISPUNITMIC);
556
 
 
557
 
                        key = io_lefgetkeyword(f);
558
 
                        if (key == 0) return(TRUE);
559
 
                        v = (float)atof(key);
560
 
                        hx = scalefromdispunit(v, DISPUNITMIC);
561
 
 
562
 
                        key = io_lefgetkeyword(f);
563
 
                        if (key == 0) return(TRUE);
564
 
                        v = (float)atof(key);
565
 
                        hy = scalefromdispunit(v, DISPUNITMIC);
566
 
 
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;
570
 
 
571
 
                        if (io_lefignoretosemicolon(f, "RECT")) return(TRUE);
572
 
                        continue;
573
 
                }
574
 
        }
575
 
        if (vd->lay1 != NOARCPROTO && vd->lay2 != NOARCPROTO)
576
 
        {
577
 
                for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
578
 
                {
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++)
583
 
                        {
584
 
                                if (pp->connects[i] == vd->lay1) lay1found = 1;
585
 
                                if (pp->connects[i] == vd->lay2) lay2found = 1;
586
 
                        }
587
 
                        if (lay1found != 0 && lay2found != 0) break;
588
 
                }
589
 
                vd->via = np;
590
 
        }
591
 
        return(FALSE);
592
 
}
593
 
 
594
 
BOOLEAN io_lefreadpin(FILE *f, NODEPROTO *facet)
595
 
{
596
 
        REGISTER char *key;
597
 
        REGISTER INTBIG portbits, usebits;
598
 
        char curkey[200], pinname[200];
599
 
 
600
 
        /* get the pin name */
601
 
        key = io_lefgetkeyword(f);
602
 
        if (key == 0)
603
 
        {
604
 
                ttyputerr(_("EOF parsing PIN name"));
605
 
                return(TRUE);
606
 
        }
607
 
        strcpy(pinname, key);
608
 
 
609
 
        portbits = usebits = 0;
610
 
        for(;;)
611
 
        {
612
 
                key = io_lefgetkeyword(f);
613
 
                if (key == 0)
614
 
                {
615
 
                        ttyputerr(_("EOF parsing PIN"));
616
 
                        return(TRUE);
617
 
                }
618
 
 
619
 
                if (namesame(key, "END") == 0)
620
 
                {
621
 
                        key = io_lefgetkeyword(f);
622
 
                        break;
623
 
                }
624
 
 
625
 
                if (namesame(key, "SHAPE") == 0 || namesame(key, "CAPACITANCE") == 0 ||
626
 
                        namesame(key, "ANTENNASIZE") == 0)
627
 
                {
628
 
                        strcpy(curkey, key);
629
 
                        if (io_lefignoretosemicolon(f, curkey)) return(TRUE);
630
 
                        continue;
631
 
                }
632
 
 
633
 
                if (namesame(key, "USE") == 0)
634
 
                {
635
 
                        key = io_lefgetkeyword(f);
636
 
                        if (key == 0)
637
 
                        {
638
 
                                ttyputerr(_("EOF reading USE clause"));
639
 
                                return(TRUE);
640
 
                        }
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
644
 
                        {
645
 
                                ttyputerr(_("Line %ld: Unknown USE keyword (%s)"),
646
 
                                        io_leflineno, key);
647
 
                        }
648
 
                        if (io_lefignoretosemicolon(f, "USE")) return(TRUE);
649
 
                        continue;
650
 
                }
651
 
 
652
 
                if (namesame(key, "DIRECTION") == 0)
653
 
                {
654
 
                        key = io_lefgetkeyword(f);
655
 
                        if (key == 0)
656
 
                        {
657
 
                                ttyputerr(_("EOF reading DIRECTION clause"));
658
 
                                return(TRUE);
659
 
                        }
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
663
 
                        {
664
 
                                ttyputerr(_("Line %ld: Unknown DIRECTION keyword (%s)"),
665
 
                                        io_leflineno, key);
666
 
                        }
667
 
                        if (io_lefignoretosemicolon(f, "DIRECTION")) return(TRUE);
668
 
                        continue;
669
 
                }
670
 
 
671
 
                if (namesame(key, "PORT") == 0)
672
 
                {
673
 
                        if (usebits != 0) portbits = usebits;
674
 
                        if (io_lefreadport(f, facet, pinname, portbits))
675
 
                                return(TRUE);
676
 
                        continue;
677
 
                }
678
 
 
679
 
                ttyputerr(_("Line %ld: Unknown PIN keyword (%s)"), io_leflineno, key);
680
 
                return(TRUE);
681
 
        }
682
 
        return(FALSE);
683
 
}
684
 
 
685
 
BOOLEAN io_lefreadport(FILE *f, NODEPROTO *facet, char *portname, INTBIG portbits)
686
 
{
687
 
        REGISTER char *key;
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;
697
 
        REGISTER GEOM *geom;
698
 
        float width, x, y;
699
 
        REGISTER LEFPATH *lefpaths, *lp, *olp;
700
 
 
701
 
        ap = NOARCPROTO;
702
 
        plnp = NONODEPROTO;
703
 
        lefpaths = NOLEFPATH;
704
 
        first = 1;
705
 
        for(;;)
706
 
        {
707
 
                key = io_lefgetkeyword(f);
708
 
                if (key == 0)
709
 
                {
710
 
                        ttyputerr(_("EOF parsing PORT"));
711
 
                        return(TRUE);
712
 
                }
713
 
 
714
 
                if (namesame(key, "END") == 0)
715
 
                {
716
 
                        break;
717
 
                }
718
 
 
719
 
                if (namesame(key, "LAYER") == 0)
720
 
                {
721
 
                        key = io_lefgetkeyword(f);
722
 
                        if (key == 0)
723
 
                        {
724
 
                                ttyputerr(_("EOF reading LAYER clause"));
725
 
                                return(TRUE);
726
 
                        }
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);
732
 
                        continue;
733
 
                }
734
 
 
735
 
                if (namesame(key, "WIDTH") == 0)
736
 
                {
737
 
                        key = io_lefgetkeyword(f);
738
 
                        if (key == 0)
739
 
                        {
740
 
                                ttyputerr(_("EOF reading WIDTH clause"));
741
 
                                return(TRUE);
742
 
                        }
743
 
                        width = (float)atof(key);
744
 
                        intwidth = scalefromdispunit(width, DISPUNITMIC);
745
 
                        if (io_lefignoretosemicolon(f, "WIDTH")) return(TRUE);
746
 
                        continue;
747
 
                }
748
 
 
749
 
                if (namesame(key, "RECT") == 0)
750
 
                {
751
 
                        if (plnp == NONODEPROTO)
752
 
                        {
753
 
                                ttyputerr(_("Line %ld: No layers for RECT"), io_leflineno);
754
 
                                return(TRUE);
755
 
                        }
756
 
                        key = io_lefgetkeyword(f);
757
 
                        if (key == 0)
758
 
                        {
759
 
                                ttyputerr(_("EOF reading RECT low X"));
760
 
                                return(TRUE);
761
 
                        }
762
 
                        x = (float)atof(key);
763
 
                        lx = scalefromdispunit(x, DISPUNITMIC);
764
 
 
765
 
                        key = io_lefgetkeyword(f);
766
 
                        if (key == 0)
767
 
                        {
768
 
                                ttyputerr(_("EOF reading RECT low Y"));
769
 
                                return(TRUE);
770
 
                        }
771
 
                        y = (float)atof(key);
772
 
                        ly = scalefromdispunit(y, DISPUNITMIC);
773
 
 
774
 
                        key = io_lefgetkeyword(f);
775
 
                        if (key == 0)
776
 
                        {
777
 
                                ttyputerr(_("EOF reading RECT high X"));
778
 
                                return(TRUE);
779
 
                        }
780
 
                        x = (float)atof(key);
781
 
                        hx = scalefromdispunit(x, DISPUNITMIC);
782
 
 
783
 
                        key = io_lefgetkeyword(f);
784
 
                        if (key == 0)
785
 
                        {
786
 
                                ttyputerr(_("EOF reading RECT high Y"));
787
 
                                return(TRUE);
788
 
                        }
789
 
                        y = (float)atof(key);
790
 
                        hy = scalefromdispunit(y, DISPUNITMIC);
791
 
 
792
 
                        if (io_lefignoretosemicolon(f, "RECT")) return(TRUE);
793
 
 
794
 
                        /* make the pin */
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)
799
 
                        {
800
 
                                ttyputerr(_("Line %ld: Cannot create pin for RECT"), io_leflineno);
801
 
                                return(TRUE);
802
 
                        }
803
 
                        endobjectchange((INTBIG)ni, VNODEINST);
804
 
 
805
 
                        if (first != 0)
806
 
                        {
807
 
                                /* create the port on the first pin */
808
 
                                first = 0;
809
 
                                pp = io_lefnewport(facet, ni, plnp->firstportproto, portname);
810
 
                                pp->userbits = (pp->userbits & ~STATEBITS) | portbits;
811
 
                        }
812
 
                        continue;
813
 
                }
814
 
 
815
 
                if (namesame(key, "PATH") == 0)
816
 
                {
817
 
                        if (ap == NOARCPROTO)
818
 
                        {
819
 
                                ttyputerr(_("Line %ld: No layers for PATH"), io_leflineno);
820
 
                                return(TRUE);
821
 
                        }
822
 
                        for(i=0; ; i++)
823
 
                        {
824
 
                                key = io_lefgetkeyword(f);
825
 
                                if (key == 0)
826
 
                                {
827
 
                                        ttyputerr(_("EOF reading PATH clause"));
828
 
                                        return(TRUE);
829
 
                                }
830
 
                                if (strcmp(key, ";") == 0) break;
831
 
                                x = (float)atof(key);
832
 
 
833
 
                                key = io_lefgetkeyword(f);
834
 
                                if (key == 0)
835
 
                                {
836
 
                                        ttyputerr(_("EOF reading PATH clause"));
837
 
                                        return(TRUE);
838
 
                                }
839
 
                                y = (float)atof(key);
840
 
 
841
 
                                /* plot this point */
842
 
                                intx = scalefromdispunit(x, DISPUNITMIC);
843
 
                                inty = scalefromdispunit(y, DISPUNITMIC);
844
 
                                if (i != 0)
845
 
                                {
846
 
                                        /* queue path */
847
 
                                        lp = io_lefnewpath();
848
 
                                        if (lp == NOLEFPATH) return(TRUE);
849
 
 
850
 
                                        /* LINTED "lastintx" used in proper order */
851
 
                                        lp->x[0] = lastintx;     lp->x[1] = intx;
852
 
 
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;
857
 
                                        lp->arc = ap;
858
 
                                        lp->nextlefpath = lefpaths;
859
 
                                        lefpaths = lp;
860
 
                                }
861
 
                                lastintx = intx;   lastinty = inty;
862
 
                        }
863
 
                        continue;
864
 
                }
865
 
 
866
 
                if (namesame(key, "VIA") == 0)
867
 
                {
868
 
                        /* get the coordinates */
869
 
                        key = io_lefgetkeyword(f);
870
 
                        if (key == 0)
871
 
                        {
872
 
                                ttyputerr(_("EOF reading VIA clause"));
873
 
                                return(TRUE);
874
 
                        }
875
 
                        x = (float)atof(key);
876
 
                        intx = scalefromdispunit(x, DISPUNITMIC);
877
 
 
878
 
                        key = io_lefgetkeyword(f);
879
 
                        if (key == 0)
880
 
                        {
881
 
                                ttyputerr(_("EOF reading VIA clause"));
882
 
                                return(TRUE);
883
 
                        }
884
 
                        y = (float)atof(key);
885
 
                        inty = scalefromdispunit(y, DISPUNITMIC);
886
 
 
887
 
                        /* find the proper via */
888
 
                        key = io_lefgetkeyword(f);
889
 
                        afunc1 = afunc2 = APUNKNOWN;
890
 
                        if (namesame(key, "via1") == 0)
891
 
                        {
892
 
                                afunc1 = APMETAL1;
893
 
                                afunc2 = APMETAL2;
894
 
                        } else if (namesame(key, "via2") == 0)
895
 
                        {
896
 
                                afunc1 = APMETAL2;
897
 
                                afunc2 = APMETAL3;
898
 
                        } else if (namesame(key, "via3") == 0)
899
 
                        {
900
 
                                afunc1 = APMETAL3;
901
 
                                afunc2 = APMETAL4;
902
 
                        } else if (namesame(key, "via4") == 0)
903
 
                        {
904
 
                                afunc1 = APMETAL4;
905
 
                                afunc2 = APMETAL5;
906
 
                        } else
907
 
                        {
908
 
                                ttyputerr(_("Line %ld: Unknown VIA type (%s)"), io_leflineno, key);
909
 
                                return(TRUE);
910
 
                        }
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)
916
 
                        {
917
 
                                if (((pin->userbits&NFUNCTION)>>NFUNCTIONSH) != NPCONTACT) continue;
918
 
                                pp = pin->firstportproto;
919
 
                                found1 = found2 = 0;
920
 
                                for(i=0; pp->connects[i] != NOARCPROTO; i++)
921
 
                                {
922
 
                                        if (pp->connects[i] == ap1) found1 = 1;
923
 
                                        if (pp->connects[i] == ap2) found2 = 1;
924
 
                                }
925
 
                                if (found1 != 0 && found2 != 0) break;
926
 
                        }
927
 
                        if (pin == NONODEPROTO)
928
 
                        {
929
 
                                ttyputerr(_("Line %ld: No Via in current technology connects %s to %s"),
930
 
                                        io_leflineno, arcfunctionname(afunc1),
931
 
                                        arcfunctionname(afunc2));
932
 
                                return(TRUE);
933
 
                        }
934
 
                        if (io_lefignoretosemicolon(f, "VIA")) return(TRUE);
935
 
 
936
 
                        /* create the via */
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)
942
 
                        {
943
 
                                ttyputerr(_("Line %ld: Cannot create VIA for PATH"), io_leflineno);
944
 
                                return(TRUE);
945
 
                        }
946
 
                        endobjectchange((INTBIG)ni, VNODEINST);
947
 
                        continue;
948
 
                }
949
 
 
950
 
                ttyputerr(_("Line %ld: Unknown PORT keyword (%s)"), io_leflineno, key);
951
 
                return(TRUE);
952
 
        }
953
 
 
954
 
        /* look for paths that end at vias */
955
 
        for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
956
 
        {
957
 
                for(i=0; i<2; i++)
958
 
                {
959
 
                        if (lp->ni[i] != NONODEINST) continue;
960
 
                        sea = initsearch(lp->x[i], lp->x[i], lp->y[i], lp->y[i], facet);
961
 
                        for(;;)
962
 
                        {
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;
970
 
                                lp->ni[i] = ni;
971
 
                                break;
972
 
                        }
973
 
                        if (lp->ni[i] == NONODEINST) continue;
974
 
 
975
 
                        /* use this via at other paths which meet here */
976
 
                        for(olp = lefpaths; olp != NOLEFPATH; olp = olp->nextlefpath)
977
 
                        {
978
 
                                for(j=0; j<2; j++)
979
 
                                {
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];
983
 
                                }
984
 
                        }
985
 
                }
986
 
        }
987
 
 
988
 
        /* create pins at all other path ends */
989
 
        for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
990
 
        {
991
 
                for(i=0; i<2; i++)
992
 
                {
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)
1001
 
                        {
1002
 
                                ttyputerr(_("Line %ld: Cannot create pin for PATH"), io_leflineno);
1003
 
                                return(TRUE);
1004
 
                        }
1005
 
                        endobjectchange((INTBIG)lp->ni[i], VNODEINST);
1006
 
 
1007
 
                        /* use this pin at other paths which meet here */
1008
 
                        for(olp = lefpaths; olp != NOLEFPATH; olp = olp->nextlefpath)
1009
 
                        {
1010
 
                                for(j=0; j<2; j++)
1011
 
                                {
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];
1015
 
                                }
1016
 
                        }
1017
 
                }
1018
 
        }
1019
 
 
1020
 
        /* now instantiate the paths */
1021
 
        for(lp = lefpaths; lp != NOLEFPATH; lp = lp->nextlefpath)
1022
 
        {
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)
1027
 
                {
1028
 
                        ttyputerr(_("Line %ld: Cannot create arc for PATH"), io_leflineno);
1029
 
                        return(TRUE);
1030
 
                }
1031
 
        }
1032
 
        io_leffreepaths(lefpaths);
1033
 
 
1034
 
        return(FALSE);
1035
 
}
1036
 
 
1037
 
/*
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.
1040
 
 */
1041
 
PORTPROTO *io_lefnewport(NODEPROTO *facet, NODEINST *ni, PORTPROTO *pp, char *thename)
1042
 
{
1043
 
        REGISTER PORTPROTO *ppt;
1044
 
        REGISTER INTBIG i;
1045
 
        REGISTER char *newname, *portname;
1046
 
 
1047
 
        portname = thename;
1048
 
        newname = 0;
1049
 
        for(i=0; ; i++)
1050
 
        {
1051
 
                for(ppt = facet->firstportproto; ppt != NOPORTPROTO; ppt = ppt->nextportproto)
1052
 
                        if (namesame(portname, ppt->protoname) == 0) break;
1053
 
                if (ppt == NOPORTPROTO)
1054
 
                {
1055
 
                        ppt = newportproto(facet, ni, pp, portname);
1056
 
                        break;
1057
 
                }
1058
 
 
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);
1062
 
                portname = newname;
1063
 
        }
1064
 
        if (newname != 0) efree(newname);
1065
 
        return(ppt);
1066
 
}
1067
 
 
1068
 
BOOLEAN io_lefreadobs(FILE *f, NODEPROTO *facet)
1069
 
{
1070
 
        REGISTER char *key;
1071
 
        INTBIG lfunc, arcfunc;
1072
 
        REGISTER INTBIG lx, hx, ly, hy, j;
1073
 
        float x, y;
1074
 
        REGISTER NODEINST *ni;
1075
 
        REGISTER NODEPROTO *np;
1076
 
 
1077
 
        np = NONODEPROTO;
1078
 
        for(;;)
1079
 
        {
1080
 
                key = io_lefgetkeyword(f);
1081
 
                if (key == 0)
1082
 
                {
1083
 
                        ttyputerr(_("EOF parsing OBS"));
1084
 
                        return(TRUE);
1085
 
                }
1086
 
 
1087
 
                if (namesame(key, "END") == 0) break;
1088
 
 
1089
 
                if (namesame(key, "LAYER") == 0)
1090
 
                {
1091
 
                        key = io_lefgetkeyword(f);
1092
 
                        if (key == 0)
1093
 
                        {
1094
 
                                ttyputerr(_("EOF reading LAYER clause"));
1095
 
                                return(TRUE);
1096
 
                        }
1097
 
                        io_lefparselayer(key, &arcfunc, &lfunc);
1098
 
                        if (lfunc == LFUNKNOWN)
1099
 
                        {
1100
 
                                ttyputerr(_("Line %ld: Unknown layer name (%s)"), io_leflineno, key);
1101
 
                                return(TRUE);
1102
 
                        }
1103
 
                        np = io_lefgetnode(lfunc);
1104
 
                        if (np == NONODEPROTO) return(TRUE);
1105
 
                        if (io_lefignoretosemicolon(f, "LAYER")) return(TRUE);
1106
 
                        continue;
1107
 
                }
1108
 
 
1109
 
                if (namesame(key, "RECT") == 0)
1110
 
                {
1111
 
                        if (np == NONODEPROTO)
1112
 
                        {
1113
 
                                ttyputerr(_("Line %ld: No layers for RECT"), io_leflineno);
1114
 
                                return(TRUE);
1115
 
                        }
1116
 
                        key = io_lefgetkeyword(f);
1117
 
                        if (key == 0)
1118
 
                        {
1119
 
                                ttyputerr(_("EOF reading RECT low X"));
1120
 
                                return(TRUE);
1121
 
                        }
1122
 
                        x = (float)atof(key);
1123
 
                        lx = scalefromdispunit(x, DISPUNITMIC);
1124
 
 
1125
 
                        key = io_lefgetkeyword(f);
1126
 
                        if (key == 0)
1127
 
                        {
1128
 
                                ttyputerr(_("EOF reading RECT low Y"));
1129
 
                                return(TRUE);
1130
 
                        }
1131
 
                        y = (float)atof(key);
1132
 
                        ly = scalefromdispunit(y, DISPUNITMIC);
1133
 
 
1134
 
                        key = io_lefgetkeyword(f);
1135
 
                        if (key == 0)
1136
 
                        {
1137
 
                                ttyputerr(_("EOF reading RECT high X"));
1138
 
                                return(TRUE);
1139
 
                        }
1140
 
                        x = (float)atof(key);
1141
 
                        hx = scalefromdispunit(x, DISPUNITMIC);
1142
 
 
1143
 
                        key = io_lefgetkeyword(f);
1144
 
                        if (key == 0)
1145
 
                        {
1146
 
                                ttyputerr(_("EOF reading RECT high Y"));
1147
 
                                return(TRUE);
1148
 
                        }
1149
 
                        y = (float)atof(key);
1150
 
                        hy = scalefromdispunit(y, DISPUNITMIC);
1151
 
 
1152
 
                        if (io_lefignoretosemicolon(f, "RECT")) return(TRUE);
1153
 
 
1154
 
                        /* make the pin */
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)
1159
 
                        {
1160
 
                                ttyputerr(_("Line %ld: Cannot create node for RECT"), io_leflineno);
1161
 
                                return(TRUE);
1162
 
                        }
1163
 
                        endobjectchange((INTBIG)ni, VNODEINST);
1164
 
                        continue;
1165
 
                }
1166
 
        }
1167
 
        return(FALSE);
1168
 
}
1169
 
 
1170
 
BOOLEAN io_lefignoretosemicolon(FILE *f, char *command)
1171
 
{
1172
 
        REGISTER char *key;
1173
 
 
1174
 
        /* ignore up to the next semicolon */
1175
 
        for(;;)
1176
 
        {
1177
 
                key = io_lefgetkeyword(f);
1178
 
                if (key == 0)
1179
 
                {
1180
 
                        ttyputerr(_("EOF parsing %s"), command);
1181
 
                        return(TRUE);
1182
 
                }
1183
 
                if (strcmp(key, ";") == 0) break;
1184
 
        }
1185
 
        return(FALSE);
1186
 
}
1187
 
 
1188
 
char *io_lefgetkeyword(FILE *f)
1189
 
{
1190
 
        REGISTER char *ret;
1191
 
        REGISTER INTBIG filepos, i;
1192
 
 
1193
 
        /* keep reading from file until something is found on a line */
1194
 
        while (io_lefline[io_leflinepos] == 0)
1195
 
        {
1196
 
                /* read a line from the file, exit at EOF */
1197
 
                if (xfgets(io_lefline, MAXLINE, f)) return(0);
1198
 
                io_leflineno++;
1199
 
                if ((io_leflineno%50) == 0)
1200
 
                {
1201
 
                        filepos = xtell(f);
1202
 
                        DiaPercent(1, filepos*100/io_leffilesize);
1203
 
                }
1204
 
 
1205
 
                /* remove comments from the line */
1206
 
                for(i=0; io_lefline[i] != 0; i++)
1207
 
                        if (io_lefline[i] == '#')
1208
 
                {
1209
 
                        io_lefline[i] = 0;
1210
 
                        break;
1211
 
                }
1212
 
 
1213
 
                /* look for the first text on the line */
1214
 
                io_leflinepos = 0;
1215
 
                while (io_lefline[io_leflinepos] == ' ' || io_lefline[io_leflinepos] == '\t')
1216
 
                        io_leflinepos++;
1217
 
        }
1218
 
 
1219
 
        /* remember where the keyword begins */
1220
 
        ret = &io_lefline[io_leflinepos];
1221
 
 
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;
1226
 
 
1227
 
        /* advance to the start of the next keyword */
1228
 
        while (io_lefline[io_leflinepos] == ' ' || io_lefline[io_leflinepos] == '\t')
1229
 
                io_leflinepos++;
1230
 
        return(ret);
1231
 
}
1232
 
 
1233
 
NODEPROTO *io_lefgetnode(INTBIG lfunc)
1234
 
{
1235
 
        REGISTER NODEPROTO *np;
1236
 
 
1237
 
        np = getpurelayernode(el_curtech, -1, lfunc);
1238
 
        if (np == NONODEPROTO)
1239
 
        {
1240
 
                ttyputerr(_("Line %ld: Layer not in current technology"),
1241
 
                        io_leflineno);
1242
 
                return(NONODEPROTO);
1243
 
        }
1244
 
        return(np);
1245
 
}
1246
 
 
1247
 
ARCPROTO *io_lefgetarc(INTBIG afunc)
1248
 
{
1249
 
        REGISTER ARCPROTO *ap;
1250
 
 
1251
 
        for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
1252
 
                if ((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH) == afunc) break;
1253
 
        if (ap == NOARCPROTO)
1254
 
        {
1255
 
                ttyputerr(_("Line %ld: Layer %s not in current technology"),
1256
 
                        io_leflineno, arcfunctionname(afunc));
1257
 
                return(NOARCPROTO);
1258
 
        }
1259
 
        return(ap);
1260
 
}
1261
 
 
1262
 
LEFPATH *io_lefnewpath(void)
1263
 
{
1264
 
        LEFPATH *lp;
1265
 
 
1266
 
        if (io_leffreepath != NOLEFPATH)
1267
 
        {
1268
 
                lp = io_leffreepath;
1269
 
                io_leffreepath = lp->nextlefpath;
1270
 
        } else
1271
 
        {
1272
 
                lp = (LEFPATH *)emalloc(sizeof(LEFPATH), io_tool->cluster);
1273
 
                if (lp == 0) lp = NOLEFPATH;
1274
 
        }
1275
 
        return(lp);
1276
 
}
1277
 
 
1278
 
void io_lefkillpath(LEFPATH *lp)
1279
 
{
1280
 
        lp->nextlefpath = io_leffreepath;
1281
 
        io_leffreepath = lp;
1282
 
}
1283
 
 
1284
 
void io_leffreepaths(LEFPATH *firstlp)
1285
 
{
1286
 
        LEFPATH *lp, *nextlp;
1287
 
 
1288
 
        for(lp = firstlp; lp != NOLEFPATH; lp = nextlp)
1289
 
        {
1290
 
                nextlp = lp->nextlefpath;
1291
 
                io_lefkillpath(lp);
1292
 
        }
1293
 
}
1294
 
 
1295
 
#endif  /* IOLEF - at top */