2
* Electric(tm) VLSI Design System
5
* Input/output tool: CIF output
6
* Written by: Steven M. Rubin, Static Free Software
8
* Copyright (c) 2000 Static Free Software.
10
* Electric(tm) is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* Electric(tm) is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with Electric(tm); see the file COPYING. If not, write to
22
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23
* Boston, Mass 02111-1307, USA.
25
* Static Free Software
27
* Portola Valley, California 94028
28
* info@staticfreesoft.com
36
#include "egraphics.h"
39
#include "efunction.h"
41
#define FULLPOLYMERGE 1 /* uncomment to use older manhattan merging */
45
static INTBIG io_prev_chr_sep, io_nchar; /* for CRC checksum */
46
static UINTBIG io_check_sum; /* for CRC checksum */
47
static UINTBIG io_cifcrctab[256]; /* for CRC checksum */
48
static INTBIG io_cif_resolution; /* for resolution tests */
49
static INTBIG io_cif_polypoints; /* for points on a polygon tests */
50
static INTBIG *io_cifoutputstate; /* current output state */
51
static INTBIG io_cifoutoffx; /* offset for current facet - for highlight */
52
static INTBIG io_cifoutoffy; /* offset for current facet - for highlight */
53
static NODEPROTO *io_cifoutcurnp; /* node proto of facet being written */
54
static BOOLEAN io_zero_offset; /* Set if there is no centering */
55
static BOOLEAN io_cif_highlightreserr; /* Set to highlight resolution errors */
56
static INTBIG io_reserr_count; /* count the resolution errors */
57
static char io_cifoutcurlayer[200]; /* current layer name written out */
58
static INTBIG io_cifoutfacetnumber; /* count of facets being written out */
59
static INTBIG io_cifoutjobsize; /* number of facets to write out */
61
/* layer requests for grouping output layers */
62
#define NOLAYERREQ ((LAYERREQ *)-1)
64
typedef struct Ilayerreq
69
struct Ilayerreq *nextlayerreq;
72
static LAYERREQ *io_ciflayerreq = NOLAYERREQ;
73
static LAYERREQ *io_ciflayerreqfree = NOLAYERREQ;
74
static LAYERREQ **io_ciflayerreqlist;
75
static INTBIG io_ciflayerreqlisttotal = 0;
77
/* prototypes for local routines */
78
static void io_cifwritefacet(NODEPROTO*, BOOLEAN);
79
static void io_outputcifpoly(TECHNOLOGY*, POLYGON*, INTBIG, INTBIG, INTBIG, INTBIG, XARRAY, GEOM*);
80
static void io_cifprintf(char *msg, ...);
81
static void io_cifreserror(GEOM*, INTBIG, INTBIG, INTBIG, INTBIG, XARRAY);
82
static void io_cif_write_polygon(INTBIG, TECHNOLOGY*, INTBIG*, INTBIG*, INTBIG);
83
static void io_cif_show_reserror(INTBIG, INTBIG, INTBIG, INTBIG);
84
static INTBIG io_cif_outscale(INTBIG value);
85
static LAYERREQ *io_alloclayerreq(void);
86
static void io_freelayerreq(LAYERREQ *req);
87
static void io_includeciflayer(TECHNOLOGY *tech, INTBIG layer);
88
static void io_writeciflayer(char *layername);
89
static void io_cifoptionsdlog(void);
90
static INTBIG io_ciffindhighestlayer(NODEPROTO *np, INTBIG x, INTBIG y);
91
static int io_ciflayerreqascending(const void *e1, const void *e2);
94
* Routine to free all memory associated with this module.
96
void io_freecifoutmemory(void)
98
REGISTER LAYERREQ *req;
100
while (io_ciflayerreq != NOLAYERREQ)
102
req = io_ciflayerreq;
103
io_ciflayerreq = req->nextlayerreq;
104
io_freelayerreq(req);
106
while (io_ciflayerreqfree != NOLAYERREQ)
108
req = io_ciflayerreqfree;
109
io_ciflayerreqfree = req->nextlayerreq;
112
if (io_ciflayerreqlisttotal > 0) efree((char *)io_ciflayerreqlist);
116
* Routine to initialize CIF I/O.
118
void io_initcif(void)
120
extern COMCOMP io_cifp;
122
DiaDeclareHook("cifopt", &io_cifp, io_cifoptionsdlog);
125
BOOLEAN io_writeciflibrary(LIBRARY *lib)
127
char file[100], *truename;
129
REGISTER NODEPROTO *np;
130
REGISTER VARIABLE *var;
131
REGISTER TECHNOLOGY *tech;
132
REGISTER LIBRARY *olib;
133
REGISTER UINTBIG bytesread, i, j;
134
static UINTBIG crcrow[8] = {0x04C11DB7, 0x09823B6E, 0x130476DC, 0x2608EDB8,
135
0x4C11DB70, 0x9823B6E0, 0x34867077, 0x690CE0EE};
136
extern DIALOG us_progressdialog;
138
/* create the proper disk file for the CIF */
139
if (lib->curnodeproto == NONODEPROTO)
141
ttyputerr(_("Must be editing a facet to generate CIF output"));
144
(void)strcpy(file, lib->curnodeproto->cell->cellname);
145
if (strcmp(&file[strlen(file)-4],".cif") != 0) (void)strcat(file, ".cif");
146
name = truepath(file);
147
io_fileout = xcreate(name, io_filetypecif, _("CIF File"), &truename);
148
if (io_fileout == NULL)
150
if (truename != 0) ttyputerr(_("Cannot write %s"), truename);
154
/* get current output state */
155
io_cifoutputstate = io_getstatebits();
157
/* get form of output */
158
if ((io_cifoutputstate[0]&CIFOUTNORMALIZE) != 0) io_zero_offset = FALSE; else
159
io_zero_offset = TRUE;
160
if ((io_cifoutputstate[1]&CIFRESHIGH) != 0) io_cif_highlightreserr = TRUE; else
161
io_cif_highlightreserr = FALSE;
163
/* get cif resolution */
164
var = getval((INTBIG)el_curtech, VTECHNOLOGY, VINTEGER, "IO_cif_resolution");
165
if (var == NOVARIABLE) io_cif_resolution = 0; else
167
io_cif_resolution = var->addr;
168
if (io_cif_resolution != 0 && io_cif_highlightreserr)
169
initerrorlogging("CIF Resolution");
172
/* get the number of allowable points on a polygon */
173
var = getval((INTBIG)el_curtech, VTECHNOLOGY, VINTEGER, "IO_cif_polypoints");
174
if (var == NOVARIABLE) io_cif_polypoints = MAXINTBIG; else
175
io_cif_polypoints = var->addr;
177
/* initialize cif merging facility if needed */
178
#ifndef FULLPOLYMERGE
179
if ((io_cifoutputstate[0]&CIFOUTMERGE) != 0) mrginit();
182
/* initialize the CRC checksum accumulation */
187
if (((1 << j) & i) != 0)
188
io_cifcrctab[i] = io_cifcrctab[i] ^ crcrow[j];
189
io_cifcrctab[i] &= 0xFFFFFFFF;
193
io_check_sum = io_cifcrctab[' '];
195
/* initialize cache of CIF layer information */
196
for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
198
var = getval((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, "IO_cif_layer_names");
199
if (var == NOVARIABLE) tech->temp1 = 0; else
201
tech->temp1 = var->addr;
202
if (getlength(var) != tech->layercount)
204
ttyputerr(_("Warning: CIF layer information is bad for technology %s. Use 'CIF Options' to fix it"),
210
var = getval((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, "TECH_layer_names");
211
tech->temp2 = (var == NOVARIABLE ? 0 : var->addr);
213
/* if ignoring DRC mask layer, delete Generic technology layer names */
214
if (tech == gen_tech && (io_cifoutputstate[0]&CIFOUTADDDRC) == 0) tech->temp1 = 0;
217
/* figure out how many facets will be written */
218
io_cifoutfacetnumber = 0;
219
for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
220
for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
222
io_cifwritefacet(lib->curnodeproto, TRUE);
223
io_cifoutjobsize = io_cifoutfacetnumber;
224
if (DiaInitDialog(&us_progressdialog)) return(TRUE);
226
DiaSetText(2, _("Writing CIF..."));
229
io_cifoutfacetnumber = 0;
232
for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
233
for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
235
io_cifwritefacet(lib->curnodeproto, FALSE);
238
if ((io_cifoutputstate[0]&CIFOUTNOTOPCALL) == 0)
239
io_cifprintf("C %ld;\n", io_cifbase);
244
#ifndef FULLPOLYMERGE
245
/* if doing polygon output */
246
if ((io_cifoutputstate[0]&CIFOUTMERGE) != 0) mrgterm();
249
/* tell the user that the file is written */
250
ttyputmsg(_("%s written"), truename);
252
/* complete the checksum accumulation */
253
if (!io_prev_chr_sep)
255
io_check_sum = (io_check_sum << 8) ^
256
io_cifcrctab[((io_check_sum >> 24) ^ (unsigned char)' ') & 0xFF];
259
bytesread = io_nchar;
260
while (bytesread > 0)
262
io_check_sum = (io_check_sum << 8) ^
263
io_cifcrctab[((io_check_sum >> 24) ^ bytesread) & 0xFF];
266
io_check_sum = ~io_check_sum & 0xFFFFFFFF;
267
ttyputmsg(_("(MOSIS CRC: %lu %ld)"), io_check_sum, io_nchar);
269
/* complete error accumulation */
270
if (io_cif_resolution != 0)
272
if (io_cif_highlightreserr)
274
io_reserr_count = numerrors();
275
termerrorlogging(TRUE);
277
if (io_reserr_count != 0)
278
ttyputerr(_("WARNING: Found %ld resolution %s"), io_reserr_count,
279
makeplural(_("error"), io_reserr_count));
285
void io_cifwritefacet(NODEPROTO *np, BOOLEAN fake)
287
REGISTER NODEINST *subni;
288
REGISTER ARCINST *ai;
289
REGISTER NODEPROTO *subnt, *onp;
290
REGISTER PORTPROTO *pp, *subpp;
291
REGISTER PORTARCINST *pi;
292
REGISTER INTBIG i, j, total, validport, toplayer, toplayerfound;
293
REGISTER INTBIG offx, offy, fun;
294
REGISTER LAYERREQ *req;
295
XARRAY trans, localtran, temp2, subrot, subt, subr, submat;
296
INTBIG rx, ry, xpos, ypos, bx, by, subcornerx, subcornery;
297
static POLYGON *poly = NOPOLYGON;
300
if (poly == NOPOLYGON) poly = allocstaticpolygon(4, io_tool->cluster);
302
io_cifoutfacetnumber++;
305
/* stop if requested */
306
if (stopping(STOPREASONCIF)) return;
310
(void)formatinfstr(_("Writing %s"), describenodeproto(np));
311
DiaSetText(2, returninfstr());
312
DiaPercent(1, io_cifoutfacetnumber * 100 / io_cifoutjobsize);
315
/* if there are any sub-facets that have not been written, write them */
316
for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
318
subnt = subni->proto;
319
if (subnt->primindex != 0) continue;
321
/* ignore recursive references (showing icon in contents) */
322
if (subnt->cell == np->cell) continue;
324
if ((subni->userbits & NEXPAND) == 0 && (io_cifoutputstate[0]&CIFOUTEXACT) != 0) continue;
326
/* convert body facets to contents facets */
327
onp = contentsview(subnt);
328
if (onp != NONODEPROTO) subnt = onp;
330
/* don't recurse if this facet has already been written */
331
if (subnt->temp1 != 0) continue;
333
/* recurse to the bottom */
334
io_cifwritefacet(subnt, fake);
337
np->temp1 = ++io_cifbase;
340
io_cifoutcurnp = np; /* set global for highlighting */
342
/* prepare to write the facet */
345
grabpoint(np, &io_cifoutoffx, &io_cifoutoffy);
346
offx = io_cifoutoffx;
347
offy = io_cifoutoffy;
350
offx = io_cifoutoffx = (np->lowx + np->highx) / 2;
351
offy = io_cifoutoffy = (np->lowy + np->highy) / 2;
353
io_cifprintf("DS %ld 1 1;\n", io_cifbase);
354
io_cifprintf("9 %s; (from library %s);\n", np->cell->cellname, np->cell->lib->libname);
356
io_cifoutcurlayer[0] = 0;
357
if ((io_cifoutputstate[0]&CIFOUTMERGE) == 0)
359
/* no polygon merging: sort by layer */
361
/* determine which layers exist in this facet */
362
while (io_ciflayerreq != NOLAYERREQ)
364
req = io_ciflayerreq;
365
io_ciflayerreq = req->nextlayerreq;
366
io_freelayerreq(req);
368
for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
370
if ((subni->userbits&WIPED) != 0) continue;
371
subnt = subni->proto;
372
if (subnt->primindex == 0) continue;
373
i = nodepolys(subni, 0, NOWINDOWPART);
376
shapenodepoly(subni, j, poly);
377
io_includeciflayer(subnt->tech, poly->layer);
380
for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
382
i = arcpolys(ai, NOWINDOWPART);
385
shapearcpoly(ai, j, poly);
386
io_includeciflayer(ai->proto->tech, poly->layer);
390
/* sort the requests by layer name */
392
for(req = io_ciflayerreq; req != NOLAYERREQ; req = req->nextlayerreq)
394
if (total > io_ciflayerreqlisttotal)
396
if (io_ciflayerreqlisttotal > 0)
397
efree((char *)io_ciflayerreqlist);
398
io_ciflayerreqlisttotal = 0;
399
io_ciflayerreqlist = (LAYERREQ **)emalloc(total * (sizeof (LAYERREQ *)),
401
if (io_ciflayerreqlist == 0) return;
402
io_ciflayerreqlisttotal = total;
405
for(req = io_ciflayerreq; req != NOLAYERREQ; req = req->nextlayerreq)
406
io_ciflayerreqlist[total++] = req;
407
esort(io_ciflayerreqlist, total, sizeof (LAYERREQ *), io_ciflayerreqascending);
408
for(i=0; i<total-1; i++)
409
io_ciflayerreqlist[i]->nextlayerreq = io_ciflayerreqlist[i+1];
410
if (total == 0) io_ciflayerreq = NOLAYERREQ; else
412
io_ciflayerreq = io_ciflayerreqlist[0];
413
io_ciflayerreqlist[total-1]->nextlayerreq = NOLAYERREQ;
416
/* now write geometry by layer */
417
for(req = io_ciflayerreq; req != NOLAYERREQ; req = req->nextlayerreq)
419
if (req->layername == 0 || *req->layername == 0) continue;
421
/* write all primitive nodes in the facet */
422
for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
424
/* don't draw anything if the node is wiped out */
425
if ((subni->userbits&WIPED) != 0) continue;
427
subnt = subni->proto;
428
if (subnt->primindex == 0) continue;
429
if (subnt->tech != req->tech) continue;
431
if (subni->transpose != 0) i = (i + 900) % 3600;
432
rx = ((cosine(i)>>14) * 100) >> 16;
433
ry = ((sine(i)>>14) * 100) >> 16;
434
makerot(subni, trans);
436
/* write a primitive nodeinst */
437
i = nodepolys(subni, 0, NOWINDOWPART);
440
shapenodepoly(subni, j, poly);
441
if (poly->layer != req->layer) continue;
442
io_outputcifpoly(subnt->tech, poly, rx,
443
(subni->transpose ? -ry : ry), offx, offy, trans, subni->geom);
447
/* write all of the arcs in the facet */
448
for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
450
if (ai->proto->tech != req->tech) continue;
451
i = arcpolys(ai, NOWINDOWPART);
454
/* write the box describing the layer */
455
shapearcpoly(ai, j, poly);
456
if (poly->layer != req->layer) continue;
457
io_outputcifpoly(ai->proto->tech, poly, 1, 0, offx, offy, el_matid, ai->geom);
467
/* doing polygon merging: just dump the geometry into the merging system */
468
for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
470
/* don't draw anything if the node is wiped out */
471
if ((subni->userbits&WIPED) != 0) continue;
473
subnt = subni->proto;
474
if (subnt->primindex == 0) continue;
476
if (subni->transpose != 0) i = (i + 900) % 3600;
477
rx = ((cosine(i)>>14) * 100) >> 16;
478
ry = ((sine(i)>>14) * 100) >> 16;
479
makerot(subni, trans);
481
/* write a primitive nodeinst */
482
i = nodepolys(subni, 0, NOWINDOWPART);
485
shapenodepoly(subni, j, poly);
486
io_outputcifpoly(subnt->tech, poly, rx,
487
(subni->transpose ? -ry : ry), offx, offy, trans, subni->geom);
491
/* write all of the arcs in the facet */
492
for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
494
i = arcpolys(ai, NOWINDOWPART);
497
/* write the box describing the layer */
498
shapearcpoly(ai, j, poly);
499
io_outputcifpoly(ai->proto->tech, poly, 1, 0, offx, offy, el_matid, ai->geom);
504
mergedone(io_cif_write_polygon);
506
mrgdonefacet(io_cif_write_polygon);
510
/* write all facet instances */
511
for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
513
subnt = subni->proto;
514
if (subnt->primindex != 0) continue;
516
/* ignore recursive references (showing icon in contents) */
517
if (subnt->cell == np->cell) continue;
520
if (subni->transpose != 0) i = (i + 900) % 3600;
521
rx = ((cosine(i)>>14) * 100) >> 16;
522
ry = ((sine(i)>>14) * 100) >> 16;
523
makerot(subni, trans);
525
/* determine offset of facet */
528
grabpoint(subni->proto, &bx, &by);
529
maketrans(subni, subt);
530
makerot(subni, subr);
531
transmult(subt, subr, submat);
532
xform(bx, by, &subcornerx, &subcornery, submat);
533
xpos = (subcornerx - offx);
534
ypos = (subcornery - offy);
537
xpos = (subni->lowx + subni->highx)/2 - offx;
538
ypos = (subni->lowy + subni->highy)/2 - offy;
540
if ((subni->userbits&NEXPAND) != 0 || (io_cifoutputstate[0]&CIFOUTEXACT) == 0)
542
/* check resolution of call */
543
if (io_cif_resolution != 0)
545
if ((xpos%io_cif_resolution) != 0 || (ypos%io_cif_resolution) != 0)
547
io_cifprintf(_("(Call to symbol %ld does not resolve to grid);\n"),
553
/* write a call to a facet */
554
io_cifprintf("C %ld R %ld %ld", subnt->temp1, rx, ry);
555
if (subni->transpose != 0) io_cifprintf(" M Y");
556
io_cifprintf(" T %ld %ld;\n", io_cif_outscale(xpos), io_cif_outscale(ypos));
559
/* write the vectors that describe an unexpanded facet */
560
io_cifprintf("0V %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld;\n",
561
io_cif_outscale(subni->lowx-offx), io_cif_outscale(subni->lowy-offy),
562
io_cif_outscale(subni->lowx-offx), io_cif_outscale(subni->highy-offy),
563
io_cif_outscale(subni->highx-offx), io_cif_outscale(subni->highy-offy),
564
io_cif_outscale(subni->highx-offx), io_cif_outscale(subni->lowy-offy),
565
io_cif_outscale(subni->lowx-offx), io_cif_outscale(subni->lowy-offy));
566
io_cifprintf("2C \"%s\" T %ld %ld;\n", describenodeproto(subnt),
567
io_cif_outscale(xpos), io_cif_outscale(ypos));
571
/* write the ports as labels */
572
for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
574
/* get the coordinate of the port label */
575
subni = pp->subnodeinst; subpp = pp->subportproto;
576
portposition(subni, subpp, &xpos, &ypos);
578
/* find the primitive node on this port */
579
makerot(subni, subrot);
580
while (subni->proto->primindex == 0)
582
maketrans(subni, localtran);
583
transmult(localtran, subrot, temp2);
584
subni = subpp->subnodeinst;
585
subpp = subpp->subportproto;
586
makerot(subni, localtran);
587
transmult(localtran, temp2, subrot);
590
/* get highest layer at this point */
591
toplayer = io_ciffindhighestlayer(np, xpos, ypos);
594
/* find valid layers on this node that surround the port */
596
total = nodepolys(subni, 0, NOWINDOWPART);
597
for(i=0; i<total; i++)
599
shapenodepoly(subni, i, poly);
600
if (poly->layer < 0) continue;
601
fun = layerfunction(poly->tech, poly->layer);
602
if ((fun&LFPSEUDO) != 0) continue;
603
xformpoly(poly, subrot);
604
if (!isinside(xpos-1, ypos, poly)) continue;
605
if (!isinside(xpos+1, ypos, poly)) continue;
606
if (!isinside(xpos, ypos-1, poly)) continue;
607
if (!isinside(xpos, ypos+1, poly)) continue;
608
if (poly->layer == toplayer) toplayerfound = 1;
614
/* look for connected arcs */
619
/* look for layers at this level of hierarchy */
620
for(pi = subpp->subnodeinst->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
623
total = arcpolys(ai, NOWINDOWPART);
624
for(i=0; i<total; i++)
626
shapearcpoly(ai, i, poly);
627
if (poly->layer < 0) continue;
628
fun = layerfunction(poly->tech, poly->layer);
629
if ((fun&LFPSEUDO) != 0) continue;
630
xformpoly(poly, subrot);
631
if (!isinside(xpos-1, ypos, poly)) continue;
632
if (!isinside(xpos+1, ypos, poly)) continue;
633
if (!isinside(xpos, ypos-1, poly)) continue;
634
if (!isinside(xpos, ypos+1, poly)) continue;
635
if (poly->layer == toplayer) toplayerfound = 1;
639
if (validport != 0) break;
641
if (validport != 0) break;
643
/* not found on this level: descend and look again */
644
if (subpp->subnodeinst->proto->primindex != 0) break;
645
maketrans(subpp->subnodeinst, localtran);
646
transmult(localtran, subrot, temp2);
647
makerot(subpp->subnodeinst, localtran);
648
transmult(localtran, temp2, subrot);
649
subpp = subpp->subportproto;
654
if (toplayerfound == 0)
655
ttyputmsg(_("Warning: facet %s, export '%s' obscured by higher layer"),
656
describenodeproto(np), pp->protoname);
657
io_cifprintf("94 %s %ld %ld;\n", pp->protoname, io_cif_outscale(xpos-offx),
658
io_cif_outscale(ypos-offy));
662
io_cifprintf("DF;\n");
665
int io_ciflayerreqascending(const void *e1, const void *e2)
667
REGISTER LAYERREQ *lr1, *lr2;
668
REGISTER char *lrname1, *lrname2;
670
lr1 = *((LAYERREQ **)e1);
671
lr2 = *((LAYERREQ **)e2);
672
lrname1 = lr1->layername;
673
if (lrname1 == 0) lrname1 = "";
674
lrname2 = lr2->layername;
675
if (lrname2 == 0) lrname2 = "";
676
return(namesame(lrname1, lrname2));
679
INTBIG io_ciffindhighestlayer(NODEPROTO *np, INTBIG x, INTBIG y)
681
REGISTER INTBIG sea, i, tot, first, bestheight, bestlayer;
682
INTBIG height, thickness;
684
REGISTER NODEINST *ni;
685
REGISTER ARCINST *ai;
686
static POLYGON *poly = NOPOLYGON;
688
if (poly == NOPOLYGON) poly = allocstaticpolygon(4, io_tool->cluster);
689
sea = initsearch(x, x, y, y, np);
693
geom = nextobject(sea);
694
if (geom == NOGEOM) break;
695
if (geom->entryisnode)
697
ni = geom->entryaddr.ni;
698
if (ni->proto->primindex == 0) continue;
699
tot = nodepolys(ni, 0, NOWINDOWPART);
702
shapenodepoly(ni, i, poly);
703
if (!isinside(x, y, poly)) continue;
704
if (get3dfactors(poly->tech, poly->layer, &height, &thickness))
707
/* LINTED "bestheight" used in proper order */
708
if (first != 0 || height > bestheight)
711
bestlayer = poly->layer;
717
ai = geom->entryaddr.ai;
718
tot = arcpolys(ai, NOWINDOWPART);
721
shapearcpoly(ai, i, poly);
722
if (!isinside(x, y, poly)) continue;
723
if (get3dfactors(poly->tech, poly->layer, &height, &thickness))
725
if (first != 0 || height > bestheight)
728
bestlayer = poly->layer;
734
if (first != 0) return(0);
739
* Routine to dump the layer name (if it has changed).
741
void io_writeciflayer(char *layername)
743
if (strcmp(layername, io_cifoutcurlayer) == 0) return;
744
io_cifprintf("L %s;\n", layername);
745
strcpy(io_cifoutcurlayer, layername);
749
* routine to write polygon "poly" to the CIF file. The polygon is from
750
* technology "tech", is rotated by the factor "rx" and "ry", and is offset
751
* by "offx" and "offy"
753
void io_outputcifpoly(TECHNOLOGY *tech, POLYGON *poly, INTBIG rx, INTBIG ry,
754
INTBIG offx, INTBIG offy, XARRAY trans, GEOM *geom)
756
REGISTER INTBIG r, k, bloat;
757
INTBIG xl, xh, yl, yh, xpos, ypos;
758
REGISTER char *layername;
760
/* get bloating for this layer */
761
if (poly->layer < 0 || tech->temp1 == 0) return;
763
(void)addstringtoinfstr(tech->techname);
764
(void)addtoinfstr(':');
765
(void)addstringtoinfstr(((char **)tech->temp2)[poly->layer]);
766
bloat = io_getoutputbloat(returninfstr());
768
/* get the CIF layer, stop if none */
769
layername = ((char **)tech->temp1)[poly->layer];
770
if (*layername == 0) return;
775
xformpoly(poly, trans);
776
r = computedistance(poly->xv[0], poly->yv[0], poly->xv[1], poly->yv[1]);
779
/* write the layer name */
780
io_writeciflayer(layername);
782
/* write the round-flash */
783
io_cifprintf(" R %ld %ld %ld;\n", r+bloat, io_cif_outscale(poly->xv[0]-offx),
784
io_cif_outscale(poly->yv[0]-offy));
789
if ((io_cifoutputstate[0]&CIFOUTMERGE) != 0)
791
xformpoly(poly, trans);
792
for(k=0; k<poly->count; k++)
797
mergestorepolygon(poly->layer, tech, poly);
802
if (isbox(poly, &xl,&xh, &yl,&yh))
804
/* ignore zero-size polygons */
805
if (xh == xl || yh == yl) return;
807
#ifndef FULLPOLYMERGE
808
if ((io_cifoutputstate[0]&CIFOUTMERGE) != 0)
810
/* do polygon format output */
811
xform((xl+xh)/2, (yl+yh)/2, &xpos, &ypos, trans);
812
if (rx != 0 && ry == 0)
814
/* no rotation needed */
815
mrgstorebox(poly->layer, tech, xh-xl+bloat, yh-yl+bloat,
816
xpos-offx, ypos-offy);
819
if (rx == 0 && ry != 0)
821
/* rotate through 90 degrees */
822
mrgstorebox(poly->layer, tech, yh-yl+bloat, xh-xl+bloat,
823
xpos-offx, ypos-offy);
826
/* nonmanhattan or worse .. fall into direct output case */
830
/* write the layer name */
831
io_writeciflayer(layername);
833
/* non-merged box: highlight resolution errors */
834
io_cifreserror(geom, xh-xl+bloat, yh-yl+bloat, (xl+xh)/2, (yl+yh)/2, trans);
836
/* want individual box output */
837
xform((xl+xh)/2, (yl+yh)/2, &xpos, &ypos, trans);
838
io_cifprintf(" B %ld %ld %ld %ld", io_cif_outscale(xh-xl+bloat),
839
io_cif_outscale(yh-yl+bloat), io_cif_outscale(xpos-offx),
840
io_cif_outscale(ypos-offy));
841
if (rx <= 0 || ry != 0) io_cifprintf(" %ld %ld", rx, ry);
845
/* write the layer name */
846
io_writeciflayer(layername);
848
xformpoly(poly, trans);
851
ttyputmsg(_("Warning: complex CIF polygon cannot be bloated"));
852
io_cifprintf(_("(NEXT POLYGON CANNOT BE BLOATED);\n"));
854
if (poly->count == 1)
855
io_cifprintf(" 0V %ld %ld %ld %ld;\n", io_cif_outscale(poly->xv[0]-offx),
856
io_cif_outscale(poly->yv[0]-offy), io_cif_outscale(poly->xv[0]-offx),
857
io_cif_outscale(poly->yv[0]-offy)); else
858
if (poly->count == 2)
859
io_cifprintf(" 0V %ld %ld %ld %ld;\n", io_cif_outscale(poly->xv[0]-offx),
860
io_cif_outscale(poly->yv[0]-offy), io_cif_outscale(poly->xv[1]-offx),
861
io_cif_outscale(poly->yv[1]-offy)); else
864
* Now call routine to write the polygon:
866
* - check for resolution errors
868
for (k = 0; k < poly->count; k++)
871
* WARNING: this changes poly!
876
io_cif_write_polygon(poly->layer, tech, poly->xv, poly->yv, poly->count);
882
#if 0 /* code to handle certain polygons without valid CIF layers */
886
xformpoly(poly, trans);
887
getbbox(poly, &xl,&xh, &yl,&yh);
888
io_cifprintf("0V %ld %ld", io_cif_outscale(xl-offx), io_cif_outscale(yl-offy));
889
io_cifprintf(" %ld %ld", io_cif_outscale(xl-offx), io_cif_outscale(yh-offy));
890
io_cifprintf(" %ld %ld", io_cif_outscale(xh-offx), io_cif_outscale(yh-offy));
891
io_cifprintf(" %ld %ld;\n", io_cif_outscale(xh-offx), io_cif_outscale(yl-offy));
899
xformpoly(poly, trans);
901
for(k=0; k<poly->count; k++)
902
io_cifprintf(" %ld %ld", io_cif_outscale(poly->xv[k]-offx), io_cif_outscale(poly->yv[k]-offy));
903
if (poly->style == CLOSED)
904
io_cifprintf(" %ld %ld", io_cif_outscale(poly->xv[k]-offx), io_cif_outscale(poly->yv[k]-offy));
909
xformpoly(poly, trans);
910
for(k=0; k<poly->count; k += 2)
912
io_cifprintf("0V %ld %ld", io_cif_outscale(poly->xv[k]-offx),
913
io_cif_outscale(poly->yv[k]-offy));
914
io_cifprintf(" %ld %ld;\n", io_cif_outscale(poly->xv[k+1]-offx),
915
io_cif_outscale(poly->yv[k+1]-offy));
923
* routine to send a line to the CIF output file and to accumulate
924
* checksum information.
926
void io_cifprintf(char *msg, ...)
933
evsnprintf(temp, 200, msg, ap);
937
for(cp = temp; *cp != 0; cp++)
942
io_check_sum = (io_check_sum << 8) ^
943
io_cifcrctab[((io_check_sum >> 24) ^ c) & 0xFF];
946
} else if (io_prev_chr_sep == 0)
948
io_check_sum = (io_check_sum << 8) ^
949
io_cifcrctab[((io_check_sum >> 24) ^ (unsigned char)' ') & 0xFF];
955
xprintf(io_fileout, "%s", temp);
958
/* routine which highlights box which doesn't resolve */
959
void io_cifreserror(GEOM *pos, INTBIG length, INTBIG width, INTBIG xc, INTBIG yc, XARRAY trans)
961
INTBIG ptx[4], pty[4], x, y;
965
/* stop if no resolution check or no geometry module */
966
if (io_cif_resolution == 0 || pos == NOGEOM) return;
968
ptx[0] = ptx[1] = xc - (length/2);
969
ptx[2] = ptx[3] = xc + (length/2);
970
pty[0] = pty[3] = yc + (width/2);
971
pty[1] = pty[2] = yc - (width/2);
974
xform(ptx[i], pty[i], &x, &y, trans);
976
/* see if it resolves to grid */
977
if ((x % io_cif_resolution) != 0 || (y % io_cif_resolution) != 0)
979
/* highlight the object */
980
if (io_cif_highlightreserr)
982
err = logerror("Resolution error", geomparent(pos), 0);
983
addgeomtoerror(err, pos, TRUE, 0, 0);
991
void io_cif_write_polygon(INTBIG layer, TECHNOLOGY *tech, INTBIG *xbuf, INTBIG *ybuf,
994
INTBIG buflen, prlen, i;
996
char outbuf[NMCHR+2], prbuf[40], *layername; /* declare buffers */
998
/* write the layer name */
999
if (layer < 0 || tech->temp1 == 0) return;
1000
layername = ((char **)tech->temp1)[layer];
1001
if (*layername == 0) return;
1002
io_writeciflayer(layername);
1004
/* set up first line */
1005
(void)sprintf(outbuf, "P ");
1006
buflen = strlen(outbuf);
1008
/* check the number of points on the polygon */
1009
if (count > io_cif_polypoints)
1010
ttyputerr(_("WARNING: Polygon has too many points (%ld)"), count);
1012
/* search for any resolution errors on this polygon */
1013
/* highlight any edges that don't resolve */
1014
if (io_cif_resolution != 0)
1016
tmpx = xbuf[count-1];
1017
tmpy = ybuf[count-1];
1018
for (i = 0; i < count; i++)
1020
if ((tmpx%io_cif_resolution) != 0 && tmpx == xbuf[i])
1022
io_cif_show_reserror(tmpx+io_cifoutoffx, tmpy+io_cifoutoffy,
1023
xbuf[i]+io_cifoutoffx, ybuf[i]+io_cifoutoffy);
1024
} else if ((tmpy%io_cif_resolution) != 0 && tmpy == ybuf[i])
1026
io_cif_show_reserror(tmpx+io_cifoutoffx, tmpy+io_cifoutoffy,
1027
xbuf[i]+io_cifoutoffx, ybuf[i]+io_cifoutoffy);
1034
for(i=0; i<count; i++)
1036
(void)sprintf(prbuf, " %ld %ld", io_cif_outscale(xbuf[i]),
1037
io_cif_outscale(ybuf[i]));
1038
prlen = strlen(prbuf); /* get length of coord. pair */
1040
/* if we have done the last point */
1043
if (prlen + buflen < NMCHR-1) /* if space in buffer */
1045
(void)strcat(outbuf, prbuf); /* concatenate strings */
1046
io_cifprintf("%s;\n", outbuf); /* write the buffer */
1049
/* write as two lines */
1050
io_cifprintf("%s\n", outbuf);
1051
io_cifprintf(" %s;\n", prbuf);
1056
if (prlen + buflen < NMCHR) /* if small enough */
1058
/* append to buffer */
1059
(void)strcat(outbuf, prbuf);
1060
buflen = strlen(outbuf);
1063
/* we must write the buffer out, and re-initialize it */
1064
io_cifprintf("%s\n", outbuf);
1065
(void)sprintf(outbuf, " %s", prbuf);
1066
buflen = strlen(outbuf);
1072
void io_cif_show_reserror(INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2)
1076
if (!io_cif_highlightreserr) return;
1078
/* show resolution error if it is in the current window */
1079
err = logerror("Resolution error", io_cifoutcurnp, 0);
1080
addlinetoerror(err, x1, y1, x2, y2);
1084
INTBIG io_cif_outscale(INTBIG value)
1088
v = scaletodispunit(value, DISPUNITCMIC);
1089
return(roundfloat(v));
1092
void io_includeciflayer(TECHNOLOGY *tech, INTBIG layer)
1094
REGISTER LAYERREQ *req;
1096
/* stop now if the layer is already in the list */
1097
for(req = io_ciflayerreq; req != NOLAYERREQ; req = req->nextlayerreq)
1098
if (req->tech == tech && req->layer == layer) return;
1100
/* add to the list */
1101
req = io_alloclayerreq();
1102
if (req == NOLAYERREQ) return;
1105
if (layer < 0 || tech->temp1 == 0) req->layername = 0; else
1106
req->layername = ((char **)tech->temp1)[layer];
1107
req->nextlayerreq = io_ciflayerreq;
1108
io_ciflayerreq = req;
1111
LAYERREQ *io_alloclayerreq(void)
1113
REGISTER LAYERREQ *req;
1115
if (io_ciflayerreqfree == NOLAYERREQ)
1117
req = (LAYERREQ *)emalloc(sizeof (LAYERREQ), io_tool->cluster);
1118
if (req == 0) return(NOLAYERREQ);
1121
req = io_ciflayerreqfree;
1122
io_ciflayerreqfree = req->nextlayerreq;
1127
void io_freelayerreq(LAYERREQ *req)
1129
req->nextlayerreq = io_ciflayerreqfree;
1130
io_ciflayerreqfree = req;
1134
static DIALOGITEM io_cifoptionsdialogitems[] =
1136
/* 1 */ {0, {224,380,248,452}, BUTTON, N_("OK")},
1137
/* 2 */ {0, {224,240,248,312}, BUTTON, N_("Cancel")},
1138
/* 3 */ {0, {8,8,248,223}, SCROLL, ""},
1139
/* 4 */ {0, {8,232,24,312}, MESSAGE, N_("CIF Layer:")},
1140
/* 5 */ {0, {8,316,24,454}, EDITTEXT, ""},
1141
/* 6 */ {0, {32,232,48,454}, CHECK, N_("Output Mimics Display")},
1142
/* 7 */ {0, {56,232,72,454}, CHECK, N_("Output Merges Boxes")},
1143
/* 8 */ {0, {148,232,164,454}, CHECK, N_("Input Squares Wires")},
1144
/* 9 */ {0, {100,232,116,454}, CHECK, N_("Output Instantiates Top Level")},
1145
/* 10 */ {0, {196,240,212,384}, MESSAGE, N_("Output resolution:")},
1146
/* 11 */ {0, {196,388,212,454}, EDITTEXT, ""},
1147
/* 12 */ {0, {172,232,188,436}, POPUP, ""},
1148
/* 13 */ {0, {124,232,140,454}, CHECK, N_("Normalize Coordinates")},
1149
/* 14 */ {0, {76,248,92,454}, MESSAGE, N_("(time consuming)")}
1151
static DIALOG io_cifoptionsdialog = {{50,75,307,538}, N_("CIF Options"), 0, 14, io_cifoptionsdialogitems};
1153
/* special items for the "CIF Options" dialog: */
1154
#define DCFO_LAYERLIST 3 /* Layer list (scroll list) */
1155
#define DCFO_NEWLAYER 5 /* New layer (edit text) */
1156
#define DCFO_OMIMICDISPLAY 6 /* Output Mimics Display (check) */
1157
#define DCFO_OMERGEBOXES 7 /* Output Merges Boxes (check) */
1158
#define DCFO_ISQUAREWIRES 8 /* Input Squares Wires (check) */
1159
#define DCFO_OINSTANTIATETOP 9 /* Output Instantiates top (check) */
1160
#define DCFO_ORESOLUTION_L 10 /* Output Resolution label (stat text) */
1161
#define DCFO_ORESOLUTION 11 /* Output resolution (edit text) */
1162
#define DCFO_ORESOLUTIONMODE 12 /* Output resolution mode (popup) */
1163
#define DCFO_ONORMALIZECOORD 13 /* Output normalizes coordinates (check) */
1165
void io_cifoptionsdlog(void)
1167
INTBIG newstate[NUMIOSTATEBITWORDS];
1168
REGISTER INTBIG *curstate, oldresolution, i, itemHit, nameschanged;
1169
REGISTER char **layernames, *pt;
1171
REGISTER VARIABLE *var, *cifvar;
1172
static char *whattodisplay[] = {N_("No Resolution Check"),
1173
N_("Report Resolution Errors"), N_("Show Resolution Errors")};
1175
if (DiaInitDialog(&io_cifoptionsdialog)) return;
1176
for(i=0; i<3; i++) newlang[i] = _(whattodisplay[i]);
1177
DiaSetPopup(DCFO_ORESOLUTIONMODE, 3, newlang);
1178
DiaInitTextDialog(DCFO_LAYERLIST, DiaNullDlogList, DiaNullDlogItem,
1179
DiaNullDlogDone, 0, SCSELMOUSE|SCREPORT);
1180
layernames = (char **)emalloc(el_curtech->layercount * (sizeof (char *)),
1182
cifvar = getval((INTBIG)el_curtech, VTECHNOLOGY, VSTRING|VISARRAY,
1183
"IO_cif_layer_names");
1184
for(i=0; i<el_curtech->layercount; i++)
1186
if (cifvar == NOVARIABLE || i >= getlength(cifvar)) pt = ""; else
1187
pt = ((char **)cifvar->addr)[i];
1188
(void)allocstring(&layernames[i], pt, el_tempcluster);
1190
(void)addstringtoinfstr(layername(el_curtech, i));
1191
(void)addstringtoinfstr(" (");
1192
(void)addstringtoinfstr(pt);
1193
(void)addstringtoinfstr(")");
1194
DiaStuffLine(DCFO_LAYERLIST, returninfstr());
1196
DiaSelectLine(DCFO_LAYERLIST, 0);
1197
DiaSetText(DCFO_NEWLAYER, layernames[0]);
1198
curstate = io_getstatebits();
1199
for(i=0; i<NUMIOSTATEBITWORDS; i++) newstate[i] = curstate[i];
1200
if ((curstate[0]&CIFOUTEXACT) != 0) DiaSetControl(DCFO_OMIMICDISPLAY, 1);
1201
if ((curstate[0]&CIFOUTMERGE) != 0) DiaSetControl(DCFO_OMERGEBOXES, 1);
1202
if ((curstate[0]&CIFINSQUARE) != 0) DiaSetControl(DCFO_ISQUAREWIRES, 1);
1203
if ((curstate[0]&CIFOUTNOTOPCALL) == 0) DiaSetControl(DCFO_OINSTANTIATETOP, 1);
1204
if ((curstate[0]&CIFOUTNORMALIZE) != 0) DiaSetControl(DCFO_ONORMALIZECOORD, 1);
1205
var = getval((INTBIG)el_curtech, VTECHNOLOGY, VINTEGER, "IO_cif_resolution");
1206
if (var == NOVARIABLE) oldresolution = 0; else oldresolution = var->addr;
1207
if (oldresolution == 0)
1209
DiaSetText(DCFO_ORESOLUTION, "");
1210
DiaSetPopupEntry(DCFO_ORESOLUTIONMODE, 0);
1211
DiaDimItem(DCFO_ORESOLUTION_L);
1212
DiaDimItem(DCFO_ORESOLUTION);
1215
DiaUnDimItem(DCFO_ORESOLUTION_L);
1216
DiaUnDimItem(DCFO_ORESOLUTION);
1217
DiaSetText(DCFO_ORESOLUTION, latoa(oldresolution));
1218
if ((curstate[1]&CIFRESHIGH) != 0)
1219
DiaSetPopupEntry(DCFO_ORESOLUTIONMODE, 2); else
1220
DiaSetPopupEntry(DCFO_ORESOLUTIONMODE, 1);
1223
/* loop until done */
1227
itemHit = DiaNextHit();
1228
if (itemHit == CANCEL) break;
1231
i = DiaGetPopupEntry(DCFO_ORESOLUTIONMODE);
1232
if (i != 0 && atola(DiaGetText(DCFO_ORESOLUTION)) == 0)
1234
DiaMessageInDialog(_("Must set nonzero output resolution"));
1239
if (itemHit == DCFO_OMIMICDISPLAY || itemHit == DCFO_OMERGEBOXES ||
1240
itemHit == DCFO_ISQUAREWIRES || itemHit == DCFO_OINSTANTIATETOP ||
1241
itemHit == DCFO_ONORMALIZECOORD)
1243
DiaSetControl(itemHit, 1 - DiaGetControl(itemHit));
1246
if (itemHit == DCFO_LAYERLIST)
1248
i = DiaGetCurLine(DCFO_LAYERLIST);
1249
DiaSetText(DCFO_NEWLAYER, layernames[i]);
1252
if (itemHit == DCFO_ORESOLUTIONMODE)
1254
i = DiaGetPopupEntry(DCFO_ORESOLUTIONMODE);
1257
DiaDimItem(DCFO_ORESOLUTION_L);
1258
DiaDimItem(DCFO_ORESOLUTION);
1259
DiaSetText(DCFO_ORESOLUTION, "");
1262
DiaUnDimItem(DCFO_ORESOLUTION_L);
1263
DiaUnDimItem(DCFO_ORESOLUTION);
1264
if (atola(DiaGetText(DCFO_ORESOLUTION)) == 0)
1265
DiaSetText(DCFO_ORESOLUTION, "1");
1269
if (itemHit == DCFO_NEWLAYER)
1271
i = DiaGetCurLine(DCFO_LAYERLIST);
1272
pt = DiaGetText(DCFO_NEWLAYER);
1273
if (strcmp(pt, layernames[i]) == 0) continue;
1275
(void)reallocstring(&layernames[i], pt, el_tempcluster);
1277
(void)addstringtoinfstr(layername(el_curtech, i));
1278
(void)addstringtoinfstr(" (");
1279
(void)addstringtoinfstr(layernames[i]);
1280
(void)addstringtoinfstr(")");
1281
DiaSetScrollLine(DCFO_LAYERLIST, i, returninfstr());
1286
if (itemHit != CANCEL)
1288
if (DiaGetControl(DCFO_OMIMICDISPLAY) != 0) newstate[0] |= CIFOUTEXACT; else
1289
newstate[0] &= ~CIFOUTEXACT;
1290
if (DiaGetControl(DCFO_OMERGEBOXES) != 0) newstate[0] |= CIFOUTMERGE; else
1291
newstate[0] &= ~CIFOUTMERGE;
1292
if (DiaGetControl(DCFO_ISQUAREWIRES) != 0) newstate[0] |= CIFINSQUARE; else
1293
newstate[0] &= ~CIFINSQUARE;
1294
if (DiaGetControl(DCFO_OINSTANTIATETOP) == 0) newstate[0] |= CIFOUTNOTOPCALL; else
1295
newstate[0] &= ~CIFOUTNOTOPCALL;
1296
if (DiaGetControl(DCFO_ONORMALIZECOORD) != 0) newstate[0] |= CIFOUTNORMALIZE; else
1297
newstate[0] &= ~CIFOUTNORMALIZE;
1298
if (DiaGetPopupEntry(DCFO_ORESOLUTIONMODE) == 2) newstate[1] |= CIFRESHIGH; else
1299
newstate[1] &= ~CIFRESHIGH;
1300
for(i=0; i<NUMIOSTATEBITWORDS; i++) if (curstate[i] != newstate[i]) break;
1301
if (i < NUMIOSTATEBITWORDS) io_setstatebits(newstate);
1302
if (nameschanged != 0)
1303
setval((INTBIG)el_curtech, VTECHNOLOGY, "IO_cif_layer_names",
1304
(INTBIG)layernames, VSTRING|VISARRAY|
1305
(el_curtech->layercount<<VLENGTHSH));
1306
i = atola(DiaGetText(DCFO_ORESOLUTION));
1307
if (i != oldresolution)
1308
setval((INTBIG)el_curtech, VTECHNOLOGY, "IO_cif_resolution", i, VINTEGER);
1310
for(i=0; i<el_curtech->layercount; i++) efree(layernames[i]);
1311
efree((char *)layernames);
1315
#endif /* IOCIF - at top */