1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: iocifin.c
6 * Input/output tool: CIF input
7 * Written by: Robert Winstanley, University of Calgary
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 #include "config.h"
33 #include "global.h"
34 #include "database.h"
35 #include "eio.h"
36 #include "usr.h"
37 #include "iocifpars.h"
38 #include "edialogs.h"
39 #include <math.h>
40
41 #define RTOD (45. / atan(1.))
42
43 /**************************** CIF CELLS ****************************/
44
45 #define NOCIFCELL ((CIFCELL *) -1)
46
47 typedef struct Icifcell
48 {
49 INTBIG cindex; /* cell index given in the define statement */
50 INTBIG l, r, t, b; /* bounding box of cell */
51 NODEPROTO *addr; /* the address of the cif cell */
52 } CIFCELL;
53
54 static CIFCELL **io_cifcells = (CIFCELL **)NOSTRING; /* hash table of 'cifcells' */
55 static INTBIG io_cifcells_size = 0; /* allocated size of io_cifcells */
56 static INTBIG io_cifcells_num = 0; /* number of used entries in io_cifcells */
57 static CIFCELL *io_curcell; /* the current cell */
58 static BOOLEAN io_cifroundwires; /* nonzero if wires should be rounded */
59
60 /**************************** CIF LISTS ****************************/
61
62 #define NOCIFLIST ((CIFLIST *) -1)
63
64 /* values for CIFLIST->identity */
65 #define C_START 0
66 #define C_END 1
67 #define C_WIRE 2
68 #define C_FLASH 3
69 #define C_BOX 4
70 #define C_POLY 5
71 #define C_COMMAND 6
72 #define C_GNAME 7
73 #define C_LABEL 8
74 #define C_CALL 9
75
76 typedef struct Iciflist
77 {
78 INTBIG identity; /* specifies the nature of the entry */
79 CHAR *member; /* will point to member's structure */
80 struct Iciflist *next; /* next entry in list */
81 } CIFLIST;
82
83 static CIFLIST *io_ciflist = NOCIFLIST; /* head of the list */
84 static CIFLIST *io_curlist; /* current location in list */
85
86 /**************************** MEMBER STRUCTURES ****************************/
87
88 typedef struct Icfstart
89 {
90 INTBIG cindex; /* cell index */
91 CHAR *name; /* cell name */
92 INTBIG l, r, t, b; /* bounding box of cell */
93 } CFSTART;
94
95 typedef struct Icbox
96 {
97 INTBIG lay; /* the corresponding layer number */
98 INTBIG length, width; /* dimensions of box */
99 INTBIG cenx, ceny; /* center point of box */
100 INTBIG xrot, yrot; /* box direction */
101 } CBOX;
102
103 typedef struct Icpolygon
104 {
105 INTBIG lay; /* the corresponding layer number */
106 INTBIG *x, *y; /* list of points */
107 INTBIG lim; /* number of points in list */
108 } CPOLY;
109
110 typedef struct Icgeoname
111 {
112 INTBIG lay; /* the corresponding layer number */
113 INTBIG x, y; /* location of name */
114 CHAR *geoname; /* the geo name */
115 } CGNAME;
116
117 typedef struct Iclabel
118 {
119 INTBIG x, y; /* location of label */
120 CHAR *label; /* the label */
121 } CLABEL;
122
123 typedef struct Iccall
124 {
125 INTBIG cindex; /* index of cell called */
126 CHAR *name; /* name of cell called */
127 struct Ictrans *list; /* list of transformations */
128 } CCALL;
129
130 /* values for the transformation type */
131 #define MIRX 1 /* mirror in x */
132 #define MIRY 2 /* mirror in y */
133 #define TRANS 3 /* translation */
134 #define ROT 4 /* rotation */
135
136 #define NOCTRANS ((CTRANS *) -1)
137
138 typedef struct Ictrans
139 {
140 INTBIG type; /* type of transformation */
141 INTBIG x, y; /* not required for the mirror types */
142 struct Ictrans *next; /* next element in list */
143 } CTRANS;
144
145 static CTRANS *io_curctrans; /* current transformation description */
146
147 /**************************** MISCELLANEOUS ****************************/
148
149 static CHAR *io_curnodeprotoname; /* name of the current cell */
150 static NODEPROTO *io_incell; /* address of cell being defined */
151 static NODEPROTO **io_cifnodes = 0; /* nodeprotos associated with CIF names */
152 static INTBIG io_varlength; /* the length of all attribute arrays */
153 static VARIABLE *io_cifnames; /* cif names for the current technology */
154 static INTBIG io_cifnotfoundcount; /* number of unknown layer names */
155 static CHAR **io_cifnotfoundlist; /* unknown layer name list */
156 static INTBIG io_cifnotfoundlimit = 0; /* size of unknown layer name list */
157
158 /* prototypes for local routines */
159 static BOOLEAN io_interpret(FILE*);
160 static BOOLEAN io_listtonodes(LIBRARY*);
161 static NODEPROTO *io_nodes_start(LIBRARY*, void*);
162 static BOOLEAN io_nodes_box(void);
163 static BOOLEAN io_nodes_poly(void);
164 static BOOLEAN io_nodes_call(void);
165 static void io_rotatelayer(INTBIG*, INTBIG*, INTBIG);
166 static BOOLEAN io_initfind(void);
167 static NODEPROTO *io_findprotonode(INTBIG);
168 static CIFCELL *io_findcifcell(INTBIG);
169 static void io_insertcifcell(CIFCELL *cifcell);
170 static CIFCELL *io_newcifcell(INTBIG);
171 static CIFLIST *io_newciflist(INTBIG);
172 static void io_placeciflist(INTBIG);
173 static CTRANS *io_newctrans(void);
174 static void io_ciffreeciflist(void);
175 static void io_ciffreecifcells(void);
176
177 /*
178 * Routine to free all memory associated with this module.
179 */
io_freecifinmemory(void)180 void io_freecifinmemory(void)
181 {
182 io_ciffreeciflist();
183 io_ciffreecifcells();
184 if (io_cifnodes != 0) efree((CHAR *)io_cifnodes);
185 }
186
io_readciflibrary(LIBRARY * lib)187 BOOLEAN io_readciflibrary(LIBRARY *lib)
188 {
189 REGISTER FILE *f;
190 CHAR *filename;
191 REGISTER INTBIG i, *curstate;
192
193 curstate = io_getstatebits();
194 if ((curstate[0]&CIFINSQUARE) != 0) io_cifroundwires = FALSE;
195 else io_cifroundwires = TRUE;
196
197 /* initialize all lists and the searching routines */
198 io_ciffreecifcells();
199 io_ciffreeciflist();
200
201 if (io_initfind()) return(TRUE);
202
203 /* get the cif file */
204 f = xopen(lib->libfile, io_filetypecif, x_(""), &filename);
205 if (f == NULL)
206 {
207 ttyputerr(_("File %s not found"), lib->libfile);
208 return(TRUE);
209 }
210
211 if (setjmp(io_filerror))
212 {
213 ttyputerr(_("Error reading CIF"));
214 return(TRUE);
215 }
216
217 /* initialize list of not-found layers */
218 io_cifnotfoundcount = 0;
219
220 /* parse the cif and create a listing */
221 if (io_interpret(f)) return(TRUE);
222
223 /* instantiate the cif as nodes */
224 if (io_listtonodes(lib)) return(TRUE);
225
226 /* clean up */
227 (void)io_doneinterpreter();
228 for(i=0; i<io_cifnotfoundcount; i++) efree((CHAR *)io_cifnotfoundlist[i]);
229
230 return(FALSE);
231 }
232
io_interpret(FILE * file)233 BOOLEAN io_interpret(FILE *file)
234 {
235 INTBIG comcount, left, right, bottom, top;
236
237 if (io_initparser())
238 {
239 ttyputerr(_("Error initializing parser"));
240 return(TRUE);
241 }
242 if (io_initinterpreter())
243 {
244 ttyputerr(_("Error initializing interpreter"));
245 return(TRUE);
246 }
247 if (io_infromfile(file)) return(TRUE);
248 comcount = io_parsefile(); /* read in the cif */
249 (void)io_doneparser();
250 if (stopping(STOPREASONCIF)) return(TRUE);
251 ttyputverbose(M_("Total CIF commands: %ld"), comcount);
252
253 if (io_fatalerrors() > 0) return(TRUE);
254
255 io_iboundbox(&left, &right, &bottom, &top);
256
257 /* construct a list: first step in the conversion */
258 (void)io_createlist();
259 return(FALSE);
260 }
261
262 /**************************** NODE CONVERSION ****************************/
263
io_listtonodes(LIBRARY * lib)264 BOOLEAN io_listtonodes(LIBRARY *lib)
265 {
266 REGISTER void *dia;
267
268 if (io_verbose < 0)
269 {
270 dia = DiaInitProgress(0, 0);
271 if (dia == 0) return(TRUE);
272 DiaSetProgress(dia, 999, 1000);
273 }
274 io_incell = NONODEPROTO;
275 for(io_curlist = io_ciflist; io_curlist != NOCIFLIST; io_curlist = io_curlist->next)
276 {
277 if (stopping(STOPREASONCIF))
278 {
279 if (io_verbose < 0) DiaDoneDialog(dia);
280 return(TRUE);
281 }
282 if (io_incell != NONODEPROTO || io_curlist->identity == C_START)
283 switch (io_curlist->identity)
284 {
285 case C_START:
286 io_incell = io_nodes_start(lib, dia);
287 if (io_incell == NONODEPROTO)
288 {
289 if (io_verbose < 0) DiaDoneProgress(dia);
290 return(TRUE);
291 }
292 break;
293 case C_END:
294 /* make cell size right */
295 db_boundcell(io_incell, &io_incell->lowx, &io_incell->highx,
296 &io_incell->lowy, &io_incell->highy);
297 lib->curnodeproto = io_incell;
298 io_incell = NONODEPROTO;
299 break;
300 case C_BOX:
301 if (io_nodes_box())
302 {
303 if (io_verbose < 0) DiaDoneProgress(dia);
304 return(TRUE);
305 }
306 break;
307 case C_POLY:
308 if (io_nodes_poly())
309 {
310 if (io_verbose < 0) DiaDoneProgress(dia);
311 return(TRUE);
312 }
313 break;
314 case C_CALL:
315 if (io_nodes_call())
316 {
317 if (io_verbose < 0) DiaDoneProgress(dia);
318 return(TRUE);
319 }
320 break;
321 }
322 }
323 if (io_verbose < 0) DiaDoneProgress(dia);
324 return(FALSE);
325 }
326
io_nodes_start(LIBRARY * lib,void * dia)327 NODEPROTO *io_nodes_start(LIBRARY *lib, void *dia)
328 {
329 CIFCELL *cifcell;
330 CFSTART *cs;
331 CHAR *opt;
332 REGISTER void *infstr;
333
334 cs = (CFSTART *)io_curlist->member;
335 if ((cifcell = io_newcifcell(cs->cindex)) == NOCIFCELL) return(NONODEPROTO);
336 cifcell->l = cs->l; cifcell->r = cs->r;
337 cifcell->b = cs->b; cifcell->t = cs->t;
338 io_curnodeprotoname = cs->name;
339
340 /* remove illegal characters */
341 for(opt = io_curnodeprotoname; *opt != 0; opt++)
342 if (*opt <= ' ' || *opt == ':' || *opt == ';' || *opt >= 0177)
343 *opt = 'X';
344 cifcell->addr = us_newnodeproto(io_curnodeprotoname, lib);
345 if (cifcell->addr == NONODEPROTO)
346 {
347 ttyputerr(_("Cannot create the cell %s"), io_curnodeprotoname);
348 return(NONODEPROTO);
349 }
350
351 if (io_verbose < 0)
352 {
353 infstr = initinfstr();
354 formatinfstr(infstr, _("Reading %s"), io_curnodeprotoname);
355 DiaSetTextProgress(dia, returninfstr(infstr));
356 } else if (io_verbose > 0) ttyputmsg(_("Reading %s"), io_curnodeprotoname);
357 return(cifcell->addr);
358 }
359
io_nodes_box(void)360 BOOLEAN io_nodes_box(void)
361 {
362 NODEPROTO *node;
363 CBOX *cb;
364 CHAR *layname;
365 INTBIG l, w, lx, ly, hx, hy, r;
366
367 cb = (CBOX *)io_curlist->member;
368 node = io_findprotonode(cb->lay);
369 if (node == NONODEPROTO)
370 {
371 layname = layername(el_curtech, cb->lay);
372 ttyputerr(_("Cannot find primitive to use for layer '%s' (number %ld)"),
373 layname, cb->lay);
374 return(TRUE);
375 }
376 l = cb->length; w = cb->width;
377 lx = cb->cenx - l/2; ly = cb->ceny - w/2;
378 hx = cb->cenx + l/2; hy = cb->ceny + w/2;
379 r = figureangle(0, 0, (INTBIG)cb->xrot, (INTBIG)cb->yrot);
380 if (newnodeinst(node, scalefromdispunit((float)lx, DISPUNITCMIC),
381 scalefromdispunit((float)hx, DISPUNITCMIC), scalefromdispunit((float)ly, DISPUNITCMIC),
382 scalefromdispunit((float)hy, DISPUNITCMIC), 0, r, io_curcell->addr) == NONODEINST)
383 {
384 layname = layername(el_curtech, cb->lay);
385 ttyputerr(_("Problems creating a box on layer %s in cell %s"), layname,
386 describenodeproto(io_curcell->addr));
387 return(TRUE);
388 }
389 return(FALSE);
390 }
391
io_nodes_poly(void)392 BOOLEAN io_nodes_poly(void)
393 {
394 REGISTER INTBIG lx, ly, hx, hy, i, *trace, cx, cy, *pt;
395 REGISTER NODEPROTO *np;
396 REGISTER NODEINST *newni;
397 REGISTER CPOLY *cp;
398
399 cp = (CPOLY *)io_curlist->member;
400 if (cp->lim == 0) return(FALSE);
401 np = io_findprotonode(cp->lay);
402 lx = hx = cp->x[0]; ly = hy = cp->y[0];
403 for(i=1; i<cp->lim; i++)
404 {
405 if (cp->x[i] < lx) lx = cp->x[i];
406 if (cp->x[i] > hx) hx = cp->x[i];
407 if (cp->y[i] < ly) ly = cp->y[i];
408 if (cp->y[i] > hy) hy = cp->y[i];
409 }
410 newni = newnodeinst(np, scalefromdispunit((float)lx, DISPUNITCMIC),
411 scalefromdispunit((float)hx, DISPUNITCMIC), scalefromdispunit((float)ly, DISPUNITCMIC),
412 scalefromdispunit((float)hy, DISPUNITCMIC), 0, 0, io_curcell->addr);
413 if (newni == NONODEINST)
414 {
415 ttyputerr(_("Problems creating a polygon on layer %ld in cell %s"), cp->lay,
416 describenodeproto(io_curcell->addr));
417 return(TRUE);
418 }
419
420 /* store the trace information */
421 pt = trace = emalloc((cp->lim*2*SIZEOFINTBIG), io_tool->cluster);
422 if (trace == 0) return(TRUE);
423 cx = (hx + lx) / 2; cy = (hy + ly) / 2;
424 for(i=0; i<cp->lim; i++)
425 {
426 *pt++ = scalefromdispunit((float)(cp->x[i] - cx), DISPUNITCMIC);
427 *pt++ = scalefromdispunit((float)(cp->y[i] - cy), DISPUNITCMIC);
428 }
429
430 /* store the trace information */
431 (void)setvalkey((INTBIG)newni, VNODEINST, el_trace_key, (INTBIG)trace,
432 VINTEGER|VISARRAY|((cp->lim*2)<<VLENGTHSH));
433
434 /* free the polygon memory */
435 efree((CHAR *)trace);
436 efree((CHAR *)cp->x); efree((CHAR *)cp->y);
437 cp->lim = 0;
438 return(FALSE);
439 }
440
io_nodes_call(void)441 BOOLEAN io_nodes_call(void)
442 {
443 CIFCELL *cell;
444 CCALL *cc;
445 CTRANS *ctrans;
446 INTBIG l, r, t, b, rot, trans, hlen, hwid, cenx, ceny, temp;
447 INTBIG deg;
448
449 cc = (CCALL *)io_curlist->member;
450 if ((cell = io_findcifcell(cc->cindex)) == NOCIFCELL)
451 {
452 ttyputerr(_("Referencing an undefined cell"));
453 return(TRUE);
454 }
455 rot = trans = 0;
456 l = cell->l; r = cell->r; b = cell->b; t = cell->t;
457 for(ctrans = cc->list; ctrans != NOCTRANS; ctrans = ctrans->next)
458 switch (ctrans->type)
459 {
460 case MIRX:
461 temp = l; l = -r; r = -temp;
462 rot = (trans) ? ((rot+2700) % 3600) : ((rot+900) % 3600);
463 trans = 1 - trans;
464 break;
465 case MIRY:
466 temp = t; t = -b; b = -temp;
467 rot = (trans) ? ((rot+900) % 3600) : ((rot+2700) % 3600);
468 trans = 1 - trans;
469 break;
470 case TRANS:
471 l += ctrans->x; r += ctrans->x;
472 b += ctrans->y; t += ctrans->y;
473 break;
474 case ROT:
475 deg = figureangle(0L, 0L, ctrans->x, ctrans->y);
476 if (deg != 0)
477 {
478 hlen = abs(((l-r)/2)); hwid = abs(((b-t)/2));
479 cenx = (l+r)/2; ceny = (b+t)/2;
480 io_rotatelayer(&cenx, &ceny, deg);
481 l = cenx - hlen; r = cenx + hlen;
482 b = ceny - hwid; t = ceny + hwid;
483 rot += ((trans) ? -deg : deg);
484 }
485 }
486 while(rot >= 3600) rot -= 3600;
487 while(rot < 0) rot += 3600;
488 if (newnodeinst((NODEPROTO *)(cell->addr), scalefromdispunit((float)l, DISPUNITCMIC),
489 scalefromdispunit((float)r, DISPUNITCMIC), scalefromdispunit((float)b, DISPUNITCMIC),
490 scalefromdispunit((float)t, DISPUNITCMIC), trans, rot, io_curcell->addr) ==
491 NONODEINST)
492 {
493 ttyputerr(_("Problems creating an instance of cell %s in cell %s"),
494 describenodeproto(cell->addr), describenodeproto(io_curcell->addr));
495 return(TRUE);
496 }
497 return(FALSE);
498 }
499
io_rotatelayer(INTBIG * cenx,INTBIG * ceny,INTBIG deg)500 void io_rotatelayer(INTBIG *cenx, INTBIG *ceny, INTBIG deg)
501 {
502 double vlen, vang, fx, fy, factx, facty, fact;
503 INTBIG temp;
504
505 /* trivial test to prevent atan2 domain errors */
506 if (*cenx == 0 && *ceny == 0) return;
507 switch (deg) /* do the manhattan cases directly (SRP)*/
508 {
509 case 0:
510 case 3600: /* just in case */
511 break;
512 case 900:
513 temp = *cenx; *cenx = -*ceny; *ceny = temp;
514 break;
515 case 1800:
516 *cenx = -*cenx; *ceny = -*ceny;
517 break;
518 case 2700:
519 temp = *cenx; *cenx = *ceny; *ceny = -temp;
520 break;
521 default: /* this old code only permits rotation by integer angles (SRP)*/
522 for(factx=1.; fabs((*cenx/factx)) > 1000; factx *= 10.) ;
523 for(facty=1.; fabs((*ceny/facty)) > 1000; facty *= 10.) ;
524 fact = (factx > facty) ? facty : factx;
525 fx = *cenx / fact; fy = *ceny / fact;
526 vlen = fact * sqrt((double)(fx*fx + fy*fy));
527 vang = (deg + figureangle(0L,0L,*cenx, *ceny)) / 10.0 / RTOD;
528 *cenx = (INTBIG)(vlen * cos(vang));
529 *ceny = (INTBIG)(vlen * sin(vang));
530 break;
531 }
532 }
533
534 /**************************** SEARCHING ROUTINES ****************************/
535
io_initfind(void)536 BOOLEAN io_initfind(void)
537 {
538 REGISTER CHAR *ch, *ch2;
539 REGISTER NODEPROTO *np;
540 REGISTER NODEINST *ni;
541 NODEINST nodeinst;
542 REGISTER INTBIG total, i, j, k;
543 static POLYGON *poly = NOPOLYGON;
544
545 /* get the array of CIF names */
546 io_cifnames = getval((INTBIG)el_curtech, VTECHNOLOGY, VSTRING|VISARRAY, x_("IO_cif_layer_names"));
547 if (io_cifnames == NOVARIABLE)
548 {
549 ttyputerr(_("There are no CIF layer names assigned in the %s technology"),
550 el_curtech->techname);
551 return(TRUE);
552 }
553 io_varlength = getlength(io_cifnames);
554 if (io_varlength < el_curtech->layercount)
555 {
556 ttyputerr(_("Warning: CIF layer information is bad for technology %s. Use 'CIF Options' to fix it"),
557 el_curtech->techname);
558 return(TRUE);
559 }
560
561 /* create the array of nodes associated with the array of CIF names */
562 total = el_curtech->layercount;
563 if (io_cifnodes != 0) efree((CHAR *)io_cifnodes);
564 io_cifnodes = (NODEPROTO **)emalloc((total * (sizeof (NODEPROTO *))), io_tool->cluster);
565 if (io_cifnodes == 0) return(TRUE);
566 for(i=0; i<total; i++) io_cifnodes[i] = NONODEPROTO;
567
568 /* create the polygon */
569 (void)needstaticpolygon(&poly, 4, io_tool->cluster);
570
571 /* run through the node prototypes in this technology */
572 for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
573 {
574 ni = &nodeinst; initdummynode(ni);
575 ni->proto = np;
576 ni->lowx = np->lowx;
577 ni->highx = np->highx;
578 ni->lowy = np->lowy;
579 ni->highy = np->highy;
580 i = nodepolys(ni, 0, NOWINDOWPART);
581 if (i != 1) continue;
582 shapenodepoly(ni, 0, poly);
583 if (poly->layer < 0) continue;
584 ch = ((CHAR **)io_cifnames->addr)[poly->layer];
585 if (*ch != 0) io_cifnodes[poly->layer] = np;
586 }
587
588 /* make sure every CIF string has an equivalent node */
589 for(i=0; i<total; i++)
590 {
591 ch = ((CHAR **)io_cifnames->addr)[i];
592 if (*ch == 0) continue;
593 if (io_cifnodes[i] != NONODEPROTO) continue;
594
595 /* first look for a layer with the same CIF name */
596 for (k=0; k<total; k++)
597 {
598 np = io_cifnodes[k];
599 if (np == NONODEPROTO) continue;
600 ni = &nodeinst; initdummynode(ni);
601 ni->proto = np;
602 ni->lowx = np->lowx;
603 ni->highx = np->highx;
604 ni->lowy = np->lowy;
605 ni->highy = np->highy;
606 (void)nodepolys(ni, 0, NOWINDOWPART);
607 shapenodepoly(ni, 0, poly);
608 ch2 = ((CHAR **)io_cifnames->addr)[poly->layer];
609 if (estrcmp(ch, ch2) != 0) continue;
610 io_cifnodes[i] = np;
611 break;
612 }
613 if (k < total) continue;
614
615 /* search for ANY node with this layer */
616 for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
617 {
618 ni = &nodeinst; initdummynode(ni);
619 ni->proto = np;
620 ni->lowx = np->lowx;
621 ni->highx = np->highx;
622 ni->lowy = np->lowy;
623 ni->highy = np->highy;
624 j = nodepolys(ni, 0, NOWINDOWPART);
625 for(k=0; k<j; k++)
626 {
627 shapenodepoly(ni, 0, poly);
628 if (poly->layer == i) break;
629 }
630 if (k >= j) continue;
631 io_cifnodes[i] = np;
632 break;
633 }
634 }
635
636 return(FALSE);
637 }
638
io_findlayernum(CHAR * name)639 INTBIG io_findlayernum(CHAR *name)
640 {
641 REGISTER INTBIG i, newlimit;
642 REGISTER CHAR **newlist;
643
644 for(i=0; i<io_varlength; i++)
645 if (estrcmp(name, ((CHAR **)io_cifnames->addr)[i]) == 0) return(i);
646
647 /* CIF name not found: see if it is in the list of unfound layers */
648 for(i=0; i<io_cifnotfoundcount; i++)
649 if (estrcmp(name, io_cifnotfoundlist[i]) == 0) return(-1);
650
651 /* add to the list */
652 if (io_cifnotfoundcount >= io_cifnotfoundlimit)
653 {
654 newlimit = io_cifnotfoundlimit * 2;
655 if (newlimit <= 0) newlimit = 10;
656 if (newlimit < io_cifnotfoundcount) newlimit = io_cifnotfoundcount;
657 newlist = (CHAR **)emalloc(newlimit * (sizeof (CHAR *)), io_tool->cluster);
658 if (newlist == 0) return(-1);
659 for(i=0; i<io_cifnotfoundcount; i++)
660 newlist[i] = io_cifnotfoundlist[i];
661 if (io_cifnotfoundlimit > 0) efree((CHAR *)io_cifnotfoundlist);
662 io_cifnotfoundlist = newlist;
663 io_cifnotfoundlimit = newlimit;
664 }
665 (void)allocstring(&io_cifnotfoundlist[io_cifnotfoundcount], name, io_tool->cluster);
666 io_cifnotfoundcount++;
667 ttyputmsg(_("Layer %s not found"), name);
668 return(-1);
669 }
670
io_findprotonode(INTBIG num)671 NODEPROTO *io_findprotonode(INTBIG num)
672 {
673 return(io_cifnodes[num]);
674 }
675
io_findcifcell(INTBIG cindex)676 CIFCELL *io_findcifcell(INTBIG cindex)
677 {
678 CIFCELL *cifcell;
679 REGISTER INTBIG i, j;
680
681 i = cindex % io_cifcells_size;
682 for(j=1; j<=io_cifcells_size; j += 2)
683 {
684 cifcell = io_cifcells[i];
685 if (cifcell == NOCIFCELL) break;
686 if (cindex == cifcell->cindex) return(cifcell);
687 i += j;
688 if (i >= io_cifcells_size) i -= io_cifcells_size;
689 }
690 return(NOCIFCELL);
691 }
692
io_insertcifcell(CIFCELL * cifcell)693 void io_insertcifcell(CIFCELL *cifcell)
694 {
695 REGISTER INTBIG i, j;
696
697 i = cifcell->cindex % io_cifcells_size;
698 for(j=1; j<=io_cifcells_size; j += 2)
699 {
700 if (io_cifcells[i] == NOCIFCELL)
701 {
702 io_cifcells[i] = cifcell;
703 break;
704 }
705 i += j;
706 if (i >= io_cifcells_size) i -= io_cifcells_size;
707 }
708 }
709
io_newcifcell(INTBIG cindex)710 CIFCELL *io_newcifcell(INTBIG cindex)
711 {
712 CIFCELL *newcc, *cc;
713 CIFCELL **old_cifcells;
714 INTBIG old_cifcells_size;
715 INTBIG new_cifcells_size;
716 INTBIG i;
717
718 newcc = (CIFCELL *)emalloc((sizeof (CIFCELL)), io_tool->cluster);
719 if (newcc == (CIFCELL *) 0)
720 {
721 ttyputerr(_("Not enough memory allocated for CIFCELL"));
722 return(NOCIFCELL);
723 }
724 io_cifcells_num++;
725 if (io_cifcells_num >= io_cifcells_size/2)
726 {
727 old_cifcells = io_cifcells;
728 old_cifcells_size = io_cifcells_size;
729 new_cifcells_size = pickprime(io_cifcells_num * 4);
730 io_cifcells = (CIFCELL **)emalloc(new_cifcells_size * (sizeof (CIFCELL *)), io_tool->cluster);
731 if (io_cifcells == (CIFCELL **) 0)
732 {
733 ttyputerr(_("Not enough memory allocated for CIFCELL"));
734 return(NOCIFCELL);
735 }
736 for (i = 0; i < new_cifcells_size; i++) io_cifcells[i] = NOCIFCELL;
737 io_cifcells_size = new_cifcells_size;
738 for (i = 0; i < old_cifcells_size; i++)
739 {
740 cc = old_cifcells[i];
741 if (cc != NOCIFCELL) io_insertcifcell(cc);
742 }
743 if (old_cifcells_size > 0) efree((CHAR *) old_cifcells);
744 }
745 newcc->addr = NONODEPROTO;
746 newcc->cindex = cindex;
747 io_insertcifcell(newcc);
748
749 io_curcell = newcc;
750 return(newcc);
751 }
752
io_ciffreecifcells(void)753 void io_ciffreecifcells(void)
754 {
755 CIFCELL *cc;
756 INTBIG i;
757
758 for (i = 0; i < io_cifcells_size; i++)
759 {
760 cc = io_cifcells[i];
761 if (cc != NOCIFCELL)
762 efree((CHAR *)cc);
763 }
764 if (io_cifcells_size > 0) efree((CHAR *)io_cifcells);
765 io_cifcells_size = 0;
766 io_cifcells_num = 0;
767 io_cifcells = (CIFCELL **)NOSTRING;
768 }
769
io_newciflist(INTBIG id)770 CIFLIST *io_newciflist(INTBIG id)
771 {
772 CIFLIST *newcl;
773 CCALL *cc;
774 CFSTART *cs;
775
776 newcl = (CIFLIST *)emalloc((sizeof (CIFLIST)), io_tool->cluster);
777 if (newcl == (CIFLIST *) 0)
778 {
779 ttyputerr(_("Not enough memory allocated for CIFLIST"));
780 return(NOCIFLIST);
781 }
782 newcl->next = NOCIFLIST;
783 newcl->identity = id;
784 switch (id)
785 {
786 case C_START:
787 cs = (CFSTART *)emalloc((sizeof (CFSTART)), io_tool->cluster);
788 if (cs == 0) return(NOCIFLIST);
789 newcl->member = (CHAR *)cs;
790 cs->name = 0;
791 break;
792 case C_BOX:
793 newcl->member = (CHAR *)emalloc((sizeof (CBOX)), io_tool->cluster);
794 if (newcl->member == (CHAR *) 0) return(NOCIFLIST);
795 break;
796 case C_POLY:
797 newcl->member = (CHAR *)emalloc((sizeof (CPOLY)), io_tool->cluster);
798 if (newcl->member == (CHAR *) 0) return(NOCIFLIST);
799 break;
800 case C_GNAME:
801 newcl->member = (CHAR *)emalloc((sizeof (CGNAME)), io_tool->cluster);
802 if (newcl->member == (CHAR *) 0) return(NOCIFLIST);
803 break;
804 case C_LABEL:
805 newcl->member = (CHAR *)emalloc((sizeof (CLABEL)), io_tool->cluster);
806 if (newcl->member == (CHAR *) 0) return(NOCIFLIST);
807 break;
808 case C_CALL:
809 cc = (CCALL *)emalloc((sizeof (CCALL)), io_tool->cluster);
810 if (cc == 0) return(NOCIFLIST);
811 newcl->member = (CHAR *)cc;
812 cc->name = 0;
813 break;
814 }
815 return(newcl);
816 }
817
io_ciffreeciflist(void)818 void io_ciffreeciflist(void)
819 {
820 REGISTER CIFLIST *cl;
821 REGISTER CCALL *cc;
822 REGISTER CTRANS *cct;
823 REGISTER CFSTART *cs;
824
825 while (io_ciflist != NOCIFLIST)
826 {
827 cl = io_ciflist;
828 io_ciflist = io_ciflist->next;
829 switch (cl->identity)
830 {
831 case C_CALL:
832 cc = (CCALL *)cl->member;
833 while (cc->list != NOCTRANS)
834 {
835 cct = cc->list;
836 cc->list = cc->list->next;
837 efree((CHAR *)cct);
838 }
839 if (cc->name != 0) efree((CHAR *)cc->name);
840 efree((CHAR *)cc);
841 break;
842 case C_START:
843 cs = (CFSTART *)cl->member;
844 if (cs->name != 0) efree((CHAR *)cs->name);
845 efree((CHAR *)cs);
846 break;
847 case C_BOX:
848 case C_POLY:
849 case C_GNAME:
850 case C_LABEL:
851 efree((CHAR *)cl->member);
852 break;
853 }
854 efree((CHAR *)cl);
855 }
856 }
857
io_placeciflist(INTBIG id)858 void io_placeciflist(INTBIG id)
859 {
860 CIFLIST *cl;
861
862 if ((cl = io_newciflist(id)) == NOCIFLIST) return;
863 if (io_ciflist == NOCIFLIST) io_ciflist = io_curlist = cl; else
864 {
865 while(io_curlist->next != NOCIFLIST)
866 io_curlist = io_curlist->next;
867 io_curlist->next = cl;
868 io_curlist = io_curlist->next;
869 }
870 }
871
io_newctrans(void)872 CTRANS *io_newctrans(void)
873 {
874 CTRANS *newct;
875 CCALL *cc;
876
877 newct = (CTRANS *)emalloc((sizeof (CTRANS)), io_tool->cluster);
878 if (newct == (CTRANS *) 0)
879 {
880 ttyputerr(_("Not enough memory allocated for CTRANS"));
881 return(NOCTRANS);
882 }
883 newct->next = NOCTRANS;
884 cc = (CCALL *)io_curlist->member;
885 if (cc->list == NOCTRANS) cc->list = newct; else
886 io_curctrans->next = newct;
887 io_curctrans = newct;
888 return(newct);
889 }
890
io_outputwire(INTBIG lay,INTBIG width,CHAR * wpath)891 void io_outputwire(INTBIG lay, INTBIG width, CHAR *wpath)
892 {
893 /* convert wires to boxes and flashes */
894 INTBIG i;
895 INTBIG llt, lrt, lbm, ltp, lim;
896 point prev, curr;
897
898 lim = io_pathlength((path)wpath);
899 prev = io_removepoint((path)wpath);
900
901 /* do not use roundflashes with zero-width wires */
902 if (width != 0 && io_cifroundwires)
903 {
904 io_bbflash(lay, width, prev, &llt, &lrt, &lbm, <p);
905 io_outputflash(lay, width, prev);
906 }
907 for (i = 1; i < lim; i++)
908 {
909 INTBIG len;
910 INTBIG xr, yr;
911 point center;
912
913 curr = io_removepoint((path)wpath);
914
915 /* do not use roundflashes with zero-width wires */
916 if (width != 0 && io_cifroundwires)
917 {
918 io_bbflash(lay, width, curr, &llt, &lrt, &lbm, <p);
919 io_outputflash(lay, width, curr);
920 }
921 xr = curr.x-prev.x; yr = curr.y-prev.y;
922 len = computedistance(0, 0, xr, yr);
923 if (!io_cifroundwires) len += width;
924 center.x = (curr.x+prev.x)/2; center.y = (curr.y+prev.y)/2;
925 io_bbbox(lay, len, width, center, xr, yr, &llt, &lrt, &lbm, <p);
926 io_outputbox(lay, len, width, center, xr, yr);
927 prev = curr;
928 }
929 }
930
io_outputflash(INTBIG lay,INTBIG diameter,point center)931 void io_outputflash(INTBIG lay, INTBIG diameter, point center)
932 {
933 /* flash approximated by an octagon */
934 INTBIG radius = diameter/2;
935 float fcx = (float)center.x;
936 float fcy = (float)center.y;
937 float offset = (((float)diameter)/2.0f)*0.414213f;
938 CHAR *fpath = io_makepath();
939 point temp;
940
941 temp.x = center.x-radius;
942 temp.y = roundfloat(fcy+offset);
943 if (io_appendpoint((path)fpath, temp)) return;
944 temp.y = roundfloat(fcy-offset);
945 if (io_appendpoint((path)fpath, temp)) return;
946 temp.x = roundfloat(fcx-offset);
947 temp.y = center.y-radius;
948 if (io_appendpoint((path)fpath, temp)) return;
949 temp.x = roundfloat(fcx+offset);
950 if (io_appendpoint((path)fpath, temp)) return;
951 temp.x = center.x+radius;
952 temp.y = roundfloat(fcy-offset);
953 if (io_appendpoint((path)fpath, temp)) return;
954 temp.y = roundfloat(fcy+offset);
955 if (io_appendpoint((path)fpath, temp)) return;
956 temp.x = roundfloat(fcx+offset);
957 temp.y = center.y+radius;
958 if (io_appendpoint((path)fpath, temp)) return;
959 temp.x = roundfloat(fcx-offset);
960 if (io_appendpoint((path)fpath, temp)) return;
961
962 io_outputpolygon(lay, fpath);
963 io_freepath((path)fpath);
964 }
965
io_outputbox(INTBIG lay,INTBIG length,INTBIG width,point center,INTBIG xrotation,INTBIG yrotation)966 void io_outputbox(INTBIG lay, INTBIG length, INTBIG width, point center,
967 INTBIG xrotation, INTBIG yrotation)
968 {
969 CBOX *cb;
970
971 if (length == 0 && width == 0) return; /* ignore null boxes */
972 io_placeciflist(C_BOX);
973 cb = (CBOX *)io_curlist->member;
974 cb->lay = lay;
975 cb->length = length; cb->width = width;
976 cb->cenx = center.x; cb->ceny = center.y;
977 cb->xrot = xrotation; cb->yrot = yrotation;
978 }
979
io_outputpolygon(INTBIG lay,CHAR * ppath)980 void io_outputpolygon(INTBIG lay, CHAR *ppath)
981 {
982 INTBIG i;
983 INTBIG lim;
984 CPOLY *cp;
985 point temp;
986
987 lim = io_pathlength((path)ppath);
988 if (lim < 3) return;
989
990 io_placeciflist(C_POLY);
991 cp = (CPOLY *)io_curlist->member;
992 cp->lay = lay;
993 cp->x = emalloc((lim * SIZEOFINTBIG), io_tool->cluster);
994 if (cp->x == 0)
995 {
996 ttyputnomemory();
997 cp->lim = 0;
998 return;
999 }
1000 cp->y = emalloc((lim * SIZEOFINTBIG), io_tool->cluster);
1001 if (cp->y == 0)
1002 {
1003 ttyputnomemory();
1004 cp->lim = 0;
1005 return;
1006 }
1007
1008 cp->lim = lim;
1009 for (i = 0; i < lim; i++)
1010 {
1011 temp = io_removepoint((path)ppath);
1012 cp->x[i] = temp.x;
1013 cp->y[i] = temp.y;
1014 }
1015 }
1016
io_outputusercommand(INTBIG command,CHAR * text)1017 void io_outputusercommand(INTBIG command, CHAR *text)
1018 {
1019 }
1020
io_outputgeoname(CHAR * name,point pt,INTBIG lay)1021 void io_outputgeoname(CHAR *name, point pt, INTBIG lay)
1022 {
1023 CGNAME *cg;
1024
1025 io_placeciflist(C_GNAME);
1026 cg = (CGNAME *)io_curlist->member;
1027 cg->lay = lay;
1028 (void)allocstring(&cg->geoname, name, io_tool->cluster);
1029 cg->x = pt.x; cg->y = pt.y;
1030 }
1031
io_outputlabel(CHAR * name,point pt)1032 void io_outputlabel(CHAR *name, point pt)
1033 {
1034 CLABEL *cl;
1035
1036 io_placeciflist(C_LABEL);
1037 cl = (CLABEL *)io_curlist->member;
1038 (void)allocstring(&cl->label, name, io_tool->cluster);
1039 cl->x = pt.x; cl->y = pt.y;
1040 }
1041
io_outputcall(INTBIG number,CHAR * name,CHAR * list)1042 void io_outputcall(INTBIG number, CHAR *name, CHAR *list)
1043 {
1044 CCALL *cc;
1045 tentry temp;
1046 INTBIG i;
1047
1048 io_placeciflist(C_CALL);
1049 cc = (CCALL *)io_curlist->member;
1050 cc->cindex = number;
1051 (void)allocstring(&cc->name, name, io_tool->cluster);
1052 cc->list = io_curctrans = NOCTRANS;
1053 for(i = io_tlistlength((tlist)list); i>0; i--)
1054 {
1055 if (io_newctrans() == NOCTRANS) return;
1056 temp = io_removetentry((tlist)list);
1057 switch (temp.kind)
1058 {
1059 case MIRROR:
1060 if (temp.guts.mi.xcoord) io_curctrans->type = MIRX; else
1061 io_curctrans->type = MIRY;
1062 break;
1063 case TRANSLATE:
1064 io_curctrans->type = TRANS;
1065 io_curctrans->x = temp.guts.tr.xt;
1066 io_curctrans->y = temp.guts.tr.yt;
1067 break;
1068 case ROTATE:
1069 io_curctrans->type = ROT;
1070 io_curctrans->x = temp.guts.ro.xrot;
1071 io_curctrans->y = temp.guts.ro.yrot;
1072 break;
1073 }
1074 }
1075 }
1076
io_outputds(INTBIG number,CHAR * name,INTBIG l,INTBIG r,INTBIG b,INTBIG t)1077 void io_outputds(INTBIG number, CHAR *name, INTBIG l, INTBIG r, INTBIG b, INTBIG t)
1078 {
1079 CFSTART *cs;
1080
1081 io_placeciflist(C_START);
1082 cs = (CFSTART *)io_curlist->member;
1083 cs->cindex = number;
1084 (void)allocstring(&cs->name, name, io_tool->cluster);
1085 cs->l = l; cs->r = r;
1086 cs->b = b; cs->t = t;
1087 }
1088
io_outputdf(void)1089 void io_outputdf(void)
1090 {
1091 io_placeciflist(C_END);
1092 }
1093