1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: iodefi.c
6 * Input/output tool: DEF (Design 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 DEF files and reverse-engineering them.
34 * It does not claim to be compliant with the DEF 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 /*************** MISCELLANEOUS ***************/
50
51 #define MAXLINE 2500
52
53 static COMCOMP iodefop = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
54 INPUTOPT, x_(" \t"), M_("DEF options"), 0};
55
56 static INTBIG io_deffilesize;
57 static INTBIG io_deflineno;
58 static CHAR io_defline[MAXLINE];
59 static CHAR io_deffilename[300];
60 static INTBIG io_deflinepos;
61 static INTBIG io_defunits;
62 static VIADEF *io_deffirstviadef;
63 static void *io_defprogressdialog;
64
65 /* prototypes for local routines */
66 static CHAR *io_defgetkeyword(FILE *f);
67 static BOOLEAN io_defignoreblock(FILE *f, CHAR *command);
68 static BOOLEAN io_defignoretosemicolon(FILE *f, CHAR *command);
69 static BOOLEAN io_defreadfile(FILE *f, LIBRARY *lib);
70 static BOOLEAN io_defreadpropertydefinitions(FILE *f);
71 static BOOLEAN io_defreadnets(FILE *f, NODEPROTO *cell, BOOLEAN special, INTBIG options);
72 static BOOLEAN io_defreadpins(FILE *f, NODEPROTO *cell);
73 static BOOLEAN io_defreadcomponents(FILE *f, NODEPROTO *cell);
74 static BOOLEAN io_defreadvias(FILE *f, NODEPROTO *cell);
75 static BOOLEAN io_defreadcomponent(FILE *f, NODEPROTO *cell);
76 static BOOLEAN io_defreadcoordinate(FILE *f, INTBIG *x, INTBIG *y);
77 static NODEPROTO *io_defgetnodeproto(CHAR *name, LIBRARY *curlib);
78 static BOOLEAN io_defreadpin(FILE *f, NODEPROTO *cell);
79 static BOOLEAN io_defreadorientation(FILE *f, INTSML *rot, INTSML *trans);
80 static void io_defgetlayernodes(CHAR *name, NODEPROTO **pin, NODEPROTO **pure, ARCPROTO **arc);
81 static BOOLEAN io_defreadunits(FILE *f);
82 static CHAR *io_defmustgetkeyword(FILE *f, CHAR *where);
83 static BOOLEAN io_defreadvia(FILE *f);
84 static BOOLEAN io_defreadnet(FILE *f, NODEPROTO *cell, BOOLEAN special, INTBIG options);
85 static void io_definerror(CHAR *command, ...);
86 static BOOLEAN io_defgetpin(INTBIG x, INTBIG y, ARCPROTO *ap, NODEPROTO *cell,
87 NODEINST **theni, PORTPROTO **thepp);
88 static void io_defoptionsdlog(void);
89 static BOOLEAN io_deffindconnection(INTBIG x, INTBIG y, ARCPROTO *ap, NODEPROTO *cell,
90 NODEINST *noti, NODEINST **theni, PORTPROTO **thepp);
91
92 /*
93 * Routine to free all memory associated with this module.
94 */
io_freedefimemory(void)95 void io_freedefimemory(void)
96 {
97 }
98
99 /*
100 * Routine to initialize DEF I/O.
101 */
io_initdef(void)102 void io_initdef(void)
103 {
104 DiaDeclareHook(x_("defopt"), &iodefop, io_defoptionsdlog);
105 }
106
io_readdeflibrary(LIBRARY * lib)107 BOOLEAN io_readdeflibrary(LIBRARY *lib)
108 {
109 FILE *fp;
110 REGISTER BOOLEAN ret;
111 CHAR *filename;
112
113 /* open the file */
114 fp = xopen(lib->libfile, io_filetypedef, x_(""), &filename);
115 if (fp == NULL)
116 {
117 ttyputerr(_("File %s not found"), lib->libfile);
118 return(TRUE);
119 }
120 estrcpy(io_deffilename, filename);
121
122 /* prepare for input */
123 io_deffilesize = filesize(fp);
124 io_defprogressdialog = DiaInitProgress(_("Reading DEF file..."), 0);
125 if (io_defprogressdialog == 0)
126 {
127 xclose(fp);
128 return(TRUE);
129 }
130 DiaSetProgress(io_defprogressdialog, 0, io_deffilesize);
131 io_deflineno = 0;
132 io_deflinepos = 0;
133 io_defline[0] = 0;
134 io_defunits = 1000;
135 io_deffirstviadef = NOVIADEF;
136
137 /* read the file */
138 ret = io_defreadfile(fp, lib);
139
140 /* clean up */
141 DiaDoneProgress(io_defprogressdialog);
142 xclose(fp);
143 if (!ret) ttyputmsg(_("DEF file %s is read"), lib->libfile); else
144 ttyputmsg(_("Error reading DEF file %s"), lib->libfile);
145 return(FALSE);
146 }
147
148 /*
149 * Routine to read the DEF file in "f".
150 */
io_defreadfile(FILE * f,LIBRARY * lib)151 BOOLEAN io_defreadfile(FILE *f, LIBRARY *lib)
152 {
153 REGISTER CHAR *key, *cellname;
154 REGISTER INTBIG *options;
155 CHAR curkey[200];
156 REGISTER NODEPROTO *cell;
157
158 options = io_getstatebits();
159
160 for(;;)
161 {
162 /* get the next keyword */
163 key = io_defgetkeyword(f);
164 if (key == 0) break;
165 if (namesame(key, x_("VERSION")) == 0 || namesame(key, x_("NAMESCASESENSITIVE")) == 0 ||
166 namesame(key, x_("DIVIDERCHAR")) == 0 || namesame(key, x_("BUSBITCHARS")) == 0 ||
167 namesame(key, x_("DIEAREA")) == 0 || namesame(key, x_("ROW")) == 0 ||
168 namesame(key, x_("TRACKS")) == 0 || namesame(key, x_("GCELLGRID")) == 0 ||
169 namesame(key, x_("HISTORY")) == 0 || namesame(key, x_("TECHNOLOGY")) == 0)
170 {
171 estrcpy(curkey, key);
172 if (io_defignoretosemicolon(f, curkey)) return(TRUE);
173 continue;
174 }
175 if (namesame(key, x_("DEFAULTCAP")) == 0 || namesame(key, x_("REGIONS")) == 0)
176 {
177 if (io_defignoreblock(f, key)) return(TRUE);
178 continue;
179 }
180 if (namesame(key, x_("DESIGN")) == 0)
181 {
182 cellname = io_defmustgetkeyword(f, x_("DESIGN"));
183 if (cellname == 0) return(TRUE);
184 cell = us_newnodeproto(cellname, lib);
185 if (cell == NONODEPROTO)
186 {
187 io_definerror(_("Cannot create cell '%s'"), cellname);
188 return(TRUE);
189 }
190 if (io_defignoretosemicolon(f, _("DESIGN"))) return(TRUE);
191 continue;
192 }
193
194 if (namesame(key, x_("UNITS")) == 0)
195 {
196 if (io_defreadunits(f)) return(TRUE);
197 continue;
198 }
199
200 if (namesame(key, x_("PROPERTYDEFINITIONS")) == 0)
201 {
202 if (io_defreadpropertydefinitions(f)) return(TRUE);
203 continue;
204 }
205
206 if (namesame(key, x_("VIAS")) == 0)
207 {
208 if (io_defreadvias(f, cell)) return(TRUE);
209 continue;
210 }
211
212 if (namesame(key, x_("COMPONENTS")) == 0)
213 {
214 if (io_defreadcomponents(f, cell)) return(TRUE);
215 continue;
216 }
217
218 if (namesame(key, x_("PINS")) == 0)
219 {
220 if (io_defreadpins(f, cell)) return(TRUE);
221 continue;
222 }
223
224 if (namesame(key, x_("SPECIALNETS")) == 0)
225 {
226 if (io_defreadnets(f, cell, TRUE, options[0])) return(TRUE);
227 continue;
228 }
229
230 if (namesame(key, x_("NETS")) == 0)
231 {
232 if (io_defreadnets(f, cell, FALSE, options[0])) return(TRUE);
233 continue;
234 }
235
236 if (namesame(key, x_("END")) == 0)
237 {
238 key = io_defgetkeyword(f);
239 break;
240 }
241 }
242 return(FALSE);
243 }
244
245 /*************** VIAS ***************/
246
io_defreadvias(FILE * f,NODEPROTO * cell)247 BOOLEAN io_defreadvias(FILE *f, NODEPROTO *cell)
248 {
249 REGISTER CHAR *key;
250 CHAR curkey[200];
251
252 if (io_defignoretosemicolon(f, _("VIAS"))) return(TRUE);
253 for(;;)
254 {
255 /* get the next keyword */
256 key = io_defmustgetkeyword(f, x_("VIAs"));
257 if (key == 0) return(TRUE);
258 if (namesame(key, x_("-")) == 0)
259 {
260 if (io_defreadvia(f)) return(TRUE);
261 continue;
262 }
263
264 if (namesame(key, x_("END")) == 0)
265 {
266 key = io_defgetkeyword(f);
267 break;
268 }
269
270 /* ignore the keyword */
271 estrcpy(curkey, key);
272 if (io_defignoretosemicolon(f, curkey)) return(TRUE);
273 }
274 return(FALSE);
275 }
276
io_defreadvia(FILE * f)277 BOOLEAN io_defreadvia(FILE *f)
278 {
279 REGISTER CHAR *key;
280 INTBIG lx, hx, ly, hy;
281 NODEPROTO *pin, *pure;
282 ARCPROTO *ap;
283 REGISTER VIADEF *vd;
284
285 /* get the via name */
286 key = io_defmustgetkeyword(f, x_("VIA"));
287 if (key == 0) return(TRUE);
288
289 /* create a new via definition */
290 vd = (VIADEF *)emalloc(sizeof (VIADEF), io_tool->cluster);
291 if (vd == 0) return(TRUE);
292 (void)allocstring(&vd->vianame, key, io_tool->cluster);
293 vd->sx = vd->sy = 0;
294 vd->via = NONODEPROTO;
295 vd->lay1 = vd->lay2 = NOARCPROTO;
296 vd->nextviadef = io_deffirstviadef;
297 io_deffirstviadef = vd;
298
299 for(;;)
300 {
301 /* get the next keyword */
302 key = io_defmustgetkeyword(f, x_("VIA"));
303 if (key == 0) return(TRUE);
304 if (namesame(key, x_("+")) == 0)
305 {
306 key = io_defmustgetkeyword(f, x_("VIA"));
307 if (key == 0) return(TRUE);
308 if (namesame(key, x_("RECT")) == 0)
309 {
310 /* handle definition of a via rectangle */
311 key = io_defmustgetkeyword(f, x_("VIA"));
312 if (key == 0) return(TRUE);
313 io_defgetlayernodes(key, &pin, &pure, &ap);
314 if (pure == NONODEPROTO)
315 {
316 io_definerror(_("Layer %s not in current technology"), key);
317 pure = NONODEPROTO;
318 }
319 if (namesamen(key, x_("VIA"), 3) == 0)
320 {
321 if (pin == NONODEPROTO) pin = gen_univpinprim;
322 vd->via = pin;
323 }
324 if (namesamen(key, x_("METAL"), 5) == 0)
325 {
326 if (ap == NOARCPROTO) ap = gen_universalarc;
327 if (vd->lay1 == NOARCPROTO) vd->lay1 = ap; else
328 vd->lay2 = ap;
329 }
330 if (io_defreadcoordinate(f, &lx, &ly)) return(TRUE);
331 if (io_defreadcoordinate(f, &hx, &hy)) return(TRUE);
332
333 /* accumulate largest contact size */
334 if (hx-lx > vd->sx) vd->sx = hx - lx;
335 if (hy-ly > vd->sy) vd->sy = hy - ly;
336 continue;
337 }
338 continue;
339 }
340
341 if (namesame(key, x_(";")) == 0)
342 break;
343 }
344 if (vd->via != NONODEPROTO)
345 {
346 if (vd->sx == 0) vd->sx = vd->via->highx - vd->via->lowx;
347 if (vd->sy == 0) vd->sy = vd->via->highy - vd->via->lowy;
348 }
349 return(FALSE);
350 }
351
352 /*************** COMPONENTS ***************/
353
io_defreadcomponents(FILE * f,NODEPROTO * cell)354 BOOLEAN io_defreadcomponents(FILE *f, NODEPROTO *cell)
355 {
356 REGISTER CHAR *key;
357 CHAR curkey[200];
358
359 if (io_defignoretosemicolon(f, _("COMPONENTS"))) return(1);
360 for(;;)
361 {
362 /* get the next keyword */
363 key = io_defmustgetkeyword(f, x_("COMPONENTs"));
364 if (key == 0) return(TRUE);
365 if (namesame(key, x_("-")) == 0)
366 {
367 if (io_defreadcomponent(f, cell)) return(TRUE);
368 continue;
369 }
370
371 if (namesame(key, x_("END")) == 0)
372 {
373 key = io_defgetkeyword(f);
374 break;
375 }
376
377 /* ignore the keyword */
378 estrcpy(curkey, key);
379 if (io_defignoretosemicolon(f, curkey)) return(TRUE);
380 }
381 return(FALSE);
382 }
383
io_defreadcomponent(FILE * f,NODEPROTO * cell)384 BOOLEAN io_defreadcomponent(FILE *f, NODEPROTO *cell)
385 {
386 REGISTER CHAR *key;
387 INTBIG x, y, cx, cy;
388 INTBIG sx, sy;
389 REGISTER INTBIG lx, hx, ly, hy;
390 REGISTER NODEINST *ni;
391 REGISTER NODEPROTO *np;
392 REGISTER VARIABLE *var;
393 INTSML rot, trans;
394 CHAR compname[200], modelname[200];
395
396 /* get the component name and model name */
397 key = io_defmustgetkeyword(f, x_("COMPONENT"));
398 if (key == 0) return(TRUE);
399 estrcpy(compname, key);
400 key = io_defmustgetkeyword(f, x_("COMPONENT"));
401 if (key == 0) return(TRUE);
402 estrcpy(modelname, key);
403
404 /* find the named cell */
405 np = io_defgetnodeproto(modelname, cell->lib);
406 if (np == NONODEPROTO)
407 {
408 io_definerror(_("Unknown cell (%s)"), modelname);
409 return(TRUE);
410 }
411
412 for(;;)
413 {
414 /* get the next keyword */
415 key = io_defmustgetkeyword(f, x_("COMPONENT"));
416 if (key == 0) return(TRUE);
417 if (namesame(key, x_("+")) == 0)
418 {
419 key = io_defmustgetkeyword(f, x_("COMPONENT"));
420 if (key == 0) return(TRUE);
421 if (namesame(key, x_("PLACED")) == 0 || namesame(key, x_("FIXED")) == 0)
422 {
423 /* handle placement */
424 if (io_defreadcoordinate(f, &x, &y)) return(TRUE);
425 if (io_defreadorientation(f, &rot, &trans)) return(TRUE);
426
427 /* place the node */
428 defaultnodesize(np, &sx, &sy);
429 corneroffset(NONODEINST, np, 0, 0, &cx, &cy, FALSE);
430 lx = x - cx; hx = lx + sx;
431 ly = y - cy; hy = ly + sy;
432 ni = newnodeinst(np, lx, hx, ly, hy, trans, rot, cell);
433 if (ni == NONODEINST)
434 {
435 io_definerror(_("Unable to create node"));
436 return(TRUE);
437 }
438 endobjectchange((INTBIG)ni, VNODEINST);
439 var = setvalkey((INTBIG)ni, VNODEINST, el_node_name_key,
440 (INTBIG)compname, VSTRING|VDISPLAY);
441 if (var != NOVARIABLE)
442 defaulttextsize(3, var->textdescript);
443 continue;
444 }
445 continue;
446 }
447
448 if (namesame(key, x_(";")) == 0)
449 break;
450 }
451 return(FALSE);
452 }
453
454 /*************** PINS ***************/
455
io_defreadpins(FILE * f,NODEPROTO * cell)456 BOOLEAN io_defreadpins(FILE *f, NODEPROTO *cell)
457 {
458 REGISTER CHAR *key;
459 CHAR curkey[200];
460
461 if (io_defignoretosemicolon(f, _("PINS"))) return(TRUE);
462 for(;;)
463 {
464 /* get the next keyword */
465 key = io_defmustgetkeyword(f, x_("PINs"));
466 if (key == 0) return(TRUE);
467 if (namesame(key, x_("-")) == 0)
468 {
469 if (io_defreadpin(f, cell)) return(TRUE);
470 continue;
471 }
472
473 if (namesame(key, x_("END")) == 0)
474 {
475 key = io_defgetkeyword(f);
476 break;
477 }
478
479 /* ignore the keyword */
480 estrcpy(curkey, key);
481 if (io_defignoretosemicolon(f, curkey)) return(TRUE);
482 }
483 return(FALSE);
484 }
485
io_defreadpin(FILE * f,NODEPROTO * cell)486 BOOLEAN io_defreadpin(FILE *f, NODEPROTO *cell)
487 {
488 REGISTER CHAR *key;
489 INTBIG lx, hx, ly, hy, x, y;
490 REGISTER INTBIG portbits, i, havecoord;
491 REGISTER NODEINST *ni;
492 NODEPROTO *np, *pure;
493 ARCPROTO *ap;
494 REGISTER PORTPROTO *pp;
495 INTSML rot, trn;
496 CHAR pinname[200];
497 XARRAY trans;
498
499 /* get the pin name */
500 key = io_defmustgetkeyword(f, x_("PIN"));
501 if (key == 0) return(TRUE);
502 estrcpy(pinname, key);
503 portbits = havecoord = 0;
504 np = NONODEPROTO;
505
506 for(;;)
507 {
508 /* get the next keyword */
509 key = io_defmustgetkeyword(f, x_("PIN"));
510 if (key == 0) return(TRUE);
511 if (namesame(key, x_("+")) == 0)
512 {
513 key = io_defmustgetkeyword(f, x_("PIN"));
514 if (key == 0) return(TRUE);
515 if (namesame(key, x_("NET")) == 0)
516 {
517 key = io_defmustgetkeyword(f, _("net name"));
518 if (key == 0) return(TRUE);
519 continue;
520 }
521 if (namesame(key, x_("DIRECTION")) == 0)
522 {
523 key = io_defmustgetkeyword(f, x_("DIRECTION"));
524 if (key == 0) return(TRUE);
525 if (namesame(key, x_("INPUT")) == 0) portbits = INPORT; else
526 if (namesame(key, x_("OUTPUT")) == 0) portbits = OUTPORT; else
527 if (namesame(key, x_("INOUT")) == 0) portbits = BIDIRPORT; else
528 if (namesame(key, x_("FEEDTHRU")) == 0) portbits = BIDIRPORT; else
529 {
530 io_definerror(_("Unknown direction (%s)"), key);
531 return(TRUE);
532 }
533 continue;
534 }
535 if (namesame(key, x_("USE")) == 0)
536 {
537 key = io_defmustgetkeyword(f, x_("USE"));
538 if (key == 0) return(TRUE);
539 if (namesame(key, x_("SIGNAL")) == 0) portbits = portbits; else
540 if (namesame(key, x_("POWER")) == 0) portbits = PWRPORT; else
541 if (namesame(key, x_("GROUND")) == 0) portbits = GNDPORT; else
542 if (namesame(key, x_("CLOCK")) == 0) portbits = CLKPORT; else
543 if (namesame(key, x_("TIEOFF")) == 0) portbits = portbits; else
544 if (namesame(key, x_("ANALOG")) == 0) portbits = portbits; else
545 {
546 io_definerror(_("Unknown usage (%s)"), key);
547 return(TRUE);
548 }
549 continue;
550 }
551 if (namesame(key, x_("LAYER")) == 0)
552 {
553 key = io_defmustgetkeyword(f, x_("LAYER"));
554 if (key == 0) return(TRUE);
555 io_defgetlayernodes(key, &np, &pure, &ap);
556 if (np == NONODEPROTO)
557 {
558 io_definerror(_("Unknown layer (%s)"), key);
559 return(TRUE);
560 }
561 if (io_defreadcoordinate(f, &lx, &ly)) return(TRUE);
562 if (io_defreadcoordinate(f, &hx, &hy)) return(TRUE);
563 continue;
564 }
565 if (namesame(key, x_("PLACED")) == 0)
566 {
567 /* get pin location and orientation */
568 if (io_defreadcoordinate(f, &x, &y)) return(TRUE);
569 if (io_defreadorientation(f, &rot, &trn)) return(TRUE);
570 havecoord = 1;
571 continue;
572 }
573 continue;
574 }
575
576 if (namesame(key, x_(";")) == 0)
577 break;
578 }
579
580 /* all factors read, now place the pin */
581 if (np != NONODEPROTO && havecoord != 0)
582 {
583 /* determine the pin size */
584 makeangle(rot, trn, trans);
585 rot = trn = 0;
586 xform(lx, ly, &lx, &ly, trans);
587 xform(hx, hy, &hx, &hy, trans);
588 if (lx > hx) { i = lx; lx = hx; hx = i; }
589 if (ly > hy) { i = ly; ly = hy; hy = i; }
590 lx += x; hx += x;
591 ly += y; hy += y;
592
593 /* make the pin */
594 ni = newnodeinst(np, lx, hx, ly, hy, trn, rot, cell);
595 if (ni == NONODEINST)
596 {
597 io_definerror(_("Unable to create pin"));
598 return(TRUE);
599 }
600 endobjectchange((INTBIG)ni, VNODEINST);
601 pp = newportproto(cell, ni, np->firstportproto, pinname);
602 if (pp == NOPORTPROTO)
603 {
604 io_definerror(_("Unable to create pin name"));
605 return(TRUE);
606 }
607 pp->userbits = (pp->userbits & ~STATEBITS) | portbits;
608 }
609 return(FALSE);
610 }
611
612 /*************** NETS ***************/
613
io_defreadnets(FILE * f,NODEPROTO * cell,BOOLEAN special,INTBIG options)614 BOOLEAN io_defreadnets(FILE *f, NODEPROTO *cell, BOOLEAN special, INTBIG options)
615 {
616 REGISTER CHAR *key;
617 CHAR curkey[200];
618
619 for(;;)
620 {
621 /* get the next keyword */
622 key = io_defmustgetkeyword(f, x_("NETs"));
623 if (key == 0) return(TRUE);
624 if (namesame(key, x_("-")) == 0)
625 {
626 if (io_defreadnet(f, cell, special, options)) return(TRUE);
627 continue;
628 }
629 if (namesame(key, x_("END")) == 0)
630 {
631 key = io_defgetkeyword(f);
632 break;
633 }
634
635 /* ignore the keyword */
636 estrcpy(curkey, key);
637 if (io_defignoretosemicolon(f, curkey)) return(TRUE);
638 }
639 return(FALSE);
640 }
641
io_defreadnet(FILE * f,NODEPROTO * cell,BOOLEAN special,INTBIG options)642 BOOLEAN io_defreadnet(FILE *f, NODEPROTO *cell, BOOLEAN special, INTBIG options)
643 {
644 REGISTER CHAR *key;
645 INTBIG lx, hx, ly, hy, plx, ply, phx, phy, sx, sy, fx, fy, tx, ty;
646 REGISTER INTBIG i, curx, cury, lastx, lasty, pathstart, placedvia, width,
647 wantpinpairs, specialwidth, bits;
648 NODEINST *ni, *lastni, *nextni;
649 REGISTER NODEINST *lastlogni;
650 REGISTER ARCINST *ai;
651 REGISTER BOOLEAN foundcoord;
652 PORTPROTO *pp, *lastpp, *nextpp;
653 REGISTER PORTPROTO *lastlogpp;
654 REGISTER NODEPROTO *np;
655 NODEPROTO *pin, *pure;
656 ARCPROTO *routap;
657 REGISTER VARIABLE *var;
658 float v;
659 CHAR netname[200];
660 REGISTER VIADEF *vd;
661
662 /* get the net name */
663 key = io_defmustgetkeyword(f, x_("NET"));
664 if (key == 0) return(TRUE);
665 estrcpy(netname, key);
666
667 /* get the next keyword */
668 key = io_defmustgetkeyword(f, x_("NET"));
669 if (key == 0) return(TRUE);
670
671 /* scan the "net" statement */
672 wantpinpairs = 1;
673 lastx = lasty = 0;
674 pathstart = 1;
675 lastlogni = NONODEINST;
676 for(;;)
677 {
678 /* examine the next keyword */
679 if (namesame(key, x_(";")) == 0) break;
680
681 if (namesame(key, x_("+")) == 0)
682 {
683 wantpinpairs = 0;
684 key = io_defmustgetkeyword(f, x_("NET"));
685 if (key == 0) return(TRUE);
686
687 if (namesame(key, x_("USE")) == 0)
688 {
689 /* ignore "USE" keyword */
690 key = io_defmustgetkeyword(f, x_("NET"));
691 if (key == 0) return(TRUE);
692 } else if (namesame(key, x_("ROUTED")) == 0)
693 {
694 /* handle "ROUTED" keyword */
695 key = io_defmustgetkeyword(f, x_("NET"));
696 if (key == 0) return(TRUE);
697 io_defgetlayernodes(key, &pin, &pure, &routap);
698 if (pin == NONODEPROTO)
699 {
700 io_definerror(_("Unknown layer (%s)"), key);
701 return(TRUE);
702 }
703 pathstart = 1;
704 if (special)
705 {
706 /* specialnets have width here */
707 key = io_defmustgetkeyword(f, x_("NET"));
708 if (key == 0) return(TRUE);
709 v = (float)eatof(key) / (float)io_defunits;
710 specialwidth = scalefromdispunit(v, DISPUNITMIC);
711 }
712 } else if (namesame(key, x_("FIXED")) == 0)
713 {
714 /* handle "FIXED" keyword */
715 key = io_defmustgetkeyword(f, x_("NET"));
716 if (key == 0) return(TRUE);
717 io_defgetlayernodes(key, &pin, &pure, &routap);
718 if (pin == NONODEPROTO)
719 {
720 io_definerror(_("Unknown layer (%s)"), key);
721 return(TRUE);
722 }
723 pathstart = 1;
724 } else if (namesame(key, x_("SHAPE")) == 0)
725 {
726 /* handle "SHAPE" keyword */
727 key = io_defmustgetkeyword(f, x_("NET"));
728 if (key == 0) return(TRUE);
729 } else
730 {
731 io_definerror(_("Cannot handle '%s' nets"), key);
732 return(TRUE);
733 }
734
735 /* get next keyword */
736 key = io_defmustgetkeyword(f, x_("NET"));
737 if (key == 0) return(TRUE);
738 continue;
739 }
740
741 /* if still parsing initial pin pairs, do so */
742 if (wantpinpairs != 0)
743 {
744 /* it must be the "(" of a pin pair */
745 if (namesame(key, x_("(")) != 0)
746 {
747 io_definerror(_("Expected '(' of pin pair"));
748 return(TRUE);
749 }
750
751 /* get the pin names */
752 key = io_defmustgetkeyword(f, x_("NET"));
753 if (key == 0) return(TRUE);
754 if (namesame(key, x_("PIN")) == 0)
755 {
756 /* find the export */
757 key = io_defmustgetkeyword(f, x_("NET"));
758 if (key == 0) return(TRUE);
759 pp = getportproto(cell, key);
760 if (pp == NOPORTPROTO)
761 {
762 io_definerror(_("Warning: unknown pin '%s'"), key);
763 if (io_defignoretosemicolon(f, _("NETS"))) return(TRUE);
764 return(FALSE);
765 }
766 ni = pp->subnodeinst;
767 pp = pp->subportproto;
768 } else
769 {
770 for(ni = cell->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
771 {
772 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key);
773 if (var == NOVARIABLE) continue;
774 if (namesame((CHAR *)var->addr, key) == 0) break;
775 }
776 if (ni == NONODEINST)
777 {
778 io_definerror(_("Unknown component '%s'"), key);
779 return(TRUE);
780 }
781
782 /* get the port name */
783 key = io_defmustgetkeyword(f, x_("NET"));
784 if (key == 0) return(TRUE);
785 pp = getportproto(ni->proto, key);
786 if (pp == NOPORTPROTO)
787 {
788 io_definerror(_("Unknown port '%s' on component '%s'"),
789 key, (CHAR *)var->addr);
790 return(TRUE);
791 }
792 }
793
794 /* get the close parentheses */
795 key = io_defmustgetkeyword(f, x_("NET"));
796 if (key == 0) return(TRUE);
797 if (namesame(key, x_(")")) != 0)
798 {
799 io_definerror(_("Expected ')' of pin pair"));
800 return(TRUE);
801 }
802
803 if (lastlogni != NONODEINST && (options&DEFNOLOGICAL) == 0)
804 {
805 portposition(ni, pp, &fx, &fy);
806
807 /* LINTED "lastlogpp" used in proper order */
808 portposition(lastlogni, lastlogpp, &tx, &ty);
809 bits = us_makearcuserbits(gen_unroutedarc);
810 ai = newarcinst(gen_unroutedarc, defaultarcwidth(gen_unroutedarc), bits,
811 ni, pp, fx, fy, lastlogni, lastlogpp, tx, ty, cell);
812 if (ai == NOARCINST)
813 {
814 io_definerror(_("Could not create unrouted arc"));
815 return(TRUE);
816 }
817 endobjectchange((INTBIG)ai, VARCINST);
818 }
819 lastlogni = ni;
820 lastlogpp = pp;
821
822 /* get the next keyword and continue parsing */
823 key = io_defmustgetkeyword(f, x_("NET"));
824 if (key == 0) return(TRUE);
825 continue;
826 }
827
828 /* handle "new" start of coordinate trace */
829 if (namesame(key, x_("NEW")) == 0)
830 {
831 key = io_defmustgetkeyword(f, x_("NET"));
832 if (key == 0) return(TRUE);
833 io_defgetlayernodes(key, &pin, &pure, &routap);
834 if (pin == NONODEPROTO)
835 {
836 io_definerror(_("Unknown layer (%s)"), key);
837 return(TRUE);
838 }
839 pathstart = 1;
840 key = io_defmustgetkeyword(f, x_("NET"));
841 if (key == 0) return(TRUE);
842 if (special)
843 {
844 /* specialnets have width here */
845 v = (float)eatof(key) / (float)io_defunits;
846 specialwidth = scalefromdispunit(v, DISPUNITMIC);
847
848 /* get the next keyword */
849 key = io_defmustgetkeyword(f, x_("NET"));
850 if (key == 0) return(TRUE);
851 }
852 continue;
853 }
854
855 foundcoord = FALSE;
856 if (namesame(key, x_("(")) == 0)
857 {
858 /* get the X coordinate */
859 foundcoord = TRUE;
860 key = io_defmustgetkeyword(f, x_("NET"));
861 if (key == 0) return(TRUE);
862 if (estrcmp(key, x_("*")) == 0) curx = lastx; else
863 {
864 v = (float)eatof(key) / (float)io_defunits;
865 curx = scalefromdispunit(v, DISPUNITMIC);
866 }
867
868 /* get the Y coordinate */
869 key = io_defmustgetkeyword(f, x_("NET"));
870 if (key == 0) return(TRUE);
871 if (estrcmp(key, x_("*")) == 0) cury = lasty; else
872 {
873 v = (float)eatof(key) / (float)io_defunits;
874 cury = scalefromdispunit(v, DISPUNITMIC);
875 }
876
877 /* get the close parentheses */
878 key = io_defmustgetkeyword(f, x_("NET"));
879 if (key == 0) return(TRUE);
880 if (namesame(key, x_(")")) != 0)
881 {
882 io_definerror(_("Expected ')' of coordinate pair"));
883 return(TRUE);
884 }
885 }
886
887 /* get the next keyword */
888 key = io_defmustgetkeyword(f, x_("NET"));
889 if (key == 0) return(TRUE);
890
891 /* see if it is a via name */
892 for(vd = io_deffirstviadef; vd != NOVIADEF; vd = vd->nextviadef)
893 if (namesame(key, vd->vianame) == 0) break;
894 if (vd == NOVIADEF)
895 {
896 /* see if the via name is from the LEF file */
897 for(vd = io_leffirstviadef; vd != NOVIADEF; vd = vd->nextviadef)
898 if (namesame(key, vd->vianame) == 0) break;
899 }
900
901 /* stop now if not placing physical nets */
902 if ((options&DEFNOPHYSICAL) != 0)
903 {
904 /* ignore the next keyword if a via name is coming */
905 if (vd != NOVIADEF)
906 {
907 key = io_defmustgetkeyword(f, x_("NET"));
908 if (key == 0) return(TRUE);
909 }
910 continue;
911 }
912
913 /* if a via is mentioned next, use it */
914 if (vd != NOVIADEF)
915 {
916 /* place the via at this location */
917 sx = vd->sx;
918 sy = vd->sy;
919 lx = curx - sx / 2; hx = lx + sx;
920 ly = cury - sy / 2; hy = ly + sy;
921 if (vd->via == NONODEPROTO)
922 {
923 io_definerror(_("Cannot to create via"));
924 return(TRUE);
925 }
926
927 /* see if there is a connection point here when starting a path */
928 if (pathstart != 0)
929 {
930 if (!io_deffindconnection(curx, cury, routap, cell, NONODEINST,
931 &lastni, &lastpp)) lastni = NONODEINST;
932 }
933
934 /* create the via */
935 nodeprotosizeoffset(vd->via, &plx, &ply, &phx, &phy, cell);
936 ni = newnodeinst(vd->via, lx-plx, hx+phx, ly-ply, hy+phy, 0, 0, cell);
937 if (ni == NONODEINST)
938 {
939 io_definerror(_("Unable to create via layer"));
940 return(TRUE);
941 }
942 endobjectchange((INTBIG)ni, VNODEINST);
943 pp = ni->proto->firstportproto;
944
945 /* if the path starts with a via, wire it */
946 if (pathstart != 0 && lastni != NONODEINST && foundcoord)
947 {
948 if (special) width = specialwidth; else
949 {
950 var = getval((INTBIG)routap, VARCPROTO, VINTEGER, x_("IO_lef_width"));
951 if (var == NOVARIABLE) width = defaultarcwidth(routap); else
952 width = var->addr;
953 }
954 ai = newarcinst(routap, width, us_makearcuserbits(routap),
955 lastni, lastpp, curx, cury, ni, pp, curx, cury, cell);
956 if (ai == NOARCINST)
957 {
958 io_definerror(_("Unable to create net starting point"));
959 return(TRUE);
960 }
961 endobjectchange((INTBIG)ai, VARCINST);
962 }
963
964 /* remember that a via was placed */
965 placedvia = 1;
966
967 /* get the next keyword */
968 key = io_defmustgetkeyword(f, x_("NET"));
969 if (key == 0) return(TRUE);
970 } else
971 {
972 /* no via mentioned: just make a pin */
973 if (io_defgetpin(curx, cury, routap, cell, &ni, &pp)) return(TRUE);
974 placedvia = 0;
975 }
976 if (!foundcoord) continue;
977
978 /* run the wire */
979 if (pathstart == 0)
980 {
981 /* make sure that this arc can connect to the current pin */
982 for(i=0; pp->connects[i] != NOARCPROTO; i++)
983 if (pp->connects[i] == routap) break;
984 if (pp->connects[i] == NOARCPROTO)
985 {
986 np = getpinproto(routap);
987 defaultnodesize(np, &sx, &sy);
988 lx = curx - sx / 2; hx = lx + sx;
989 ly = cury - sy / 2; hy = ly + sy;
990 ni = newnodeinst(np, lx, hx, ly, hy, 0, 0, cell);
991 if (ni == NONODEINST)
992 {
993 io_definerror(_("Unable to create net pin"));
994 return(TRUE);
995 }
996 endobjectchange((INTBIG)ni, VNODEINST);
997 pp = ni->proto->firstportproto;
998 }
999
1000 /* run the wire */
1001 if (special) width = specialwidth; else
1002 {
1003 var = getval((INTBIG)routap, VARCPROTO, VINTEGER, x_("IO_lef_width"));
1004 if (var == NOVARIABLE) width = defaultarcwidth(routap); else
1005 width = var->addr;
1006 }
1007 ai = newarcinst(routap, width, us_makearcuserbits(routap),
1008 lastni, lastpp, lastx, lasty, ni, pp, curx, cury, cell);
1009 if (ai == NOARCINST)
1010 {
1011 io_definerror(_("Unable to create net path"));
1012 return(TRUE);
1013 }
1014 endobjectchange((INTBIG)ai, VARCINST);
1015 }
1016 lastx = curx; lasty = cury;
1017 pathstart = 0;
1018 lastni = ni;
1019 lastpp = pp;
1020
1021 /* switch layers to the other one supported by the via */
1022 if (placedvia != 0)
1023 {
1024 if (routap == vd->lay1)
1025 {
1026 routap = vd->lay2;
1027 } else if (routap == vd->lay2)
1028 {
1029 routap = vd->lay1;
1030 }
1031 pin = getpinproto(routap);
1032 }
1033
1034 /* if the path ends here, connect it */
1035 if (namesame(key, x_("NEW")) == 0 || namesame(key, x_(";")) == 0)
1036 {
1037 /* see if there is a connection point here when starting a path */
1038 if (!io_deffindconnection(curx, cury, routap, cell, ni, &nextni, &nextpp))
1039 nextni = NONODEINST;
1040
1041 /* if the path starts with a via, wire it */
1042 if (nextni != NONODEINST)
1043 {
1044 if (special) width = specialwidth; else
1045 {
1046 var = getval((INTBIG)routap, VARCPROTO, VINTEGER, x_("IO_lef_width"));
1047 if (var == NOVARIABLE) width = defaultarcwidth(routap); else
1048 width = var->addr;
1049 }
1050 ai = newarcinst(routap, width, us_makearcuserbits(routap),
1051 ni, pp, curx, cury, nextni, nextpp, curx, cury, cell);
1052 if (ai == NOARCINST)
1053 {
1054 io_definerror(_("Unable to create net ending point"));
1055 return(TRUE);
1056 }
1057 endobjectchange((INTBIG)ai, VARCINST);
1058 }
1059 }
1060 }
1061 return(FALSE);
1062 }
1063
1064 /*
1065 * Routine to look for a connection to arcs of type "ap" in cell "cell"
1066 * at (x, y). The connection can not be on "not" (if it is not NONODEINST).
1067 * If found, return true and places the node and port in "theni" and "thepp".
1068 */
io_deffindconnection(INTBIG x,INTBIG y,ARCPROTO * ap,NODEPROTO * cell,NODEINST * noti,NODEINST ** theni,PORTPROTO ** thepp)1069 BOOLEAN io_deffindconnection(INTBIG x, INTBIG y, ARCPROTO *ap, NODEPROTO *cell, NODEINST *noti,
1070 NODEINST **theni, PORTPROTO **thepp)
1071 {
1072 REGISTER INTBIG sea, i;
1073 REGISTER NODEINST *ni;
1074 REGISTER PORTPROTO *pp;
1075 REGISTER GEOM *geom;
1076 static POLYGON *poly = NOPOLYGON;
1077
1078 /* get polygons */
1079 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1080
1081 sea = initsearch(x, x, y, y, cell);
1082 for(;;)
1083 {
1084 geom = nextobject(sea);
1085 if (geom == NOGEOM) break;
1086 if (!geom->entryisnode) continue;
1087 ni = geom->entryaddr.ni;
1088 if (ni == noti) continue;
1089 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1090 {
1091 for(i=0; pp->connects[i] != NOARCPROTO; i++)
1092 if (pp->connects[i] == ap) break;
1093 if (pp->connects[i] == NOARCPROTO) continue;
1094 shapeportpoly(ni, pp, poly, FALSE);
1095 if (isinside(x, y, poly))
1096 {
1097 termsearch(sea);
1098 *theni = ni;
1099 *thepp = pp;
1100 return(TRUE);
1101 }
1102 }
1103 }
1104 return(FALSE);
1105 }
1106
1107 /*
1108 * Routine to look for a connection to arcs of type "ap" in cell "cell"
1109 * at (x, y). If nothing is found, create a pin. In any case, return
1110 * the node and port in "theni" and "thepp". Returns true on error.
1111 */
io_defgetpin(INTBIG x,INTBIG y,ARCPROTO * ap,NODEPROTO * cell,NODEINST ** theni,PORTPROTO ** thepp)1112 BOOLEAN io_defgetpin(INTBIG x, INTBIG y, ARCPROTO *ap, NODEPROTO *cell,
1113 NODEINST **theni, PORTPROTO **thepp)
1114 {
1115 INTBIG sx, sy;
1116 REGISTER INTBIG lx, hx, ly, hy;
1117 REGISTER NODEINST *ni;
1118 REGISTER NODEPROTO *pin;
1119
1120 /* if there is an existing connection, return it */
1121 if (io_deffindconnection(x, y, ap, cell, NONODEINST, theni, thepp)) return(FALSE);
1122
1123 /* nothing found at this location: create a pin */
1124 pin = getpinproto(ap);
1125 defaultnodesize(pin, &sx, &sy);
1126 lx = x - sx / 2; hx = lx + sx;
1127 ly = y - sy / 2; hy = ly + sy;
1128 ni = newnodeinst(pin, lx, hx, ly, hy, 0, 0, cell);
1129 if (ni == NONODEINST)
1130 {
1131 io_definerror(_("Unable to create net pin"));
1132 return(TRUE);
1133 }
1134 endobjectchange((INTBIG)ni, VNODEINST);
1135 *theni = ni;
1136 *thepp = ni->proto->firstportproto;
1137 return(FALSE);
1138 }
1139
1140 /*************** UNITS ***************/
1141
io_defreadunits(FILE * f)1142 BOOLEAN io_defreadunits(FILE *f)
1143 {
1144 REGISTER CHAR *key;
1145
1146 /* get the "DISTANCE" keyword */
1147 key = io_defmustgetkeyword(f, x_("UNITS"));
1148 if (key == 0) return(TRUE);
1149 if (namesame(key, x_("DISTANCE")) != 0)
1150 {
1151 io_definerror(_("Expected 'DISTANCE' after 'UNITS'"));
1152 return(TRUE);
1153 }
1154
1155 /* get the "MICRONS" keyword */
1156 key = io_defmustgetkeyword(f, x_("UNITS"));
1157 if (key == 0) return(TRUE);
1158 if (namesame(key, x_("MICRONS")) != 0)
1159 {
1160 io_definerror(_("Expected 'MICRONS' after 'UNITS'"));
1161 return(TRUE);
1162 }
1163
1164 /* get the amount */
1165 key = io_defmustgetkeyword(f, x_("UNITS"));
1166 if (key == 0) return(TRUE);
1167 io_defunits = eatoi(key);
1168
1169 /* ignore the keyword */
1170 if (io_defignoretosemicolon(f, _("UNITS"))) return(TRUE);
1171 return(FALSE);
1172 }
1173
1174 /*************** PROPERTY DEFINITIONS ***************/
1175
io_defreadpropertydefinitions(FILE * f)1176 BOOLEAN io_defreadpropertydefinitions(FILE *f)
1177 {
1178 REGISTER CHAR *key;
1179 CHAR curkey[200];
1180
1181 for(;;)
1182 {
1183 /* get the next keyword */
1184 key = io_defmustgetkeyword(f, x_("PROPERTYDEFINITION"));
1185 if (key == 0) return(TRUE);
1186 if (namesame(key, x_("END")) == 0)
1187 {
1188 key = io_defgetkeyword(f);
1189 break;
1190 }
1191
1192 /* ignore the keyword */
1193 estrcpy(curkey, key);
1194 if (io_defignoretosemicolon(f, curkey)) return(TRUE);
1195 }
1196 return(FALSE);
1197 }
1198
1199 /*************** DATABASE SUPPORT ***************/
1200
io_defgetnodeproto(CHAR * name,LIBRARY * curlib)1201 NODEPROTO *io_defgetnodeproto(CHAR *name, LIBRARY *curlib)
1202 {
1203 REGISTER NODEPROTO *np, *newnp;
1204 REGISTER LIBRARY *lib;
1205
1206 /* first see if this cell is in the current library */
1207 for(np = curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1208 if (namesame(name, np->protoname) == 0) return(np);
1209
1210 /* now look in other libraries */
1211 for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
1212 {
1213 if (lib == curlib) continue;
1214 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1215 if (namesame(name, np->protoname) == 0) break;
1216 if (np != NONODEPROTO)
1217 {
1218 /* must copy the cell */
1219 newnp = us_copyrecursively(np, np->protoname, curlib, np->cellview,
1220 FALSE, FALSE, x_(""), FALSE, FALSE, FALSE);
1221 return(newnp);
1222 }
1223 }
1224 return(NONODEPROTO);
1225 }
1226
1227 /* returns nonzero on error */
io_defgetlayernodes(CHAR * name,NODEPROTO ** pin,NODEPROTO ** pure,ARCPROTO ** arc)1228 void io_defgetlayernodes(CHAR *name, NODEPROTO **pin, NODEPROTO **pure, ARCPROTO **arc)
1229 {
1230 REGISTER INTBIG laynum, i, j, lfunc;
1231 REGISTER INTBIG afunc, afunc1, afunc2, ap1found, ap2found, vialayer;
1232 REGISTER ARCPROTO *ap, *ap1, *ap2;
1233 REGISTER NODEPROTO *np;
1234 REGISTER NODEINST *ni;
1235 NODEINST node;
1236 REGISTER PORTPROTO *pp;
1237 static POLYGON *poly = NOPOLYGON;
1238
1239 /* initialize */
1240 (void)needstaticpolygon(&poly, 4, io_tool->cluster);
1241 *pin = NONODEPROTO;
1242 *pure = NONODEPROTO;
1243 *arc = NOARCPROTO;
1244
1245 /* handle via layers */
1246 j = 0;
1247 if (namesamen(name, x_("VIA"), 3) == 0) j = 3; else
1248 if (namesamen(name, x_("V"), 1) == 0) j = 1;
1249 if (j != 0)
1250 {
1251 /* find the two layer functions */
1252 if (name[j] == 0)
1253 {
1254 afunc1 = APMETAL1;
1255 afunc2 = APMETAL2;
1256 } else if (name[j+1] == 0)
1257 {
1258 afunc1 = name[j] - '1' + APMETAL1;
1259 afunc2 = afunc1 + 1;
1260 } else
1261 {
1262 afunc1 = name[j] - '1' + APMETAL1;
1263 afunc2 = name[j+1] - '1' + APMETAL1;
1264 }
1265
1266 /* find the arcprotos that embody these layers */
1267 for(ap1 = el_curtech->firstarcproto; ap1 != NOARCPROTO; ap1 = ap1->nextarcproto)
1268 if ((INTBIG)((ap1->userbits&AFUNCTION)>>AFUNCTIONSH) == afunc1) break;
1269 for(ap2 = el_curtech->firstarcproto; ap2 != NOARCPROTO; ap2 = ap2->nextarcproto)
1270 if ((INTBIG)((ap2->userbits&AFUNCTION)>>AFUNCTIONSH) == afunc2) break;
1271 if (ap1 == NOARCPROTO || ap2 == NOARCPROTO) return;
1272
1273 /* find the via that connects these two arcs */
1274 for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1275 {
1276 /* must have just one port */
1277 pp = np->firstportproto;
1278 if (pp == NOPORTPROTO) continue;
1279 if (pp->nextportproto != NOPORTPROTO) continue;
1280
1281 /* port must connect to both arcs */
1282 ap1found = ap2found = 0;
1283 for(i=0; pp->connects[i] != NOARCPROTO; i++)
1284 {
1285 if (pp->connects[i] == ap1) ap1found++;
1286 if (pp->connects[i] == ap2) ap2found++;
1287 }
1288 if (ap1found != 0 && ap2found != 0) break;
1289 }
1290 *pin = np;
1291
1292 /* find the pure layer node that is the via contact */
1293 if (np != NONODEPROTO)
1294 {
1295 /* find the layer on this node that is of type "contact" */
1296 ni = &node; initdummynode(ni);
1297 ni->proto = np;
1298 ni->lowx = 0; ni->highx = 1000;
1299 ni->lowy = 0; ni->highy = 1000;
1300 j = nodepolys(ni, 0, NOWINDOWPART);
1301 for(i=0; i<j; i++)
1302 {
1303 shapenodepoly(ni, i, poly);
1304 vialayer = poly->layer;
1305 lfunc = layerfunction(el_curtech, vialayer) & LFTYPE;
1306 if (layeriscontact(lfunc)) break;
1307 }
1308 if (i >= j) return;
1309
1310 /* now find the pure layer node that has this layer */
1311 np = getpurelayernode(el_curtech, vialayer, 0);
1312 *pure = np;
1313 }
1314 return;
1315 }
1316
1317 /* handle metal layers */
1318 j = 0;
1319 if (namesamen(name, x_("METAL"), 5) == 0) j = 5; else
1320 if (namesamen(name, x_("MET"), 3) == 0) j = 3; else
1321 if (namesamen(name, x_("M"), 1) == 0) j = 1;
1322 if (j != 0)
1323 {
1324 laynum = eatoi(&name[j]);
1325 afunc = APUNKNOWN;
1326 lfunc = LFUNKNOWN;
1327 switch (laynum)
1328 {
1329 case 1: afunc = APMETAL1; lfunc = LFMETAL1; break;
1330 case 2: afunc = APMETAL2; lfunc = LFMETAL2; break;
1331 case 3: afunc = APMETAL3; lfunc = LFMETAL3; break;
1332 case 4: afunc = APMETAL4; lfunc = LFMETAL4; break;
1333 case 5: afunc = APMETAL5; lfunc = LFMETAL5; break;
1334 case 6: afunc = APMETAL6; lfunc = LFMETAL6; break;
1335 case 7: afunc = APMETAL7; lfunc = LFMETAL7; break;
1336 case 8: afunc = APMETAL8; lfunc = LFMETAL8; break;
1337 case 9: afunc = APMETAL9; lfunc = LFMETAL9; break;
1338 case 10: afunc = APMETAL10; lfunc = LFMETAL10; break;
1339 case 11: afunc = APMETAL11; lfunc = LFMETAL11; break;
1340 case 12: afunc = APMETAL12; lfunc = LFMETAL12; break;
1341 }
1342 if (afunc == APUNKNOWN || lfunc == LFUNKNOWN) return;
1343
1344 /* find the arc with this function */
1345 for(ap = el_curtech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
1346 if ((INTBIG)((ap->userbits&AFUNCTION)>>AFUNCTIONSH) == afunc) break;
1347 if (ap != NOARCPROTO)
1348 {
1349 *arc = ap;
1350 *pin = getpinproto(ap);
1351 }
1352
1353 /* find the pure layer node with this function */
1354 np = getpurelayernode(el_curtech, -1, lfunc);
1355 *pure = np;
1356 return;
1357 }
1358 }
1359
1360 /*************** FILE SUPPORT ***************/
1361
io_defreadcoordinate(FILE * f,INTBIG * x,INTBIG * y)1362 BOOLEAN io_defreadcoordinate(FILE *f, INTBIG *x, INTBIG *y)
1363 {
1364 CHAR *key;
1365 float v;
1366
1367 /* get "(" */
1368 key = io_defmustgetkeyword(f, _("coordinate"));
1369 if (key == 0) return(TRUE);
1370 if (estrcmp(key, x_("(")) != 0)
1371 {
1372 io_definerror(_("Expected '(' in coordinate"));
1373 return(TRUE);
1374 }
1375
1376 /* get X */
1377 key = io_defmustgetkeyword(f, _("coordinate"));
1378 if (key == 0) return(TRUE);
1379 v = (float)eatof(key) / (float)io_defunits;
1380 *x = scalefromdispunit(v, DISPUNITMIC);
1381
1382 /* get Y */
1383 key = io_defmustgetkeyword(f, _("coordinate"));
1384 if (key == 0) return(TRUE);
1385 v = (float)eatof(key) / (float)io_defunits;
1386 *y = scalefromdispunit(v, DISPUNITMIC);
1387
1388 /* get ")" */
1389 key = io_defmustgetkeyword(f, _("coordinate"));
1390 if (key == 0) return(TRUE);
1391 if (estrcmp(key, x_(")")) != 0)
1392 {
1393 io_definerror(_("Expected ')' in coordinate"));
1394 return(TRUE);
1395 }
1396 return(FALSE);
1397 }
1398
io_defreadorientation(FILE * f,INTSML * rot,INTSML * trans)1399 BOOLEAN io_defreadorientation(FILE *f, INTSML *rot, INTSML *trans)
1400 {
1401 REGISTER CHAR *key;
1402
1403 key = io_defmustgetkeyword(f, _("orientation"));
1404 if (key == 0) return(TRUE);
1405 if (namesame(key, x_("N")) == 0) { *rot = 0; *trans = 0; } else
1406 if (namesame(key, x_("S")) == 0) { *rot = 1800; *trans = 0; } else
1407 if (namesame(key, x_("E")) == 0) { *rot = 2700; *trans = 0; } else
1408 if (namesame(key, x_("W")) == 0) { *rot = 900; *trans = 0; } else
1409 if (namesame(key, x_("FN")) == 0) { *rot = 900; *trans = 1; } else
1410 if (namesame(key, x_("FS")) == 0) { *rot = 2700; *trans = 1; } else
1411 if (namesame(key, x_("FE")) == 0) { *rot = 1800; *trans = 1; } else
1412 if (namesame(key, x_("FW")) == 0) { *rot = 0; *trans = 1; } else
1413 {
1414 io_definerror(_("Unknown orientation (%s)"), key);
1415 return(TRUE);
1416 }
1417 return(FALSE);
1418 }
1419
io_defignoretosemicolon(FILE * f,CHAR * command)1420 BOOLEAN io_defignoretosemicolon(FILE *f, CHAR *command)
1421 {
1422 REGISTER CHAR *key;
1423
1424 /* ignore up to the next semicolon */
1425 for(;;)
1426 {
1427 key = io_defmustgetkeyword(f, command);
1428 if (key == 0) return(TRUE);
1429 if (estrcmp(key, x_(";")) == 0) break;
1430 }
1431 return(FALSE);
1432 }
1433
io_defignoreblock(FILE * f,CHAR * command)1434 BOOLEAN io_defignoreblock(FILE *f, CHAR *command)
1435 {
1436 REGISTER CHAR *key;
1437
1438 for(;;)
1439 {
1440 /* get the next keyword */
1441 key = io_defmustgetkeyword(f, command);
1442 if (key == 0) return(TRUE);
1443
1444 if (namesame(key, x_("END")) == 0)
1445 {
1446 (void)io_defgetkeyword(f);
1447 break;
1448 }
1449 }
1450 return(FALSE);
1451 }
1452
io_defmustgetkeyword(FILE * f,CHAR * where)1453 CHAR *io_defmustgetkeyword(FILE *f, CHAR *where)
1454 {
1455 CHAR *key;
1456
1457 key = io_defgetkeyword(f);
1458 if (key == 0) io_definerror(_("EOF parsing %s"), where);
1459 return(key);
1460 }
1461
io_defgetkeyword(FILE * f)1462 CHAR *io_defgetkeyword(FILE *f)
1463 {
1464 REGISTER CHAR *ret;
1465 REGISTER INTBIG filepos;
1466
1467 /* keep reading from file until something is found on a line */
1468 while (io_defline[io_deflinepos] == 0)
1469 {
1470 /* read a line from the file, exit at EOF */
1471 if (xfgets(io_defline, MAXLINE, f)) return(0);
1472 io_deflineno++;
1473 if ((io_deflineno%50) == 0)
1474 {
1475 filepos = xtell(f);
1476 DiaSetProgress(io_defprogressdialog, filepos, io_deffilesize);
1477 }
1478
1479 /* look for the first text on the line */
1480 io_deflinepos = 0;
1481 while (io_defline[io_deflinepos] == ' ' || io_defline[io_deflinepos] == '\t')
1482 io_deflinepos++;
1483 }
1484
1485 /* remember where the keyword begins */
1486 ret = &io_defline[io_deflinepos];
1487
1488 /* scan to the end of the keyword */
1489 while (io_defline[io_deflinepos] != 0 && io_defline[io_deflinepos] != ' ' &&
1490 io_defline[io_deflinepos] != '\t') io_deflinepos++;
1491 if (io_defline[io_deflinepos] != 0) io_defline[io_deflinepos++] = 0;
1492
1493 /* advance to the start of the next keyword */
1494 while (io_defline[io_deflinepos] == ' ' || io_defline[io_deflinepos] == '\t')
1495 io_deflinepos++;
1496 return(ret);
1497 }
1498
io_definerror(CHAR * command,...)1499 void io_definerror(CHAR *command, ...)
1500 {
1501 va_list ap;
1502 CHAR line[500];
1503
1504 var_start(ap, command);
1505 evsnprintf(line, 500, command, ap);
1506 va_end(ap);
1507 ttyputerr(_("File %s, line %ld: %s"), io_deffilename, io_deflineno, line);
1508 }
1509
1510 /* DEF Options */
1511 static DIALOGITEM io_defoptionsdialogitems[] =
1512 {
1513 /* 1 */ {0, {64,156,88,228}, BUTTON, N_("OK")},
1514 /* 2 */ {0, {64,16,88,88}, BUTTON, N_("Cancel")},
1515 /* 3 */ {0, {32,8,48,230}, CHECK, N_("Place logical interconnect")},
1516 /* 4 */ {0, {8,8,24,230}, CHECK, N_("Place physical interconnect")}
1517 };
1518 static DIALOG io_defoptionsdialog = {{50,75,147,314}, N_("DEF Options"), 0, 4, io_defoptionsdialogitems, 0, 0};
1519
1520 /* special items for the "DEF Options" dialog: */
1521 #define DDFO_PLACELOGICAL 3 /* Place logical interconnect (check) */
1522 #define DDFO_PLACEPHYSICAL 4 /* Place physical interconnect (check) */
1523
io_defoptionsdlog(void)1524 void io_defoptionsdlog(void)
1525 {
1526 REGISTER INTBIG itemHit, *curstate, i;
1527 INTBIG newstate[NUMIOSTATEBITWORDS];
1528 REGISTER void *dia;
1529
1530 dia = DiaInitDialog(&io_defoptionsdialog);
1531 if (dia == 0) return;
1532 curstate = io_getstatebits();
1533 for(i=0; i<NUMIOSTATEBITWORDS; i++) newstate[i] = curstate[i];
1534 if ((curstate[0]&DEFNOLOGICAL) == 0) DiaSetControl(dia, DDFO_PLACELOGICAL, 1);
1535 if ((curstate[0]&DEFNOPHYSICAL) == 0) DiaSetControl(dia, DDFO_PLACEPHYSICAL, 1);
1536
1537 /* loop until done */
1538 for(;;)
1539 {
1540 itemHit = DiaNextHit(dia);
1541 if (itemHit == OK || itemHit == CANCEL) break;
1542 if (itemHit == DDFO_PLACELOGICAL || itemHit == DDFO_PLACEPHYSICAL)
1543 {
1544 DiaSetControl(dia, itemHit, 1 - DiaGetControl(dia, itemHit));
1545 continue;
1546 }
1547 }
1548
1549 if (itemHit != CANCEL)
1550 {
1551 if (DiaGetControl(dia, DDFO_PLACELOGICAL) == 0) newstate[0] |= DEFNOLOGICAL; else
1552 newstate[0] &= ~DEFNOLOGICAL;
1553 if (DiaGetControl(dia, DDFO_PLACEPHYSICAL) == 0) newstate[0] |= DEFNOPHYSICAL; else
1554 newstate[0] &= ~DEFNOPHYSICAL;
1555 for(i=0; i<NUMIOSTATEBITWORDS; i++) if (curstate[i] != newstate[i]) break;
1556 if (i < NUMIOSTATEBITWORDS) io_setstatebits(newstate);
1557 }
1558 DiaDoneDialog(dia);
1559 }
1560