1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usredtecp.c
6 * User interface technology editor: conversion from library to technology
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 #include "global.h"
33 #include "egraphics.h"
34 #include "efunction.h"
35 #include "tech.h"
36 #include "tecgen.h"
37 #include "tecart.h"
38 #include "usr.h"
39 #include "drc.h"
40 #include "usredtec.h"
41
42 /* the globals that define a technology */
43 static INTBIG us_tecflags;
44 static INTBIG us_teclayer_count;
45 static CHAR **us_teclayer_iname = 0;
46 static CHAR **us_teclayer_names = 0;
47 static CHAR **us_teccif_layers = 0;
48 static CHAR **us_tecdxf_layers = 0;
49 static CHAR **us_tecgds_layers = 0;
50 static INTBIG *us_teclayer_function = 0;
51 static CHAR **us_teclayer_letters = 0;
52 static DRCRULES *us_tecdrc_rules = 0;
53 static float *us_tecspice_res = 0;
54 static float *us_tecspice_cap = 0;
55 static float *us_tecspice_ecap = 0;
56 static INTBIG *us_tec3d_height = 0;
57 static INTBIG *us_tec3d_thickness = 0;
58 static INTBIG *us_tecprint_colors = 0;
59 static INTBIG us_tecarc_count;
60 static INTBIG *us_tecarc_widoff = 0;
61 static INTBIG us_tecnode_count;
62 static INTBIG *us_tecnode_widoff = 0;
63 static INTBIG *us_tecnode_grab = 0;
64 static INTBIG us_tecnode_grabcount;
65 static TECH_COLORMAP us_teccolmap[32];
66
67 static PCON *us_tecedfirstpcon = NOPCON; /* list of port connections */
68 static RULE *us_tecedfirstrule = NORULE; /* list of rules */
69
70 /* working memory for "us_tecedmakeprim()" */
71 static INTBIG *us_tecedmakepx, *us_tecedmakepy, *us_tecedmakefactor,
72 *us_tecedmakeleftdist, *us_tecedmakerightdist, *us_tecedmakebotdist,
73 *us_tecedmaketopdist, *us_tecedmakecentxdist, *us_tecedmakecentydist, *us_tecedmakeratiox,
74 *us_tecedmakeratioy, *us_tecedmakecx, *us_tecedmakecy;
75 static INTBIG us_tecedmakearrlen = 0;
76
77 /* working memory for "us_teceditgetdependents()" */
78 static LIBRARY **us_teceddepliblist;
79 static INTBIG us_teceddepliblistsize = 0;
80
81 /* prototypes for local routines */
82 static void us_tecedcheck(TECHNOLOGY*);
83 static BOOLEAN us_tecedmakefactors(LIBRARY**, INTBIG, TECHNOLOGY*);
84 static BOOLEAN us_tecedmakelayers(LIBRARY**, INTBIG, TECHNOLOGY*);
85 static BOOLEAN us_tecedmakearcs(LIBRARY**, INTBIG, TECHNOLOGY*);
86 static BOOLEAN us_tecedmakenodes(LIBRARY**, INTBIG, TECHNOLOGY*);
87 static INTBIG us_tecedfindport(TECH_NODES*, EXAMPLE*, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
88 static BOOLEAN us_tecedassociateexamples(EXAMPLE*, NODEPROTO*);
89 static BOOLEAN us_tecedmakeprim(EXAMPLE*, NODEPROTO*, TECHNOLOGY*, TECH_NODES*, INTBIG);
90 static void us_tecedforcearrays(INTBIG);
91 static INTBIG *us_tecedstretchpoints(INTBIG*, INTBIG*, INTBIG, INTBIG*, SAMPLE*, NODEPROTO*, EXAMPLE*);
92 static BOOLEAN us_tecedmulticut(SAMPLE*, EXAMPLE*, NODEPROTO*);
93 static PCON *us_tecedaddportlist(INTBIG, INTBIG*);
94 static CHAR *us_tecedmakesymbol(CHAR*);
95 static CHAR *us_tecedmakefract(INTBIG);
96 static void us_teceditdumpdrctab(FILE*, void*, TECHNOLOGY*, BOOLEAN);
97 static CHAR *us_tecedmakeupper(CHAR*);
98 static CHAR *us_tecededgelabel(INTBIG, INTBIG, BOOLEAN);
99 static void us_tecedfreetechmemory(void);
100 static RULE *us_tecedaddrule(INTBIG list[8], INTBIG count, BOOLEAN multcut, CHAR *istext);
101 static int us_samplecoordascending(const void *e1, const void *e2);
102 static void us_teceditdumplayers(FILE *f, TECHNOLOGY *tech, CHAR *techname);
103 static void us_teceditdumparcs(FILE *f, TECHNOLOGY *tech, CHAR *techname);
104 static void us_teceditdumpnodes(FILE *f, TECHNOLOGY *tech, CHAR *techname);
105 static void us_teceditdumpvars(FILE *f, TECHNOLOGY *tech, CHAR *techname);
106 static CHAR *us_tecedmakefloatstring(float v);
107 static RULE *us_tecedaddmulticutrule(INTBIG multixs, INTBIG multiys, INTBIG multiindent, INTBIG multisep);
108 static SAMPLE *us_tecedneedhighlightlayer(EXAMPLE *nelist, NODEPROTO *np);
109 static CHAR *us_teceditgetparameter(VARIABLE *var);
110 static void us_teceditdumpjavalayers(FILE *f, TECHNOLOGY *tech, CHAR *techname);
111 static void us_teceditdumpjavadrctab(FILE *f, void *distances, TECHNOLOGY *tech, BOOLEAN isstring);
112 static void us_teceditdumpjavaarcs(FILE *f, TECHNOLOGY *tech, CHAR *techname);
113 static void us_teceditdumpjavanodes(FILE *f, TECHNOLOGY *tech, CHAR *techname);
114 static CHAR *us_tecededgelabeljava(INTBIG mul, INTBIG add, BOOLEAN yaxis);
115 static CHAR *us_teceditconverttojava(CHAR *string);
116
117 /*
118 * Routine to free all memory associated with this module.
119 */
us_freeedtecpmemory(void)120 void us_freeedtecpmemory(void)
121 {
122 if (us_tecedmakearrlen != 0)
123 {
124 efree((CHAR *)us_tecedmakepx);
125 efree((CHAR *)us_tecedmakepy);
126 efree((CHAR *)us_tecedmakecx);
127 efree((CHAR *)us_tecedmakecy);
128 efree((CHAR *)us_tecedmakefactor);
129 efree((CHAR *)us_tecedmakeleftdist);
130 efree((CHAR *)us_tecedmakerightdist);
131 efree((CHAR *)us_tecedmakebotdist);
132 efree((CHAR *)us_tecedmaketopdist);
133 efree((CHAR *)us_tecedmakecentxdist);
134 efree((CHAR *)us_tecedmakecentydist);
135 efree((CHAR *)us_tecedmakeratiox);
136 efree((CHAR *)us_tecedmakeratioy);
137 }
138 if (us_teceddepliblistsize != 0) efree((CHAR *)us_teceddepliblist);
139 us_tecedfreetechmemory();
140 }
141
142 /*
143 * the routine invoked for the "technology edit library-to-tech" command. Dumps
144 * C code if "dumpc" is nonzero
145 */
us_tecfromlibinit(LIBRARY * lib,CHAR * techname,INTBIG dumpformat)146 void us_tecfromlibinit(LIBRARY *lib, CHAR *techname, INTBIG dumpformat)
147 {
148 REGISTER FILE *f;
149 REGISTER TECHNOLOGY *tech;
150 REGISTER CLUSTER *clus;
151 REGISTER VARIABLE *var, *ovar;
152 REGISTER CHAR **varnames;
153 CHAR *truename, *newtechname;
154 LIBRARY **dependentlibs;
155 REGISTER INTBIG dependentlibcount, i, j, modified;
156 REGISTER void *infstr;
157 static TECH_VARIABLES us_tecvariables[2] = {{NULL, NULL, 0.0, 0},
158 {NULL, NULL, 0.0, 0}};
159
160 /* make sure network tool is on */
161 if ((net_tool->toolstate&TOOLON) == 0)
162 {
163 ttyputerr(_("Network tool must be running...turning it on"));
164 toolturnon(net_tool);
165 ttyputerr(_("...now reissue the technology editing command"));
166 return;
167 }
168
169 /* loop until the name is valid */
170 if (techname == 0) techname = lib->libname;
171 if (allocstring(&newtechname, techname, el_tempcluster)) return;
172 modified = 0;
173 for(;;)
174 {
175 /* search by hand because "gettechnology" handles partial matches */
176 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
177 if (namesame(newtechname, tech->techname) == 0) break;
178 if (tech == NOTECHNOLOGY) break;
179 infstr = initinfstr();
180 addstringtoinfstr(infstr, newtechname);
181 addtoinfstr(infstr, 'X');
182 (void)reallocstring(&newtechname, returninfstr(infstr), el_tempcluster);
183 modified= 1;
184 }
185
186 /* create the technology */
187 infstr = initinfstr();
188 addstringtoinfstr(infstr, x_("tech:"));
189 addstringtoinfstr(infstr, newtechname);
190 clus = alloccluster(returninfstr(infstr));
191 if (clus == NOCLUSTER) return;
192 tech = alloctechnology(clus);
193 if (tech == NOTECHNOLOGY) return;
194
195 /* set the technology name */
196 if (allocstring(&tech->techname, newtechname, clus)) return;
197 efree((CHAR *)newtechname);
198 if (modified != 0)
199 ttyputmsg(_("Warning: already a technology called %s. Naming this %s"),
200 techname, tech->techname);
201
202 /* set technology description */
203 if (allocstring(&tech->techdescript, tech->techname, clus)) return;
204
205 /* free any previous memory for the technology */
206 us_tecedfreetechmemory();
207
208 /* get list of dependent libraries */
209 dependentlibcount = us_teceditgetdependents(lib, &dependentlibs);
210
211 /* initialize the state of this technology */
212 us_tecflags = 0;
213 if (us_tecedmakefactors(dependentlibs, dependentlibcount, tech)) return;
214
215 /* build layer structures */
216 if (us_tecedmakelayers(dependentlibs, dependentlibcount, tech)) return;
217
218 /* build arc structures */
219 if (us_tecedmakearcs(dependentlibs, dependentlibcount, tech)) return;
220
221 /* build node structures */
222 if (us_tecedmakenodes(dependentlibs, dependentlibcount, tech)) return;
223
224 /* copy any miscellaneous variables (should use dependent libraries facility) */
225 var = getval((INTBIG)lib, VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_variable_list"));
226 if (var != NOVARIABLE)
227 {
228 j = getlength(var);
229 varnames = (CHAR **)var->addr;
230 for(i=0; i<j; i++)
231 {
232 ovar = getval((INTBIG)lib, VLIBRARY, -1, varnames[i]);
233 if (ovar == NOVARIABLE) continue;
234 (void)setval((INTBIG)tech, VTECHNOLOGY, varnames[i], ovar->addr, ovar->type);
235 }
236 }
237
238 /* check technology for consistency */
239 us_tecedcheck(tech);
240
241 if (dumpformat > 0)
242 {
243 /* print the technology as C code */
244 infstr = initinfstr();
245 addstringtoinfstr(infstr, x_("tec"));
246 addstringtoinfstr(infstr, techname);
247 addstringtoinfstr(infstr, x_(".c"));
248 f = xcreate(returninfstr(infstr), el_filetypetext, _("Technology Code File"), &truename);
249 if (f == NULL)
250 {
251 if (truename != 0) ttyputerr(_("Cannot write %s"), truename);
252 return;
253 }
254 ttyputverbose(M_("Writing: %s"), truename);
255
256 /* write the layers, arcs, and nodes */
257 us_teceditdumplayers(f, tech, techname);
258 us_teceditdumparcs(f, tech, techname);
259 us_teceditdumpnodes(f, tech, techname);
260 us_teceditdumpvars(f, tech, techname);
261
262 /* clean up */
263 xclose(f);
264 }
265
266 if (dumpformat < 0)
267 {
268 /* print the technology as Java code */
269 infstr = initinfstr();
270 addstringtoinfstr(infstr, techname);
271 addstringtoinfstr(infstr, x_(".java"));
272 f = xcreate(returninfstr(infstr), el_filetypetext, _("Technology Code File"), &truename);
273 if (f == NULL)
274 {
275 if (truename != 0) ttyputerr(_("Cannot write %s"), truename);
276 return;
277 }
278 ttyputverbose(M_("Writing: %s"), truename);
279
280 /* write the layers, arcs, and nodes */
281 us_teceditdumpjavalayers(f, tech, techname);
282 us_teceditdumpjavaarcs(f, tech, techname);
283 us_teceditdumpjavanodes(f, tech, techname);
284 xprintf(f, x_("}\n"));
285
286 /* clean up */
287 xclose(f);
288 }
289
290 /* finish initializing the technology */
291 if ((us_tecflags&HASGRAB) == 0) us_tecvariables[0].name = 0; else
292 {
293 us_tecvariables[0].name = x_("prototype_center");
294 us_tecvariables[0].value = (CHAR *)us_tecnode_grab;
295 us_tecvariables[0].type = us_tecnode_grabcount/3;
296 }
297 tech->variables = us_tecvariables;
298 if (tech_doinitprocess(tech)) return;
299 if (tech_doaddportsandvars(tech)) return;
300
301 /* install the technology fully */
302 addtechnology(tech);
303
304 /* let the user interface process it */
305 us_figuretechopaque(tech);
306
307 /* switch to this technology */
308 ttyputmsg(_("Technology %s built. Switching to it."), tech->techname);
309 us_setnodeproto(NONODEPROTO);
310 us_setarcproto(NOARCPROTO, TRUE);
311
312 /* disable option tracking while colormap is updated */
313 (void)setvalkey((INTBIG)us_tool, VTOOL, us_ignoreoptionchangeskey, 1,
314 VINTEGER|VDONTSAVE);
315 us_getcolormap(tech, COLORSEXISTING, TRUE);
316 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_ignoreoptionchangeskey);
317 if (var != NOVARIABLE)
318 (void)delvalkey((INTBIG)us_tool, VTOOL, us_ignoreoptionchangeskey);
319
320 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_technology_key, (INTBIG)tech,
321 VTECHNOLOGY|VDONTSAVE);
322
323 /* fix up the menu entries */
324 us_setmenunodearcs();
325 if ((us_state&NONPERSISTENTCURNODE) == 0) us_setnodeproto(tech->firstnodeproto);
326 us_setarcproto(tech->firstarcproto, TRUE);
327 }
328
us_tecedcheck(TECHNOLOGY * tech)329 void us_tecedcheck(TECHNOLOGY *tech)
330 {
331 REGISTER INTBIG i, j, k, l;
332 REGISTER TECH_POLYGON *plist;
333 REGISTER TECH_NODES *nlist;
334
335 /* make sure there is a pure-layer node for every nonpseudo layer */
336 for(i=0; i<tech->layercount; i++)
337 {
338 if ((us_teclayer_function[i]&LFPSEUDO) != 0) continue;
339 for(j=0; j<tech->nodeprotocount; j++)
340 {
341 nlist = tech->nodeprotos[j];
342 if (((nlist->initialbits&NFUNCTION)>>NFUNCTIONSH) != NPNODE) continue;
343 plist = &nlist->layerlist[0];
344 if (plist->layernum == i) break;
345 }
346 if (j < tech->nodeprotocount) continue;
347 ttyputmsg(_("Warning: Layer %s has no associated pure-layer node"),
348 us_teclayer_names[i]);
349 }
350
351 /* make sure there is a pin for every arc and that it uses pseudo-layers */
352 for(i=0; i<tech->arcprotocount; i++)
353 {
354 for(j=0; j<tech->nodeprotocount; j++)
355 {
356 nlist = tech->nodeprotos[j];
357 if (((nlist->initialbits&NFUNCTION)>>NFUNCTIONSH) != NPPIN) continue;
358 for(k=0; k<nlist->portcount; k++)
359 {
360 for(l=1; nlist->portlist[k].portarcs[l] >= 0; l++)
361 if (nlist->portlist[k].portarcs[l] == i) break;
362 if (nlist->portlist[k].portarcs[l] >= 0) break;
363 }
364 if (k < nlist->portcount) break;
365 }
366 if (j < tech->nodeprotocount)
367 {
368 /* pin found: make sure it uses pseudo-layers */
369 nlist = tech->nodeprotos[j];
370 for(k=0; k<nlist->layercount; k++)
371 {
372 plist = &nlist->layerlist[k];
373 if ((us_teclayer_function[plist->layernum]&LFPSEUDO) == 0) break;
374 }
375 if (k < nlist->layercount)
376 ttyputmsg(_("Warning: Pin %s is not composed of pseudo-layers"),
377 tech->nodeprotos[j]->nodename);
378 continue;
379 }
380 ttyputmsg(_("Warning: Arc %s has no associated pin node"), tech->arcprotos[i]->arcname);
381 }
382 }
383
us_tecedfreetechmemory(void)384 void us_tecedfreetechmemory(void)
385 {
386 REGISTER INTBIG i;
387 REGISTER PCON *pc;
388 REGISTER RULE *r;
389
390 /* free DRC layer name information */
391 if (us_teceddrclayernames != 0)
392 {
393 for(i=0; i<us_teceddrclayers; i++) efree(us_teceddrclayernames[i]);
394 efree((CHAR *)us_teceddrclayernames);
395 us_teceddrclayernames = 0;
396 }
397
398 if (us_teclayer_iname != 0)
399 {
400 for(i=0; i<us_teclayer_count; i++)
401 if (us_teclayer_iname[i] != 0) efree((CHAR *)us_teclayer_iname[i]);
402 efree((CHAR *)us_teclayer_iname);
403 us_teclayer_iname = 0;
404 }
405 if (us_teclayer_names != 0)
406 {
407 for(i=0; i<us_teclayer_count; i++)
408 if (us_teclayer_names[i] != 0) efree((CHAR *)us_teclayer_names[i]);
409 efree((CHAR *)us_teclayer_names);
410 us_teclayer_names = 0;
411 }
412 if (us_teccif_layers != 0)
413 {
414 for(i=0; i<us_teclayer_count; i++)
415 if (us_teccif_layers[i] != 0) efree((CHAR *)us_teccif_layers[i]);
416 efree((CHAR *)us_teccif_layers);
417 us_teccif_layers = 0;
418 }
419 if (us_tecdxf_layers != 0)
420 {
421 for(i=0; i<us_teclayer_count; i++)
422 if (us_tecdxf_layers[i] != 0) efree((CHAR *)us_tecdxf_layers[i]);
423 efree((CHAR *)us_tecdxf_layers);
424 us_tecdxf_layers = 0;
425 }
426 if (us_tecgds_layers != 0)
427 {
428 for(i=0; i<us_teclayer_count; i++)
429 if (us_tecgds_layers[i] != 0) efree((CHAR *)us_tecgds_layers[i]);
430 efree((CHAR *)us_tecgds_layers);
431 us_tecgds_layers = 0;
432 }
433 if (us_teclayer_function != 0)
434 {
435 efree((CHAR *)us_teclayer_function);
436 us_teclayer_function = 0;
437 }
438 if (us_teclayer_letters != 0)
439 {
440 for(i=0; i<us_teclayer_count; i++)
441 if (us_teclayer_letters[i] != 0) efree((CHAR *)us_teclayer_letters[i]);
442 efree((CHAR *)us_teclayer_letters);
443 us_teclayer_letters = 0;
444 }
445 if (us_tecdrc_rules != 0)
446 {
447 dr_freerules(us_tecdrc_rules);
448 us_tecdrc_rules = 0;
449 }
450 if (us_tecspice_res != 0)
451 {
452 efree((CHAR *)us_tecspice_res);
453 us_tecspice_res = 0;
454 }
455 if (us_tecspice_cap != 0)
456 {
457 efree((CHAR *)us_tecspice_cap);
458 us_tecspice_cap = 0;
459 }
460 if (us_tecspice_ecap != 0)
461 {
462 efree((CHAR *)us_tecspice_ecap);
463 us_tecspice_ecap = 0;
464 }
465 if (us_tec3d_height != 0)
466 {
467 efree((CHAR *)us_tec3d_height);
468 us_tec3d_height = 0;
469 }
470 if (us_tec3d_thickness != 0)
471 {
472 efree((CHAR *)us_tec3d_thickness);
473 us_tec3d_thickness = 0;
474 }
475 if (us_tecprint_colors != 0)
476 {
477 efree((CHAR *)us_tecprint_colors);
478 us_tecprint_colors = 0;
479 }
480
481 if (us_tecarc_widoff != 0)
482 {
483 efree((CHAR *)us_tecarc_widoff);
484 us_tecarc_widoff = 0;
485 }
486
487 if (us_tecnode_widoff != 0)
488 {
489 efree((CHAR *)us_tecnode_widoff);
490 us_tecnode_widoff = 0;
491 }
492 if (us_tecnode_grab != 0)
493 {
494 efree((CHAR *)us_tecnode_grab);
495 us_tecnode_grab = 0;
496 }
497
498 while (us_tecedfirstpcon != NOPCON)
499 {
500 pc = us_tecedfirstpcon;
501 us_tecedfirstpcon = us_tecedfirstpcon->nextpcon;
502 efree((CHAR *)pc->connects);
503 efree((CHAR *)pc->assoc);
504 efree((CHAR *)pc);
505 }
506
507 while (us_tecedfirstrule != NORULE)
508 {
509 r = us_tecedfirstrule;
510 us_tecedfirstrule = us_tecedfirstrule->nextrule;
511 efree((CHAR *)r->value);
512 efree((CHAR *)r);
513 }
514 }
515
516 /*
517 * routine to scan the "dependentlibcount" libraries in "dependentlibs",
518 * and get global factors for technology "tech". Returns true on error.
519 */
us_tecedmakefactors(LIBRARY ** dependentlibs,INTBIG dependentlibcount,TECHNOLOGY * tech)520 BOOLEAN us_tecedmakefactors(LIBRARY **dependentlibs, INTBIG dependentlibcount, TECHNOLOGY *tech)
521 {
522 REGISTER NODEPROTO *np;
523 REGISTER NODEINST *ni;
524 REGISTER VARIABLE *var;
525 REGISTER INTBIG opt;
526 REGISTER CHAR *str;
527 REGISTER INTBIG i;
528
529 np = NONODEPROTO;
530 for(i=dependentlibcount-1; i>=0; i--)
531 {
532 for(np = dependentlibs[i]->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
533 if (namesame(np->protoname, x_("factors")) == 0) break;
534 if (np != NONODEPROTO) break;
535 }
536 if (np == NONODEPROTO)
537 {
538 tech->deflambda = 2000;
539 return(FALSE);
540 }
541
542 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
543 {
544 opt = us_tecedgetoption(ni);
545 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
546 if (var == NOVARIABLE) continue;
547 str = (CHAR *)var->addr;
548 switch (opt)
549 {
550 case TECHLAMBDA: /* lambda */
551 tech->deflambda = myatoi(&str[8]);
552 break;
553 case TECHDESCRIPT: /* description */
554 (void)reallocstring(&tech->techdescript, &str[13], tech->cluster);
555 break;
556 default:
557 us_tecedpointout(ni, np);
558 ttyputerr(_("Unknown object in miscellaneous-information cell"));
559 return(TRUE);
560 }
561 }
562 return(FALSE);
563 }
564
565 /*
566 * routine to scan the "dependentlibcount" libraries in "dependentlibs",
567 * and build the layer structures for it in technology "tech". Returns true on error.
568 */
us_tecedmakelayers(LIBRARY ** dependentlibs,INTBIG dependentlibcount,TECHNOLOGY * tech)569 BOOLEAN us_tecedmakelayers(LIBRARY **dependentlibs, INTBIG dependentlibcount, TECHNOLOGY *tech)
570 {
571 REGISTER NODEPROTO *np;
572 NODEPROTO **sequence, **nodesequence;
573 REGISTER INTBIG i, j, l, total, nodecount, *drcptr, drcsize;
574 REGISTER CHAR *ab;
575 REGISTER VARIABLE *var;
576 REGISTER void *infstr;
577
578 /* first find the number of layers */
579 tech->layercount = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("layer-"),
580 x_("EDTEC_layersequence"), &sequence);
581 if (tech->layercount <= 0)
582 {
583 ttyputerr(_("No layers found"));
584 if ((us_tool->toolstate&NODETAILS) == 0)
585 ttyputerr(_("Create them with the 'edit-layer' option"));
586 return(TRUE);
587 }
588
589 /* allocate the arrays for the layers */
590 us_teclayer_count = tech->layercount;
591 drcsize = us_teclayer_count*us_teclayer_count/2 + (us_teclayer_count+1)/2;
592
593 us_teclayer_iname = (CHAR **)emalloc((us_teclayer_count * (sizeof (CHAR *))), us_tool->cluster);
594 if (us_teclayer_iname == 0) return(TRUE);
595 for(i=0; i<us_teclayer_count; i++) us_teclayer_iname[i] = 0;
596
597 tech->layers = (GRAPHICS **)emalloc(((us_teclayer_count+1) * (sizeof (GRAPHICS *))), tech->cluster);
598 if (tech->layers == 0) return(TRUE);
599 for(i=0; i<us_teclayer_count; i++) tech->layers[i] = (GRAPHICS *)emalloc(sizeof (GRAPHICS), tech->cluster);
600 tech->layers[us_teclayer_count] = NOGRAPHICS;
601
602 us_teclayer_names = (CHAR **)emalloc((us_teclayer_count * (sizeof (CHAR *))), us_tool->cluster);
603 if (us_teclayer_names == 0) return(TRUE);
604 for(i=0; i<us_teclayer_count; i++) us_teclayer_names[i] = 0;
605
606 us_teccif_layers = (CHAR **)emalloc((us_teclayer_count * (sizeof (CHAR *))), us_tool->cluster);
607 if (us_teccif_layers == 0) return(TRUE);
608 for(i=0; i<us_teclayer_count; i++) us_teccif_layers[i] = 0;
609
610 us_tecdxf_layers = (CHAR **)emalloc((us_teclayer_count * (sizeof (CHAR *))), us_tool->cluster);
611 if (us_tecdxf_layers == 0) return(TRUE);
612 for(i=0; i<us_teclayer_count; i++) us_tecdxf_layers[i] = 0;
613
614 us_tecgds_layers = (CHAR **)emalloc((us_teclayer_count * (sizeof (CHAR *))), us_tool->cluster);
615 if (us_tecgds_layers == 0) return(TRUE);
616 for(i=0; i<us_teclayer_count; i++) us_tecgds_layers[i] = 0;
617
618 us_teclayer_function = emalloc((us_teclayer_count * SIZEOFINTBIG), us_tool->cluster);
619 if (us_teclayer_function == 0) return(TRUE);
620
621 us_teclayer_letters = (CHAR **)emalloc((us_teclayer_count * (sizeof (CHAR *))), us_tool->cluster);
622 if (us_teclayer_letters == 0) return(TRUE);
623 for(i=0; i<us_teclayer_count; i++) us_teclayer_letters[i] = 0;
624
625 us_tecspice_res = (float *)emalloc((us_teclayer_count * (sizeof (float))), us_tool->cluster);
626 if (us_tecspice_res == 0) return(TRUE);
627 for(i=0; i<us_teclayer_count; i++) us_tecspice_res[i] = 0.0;
628
629 us_tecspice_cap = (float *)emalloc((us_teclayer_count * (sizeof (float))), us_tool->cluster);
630 if (us_tecspice_cap == 0) return(TRUE);
631 for(i=0; i<us_teclayer_count; i++) us_tecspice_cap[i] = 0.0;
632
633 us_tecspice_ecap = (float *)emalloc((us_teclayer_count * (sizeof (float))), us_tool->cluster);
634 if (us_tecspice_ecap == 0) return(TRUE);
635 for(i=0; i<us_teclayer_count; i++) us_tecspice_ecap[i] = 0.0;
636
637 us_tec3d_height = (INTBIG *)emalloc((us_teclayer_count * SIZEOFINTBIG), us_tool->cluster);
638 if (us_tec3d_height == 0) return(TRUE);
639 for(i=0; i<us_teclayer_count; i++) us_tec3d_height[i] = 0;
640
641 us_tec3d_thickness = (INTBIG *)emalloc((us_teclayer_count * SIZEOFINTBIG), us_tool->cluster);
642 if (us_tec3d_thickness == 0) return(TRUE);
643 for(i=0; i<us_teclayer_count; i++) us_tec3d_thickness[i] = 0;
644
645 us_tecprint_colors = (INTBIG *)emalloc((us_teclayer_count * 5 * SIZEOFINTBIG), us_tool->cluster);
646 if (us_tecprint_colors == 0) return(TRUE);
647 for(i=0; i<us_teclayer_count*5; i++) us_tecprint_colors[i] = 0;
648
649 /* get the design rules */
650 us_tecedgetlayernamelist();
651 if (us_tecdrc_rules != 0)
652 {
653 dr_freerules(us_tecdrc_rules);
654 us_tecdrc_rules = 0;
655 }
656 nodecount = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("node-"),
657 x_("EDTEC_nodesequence"), &nodesequence);
658 us_tecdrc_rules = dr_allocaterules(us_teceddrclayers, nodecount, x_("EDITED TECHNOLOGY"));
659 if (us_tecdrc_rules == NODRCRULES) return(TRUE);
660 for(i=0; i<us_teceddrclayers; i++)
661 (void)allocstring(&us_tecdrc_rules->layernames[i], us_teceddrclayernames[i], el_tempcluster);
662 for(i=0; i<nodecount; i++)
663 (void)allocstring(&us_tecdrc_rules->nodenames[i], &nodesequence[i]->protoname[5], el_tempcluster);
664 if (nodecount > 0) efree((CHAR *)nodesequence);
665 var = NOVARIABLE;
666 for(i=dependentlibcount-1; i>=0; i--)
667 {
668 var = getval((INTBIG)dependentlibs[i], VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_DRC"));
669 if (var != NOVARIABLE) break;
670 }
671 us_teceditgetdrcarrays(var, us_tecdrc_rules);
672
673 /* now scan each layer and fill in the data */
674 for(total=0; total<us_teclayer_count; total++)
675 {
676 /* set the layer name */
677 np = sequence[total];
678 (void)allocstring(&us_teclayer_names[total], &np->protoname[6], us_tool->cluster);
679
680 if (us_teceditgetlayerinfo(np, tech->layers[total], &us_teccif_layers[total],
681 &us_teclayer_function[total], &us_teclayer_letters[total], &us_tecdxf_layers[total],
682 &us_tecgds_layers[total], &us_tecspice_res[total], &us_tecspice_cap[total],
683 &us_tecspice_ecap[total], &us_tecdrc_rules->minwidth[total],
684 &us_tec3d_height[total], &us_tec3d_thickness[total],
685 &us_tecprint_colors[total*5])) return(TRUE);
686 if (us_teccif_layers[total] != 0 && namesame(us_teccif_layers[total], x_("xx")) != 0)
687 us_tecflags |= HASCIF;
688 if (us_tecdxf_layers[total] != 0) us_tecflags |= HASDXF;
689 if (us_tecgds_layers[total] != 0) us_tecflags |= HASGDS;
690 if (us_tecspice_res[total] != 0.0) us_tecflags |= HASSPIRES;
691 if (us_tecspice_cap[total] != 0.0) us_tecflags |= HASSPICAP;
692 if (us_tecspice_ecap[total] != 0.0) us_tecflags |= HASSPIECAP;
693 if (us_tec3d_height[total] != 0 || us_tec3d_thickness[total] != 0) us_tecflags |= HAS3DINFO;
694 if (us_tecprint_colors[total*5] != 0 || us_tecprint_colors[total*5+1] != 0 ||
695 us_tecprint_colors[total*5+2] != 0 || us_tecprint_colors[total*5+3] != 0 ||
696 us_tecprint_colors[total*5+4] != 0) us_tecflags |= HASPRINTCOL;
697 tech->layers[total]->firstvar = NOVARIABLE;
698 tech->layers[total]->numvar = 0;
699 }
700
701 for(i=0; i<total; i++)
702 {
703 (void)allocstring(&us_teclayer_iname[i], makeabbrev(us_teclayer_names[i], TRUE),
704 us_tool->cluster);
705
706 /* loop until the name is unique */
707 for(;;)
708 {
709 /* see if a previously assigned abbreviation is the same */
710 for(j=0; j<i; j++)
711 if (namesame(us_teclayer_iname[i], us_teclayer_iname[j]) == 0)
712 break;
713 if (j >= i) break;
714
715 /* name conflicts: change it */
716 l = estrlen(ab = us_teclayer_iname[i]);
717 if (ab[l-1] >= '0' && ab[l-1] <= '8') ab[l-1]++; else
718 {
719 infstr = initinfstr();
720 addstringtoinfstr(infstr, ab);
721 addtoinfstr(infstr, '0');
722 (void)reallocstring(&us_teclayer_iname[i], returninfstr(infstr), us_tool->cluster);
723 }
724 }
725 }
726
727 /* get the color map */
728 var = NOVARIABLE;
729 for(i=dependentlibcount-1; i>=0; i--)
730 {
731 var = getval((INTBIG)dependentlibs[i], VLIBRARY, VINTEGER|VISARRAY, x_("EDTEC_colormap"));
732 if (var != NOVARIABLE) break;
733 }
734 if (var != NOVARIABLE)
735 {
736 us_tecflags |= HASCOLORMAP;
737 drcptr = (INTBIG *)var->addr;
738 for(i=0; i<32; i++)
739 {
740 us_teccolmap[i].red = (INTSML)drcptr[(i<<2)*3];
741 us_teccolmap[i].green = (INTSML)drcptr[(i<<2)*3+1];
742 us_teccolmap[i].blue = (INTSML)drcptr[(i<<2)*3+2];
743 }
744 }
745
746 /* see which design rules exist */
747 for(i=0; i<us_teceddrclayers; i++)
748 {
749 if (us_tecdrc_rules->minwidth[i] >= 0) us_tecflags |= HASDRCMINWID;
750 if (*us_tecdrc_rules->minwidthR[i] != 0) us_tecflags |= HASDRCMINWIDR;
751 }
752 for(i=0; i<drcsize; i++)
753 {
754 if (us_tecdrc_rules->conlist[i] >= 0) us_tecflags |= HASCONDRC;
755 if (*us_tecdrc_rules->conlistR[i] != 0) us_tecflags |= HASCONDRCR;
756 if (us_tecdrc_rules->unconlist[i] >= 0) us_tecflags |= HASUNCONDRC;
757 if (*us_tecdrc_rules->unconlistR[i] != 0) us_tecflags |= HASUNCONDRCR;
758 if (us_tecdrc_rules->conlistW[i] >= 0) us_tecflags |= HASCONDRCW;
759 if (*us_tecdrc_rules->conlistWR[i] != 0) us_tecflags |= HASCONDRCWR;
760 if (us_tecdrc_rules->unconlistW[i] >= 0) us_tecflags |= HASUNCONDRCW;
761 if (*us_tecdrc_rules->unconlistWR[i] != 0) us_tecflags |= HASUNCONDRCWR;
762 if (us_tecdrc_rules->conlistM[i] >= 0) us_tecflags |= HASCONDRCM;
763 if (*us_tecdrc_rules->conlistMR[i] != 0) us_tecflags |= HASCONDRCMR;
764 if (us_tecdrc_rules->unconlistM[i] >= 0) us_tecflags |= HASUNCONDRCM;
765 if (*us_tecdrc_rules->unconlistMR[i] != 0) us_tecflags |= HASUNCONDRCMR;
766 if (us_tecdrc_rules->edgelist[i] >= 0) us_tecflags |= HASEDGEDRC;
767 if (*us_tecdrc_rules->edgelistR[i] != 0) us_tecflags |= HASEDGEDRCR;
768 }
769 for(i=0; i<us_tecdrc_rules->numnodes; i++)
770 {
771 if (us_tecdrc_rules->minnodesize[i*2] > 0 ||
772 us_tecdrc_rules->minnodesize[i*2+1] > 0) us_tecflags |= HASMINNODE;
773 if (*us_tecdrc_rules->minnodesizeR[i] != 0) us_tecflags |= HASMINNODER;
774 }
775
776 /* store this information on the technology object */
777 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("TECH_layer_names"), (INTBIG)us_teclayer_names,
778 VSTRING|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
779 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("TECH_layer_function"), (INTBIG)us_teclayer_function,
780 VINTEGER|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
781 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, us_layer_letters_key, (INTBIG)us_teclayer_letters,
782 VSTRING|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
783 if ((us_tecflags&HASCOLORMAP) != 0)
784 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("USER_color_map"), (INTBIG)us_teccolmap,
785 VCHAR|VDONTSAVE|VISARRAY|((sizeof us_teccolmap)<<VLENGTHSH));
786 if ((us_tecflags&HASCIF) != 0)
787 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("IO_cif_layer_names"), (INTBIG)us_teccif_layers,
788 VSTRING|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
789 if ((us_tecflags&HASDXF) != 0)
790 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("IO_dxf_layer_names"), (INTBIG)us_tecdxf_layers,
791 VSTRING|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
792 if ((us_tecflags&HASGDS) != 0)
793 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("IO_gds_layer_numbers"), (INTBIG)us_tecgds_layers,
794 VSTRING|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
795
796 if ((us_tecflags&(HASCONDRCW|HASUNCONDRCW)) != 0)
797 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_wide_limitkey, us_tecdrc_rules->widelimit,
798 VFRACT|VDONTSAVE);
799 if ((us_tecflags&HASDRCMINWID) != 0)
800 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_min_widthkey, (INTBIG)us_tecdrc_rules->minwidth,
801 VFRACT|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
802 if ((us_tecflags&HASDRCMINWIDR) != 0)
803 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_min_width_rulekey, (INTBIG)us_tecdrc_rules->minwidthR,
804 VSTRING|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
805 if ((us_tecflags&HASCONDRC) != 0)
806 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_connected_distanceskey,
807 (INTBIG)us_tecdrc_rules->conlist, VFRACT|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
808 if ((us_tecflags&HASCONDRCR) != 0)
809 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_connected_distances_rulekey,
810 (INTBIG)us_tecdrc_rules->conlistR, VSTRING|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
811 if ((us_tecflags&HASUNCONDRC) != 0)
812 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_unconnected_distanceskey,
813 (INTBIG)us_tecdrc_rules->unconlist, VFRACT|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
814 if ((us_tecflags&HASUNCONDRCR) != 0)
815 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_unconnected_distances_rulekey,
816 (INTBIG)us_tecdrc_rules->unconlistR, VSTRING|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
817 if ((us_tecflags&HASCONDRCW) != 0)
818 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_connected_distancesWkey,
819 (INTBIG)us_tecdrc_rules->conlistW, VFRACT|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
820 if ((us_tecflags&HASCONDRCWR) != 0)
821 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_connected_distancesW_rulekey,
822 (INTBIG)us_tecdrc_rules->conlistWR, VSTRING|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
823 if ((us_tecflags&HASUNCONDRCW) != 0)
824 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_unconnected_distancesWkey,
825 (INTBIG)us_tecdrc_rules->unconlistW, VFRACT|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
826 if ((us_tecflags&HASUNCONDRCWR) != 0)
827 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_unconnected_distancesW_rulekey,
828 (INTBIG)us_tecdrc_rules->unconlistWR, VSTRING|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
829 if ((us_tecflags&HASCONDRCM) != 0)
830 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_connected_distancesMkey,
831 (INTBIG)us_tecdrc_rules->conlistM, VFRACT|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
832 if ((us_tecflags&HASCONDRCMR) != 0)
833 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_connected_distancesM_rulekey,
834 (INTBIG)us_tecdrc_rules->conlistMR, VSTRING|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
835 if ((us_tecflags&HASUNCONDRCM) != 0)
836 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_unconnected_distancesMkey,
837 (INTBIG)us_tecdrc_rules->unconlistM, VFRACT|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
838 if ((us_tecflags&HASUNCONDRCMR) != 0)
839 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_unconnected_distancesM_rulekey,
840 (INTBIG)us_tecdrc_rules->unconlistMR, VSTRING|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
841 if ((us_tecflags&HASEDGEDRC) != 0)
842 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_edge_distanceskey,
843 (INTBIG)us_tecdrc_rules->edgelist, VFRACT|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
844 if ((us_tecflags&HASEDGEDRCR) != 0)
845 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_edge_distances_rulekey,
846 (INTBIG)us_tecdrc_rules->edgelistR, VSTRING|VDONTSAVE|VISARRAY|(drcsize<<VLENGTHSH));
847 if ((us_tecflags&HASMINNODE) != 0)
848 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_min_node_sizekey,
849 (INTBIG)us_tecdrc_rules->minnodesize, VFRACT|VDONTSAVE|VISARRAY|((us_tecdrc_rules->numnodes*2)<<VLENGTHSH));
850 if ((us_tecflags&HASMINNODER) != 0)
851 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, dr_min_node_size_rulekey,
852 (INTBIG)us_tecdrc_rules->minnodesizeR, VSTRING|VDONTSAVE|VISARRAY|(us_tecdrc_rules->numnodes<<VLENGTHSH));
853 if ((us_tecflags&HASSPIRES) != 0)
854 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("SIM_spice_resistance"), (INTBIG)us_tecspice_res,
855 VFLOAT|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
856 if ((us_tecflags&HASSPICAP) != 0)
857 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("SIM_spice_capacitance"), (INTBIG)us_tecspice_cap,
858 VFLOAT|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
859 if ((us_tecflags&HASSPIECAP) != 0)
860 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("SIM_spice_edge_capacitance"), (INTBIG)us_tecspice_ecap,
861 VFLOAT|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
862 if ((us_tecflags&HAS3DINFO) != 0)
863 {
864 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("TECH_layer_3dheight"), (INTBIG)us_tec3d_height,
865 VINTEGER|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
866 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("TECH_layer_3dthickness"), (INTBIG)us_tec3d_thickness,
867 VINTEGER|VDONTSAVE|VISARRAY|(tech->layercount<<VLENGTHSH));
868 }
869 if ((us_tecflags&HASPRINTCOL) != 0)
870 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("USER_print_colors"), (INTBIG)us_tecprint_colors,
871 VINTEGER|VDONTSAVE|VISARRAY|((tech->layercount*5)<<VLENGTHSH));
872
873
874 efree((CHAR *)sequence);
875 return(FALSE);
876 }
877
878 /*
879 * routine to scan the "dependentlibcount" libraries in "dependentlibs",
880 * and build the arc structures for it in technology "tech". Returns true on error.
881 */
us_tecedmakearcs(LIBRARY ** dependentlibs,INTBIG dependentlibcount,TECHNOLOGY * tech)882 BOOLEAN us_tecedmakearcs(LIBRARY **dependentlibs, INTBIG dependentlibcount,
883 TECHNOLOGY *tech)
884 {
885 REGISTER NODEPROTO *np;
886 NODEPROTO **sequence;
887 REGISTER INTBIG arcindex, count, j, k, layerindex, typ;
888 REGISTER INTBIG maxwid, hwid, wid, lambda;
889 REGISTER CHAR *str;
890 REGISTER NODEINST *ni;
891 REGISTER EXAMPLE *nelist;
892 REGISTER SAMPLE *ns;
893 REGISTER VARIABLE *var;
894
895 /* count the number of arcs in the technology */
896 us_tecarc_count = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("arc-"),
897 x_("EDTEC_arcsequence"), &sequence);
898 if (us_tecarc_count <= 0)
899 {
900 ttyputerr(_("No arcs found"));
901 if ((us_tool->toolstate&NODETAILS) == 0)
902 ttyputerr(_("Create them with the 'edit-arc' option"));
903 return(TRUE);
904 }
905 tech->arcprotocount = us_tecarc_count;
906
907 /* allocate the arcs */
908 tech->arcprotos = (TECH_ARCS **)emalloc(((us_tecarc_count+1) * (sizeof (TECH_ARCS *))),
909 tech->cluster);
910 if (tech->arcprotos == 0) return(TRUE);
911 tech->arcprotos[us_tecarc_count] = ((TECH_ARCS *)-1);
912 us_tecarc_widoff = emalloc((us_tecarc_count * SIZEOFINTBIG), us_tool->cluster);
913 if (us_tecarc_widoff == 0) return(TRUE);
914
915 /* create the arc structures */
916 lambda = el_curlib->lambda[art_tech->techindex];
917 for(arcindex=0; arcindex<us_tecarc_count; arcindex++)
918 {
919 /* build a list of examples found in this arc */
920 np = sequence[arcindex];
921 nelist = us_tecedgetexamples(np, FALSE);
922 if (nelist == NOEXAMPLE) return(TRUE);
923 if (nelist->nextexample != NOEXAMPLE)
924 {
925 us_tecedpointout(NONODEINST, np);
926 ttyputerr(_("Can only be one example of %s but more were found"),
927 describenodeproto(np));
928 us_tecedfreeexamples(nelist);
929 return(TRUE);
930 }
931
932 /* get width and polygon count information */
933 count = 0;
934 maxwid = hwid = -1;
935 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
936 {
937 wid = mini(ns->node->highx - ns->node->lowx, ns->node->highy - ns->node->lowy);
938 if (wid > maxwid) maxwid = wid;
939 if (ns->layer == NONODEPROTO) hwid = wid; else count++;
940 }
941
942 /* error if there is no highlight box */
943 if (hwid < 0)
944 {
945 us_tecedpointout(NONODEINST, np);
946 ttyputerr(_("No highlight layer found in %s"), describenodeproto(np));
947 if ((us_tool->toolstate&NODETAILS) == 0)
948 ttyputmsg(_("Use 'place-layer' option to create HIGHLIGHT"));
949 us_tecedfreeexamples(nelist);
950 return(TRUE);
951 }
952
953 /* create and fill the basic structure entries for this arc */
954 tech->arcprotos[arcindex] = (TECH_ARCS *)emalloc(sizeof (TECH_ARCS), tech->cluster);
955 if (tech->arcprotos[arcindex] == 0) return(TRUE);
956 (void)allocstring(&tech->arcprotos[arcindex]->arcname, &np->protoname[4],
957 tech->cluster);
958 tech->arcprotos[arcindex]->arcwidth = maxwid * WHOLE / lambda;
959 tech->arcprotos[arcindex]->arcindex = arcindex;
960 tech->arcprotos[arcindex]->creation = NOARCPROTO;
961 tech->arcprotos[arcindex]->laycount = count;
962 us_tecarc_widoff[arcindex] = (maxwid - hwid) * WHOLE / lambda;
963 if (us_tecarc_widoff[arcindex] != 0) us_tecflags |= HASARCWID;
964
965 /* look for descriptive nodes in the cell */
966 tech->arcprotos[arcindex]->initialbits = 0;
967 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
968 {
969 typ = us_tecedgetoption(ni);
970 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
971 if (var == NOVARIABLE) continue;
972
973 /* the "Function:" node */
974 if (typ == ARCFUNCTION)
975 {
976 str = us_teceditgetparameter(var);
977 for(j=0; us_tecarc_functions[j].name != 0; j++)
978 if (namesame(str, us_tecarc_functions[j].name) == 0)
979 {
980 tech->arcprotos[arcindex]->initialbits |=
981 (us_tecarc_functions[j].value << AFUNCTIONSH);
982 break;
983 }
984 }
985
986 /* the "Fixed-angle:" node */
987 if (typ == ARCFIXANG)
988 {
989 str = (CHAR *)var->addr;
990 if (str[9] == ':') str = &str[11]; else str = &str[13];
991 if (namesame(str, x_("yes")) == 0)
992 tech->arcprotos[arcindex]->initialbits |= WANTFIXANG;
993 }
994
995 /* the "Wipes pins:" node */
996 if (typ == ARCWIPESPINS)
997 {
998 str = us_teceditgetparameter(var);
999 if (namesame(str, x_("yes")) == 0)
1000 tech->arcprotos[arcindex]->initialbits |= CANWIPE;
1001 }
1002
1003 /* the "Extend arcs:" node */
1004 if (typ == ARCNOEXTEND)
1005 {
1006 str = us_teceditgetparameter(var);
1007 if (namesame(str, x_("no")) == 0)
1008 tech->arcprotos[arcindex]->initialbits |= WANTNOEXTEND;
1009 }
1010
1011 /* the "Angle increment:" node */
1012 if (typ == ARCINC)
1013 {
1014 str = us_teceditgetparameter(var);
1015 j = myatoi(str) % 360;
1016 if (j < 0) j += 360;
1017 tech->arcprotos[arcindex]->initialbits &= ~AANGLEINC;
1018 tech->arcprotos[arcindex]->initialbits |= (j << AANGLEINCSH);
1019 }
1020 }
1021
1022 /* allocate the individual arc layer structures */
1023 tech->arcprotos[arcindex]->list = (TECH_ARCLAY *)emalloc((count * (sizeof (TECH_ARCLAY))),
1024 tech->cluster);
1025 if (tech->arcprotos[arcindex]->list == 0) return(TRUE);
1026
1027 /* fill the individual arc layer structures */
1028 layerindex = 0;
1029 for(k=0; k<2; k++)
1030 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
1031 {
1032 if (ns->layer == NONODEPROTO) continue;
1033
1034 /* get the layer index */
1035 for(j=0; j<tech->layercount; j++)
1036 if (namesame(&ns->layer->protoname[6], us_teclayer_names[j]) == 0) break;
1037 if (j >= tech->layercount)
1038 {
1039 ttyputerr(_("Cannot find layer %s, used in %s"), describenodeproto(ns->layer),
1040 describenodeproto(np));
1041 us_tecedfreeexamples(nelist);
1042 return(TRUE);
1043 }
1044
1045 /* only add transparent layers when k=0 */
1046 if (k == 0)
1047 {
1048 if (tech->layers[j]->bits == LAYERO) continue;
1049 } else
1050 {
1051 if (tech->layers[j]->bits != LAYERO) continue;
1052 }
1053
1054 tech->arcprotos[arcindex]->list[layerindex].lay = j;
1055
1056 /* determine the style of this arc layer */
1057 if (ns->node->proto == art_filledboxprim)
1058 tech->arcprotos[arcindex]->list[layerindex].style = FILLED; else
1059 tech->arcprotos[arcindex]->list[layerindex].style = CLOSED;
1060
1061 /* determine the width offset of this arc layer */
1062 wid = mini(ns->node->highx-ns->node->lowx, ns->node->highy-ns->node->lowy);
1063 tech->arcprotos[arcindex]->list[layerindex].off = (maxwid-wid) * WHOLE /
1064 lambda;
1065
1066 layerindex++;
1067 }
1068 us_tecedfreeexamples(nelist);
1069 }
1070
1071 /* store width offset on the technology */
1072 if ((us_tecflags&HASARCWID) != 0)
1073 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("TECH_arc_width_offset"), (INTBIG)us_tecarc_widoff,
1074 VFRACT|VDONTSAVE|VISARRAY|(us_tecarc_count<<VLENGTHSH));
1075 efree((CHAR *)sequence);
1076 return(FALSE);
1077 }
1078
1079 /*
1080 * routine to scan the "dependentlibcount" libraries in "dependentlibs",
1081 * and build the node structures for it in technology "tech". Returns true on error.
1082 */
us_tecedmakenodes(LIBRARY ** dependentlibs,INTBIG dependentlibcount,TECHNOLOGY * tech)1083 BOOLEAN us_tecedmakenodes(LIBRARY **dependentlibs, INTBIG dependentlibcount,
1084 TECHNOLOGY *tech)
1085 {
1086 REGISTER NODEPROTO *np;
1087 NODEPROTO **sequence;
1088 REGISTER NODEINST *ni;
1089 REGISTER VARIABLE *var;
1090 REGISTER CHAR *str, *portname;
1091 REGISTER INTBIG *list, save1, nfunction, x1pos, x2pos, y1pos, y2pos, net, lambda;
1092 REGISTER INTBIG i, j, k, l, m, pass, nodeindex, sty, difindex, polindex,
1093 serpdifind, opt, nsindex, err, portchecked;
1094 INTBIG pol1port, pol2port, dif1port, dif2port;
1095 INTBIG serprule[8];
1096 REGISTER EXAMPLE *nelist;
1097 REGISTER SAMPLE *ns, *ons, *diflayer, *pollayer;
1098 REGISTER PCON *pc;
1099 REGISTER RULE *r;
1100 REGISTER TECH_NODES *tlist;
1101
1102 /* no rectangle rules */
1103 us_tecedfirstrule = NORULE;
1104
1105 us_tecnode_count = us_teceditfindsequence(dependentlibs, dependentlibcount, x_("node-"),
1106 x_("EDTEC_nodesequence"), &sequence);
1107 if (us_tecnode_count <= 0)
1108 {
1109 ttyputerr(_("No nodes found"));
1110 if ((us_tool->toolstate&NODETAILS) == 0)
1111 ttyputerr(_("Create them with the 'edit-node' option"));
1112 return(TRUE);
1113 }
1114 tech->nodeprotocount = us_tecnode_count;
1115
1116 /* allocate the nodes */
1117 tech->nodeprotos = (TECH_NODES **)emalloc((us_tecnode_count+1) *
1118 (sizeof (TECH_NODES *)), tech->cluster);
1119 if (tech->nodeprotos == 0) return(TRUE);
1120 tech->nodeprotos[us_tecnode_count] = ((TECH_NODES *)-1);
1121 us_tecnode_widoff = emalloc((4*us_tecnode_count * SIZEOFINTBIG), us_tool->cluster);
1122 if (us_tecnode_widoff == 0) return(TRUE);
1123 us_tecnode_grab = emalloc((3*us_tecnode_count * SIZEOFINTBIG), us_tool->cluster);
1124 if (us_tecnode_grab == 0) return(TRUE);
1125 us_tecnode_grabcount = 0;
1126
1127 /* get the nodes */
1128 lambda = el_curlib->lambda[art_tech->techindex];
1129 nodeindex = 0;
1130 for(pass=0; pass<3; pass++)
1131 for(m=0; m<us_tecnode_count; m++)
1132 {
1133 /* make sure this is the right type of node for this pass of the nodes */
1134 np = sequence[m];
1135 nfunction = NPUNKNOWN;
1136 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1137 {
1138 /* get the node function */
1139 if (us_tecedgetoption(ni) != NODEFUNCTION) continue;
1140 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
1141 if (var == NOVARIABLE) continue;
1142 str = us_teceditgetparameter(var);
1143 for(j=0; j<MAXNODEFUNCTION; j++)
1144 if (namesame(str, nodefunctionname(j, NONODEINST)) == 0) break;
1145 if (j < MAXNODEFUNCTION)
1146 {
1147 nfunction = j;
1148 break;
1149 }
1150 }
1151
1152 /* only want pins on pass 0, pure-layer nodes on pass 2 */
1153 if (pass == 0 && nfunction != NPPIN) continue;
1154 if (pass == 1 && (nfunction == NPPIN || nfunction == NPNODE)) continue;
1155 if (pass == 2 && nfunction != NPNODE) continue;
1156
1157 /* build a list of examples found in this node */
1158 nelist = us_tecedgetexamples(np, TRUE);
1159 if (nelist == NOEXAMPLE) return(TRUE);
1160
1161 /* associate the samples in each example */
1162 if (us_tecedassociateexamples(nelist, np))
1163 {
1164 us_tecedfreeexamples(nelist);
1165 return(TRUE);
1166 }
1167
1168 /* allocate and fill the TECH_NODES structure */
1169 tlist = (TECH_NODES *)emalloc(sizeof (TECH_NODES), tech->cluster);
1170 if (tlist == 0) return(TRUE);
1171 tech->nodeprotos[nodeindex] = tlist;
1172 (void)allocstring(&tlist->nodename, &np->protoname[5], tech->cluster);
1173 tlist->nodeindex = (INTSML)(nodeindex + 1);
1174 tlist->creation = NONODEPROTO;
1175 tlist->xsize = (nelist->hx-nelist->lx)*WHOLE/lambda;
1176 tlist->ysize = (nelist->hy-nelist->ly)*WHOLE/lambda;
1177 tlist->layerlist = 0;
1178 tlist->layercount = 0;
1179 tlist->special = 0;
1180 tlist->f1 = 0;
1181 tlist->f2 = 0;
1182 tlist->f3 = 0;
1183 tlist->f4 = 0;
1184 tlist->f5 = 0;
1185 tlist->f6 = 0;
1186 tlist->gra = 0;
1187 tlist->ele = 0;
1188
1189 /* determine user bits */
1190 tlist->initialbits = nfunction<<NFUNCTIONSH;
1191 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1192 {
1193 opt = us_tecedgetoption(ni);
1194
1195 /* pick up square node information */
1196 if (opt == NODESQUARE)
1197 {
1198 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
1199 if (var == NOVARIABLE) continue;
1200 str = us_teceditgetparameter(var);
1201 if (namesame(str, x_("yes")) == 0) tlist->initialbits |= NSQUARE;
1202 continue;
1203 }
1204
1205 /* pick up invisible on 1 or 2 arc information */
1206 if (opt == NODEWIPES)
1207 {
1208 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
1209 if (var == NOVARIABLE) continue;
1210 str = us_teceditgetparameter(var);
1211 if (namesame(str, x_("yes")) == 0)
1212 tlist->initialbits = WIPEON1OR2 | (tlist->initialbits & ~(ARCSWIPE|ARCSHRINK));
1213 continue;
1214 }
1215
1216 /* pick up lockable information */
1217 if (opt == NODELOCKABLE)
1218 {
1219 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
1220 if (var == NOVARIABLE) continue;
1221 str = us_teceditgetparameter(var);
1222 if (namesame(str, x_("yes")) == 0) tlist->initialbits |= LOCKEDPRIM;
1223 continue;
1224 }
1225
1226 /* pick up multicut information */
1227 if (opt == NODEMULTICUT)
1228 {
1229 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
1230 if (var == NOVARIABLE) continue;
1231 str = us_teceditgetparameter(var);
1232 tlist->f4 = (INTSML)atofr(str);
1233 continue;
1234 }
1235
1236 /* pick up serpentine transistor information */
1237 if (opt == NODESERPENTINE)
1238 {
1239 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
1240 if (var == NOVARIABLE) continue;
1241 str = us_teceditgetparameter(var);
1242 if (namesame(str, x_("yes")) == 0)
1243 {
1244 if (tlist->special != 0)
1245 {
1246 us_tecedpointout(ni, np);
1247 ttyputerr(_("Serpentine %s must have Transistor function"),
1248 describenodeproto(np));
1249 us_tecedfreeexamples(nelist);
1250 return(TRUE);
1251 }
1252 tlist->special = SERPTRANS;
1253 tlist->initialbits |= (NODESHRINK | HOLDSTRACE);
1254 }
1255 continue;
1256 }
1257 }
1258
1259 /* derive primitives from the examples */
1260 if (us_tecedmakeprim(nelist, np, tech, tlist, lambda))
1261 {
1262 us_tecedfreeexamples(nelist);
1263 efree((CHAR *)tlist->nodename);
1264 efree((CHAR *)tlist);
1265 return(TRUE);
1266 }
1267
1268 /* analyze special node function circumstances */
1269 switch (nfunction)
1270 {
1271 case NPNODE:
1272 if (tlist->special != 0)
1273 {
1274 us_tecedpointout(NONODEINST, np);
1275 ttyputerr(_("Pure layer %s can not be serpentine"), describenodeproto(np));
1276 us_tecedfreeexamples(nelist);
1277 return(TRUE);
1278 }
1279 tlist->special = POLYGONAL;
1280 tlist->initialbits |= HOLDSTRACE;
1281 break;
1282 case NPPIN:
1283 if ((tlist->initialbits&WIPEON1OR2) == 0)
1284 {
1285 tlist->initialbits |= ARCSWIPE;
1286 tlist->initialbits |= ARCSHRINK;
1287 }
1288 break;
1289 }
1290
1291 /* count the number of ports on this node */
1292 tlist->portcount = 0;
1293 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
1294 if (ns->layer == gen_portprim) tlist->portcount++;
1295 if (tlist->portcount == 0)
1296 {
1297 us_tecedpointout(NONODEINST, np);
1298 ttyputerr(_("No ports found in %s"), describenodeproto(np));
1299 if ((us_tool->toolstate&NODETAILS) == 0)
1300 ttyputmsg(_("Use 'place-layer port' option to create one"));
1301 us_tecedfreeexamples(nelist);
1302 return(TRUE);
1303 }
1304
1305 /* allocate space for the ports */
1306 tlist->portlist = (TECH_PORTS *)emalloc((tlist->portcount * (sizeof (TECH_PORTS))),
1307 tech->cluster);
1308 if (tlist->portlist == 0) return(TRUE);
1309
1310 /* fill the port structures */
1311 pol1port = pol2port = dif1port = dif2port = -1;
1312 i = 0;
1313 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
1314 {
1315 if (ns->layer != gen_portprim) continue;
1316
1317 /* port connections */
1318 var = getval((INTBIG)ns->node, VNODEINST, VNODEPROTO|VISARRAY, x_("EDTEC_connects"));
1319 if (var == NOVARIABLE) pc = us_tecedaddportlist(0, (INTBIG *)0); else
1320 {
1321 /* convert "arc-CELL" pointers to indices */
1322 l = getlength(var);
1323 list = emalloc((l * SIZEOFINTBIG), el_tempcluster);
1324 if (list == 0) return(TRUE);
1325 portchecked = 0;
1326 for(j=0; j<l; j++)
1327 {
1328 /* find arc that connects */
1329 for(k=0; k<tech->arcprotocount; k++)
1330 if (namesame(tech->arcprotos[k]->arcname,
1331 &((NODEPROTO **)var->addr)[j]->protoname[4]) == 0) break;
1332 if (k >= tech->arcprotocount)
1333 {
1334 us_tecedpointout(ns->node, ns->node->parent);
1335 ttyputerr(_("Invalid connection list on port in %s"),
1336 describenodeproto(np));
1337 if ((us_tool->toolstate&NODETAILS) == 0)
1338 ttyputmsg(_("Use 'change' option to remove arc %s"),
1339 &((NODEPROTO **)var->addr)[j]->protoname[4]);
1340 us_tecedfreeexamples(nelist);
1341 return(TRUE);
1342 }
1343
1344 /* fill in the connection information */
1345 list[j] = k;
1346
1347 /* find port characteristics for possible transistors */
1348 if (portchecked != 0) continue;
1349 switch ((tech->arcprotos[k]->initialbits&AFUNCTION)>>AFUNCTIONSH)
1350 {
1351 case APPOLY1: case APPOLY2:
1352 if (pol1port < 0)
1353 {
1354 pol1port = i;
1355 portchecked++;
1356 } else if (pol2port < 0)
1357 {
1358 pol2port = i;
1359 portchecked++;
1360 }
1361 break;
1362 case APDIFF: case APDIFFP: case APDIFFN:
1363 case APDIFFS: case APDIFFW:
1364 if (dif1port < 0)
1365 {
1366 dif1port = i;
1367 portchecked++;
1368 } else if (dif2port < 0)
1369 {
1370 dif2port = i;
1371 portchecked++;
1372 }
1373 break;
1374 }
1375 }
1376
1377 /* store complete list in memory */
1378 pc = us_tecedaddportlist(l, list);
1379 efree((CHAR *)list);
1380 }
1381
1382 /* link connection list to the port */
1383 if (pc == NOPCON) return(TRUE);
1384 tlist->portlist[i].portarcs = pc->connects;
1385
1386 /* port name */
1387 portname = us_tecedgetportname(ns->node);
1388 if (portname == 0)
1389 {
1390 us_tecedpointout(ns->node, np);
1391 ttyputerr(_("Cell %s: port does not have a name"), describenodeproto(np));
1392 us_tecedfreeexamples(nelist);
1393 return(TRUE);
1394 }
1395 for(str = portname; *str != 0; str++)
1396 if (*str <= ' ' || *str >= 0177)
1397 {
1398 us_tecedpointout(ns->node, np);
1399 ttyputerr(_("Invalid port name '%s' in %s"), portname,
1400 describenodeproto(np));
1401 us_tecedfreeexamples(nelist);
1402 return(TRUE);
1403 }
1404 (void)allocstring(&tlist->portlist[i].protoname, portname, tech->cluster);
1405
1406 /* port angle and range */
1407 tlist->portlist[i].initialbits = 0;
1408 var = getval((INTBIG)ns->node, VNODEINST, VINTEGER, x_("EDTEC_portangle"));
1409 if (var != NOVARIABLE)
1410 tlist->portlist[i].initialbits |= var->addr << PORTANGLESH;
1411 var = getval((INTBIG)ns->node, VNODEINST, VINTEGER, x_("EDTEC_portrange"));
1412 if (var != NOVARIABLE)
1413 tlist->portlist[i].initialbits |= var->addr << PORTARANGESH; else
1414 tlist->portlist[i].initialbits |= 180 << PORTARANGESH;
1415
1416 /* port connectivity */
1417 net = i;
1418 if (ns->node->firstportarcinst != NOPORTARCINST)
1419 {
1420 j = 0;
1421 for(ons = nelist->firstsample; ons != ns; ons = ons->nextsample)
1422 {
1423 if (ons->layer != gen_portprim) continue;
1424 if (ons->node->firstportarcinst != NOPORTARCINST)
1425 {
1426 if (ns->node->firstportarcinst->conarcinst->network ==
1427 ons->node->firstportarcinst->conarcinst->network)
1428 {
1429 net = j;
1430 break;
1431 }
1432 }
1433 j++;
1434 }
1435 }
1436 tlist->portlist[i].initialbits |= (net << PORTNETSH);
1437
1438 /* port area rule */
1439 r = ns->rule;
1440 if (r == NORULE) continue;
1441 tlist->portlist[i].lowxmul = (INTSML)r->value[0];
1442 tlist->portlist[i].lowxsum = (INTSML)r->value[1];
1443 tlist->portlist[i].lowymul = (INTSML)r->value[2];
1444 tlist->portlist[i].lowysum = (INTSML)r->value[3];
1445 tlist->portlist[i].highxmul = (INTSML)r->value[4];
1446 tlist->portlist[i].highxsum = (INTSML)r->value[5];
1447 tlist->portlist[i].highymul = (INTSML)r->value[6];
1448 tlist->portlist[i].highysum = (INTSML)r->value[7];
1449 i++;
1450 }
1451
1452 /* on FET transistors, make sure ports 0 and 2 are poly */
1453 if (nfunction == NPTRANMOS || nfunction == NPTRADMOS || nfunction == NPTRAPMOS ||
1454 nfunction == NPTRADMES || nfunction == NPTRAEMES)
1455 {
1456 if (pol1port < 0 || pol2port < 0 || dif1port < 0 || dif2port < 0)
1457 {
1458 us_tecedpointout(NONODEINST, np);
1459 ttyputerr(_("Need 2 gate and 2 active ports on field-effect transistor %s"),
1460 describenodeproto(np));
1461 us_tecedfreeexamples(nelist);
1462 return(TRUE);
1463 }
1464 if (pol1port != 0)
1465 {
1466 if (pol2port == 0) us_tecedswapports(&pol1port, &pol2port, tlist); else
1467 if (dif1port == 0) us_tecedswapports(&pol1port, &dif1port, tlist); else
1468 if (dif2port == 0) us_tecedswapports(&pol1port, &dif2port, tlist);
1469 }
1470 if (pol2port != 2)
1471 {
1472 if (dif1port == 2) us_tecedswapports(&pol2port, &dif1port, tlist); else
1473 if (dif2port == 2) us_tecedswapports(&pol2port, &dif2port, tlist);
1474 }
1475 if (dif1port != 1) us_tecedswapports(&dif1port, &dif2port, tlist);
1476
1477 /* also make sure that dif1port is positive and dif2port is negative */
1478 x1pos = (tlist->portlist[dif1port].lowxmul*tlist->xsize +
1479 tlist->portlist[dif1port].lowxsum +
1480 tlist->portlist[dif1port].highxmul*tlist->xsize +
1481 tlist->portlist[dif1port].highxsum) / 2;
1482 x2pos = (tlist->portlist[dif2port].lowxmul*tlist->xsize +
1483 tlist->portlist[dif2port].lowxsum +
1484 tlist->portlist[dif2port].highxmul*tlist->xsize +
1485 tlist->portlist[dif2port].highxsum) / 2;
1486 y1pos = (tlist->portlist[dif1port].lowymul*tlist->ysize +
1487 tlist->portlist[dif1port].lowysum +
1488 tlist->portlist[dif1port].highymul*tlist->ysize +
1489 tlist->portlist[dif1port].highysum) / 2;
1490 y2pos = (tlist->portlist[dif2port].lowymul*tlist->ysize +
1491 tlist->portlist[dif2port].lowysum +
1492 tlist->portlist[dif2port].highymul*tlist->ysize +
1493 tlist->portlist[dif2port].highysum) / 2;
1494 if (abs(x1pos-x2pos) > abs(y1pos-y2pos))
1495 {
1496 if (x1pos < x2pos)
1497 {
1498 us_tecedswapports(&dif1port, &dif2port, tlist);
1499 j = dif1port; dif1port = dif2port; dif2port = j;
1500 }
1501 } else
1502 {
1503 if (y1pos < y2pos)
1504 {
1505 us_tecedswapports(&dif1port, &dif2port, tlist);
1506 j = dif1port; dif1port = dif2port; dif2port = j;
1507 }
1508 }
1509
1510 /* also make sure that pol1port is negative and pol2port is positive */
1511 x1pos = (tlist->portlist[pol1port].lowxmul*tlist->xsize +
1512 tlist->portlist[pol1port].lowxsum +
1513 tlist->portlist[pol1port].highxmul*tlist->xsize +
1514 tlist->portlist[pol1port].highxsum) / 2;
1515 x2pos = (tlist->portlist[pol2port].lowxmul*tlist->xsize +
1516 tlist->portlist[pol2port].lowxsum +
1517 tlist->portlist[pol2port].highxmul*tlist->xsize +
1518 tlist->portlist[pol2port].highxsum) / 2;
1519 y1pos = (tlist->portlist[pol1port].lowymul*tlist->ysize +
1520 tlist->portlist[pol1port].lowysum +
1521 tlist->portlist[pol1port].highymul*tlist->ysize +
1522 tlist->portlist[pol1port].highysum) / 2;
1523 y2pos = (tlist->portlist[pol2port].lowymul*tlist->ysize +
1524 tlist->portlist[pol2port].lowysum +
1525 tlist->portlist[pol2port].highymul*tlist->ysize +
1526 tlist->portlist[pol2port].highysum) / 2;
1527 if (abs(x1pos-x2pos) > abs(y1pos-y2pos))
1528 {
1529 if (x1pos > x2pos)
1530 {
1531 us_tecedswapports(&pol1port, &pol2port, tlist);
1532 j = pol1port; pol1port = pol2port; pol2port = j;
1533 }
1534 } else
1535 {
1536 if (y1pos > y2pos)
1537 {
1538 us_tecedswapports(&pol1port, &pol2port, tlist);
1539 j = pol1port; pol1port = pol2port; pol2port = j;
1540 }
1541 }
1542 }
1543
1544 /* count the number of layers on the node */
1545 tlist->layercount = 0;
1546 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
1547 {
1548 if (ns->rule != NORULE && ns->layer != gen_portprim &&
1549 ns->layer != gen_cellcenterprim && ns->layer != NONODEPROTO)
1550 tlist->layercount++;
1551 }
1552
1553 /* allocate space for the layers */
1554 if (tlist->special != SERPTRANS)
1555 {
1556 tlist->layerlist = (TECH_POLYGON *)emalloc((tlist->layercount *
1557 (sizeof (TECH_POLYGON))), tech->cluster);
1558 if (tlist->layerlist == 0) return(TRUE);
1559 } else
1560 {
1561 tlist->gra = (TECH_SERPENT *)emalloc(((sizeof (TECH_SERPENT)) * tlist->layercount),
1562 tech->cluster);
1563 if (tlist->gra == 0) return(TRUE);
1564 tlist->ele = (TECH_SERPENT *)emalloc(((sizeof (TECH_SERPENT)) * (tlist->layercount+1)),
1565 tech->cluster);
1566 if (tlist->ele == 0) return(TRUE);
1567 }
1568
1569 /* fill the layer structures (3 times: transparent, opaque, multicut) */
1570 i = 0;
1571 pollayer = diflayer = NOSAMPLE;
1572 for(k=0; k<3; k++)
1573 for(nsindex=0, ns = nelist->firstsample; ns != NOSAMPLE; nsindex++, ns = ns->nextsample)
1574 {
1575 r = ns->rule;
1576 if (r == NORULE || ns->layer == gen_portprim ||
1577 ns->layer == gen_cellcenterprim || ns->layer == NONODEPROTO) continue;
1578
1579 /* add cut layers last (only when k=2) */
1580 if (k == 2)
1581 {
1582 if (!r->multicut) continue;
1583 if (tlist->special != 0)
1584 {
1585 us_tecedpointout(ns->node, ns->node->parent);
1586 ttyputerr(_("%s is too complex (multiple cuts AND serpentine)"),
1587 describenodeproto(np));
1588 us_tecedfreeexamples(nelist);
1589 return(TRUE);
1590 }
1591 tlist->special = MULTICUT;
1592 tlist->f1 = (INTSML)(r->multixs*WHOLE/lambda);
1593 tlist->f2 = (INTSML)(r->multiys*WHOLE/lambda);
1594 tlist->f3 = (INTSML)(r->multiindent*WHOLE/lambda);
1595 tlist->f4 = (INTSML)(r->multisep*WHOLE/lambda);
1596 } else
1597 {
1598 if (r->multicut) continue;
1599 }
1600
1601 /* layer number */
1602 for(j=0; j<tech->layercount; j++)
1603 if (namesame(&ns->layer->protoname[6], us_teclayer_names[j]) == 0) break;
1604 if (j >= tech->layercount)
1605 {
1606 ttyputerr(_("Cannot find layer %s in %s"), describenodeproto(ns->layer),
1607 describenodeproto(np));
1608 return(TRUE);
1609 }
1610
1611 /* only add transparent layers when k=0 */
1612 if (k == 0)
1613 {
1614 if (tech->layers[j]->bits == LAYERO) continue;
1615 } else if (k == 1)
1616 {
1617 if (tech->layers[j]->bits != LAYERO) continue;
1618 }
1619
1620 /* layer style */
1621 sty = -1;
1622 if (ns->node->proto == art_filledboxprim) sty = FILLEDRECT; else
1623 if (ns->node->proto == art_boxprim) sty = CLOSEDRECT; else
1624 if (ns->node->proto == art_crossedboxprim) sty = CROSSED; else
1625 if (ns->node->proto == art_filledpolygonprim) sty = FILLED; else
1626 if (ns->node->proto == art_closedpolygonprim) sty = CLOSED; else
1627 if (ns->node->proto == art_openedpolygonprim) sty = OPENED; else
1628 if (ns->node->proto == art_openeddottedpolygonprim) sty = OPENEDT1; else
1629 if (ns->node->proto == art_openeddashedpolygonprim) sty = OPENEDT2; else
1630 if (ns->node->proto == art_openedthickerpolygonprim) sty = OPENEDT3; else
1631 if (ns->node->proto == art_filledcircleprim) sty = DISC; else
1632 if (ns->node->proto == art_circleprim)
1633 {
1634 var = getvalkey((INTBIG)ns->node, VNODEINST, VINTEGER, art_degreeskey);
1635 if (var != NOVARIABLE) sty = CIRCLEARC; else sty = CIRCLE;
1636 } else if (ns->node->proto == art_thickcircleprim)
1637 {
1638 var = getvalkey((INTBIG)ns->node, VNODEINST, VINTEGER, art_degreeskey);
1639 if (var != NOVARIABLE) sty = THICKCIRCLEARC; else sty = THICKCIRCLE;
1640 } else if (ns->node->proto == gen_invispinprim)
1641 {
1642 var = getvalkey((INTBIG)ns->node, VNODEINST, VSTRING|VISARRAY, art_messagekey);
1643 if (var != NOVARIABLE)
1644 {
1645 switch (TDGETPOS(var->textdescript))
1646 {
1647 case VTPOSBOXED: sty = TEXTBOX; break;
1648 case VTPOSCENT: sty = TEXTCENT; break;
1649 case VTPOSUP: sty = TEXTBOT; break;
1650 case VTPOSDOWN: sty = TEXTTOP; break;
1651 case VTPOSLEFT: sty = TEXTRIGHT; break;
1652 case VTPOSRIGHT: sty = TEXTLEFT; break;
1653 case VTPOSUPLEFT: sty = TEXTBOTRIGHT; break;
1654 case VTPOSUPRIGHT: sty = TEXTBOTLEFT; break;
1655 case VTPOSDOWNLEFT: sty = TEXTTOPRIGHT; break;
1656 case VTPOSDOWNRIGHT: sty = TEXTTOPLEFT; break;
1657 }
1658 }
1659 }
1660 if (sty == -1)
1661 ttyputmsg(_("Cannot determine style to use for %s node in %s"),
1662 describenodeproto(ns->node->proto), describenodeproto(np));
1663
1664 /* load the layer structure(s) */
1665 if (tlist->special == SERPTRANS)
1666 {
1667 /* determine port numbers for serpentine transistors */
1668 if (layerismetal(us_teclayer_function[j]))
1669 {
1670 tlist->gra[i].basics.portnum = 0;
1671 } else if (layerispoly(us_teclayer_function[j]))
1672 {
1673 pollayer = ns;
1674 if (pol1port >= 0)
1675 tlist->gra[i].basics.portnum = (INTSML)pol1port; else
1676 tlist->gra[i].basics.portnum = 0;
1677 polindex = i;
1678 } else if ((us_teclayer_function[j]&LFTYPE) == LFDIFF)
1679 {
1680 diflayer = ns;
1681 difindex = i;
1682 tlist->gra[i].basics.portnum = 0;
1683 } else
1684 {
1685 tlist->gra[i].basics.portnum = -1;
1686 }
1687
1688 tlist->gra[i].basics.layernum = (INTSML)j;
1689 tlist->gra[i].basics.count = (INTSML)(r->count/4);
1690 if (sty == CROSSED || sty == FILLEDRECT || sty == FILLED || sty == CLOSEDRECT ||
1691 sty == CLOSED)
1692 {
1693 if (tlist->gra[i].basics.count == 4)
1694 {
1695 ttyputmsg(_("Ignoring Minimum-Size setting on layer %s in serpentine transistor %s"),
1696 &ns->layer->protoname[6], &np->protoname[5]);
1697 tlist->gra[i].basics.count = 2;
1698 }
1699 }
1700 tlist->gra[i].basics.style = (INTSML)sty;
1701 if (tlist->gra[i].basics.count == 2 && (sty == CROSSED ||
1702 sty == FILLEDRECT || sty == FILLED || sty == CLOSEDRECT || sty == CLOSED))
1703 {
1704 tlist->gra[i].basics.representation = BOX;
1705 tlist->gra[i].basics.count = 4;
1706 } else tlist->gra[i].basics.representation = POINTS;
1707 tlist->gra[i].basics.points = r->value;
1708 tlist->gra[i].lwidth = (INTSML)nsindex;
1709 tlist->gra[i].rwidth = 0;
1710 tlist->gra[i].extendt = 0;
1711 tlist->gra[i].extendb = 0;
1712 } else
1713 {
1714 tlist->layerlist[i].portnum = (INTSML)us_tecedfindport(tlist, nelist,
1715 ns->node->lowx, ns->node->highx, ns->node->lowy, ns->node->highy,
1716 lambdaofnode(ns->node));
1717 tlist->layerlist[i].layernum = (INTSML)j;
1718 tlist->layerlist[i].count = (INTSML)(r->count/4);
1719 tlist->layerlist[i].style = (INTSML)sty;
1720 tlist->layerlist[i].representation = POINTS;
1721 if (sty == CROSSED || sty == FILLEDRECT || sty == FILLED || sty == CLOSEDRECT ||
1722 sty == CLOSED)
1723 {
1724 if (r->count == 8)
1725 {
1726 tlist->layerlist[i].representation = BOX;
1727 tlist->layerlist[i].count = 4;
1728 } else if (r->count == 16)
1729 {
1730 tlist->layerlist[i].representation = MINBOX;
1731 tlist->layerlist[i].count = 4;
1732 }
1733 }
1734 tlist->layerlist[i].points = r->value;
1735 }
1736
1737 /* mark this rectangle rule "used" */
1738 r->used = TRUE;
1739 i++;
1740 }
1741
1742 /* finish up serpentine transistors */
1743 if (tlist->special == SERPTRANS)
1744 {
1745 if (diflayer == NOSAMPLE || pollayer == NOSAMPLE || dif1port < 0)
1746 {
1747 us_tecedpointout(NONODEINST, np);
1748 ttyputerr(_("No diffusion and polysilicon layers in transistor %s"),
1749 describenodeproto(np));
1750 us_tecedfreeexamples(nelist);
1751 return(TRUE);
1752 }
1753
1754 /* compute port extension factors */
1755 tlist->f1 = tlist->layercount+1;
1756 if (tlist->portlist[dif1port].lowxsum >
1757 tlist->portlist[dif1port].lowysum)
1758 {
1759 /* vertical diffusion layer: determine polysilicon width */
1760 tlist->f4 = (INTSML)((muldiv(tlist->ysize, tlist->gra[polindex].basics.points[6], WHOLE) +
1761 tlist->gra[polindex].basics.points[7]) -
1762 (muldiv(tlist->ysize, tlist->gra[polindex].basics.points[2], WHOLE) +
1763 tlist->gra[polindex].basics.points[3]));
1764
1765 /* determine diffusion port rule */
1766 tlist->f2 = (INTSML)((muldiv(tlist->xsize, tlist->portlist[dif1port].lowxmul, WHOLE) +
1767 tlist->portlist[dif1port].lowxsum) -
1768 (muldiv(tlist->xsize, tlist->gra[difindex].basics.points[0], WHOLE) +
1769 tlist->gra[difindex].basics.points[1]));
1770 tlist->f3 = (INTSML)((muldiv(tlist->ysize, tlist->portlist[dif1port].lowymul, WHOLE) +
1771 tlist->portlist[dif1port].lowysum) -
1772 (muldiv(tlist->ysize, tlist->gra[polindex].basics.points[6], WHOLE) +
1773 tlist->gra[polindex].basics.points[7]));
1774
1775 /* determine polysilicon port rule */
1776 tlist->f5 = (INTSML)((muldiv(tlist->ysize, tlist->portlist[pol1port].lowymul, WHOLE) +
1777 tlist->portlist[pol1port].lowysum) -
1778 (muldiv(tlist->ysize, tlist->gra[polindex].basics.points[2], WHOLE) +
1779 tlist->gra[polindex].basics.points[3]));
1780 tlist->f6 = (INTSML)((muldiv(tlist->xsize, tlist->gra[difindex].basics.points[0], WHOLE) +
1781 tlist->gra[difindex].basics.points[1]) -
1782 (muldiv(tlist->xsize, tlist->portlist[pol1port].highxmul, WHOLE) +
1783 tlist->portlist[pol1port].highxsum));
1784 } else
1785 {
1786 /* horizontal diffusion layer: determine polysilicon width */
1787 tlist->f4 = (INTSML)((muldiv(tlist->xsize, tlist->gra[polindex].basics.points[4], WHOLE) +
1788 tlist->gra[polindex].basics.points[5]) -
1789 (muldiv(tlist->xsize, tlist->gra[polindex].basics.points[0], WHOLE) +
1790 tlist->gra[polindex].basics.points[1]));
1791
1792 /* determine diffusion port rule */
1793 tlist->f2 = (INTSML)((muldiv(tlist->ysize, tlist->portlist[dif1port].lowymul, WHOLE) +
1794 tlist->portlist[dif1port].lowysum) -
1795 (muldiv(tlist->ysize, tlist->gra[difindex].basics.points[2], WHOLE) +
1796 tlist->gra[difindex].basics.points[3]));
1797 tlist->f3 = (INTSML)((muldiv(tlist->xsize, tlist->gra[polindex].basics.points[0], WHOLE) +
1798 tlist->gra[polindex].basics.points[1]) -
1799 (muldiv(tlist->xsize, tlist->portlist[dif1port].highxmul, WHOLE) +
1800 tlist->portlist[dif1port].highxsum));
1801
1802 /* determine polysilicon port rule */
1803 tlist->f5 = (INTSML)((muldiv(tlist->xsize, tlist->portlist[pol1port].lowxmul, WHOLE) +
1804 tlist->portlist[pol1port].lowxsum) -
1805 (muldiv(tlist->xsize, tlist->gra[polindex].basics.points[0], WHOLE) +
1806 tlist->gra[polindex].basics.points[1]));
1807 tlist->f6 = (INTSML)((muldiv(tlist->ysize, tlist->gra[difindex].basics.points[2], WHOLE) +
1808 tlist->gra[difindex].basics.points[3]) -
1809 (muldiv(tlist->ysize, tlist->portlist[pol1port].highymul, WHOLE) +
1810 tlist->portlist[pol1port].highysum));
1811 }
1812
1813 /* find width and extension from comparison to poly layer */
1814 for(i=0; i<tlist->layercount; i++)
1815 {
1816 for(nsindex=0, ns = nelist->firstsample; ns != NOSAMPLE;
1817 nsindex++, ns = ns->nextsample)
1818 if (tlist->gra[i].lwidth == nsindex) break;
1819 if (ns == NOSAMPLE)
1820 {
1821 us_tecedpointout(NONODEINST, np);
1822 ttyputerr(_("Internal error in serpentine %s"), describenodeproto(np));
1823 us_tecedfreeexamples(nelist);
1824 continue;
1825 }
1826
1827 if (pollayer->node->highx-pollayer->node->lowx >
1828 pollayer->node->highy-pollayer->node->lowy)
1829 {
1830 /* horizontal layer */
1831 tlist->gra[i].lwidth = (INTSML)((ns->node->highy - (ns->parent->ly + ns->parent->hy)/2) *
1832 WHOLE/lambda);
1833 tlist->gra[i].rwidth = (INTSML)(((ns->parent->ly + ns->parent->hy)/2 - ns->node->lowy) *
1834 WHOLE/lambda);
1835 tlist->gra[i].extendt = (INTSML)((diflayer->node->lowx - ns->node->lowx) * WHOLE /
1836 lambda);
1837 } else
1838 {
1839 /* vertical layer */
1840 tlist->gra[i].lwidth = (INTSML)((ns->node->highx - (ns->parent->lx + ns->parent->hx)/2) *
1841 WHOLE/lambda);
1842 tlist->gra[i].rwidth = (INTSML)(((ns->parent->lx + ns->parent->hx)/2 - ns->node->lowx) *
1843 WHOLE/lambda);
1844 tlist->gra[i].extendt = (INTSML)((diflayer->node->lowy - ns->node->lowy) * WHOLE /
1845 lambda);
1846 }
1847 tlist->gra[i].extendb = tlist->gra[i].extendt;
1848 }
1849
1850 /* copy basic graphics to electrical version, doubling diffusion */
1851 i = 0;
1852 for(j=0; j<tlist->layercount; j++)
1853 {
1854 if (j != difindex) k = 1; else
1855 {
1856 k = 2;
1857
1858 /* copy rectangle rule and prepare for electrical layers */
1859 r = diflayer->rule;
1860 if (r->count != 8)
1861 {
1862 us_tecedpointout(NONODEINST, np);
1863 ttyputerr(_("Nonrectangular diffusion in Serpentine %s"),
1864 describenodeproto(np));
1865 us_tecedfreeexamples(nelist);
1866 return(TRUE);
1867 }
1868 for(l=0; l<r->count; l++) serprule[l] = r->value[l];
1869 if (serprule[0] != -H0 || serprule[2] != -H0 ||
1870 serprule[4] != H0 || serprule[6] != H0)
1871 {
1872 us_tecedpointout(NONODEINST, np);
1873 ttyputerr(_("Unusual diffusion in Serpentine %s"), describenodeproto(np));
1874 us_tecedfreeexamples(nelist);
1875 return(TRUE);
1876 }
1877 if (tlist->xsize - serprule[1] + serprule[5] <
1878 tlist->ysize - serprule[3] + serprule[7]) serpdifind = 2; else
1879 serpdifind = 0;
1880 }
1881 for(l=0; l<k; l++)
1882 {
1883 tlist->ele[i].basics.layernum = tlist->gra[j].basics.layernum;
1884 tlist->ele[i].basics.count = tlist->gra[j].basics.count;
1885 tlist->ele[i].basics.style = tlist->gra[j].basics.style;
1886 tlist->ele[i].basics.representation = tlist->gra[j].basics.representation;
1887 tlist->ele[i].basics.points = tlist->gra[j].basics.points;
1888 tlist->ele[i].lwidth = tlist->gra[j].lwidth;
1889 tlist->ele[i].rwidth = tlist->gra[j].rwidth;
1890 tlist->ele[i].extendt = tlist->gra[j].extendt;
1891 tlist->ele[i].extendb = tlist->gra[j].extendb;
1892 if (k == 1) tlist->ele[i].basics.portnum = tlist->gra[j].basics.portnum; else
1893 switch (l)
1894 {
1895 case 0:
1896 tlist->ele[i].basics.portnum = (INTSML)dif1port;
1897 tlist->ele[i].rwidth = -tlist->gra[polindex].lwidth;
1898 save1 = serprule[serpdifind+1];
1899
1900 /* in transistor, diffusion stops in center */
1901 serprule[serpdifind] = 0;
1902 serprule[serpdifind+1] = 0;
1903 r = us_tecedaddrule(serprule, 8, FALSE, (CHAR *)0);
1904 if (r == NORULE) return(TRUE);
1905 r->used = TRUE;
1906 tlist->ele[i].basics.points = r->value;
1907 serprule[serpdifind] = -H0;
1908 serprule[serpdifind+1] = save1;
1909 break;
1910 case 1:
1911 tlist->ele[i].basics.portnum = (INTSML)dif2port;
1912 tlist->ele[i].lwidth = -tlist->gra[polindex].rwidth;
1913 save1 = serprule[serpdifind+5];
1914
1915 /* in transistor, diffusion stops in center */
1916 serprule[serpdifind+4] = 0;
1917 serprule[serpdifind+5] = 0;
1918 r = us_tecedaddrule(serprule, 8, FALSE, (CHAR *)0);
1919 if (r == NORULE) return(TRUE);
1920 r->used = TRUE;
1921 tlist->ele[i].basics.points = r->value;
1922 serprule[serpdifind+4] = H0;
1923 serprule[serpdifind+5] = save1;
1924 break;
1925 }
1926 i++;
1927 }
1928 }
1929 }
1930
1931 /* extract width offset information */
1932 us_tecnode_widoff[nodeindex*4] = 0;
1933 us_tecnode_widoff[nodeindex*4+1] = 0;
1934 us_tecnode_widoff[nodeindex*4+2] = 0;
1935 us_tecnode_widoff[nodeindex*4+3] = 0;
1936 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
1937 if (ns->layer == NONODEPROTO) break;
1938 if (ns != NOSAMPLE)
1939 {
1940 r = ns->rule;
1941 if (r != NORULE)
1942 {
1943 err = 0;
1944 switch (r->value[0]) /* left edge offset */
1945 {
1946 case -H0:
1947 us_tecnode_widoff[nodeindex*4] = r->value[1];
1948 break;
1949 case H0:
1950 us_tecnode_widoff[nodeindex*4] = tlist->xsize + r->value[1];
1951 break;
1952 default:
1953 err++;
1954 break;
1955 }
1956 switch (r->value[2]) /* bottom edge offset */
1957 {
1958 case -H0:
1959 us_tecnode_widoff[nodeindex*4+2] = r->value[3];
1960 break;
1961 case H0:
1962 us_tecnode_widoff[nodeindex*4+2] = tlist->ysize + r->value[3];
1963 break;
1964 default:
1965 err++;
1966 break;
1967 }
1968 switch (r->value[4]) /* right edge offset */
1969 {
1970 case H0:
1971 us_tecnode_widoff[nodeindex*4+1] = -r->value[5];
1972 break;
1973 case -H0:
1974 us_tecnode_widoff[nodeindex*4+1] = tlist->xsize - r->value[5];
1975 break;
1976 default:
1977 err++;
1978 break;
1979 }
1980 switch (r->value[6]) /* top edge offset */
1981 {
1982 case H0:
1983 us_tecnode_widoff[nodeindex*4+3] = -r->value[7];
1984 break;
1985 case -H0:
1986 us_tecnode_widoff[nodeindex*4+3] = tlist->ysize - r->value[7];
1987 break;
1988 default:
1989 err++;
1990 break;
1991 }
1992 if (err != 0)
1993 {
1994 us_tecedpointout(ns->node, ns->node->parent);
1995 ttyputmsg(_("Highlighting cannot scale from center in %s"), describenodeproto(np));
1996 us_tecedfreeexamples(nelist);
1997 return(TRUE);
1998 }
1999 } else
2000 {
2001 us_tecedpointout(ns->node, ns->node->parent);
2002 ttyputerr(_("No rule found for highlight in %s"), describenodeproto(np));
2003 us_tecedfreeexamples(nelist);
2004 return(TRUE);
2005 }
2006 } else
2007 {
2008 us_tecedpointout(NONODEINST, np);
2009 ttyputerr(_("No highlight found in %s"), describenodeproto(np));
2010 if ((us_tool->toolstate&NODETAILS) == 0)
2011 ttyputmsg(_("Use 'place-layer' option to create HIGHLIGHT"));
2012 us_tecedfreeexamples(nelist);
2013 return(TRUE);
2014 }
2015
2016 /* get grab point information */
2017 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
2018 if (ns->layer == gen_cellcenterprim) break;
2019 if (ns != NOSAMPLE)
2020 {
2021 us_tecnode_grab[us_tecnode_grabcount++] = nodeindex+1;
2022 us_tecnode_grab[us_tecnode_grabcount++] = (ns->node->geom->lowx +
2023 ns->node->geom->highx - nelist->lx - nelist->hx)/2 *
2024 el_curlib->lambda[tech->techindex] / lambda;
2025 us_tecnode_grab[us_tecnode_grabcount++] = (ns->node->geom->lowy +
2026 ns->node->geom->highy - nelist->ly - nelist->hy)/2 *
2027 el_curlib->lambda[tech->techindex] / lambda;
2028 us_tecflags |= HASGRAB;
2029 }
2030
2031 /* free all examples */
2032 us_tecedfreeexamples(nelist);
2033
2034 /* advance the fill pointer */
2035 nodeindex++;
2036 }
2037
2038 /* store width offset on the technology */
2039 (void)setval((INTBIG)tech, VTECHNOLOGY, x_("TECH_node_width_offset"), (INTBIG)us_tecnode_widoff,
2040 VFRACT|VDONTSAVE|VISARRAY|((us_tecnode_count*4)<<VLENGTHSH));
2041 efree((CHAR *)sequence);
2042 return(FALSE);
2043 }
2044
2045 /*
2046 * routine to find the closest port to the layer describe by "lx<=X<=hx" and
2047 * "ly<+Y<=hy" in the list "nelist". The ports are listed in "tlist". The algorithm
2048 * is to find a port that overlaps this layer. If there is only one, or if all of
2049 * them electrically connect, use that. If there are no such ports, or multiple
2050 * unconnected ports, presume that the layer is not related to any port.
2051 */
us_tecedfindport(TECH_NODES * tlist,EXAMPLE * nelist,INTBIG lx,INTBIG hx,INTBIG ly,INTBIG hy,INTBIG lambda)2052 INTBIG us_tecedfindport(TECH_NODES *tlist, EXAMPLE *nelist, INTBIG lx, INTBIG hx, INTBIG ly,
2053 INTBIG hy, INTBIG lambda)
2054 {
2055 REGISTER INTBIG bestport, l, oldnet, newnet;
2056 INTBIG portlx, porthx, portly, porthy;
2057 REGISTER INTBIG swap;
2058
2059 bestport = -1;
2060 for(l=0; l<tlist->portcount; l++)
2061 {
2062 subrange(nelist->lx, nelist->hx, tlist->portlist[l].lowxmul,
2063 tlist->portlist[l].lowxsum, tlist->portlist[l].highxmul,
2064 tlist->portlist[l].highxsum, &portlx, &porthx, lambda);
2065 if (portlx > porthx)
2066 {
2067 swap = portlx; portlx = porthx; porthx = swap;
2068 }
2069 subrange(nelist->ly, nelist->hy, tlist->portlist[l].lowymul,
2070 tlist->portlist[l].lowysum, tlist->portlist[l].highymul,
2071 tlist->portlist[l].highysum, &portly, &porthy, lambda);
2072 if (portlx > porthx)
2073 {
2074 swap = portly; portly = porthy; porthy = swap;
2075 }
2076
2077 /* ignore the port if there is no intersection */
2078 if (lx > porthx || hx < portlx || ly > porthy || hy < portly) continue;
2079
2080 /* if there is no previous overlapping port, use this */
2081 if (bestport == -1)
2082 {
2083 bestport = l;
2084 continue;
2085 }
2086
2087 /* if these two ports connect, all is well */
2088 newnet = (tlist->portlist[l].initialbits & PORTNET) >> PORTNETSH;
2089 oldnet = (tlist->portlist[bestport].initialbits & PORTNET) >> PORTNETSH;
2090 if (newnet == oldnet) continue;
2091
2092 /* two unconnected ports intersect layer: make it free */
2093 return(-1);
2094 }
2095 return(bestport);
2096 }
2097
2098 /*
2099 * Routine to free the examples created by "us_tecedgetexamples()".
2100 */
us_tecedfreeexamples(EXAMPLE * nelist)2101 void us_tecedfreeexamples(EXAMPLE *nelist)
2102 {
2103 REGISTER EXAMPLE *ne;
2104 REGISTER SAMPLE *ns;
2105
2106 while (nelist != NOEXAMPLE)
2107 {
2108 ne = nelist;
2109 nelist = nelist->nextexample;
2110 while (ne->firstsample != NOSAMPLE)
2111 {
2112 ns = ne->firstsample;
2113 ne->firstsample = ne->firstsample->nextsample;
2114 efree((CHAR *)ns);
2115 }
2116 efree((CHAR *)ne);
2117 }
2118 }
2119
2120 /*
2121 * routine to parse the node examples in cell "np" and return a list of
2122 * EXAMPLEs (one per example). "isnode" is true if this is a node
2123 * being examined. Returns NOEXAMPLE on error.
2124 */
us_tecedgetexamples(NODEPROTO * np,BOOLEAN isnode)2125 EXAMPLE *us_tecedgetexamples(NODEPROTO *np, BOOLEAN isnode)
2126 {
2127 REGISTER SAMPLE *ns;
2128 REGISTER EXAMPLE *ne, *nelist, *bestne;
2129 REGISTER NODEINST *ni, *otherni;
2130 REGISTER INTBIG sea, sizex, sizey, newsize, locx, locy, lambda, hcount, funct;
2131 REGISTER BOOLEAN foundone, gotbbox;
2132 INTBIG lx, hx, ly, hy, sflx, sfhx, sfly, sfhy;
2133 REGISTER GEOM *geom;
2134 XARRAY trans;
2135 static POLYGON *poly = NOPOLYGON;
2136
2137 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2138 {
2139 ni->temp1 = (INTBIG)NOEXAMPLE;
2140
2141 /* ignore special nodes with function information */
2142 funct = us_tecedgetoption(ni);
2143 if (funct != LAYERPATCH && funct != PORTOBJ && funct != HIGHLIGHTOBJ) ni->temp1 = 0;
2144 }
2145
2146 nelist = NOEXAMPLE;
2147 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2148 {
2149 if (ni->temp1 != (INTBIG)NOEXAMPLE) continue;
2150
2151 /* get a new cluster of nodes */
2152 ne = (EXAMPLE *)emalloc((sizeof (EXAMPLE)), us_tool->cluster);
2153 if (ne == 0) return(NOEXAMPLE);
2154 ne->firstsample = NOSAMPLE;
2155 gotbbox = FALSE;
2156 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
2157 nodesizeoffset(ni, &lx, &ly, &hx, &hy);
2158 maketruerectpoly(ni->lowx+lx, ni->highx-hx, ni->lowy+ly, ni->highy-hy, poly);
2159 makerot(ni, trans);
2160 xformpoly(poly, trans);
2161 getbbox(poly, &sflx, &sfhx, &sfly, &sfhy);
2162 ne->nextexample = nelist;
2163 nelist = ne;
2164
2165 /* now find all others that touch this area */
2166 foundone = TRUE;
2167 hcount = 0;
2168 while (foundone)
2169 {
2170 foundone = FALSE;
2171
2172 /* begin to search the area so far */
2173 sea = initsearch(sflx, sfhx, sfly, sfhy, np);
2174 if (sea == -1) return(NOEXAMPLE);
2175 for(;;)
2176 {
2177 /* get next node in the area */
2178 geom = nextobject(sea);
2179 if (geom == NOGEOM) break;
2180 if (!geom->entryisnode) continue;
2181 otherni = geom->entryaddr.ni;
2182 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
2183 nodesizeoffset(otherni, &lx, &ly, &hx, &hy);
2184 maketruerectpoly(otherni->lowx+lx, otherni->highx-hx, otherni->lowy+ly, otherni->highy-hy, poly);
2185 makerot(otherni, trans);
2186 xformpoly(poly, trans);
2187 getbbox(poly, &lx, &hx, &ly, &hy);
2188 if (hx < sflx || lx > sfhx || hy < sfly || ly > sfhy) continue;
2189
2190 /* make sure the node is valid */
2191 if (otherni->temp1 != (INTBIG)NOEXAMPLE)
2192 {
2193 if (otherni->temp1 == 0) continue;
2194 if (otherni->temp1 == (INTBIG)ne) continue;
2195 us_tecedpointout(otherni, np);
2196 ttyputerr(_("Examples are too close in %s"), describenodeproto(np));
2197 termsearch(sea);
2198 return(NOEXAMPLE);
2199 }
2200 otherni->temp1 = (INTBIG)ne;
2201
2202 /* add it to the cluster */
2203 ns = (SAMPLE *)emalloc((sizeof (SAMPLE)), us_tool->cluster);
2204 if (ns == 0) return(NOEXAMPLE);
2205 ns->node = otherni;
2206 ns->rule = NORULE;
2207 ns->parent = ne;
2208 ns->nextsample = ne->firstsample;
2209 ne->firstsample = ns;
2210 ns->assoc = NOSAMPLE;
2211 ns->xpos = (lx + hx) / 2;
2212 ns->ypos = (ly + hy) / 2;
2213 if (otherni->proto == gen_portprim)
2214 {
2215 if (!isnode)
2216 {
2217 us_tecedpointout(otherni, np);
2218 ttyputerr(_("%s cannot have ports. Delete this"), describenodeproto(np));
2219 termsearch(sea);
2220 return(NOEXAMPLE);
2221 }
2222 ns->layer = gen_portprim;
2223 } else if (otherni->proto == gen_cellcenterprim)
2224 {
2225 if (!isnode)
2226 {
2227 us_tecedpointout(otherni, np);
2228 ttyputerr(_("%s cannot have a grab point. Delete this"), describenodeproto(np));
2229 termsearch(sea);
2230 return(NOEXAMPLE);
2231 }
2232 ns->layer = gen_cellcenterprim;
2233 } else
2234 {
2235 ns->layer = us_tecedgetlayer(otherni);
2236 if (ns->layer == 0)
2237 {
2238 us_tecedpointout(otherni, np);
2239 ttyputerr(_("No layer information on this sample in %s"),
2240 describenodeproto(np));
2241 if ((us_tool->toolstate&NODETAILS) == 0)
2242 ttyputmsg(_("Use 'change' option or delete it"));
2243 termsearch(sea);
2244 return(NOEXAMPLE);
2245 }
2246 if (ns->layer == NONODEPROTO) hcount++;
2247 }
2248
2249 /* accumulate state if this is not a "grab point" mark */
2250 if (otherni->proto != gen_cellcenterprim)
2251 {
2252 if (!gotbbox)
2253 {
2254 ne->lx = lx; ne->hx = hx;
2255 ne->ly = ly; ne->hy = hy;
2256 gotbbox = TRUE;
2257 } else
2258 {
2259 if (lx < ne->lx) ne->lx = lx;
2260 if (hx > ne->hx) ne->hx = hx;
2261 if (ly < ne->ly) ne->ly = ly;
2262 if (hy > ne->hy) ne->hy = hy;
2263 }
2264 sflx = ne->lx; sfhx = ne->hx;
2265 sfly = ne->ly; sfhy = ne->hy;
2266 }
2267 foundone = TRUE;
2268 }
2269 }
2270 if (hcount == 0)
2271 {
2272 us_tecedpointout(NONODEINST, np);
2273 ttyputerr(_("No highlight layer in %s example"), describenodeproto(np));
2274 if ((us_tool->toolstate&NODETAILS) == 0)
2275 ttyputmsg(_("Use 'place-layer' option to create HIGHLIGHT"));
2276 return(NOEXAMPLE);
2277 }
2278 if (hcount != 1)
2279 {
2280 us_tecedpointout(NONODEINST, np);
2281 ttyputerr(_("Too many highlight layers in %s example. Delete some"), describenodeproto(np));
2282 return(NOEXAMPLE);
2283 }
2284 }
2285 if (nelist == NOEXAMPLE)
2286 {
2287 us_tecedpointout(NONODEINST, np);
2288 ttyputerr(_("No examples found in %s"), describenodeproto(np));
2289 if ((us_tool->toolstate&NODETAILS) == 0)
2290 ttyputmsg(_("Use 'place-layer' option to produce some geometry"));
2291 return(nelist);
2292 }
2293
2294 /*
2295 * now search the list for the smallest, most upper-right example
2296 * (the "main" example)
2297 */
2298 lambda = el_curlib->lambda[art_tech->techindex];
2299 sizex = (nelist->hx - nelist->lx) / lambda;
2300 sizey = (nelist->hy - nelist->ly) / lambda;
2301 locx = (nelist->lx + nelist->hx) / 2;
2302 locy = (nelist->ly + nelist->hy) / 2;
2303 bestne = nelist;
2304 for(ne = nelist; ne != NOEXAMPLE; ne = ne->nextexample)
2305 {
2306 newsize = (ne->hx-ne->lx) / lambda;
2307 newsize *= (ne->hy-ne->ly) / lambda;
2308 if (newsize > sizex*sizey) continue;
2309 if (newsize == sizex*sizey && (ne->lx+ne->hx)/2 >= locx && (ne->ly+ne->hy)/2 <= locy)
2310 continue;
2311 sizex = (ne->hx - ne->lx) / lambda;
2312 sizey = (ne->hy - ne->ly) / lambda;
2313 locx = (ne->lx + ne->hx) / 2;
2314 locy = (ne->ly + ne->hy) / 2;
2315 bestne = ne;
2316 }
2317
2318 /* place the main example at the top of the list */
2319 if (bestne != nelist)
2320 {
2321 for(ne = nelist; ne != NOEXAMPLE; ne = ne->nextexample)
2322 if (ne->nextexample == bestne)
2323 {
2324 ne->nextexample = bestne->nextexample;
2325 break;
2326 }
2327 bestne->nextexample = nelist;
2328 nelist = bestne;
2329 }
2330
2331 /* done */
2332 return(nelist);
2333 }
2334
2335 /*
2336 * Routine to associate the samples of example "nelist" in cell "np"
2337 * Returns true if there is an error
2338 */
us_tecedassociateexamples(EXAMPLE * nelist,NODEPROTO * np)2339 BOOLEAN us_tecedassociateexamples(EXAMPLE *nelist, NODEPROTO *np)
2340 {
2341 REGISTER EXAMPLE *ne;
2342 REGISTER SAMPLE *ns, *nslist, *nsfound, **listsort, **thissort;
2343 REGISTER INTBIG total, i;
2344 REGISTER CHAR *name, *othername;
2345
2346 /* if there is only one example, no association */
2347 if (nelist->nextexample == NOEXAMPLE) return(FALSE);
2348
2349 /* associate each example "ne" with the original in "nelist" */
2350 for(ne = nelist->nextexample; ne != NOEXAMPLE; ne = ne->nextexample)
2351 {
2352 /* clear associations for every sample "ns" in the example "ne" */
2353 for(ns = ne->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
2354 ns->assoc = NOSAMPLE;
2355
2356 /* associate every sample "ns" in the example "ne" */
2357 for(ns = ne->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
2358 {
2359 if (ns->assoc != NOSAMPLE) continue;
2360
2361 /* cannot have center in other examples */
2362 if (ns->layer == gen_cellcenterprim)
2363 {
2364 us_tecedpointout(ns->node, ns->node->parent);
2365 ttyputerr(_("Grab point should only be in main example of %s"),
2366 describenodeproto(np));
2367 return(TRUE);
2368 }
2369
2370 /* count number of similar layers in original example "nelist" */
2371 for(total = 0, nslist = nelist->firstsample; nslist != NOSAMPLE;
2372 nslist = nslist->nextsample)
2373 {
2374 if (nslist->layer != ns->layer) continue;
2375 total++;
2376 nsfound = nslist;
2377 }
2378
2379 /* no similar layer found in the original: error */
2380 if (total == 0)
2381 {
2382 us_tecedpointout(ns->node, ns->node->parent);
2383 ttyputerr(_("Layer %s not found in main example of %s"),
2384 us_tecedsamplename(ns->layer), describenodeproto(np));
2385 return(TRUE);
2386 }
2387
2388 /* just one in the original: simple association */
2389 if (total == 1)
2390 {
2391 ns->assoc = nsfound;
2392 continue;
2393 }
2394
2395 /* if it is a port, associate by port name */
2396 if (ns->layer == gen_portprim)
2397 {
2398 name = us_tecedgetportname(ns->node);
2399 if (name == 0)
2400 {
2401 us_tecedpointout(ns->node, ns->node->parent);
2402 ttyputerr(_("Cell %s: port does not have a name"), describenodeproto(np));
2403 return(TRUE);
2404 }
2405
2406 /* search the original for that port */
2407 for(nslist = nelist->firstsample; nslist != NOSAMPLE; nslist = nslist->nextsample)
2408 if (nslist->layer == gen_portprim)
2409 {
2410 othername = us_tecedgetportname(nslist->node);
2411 if (othername == 0)
2412 {
2413 us_tecedpointout(nslist->node, nslist->node->parent);
2414 ttyputerr(_("Cell %s: port does not have a name"), describenodeproto(np));
2415 return(TRUE);
2416 }
2417 if (namesame(name, othername) != 0) continue;
2418 ns->assoc = nslist;
2419 break;
2420 }
2421 if (nslist == NOSAMPLE)
2422 {
2423 us_tecedpointout(NONODEINST, np);
2424 ttyputerr(_("Could not find port %s in all examples of %s"),
2425 name, describenodeproto(np));
2426 return(TRUE);
2427 }
2428 continue;
2429 }
2430
2431 /* count the number of this layer in example "ne" */
2432 for(i = 0, nslist = ne->firstsample; nslist != NOSAMPLE;
2433 nslist = nslist->nextsample)
2434 if (nslist->layer == ns->layer) i++;
2435
2436 /* if number of similar layers differs: error */
2437 if (total != i)
2438 {
2439 us_tecedpointout(ns->node, ns->node->parent);
2440 ttyputerr(_("Layer %s found %ld times in main example, %ld in other"),
2441 us_tecedsamplename(ns->layer), total, i);
2442 ttyputmsg(_("Make the counts consistent"));
2443 return(TRUE);
2444 }
2445
2446 /* make a list of samples on this layer in original */
2447 listsort = (SAMPLE **)emalloc((total * (sizeof (SAMPLE *))), el_tempcluster);
2448 if (listsort == 0) return(TRUE);
2449 for(i = 0, nslist = nelist->firstsample; nslist != NOSAMPLE;
2450 nslist = nslist->nextsample)
2451 if (nslist->layer == ns->layer) listsort[i++] = nslist;
2452
2453 /* make a list of samples on this layer in example "ne" */
2454 thissort = (SAMPLE **)emalloc((total * (sizeof (SAMPLE *))), el_tempcluster);
2455 if (thissort == 0) return(TRUE);
2456 for(i = 0, nslist = ne->firstsample; nslist != NOSAMPLE; nslist = nslist->nextsample)
2457 if (nslist->layer == ns->layer) thissort[i++] = nslist;
2458
2459 /* sort each list in X/Y/shape */
2460 esort(listsort, total, sizeof (SAMPLE *), us_samplecoordascending);
2461 esort(thissort, total, sizeof (SAMPLE *), us_samplecoordascending);
2462
2463 /* see if the lists have duplication */
2464 for(i=1; i<total; i++)
2465 if ((thissort[i]->xpos == thissort[i-1]->xpos &&
2466 thissort[i]->ypos == thissort[i-1]->ypos &&
2467 thissort[i]->node->proto == thissort[i-1]->node->proto) ||
2468 (listsort[i]->xpos == listsort[i-1]->xpos &&
2469 listsort[i]->ypos == listsort[i-1]->ypos &&
2470 listsort[i]->node->proto == listsort[i-1]->node->proto)) break;
2471 if (i >= total)
2472 {
2473 /* association can be made in X */
2474 for(i=0; i<total; i++) thissort[i]->assoc = listsort[i];
2475 efree((CHAR *)thissort);
2476 efree((CHAR *)listsort);
2477 continue;
2478 }
2479
2480 /* don't know how to associate this sample */
2481 us_tecedpointout(thissort[i]->node, thissort[i]->node->parent);
2482 ttyputerr(_("Sample %s is unassociated in %s"),
2483 us_tecedsamplename(thissort[i]->layer), describenodeproto(np));
2484 efree((CHAR *)thissort);
2485 efree((CHAR *)listsort);
2486 return(TRUE);
2487 }
2488
2489 /* final check: make sure every sample in original example associates */
2490 for(nslist = nelist->firstsample; nslist != NOSAMPLE;
2491 nslist = nslist->nextsample) nslist->assoc = NOSAMPLE;
2492 for(ns = ne->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
2493 ns->assoc->assoc = ns;
2494 for(nslist = nelist->firstsample; nslist != NOSAMPLE;
2495 nslist = nslist->nextsample) if (nslist->assoc == NOSAMPLE)
2496 {
2497 if (nslist->layer == gen_cellcenterprim) continue;
2498 us_tecedpointout(nslist->node, nslist->node->parent);
2499 ttyputerr(_("Layer %s found in main example, but not others in %s"),
2500 us_tecedsamplename(nslist->layer), describenodeproto(np));
2501 return(TRUE);
2502 }
2503 }
2504 return(FALSE);
2505 }
2506
2507 /*
2508 * Helper routine to "xx()" for sorting samples by coordinate value.
2509 */
us_samplecoordascending(const void * e1,const void * e2)2510 int us_samplecoordascending(const void *e1, const void *e2)
2511 {
2512 SAMPLE *s1, *s2;
2513
2514 s1 = *((SAMPLE **)e1);
2515 s2 = *((SAMPLE **)e2);
2516 if (s1->xpos != s2->xpos) return(s1->xpos - s2->xpos);
2517 if (s1->ypos != s2->ypos) return(s1->ypos - s2->ypos);
2518 return(s1->node->proto - s2->node->proto);
2519 }
2520
2521 /* flags about the edge positions in the examples */
2522 #define TOEDGELEFT 01 /* constant to left edge */
2523 #define TOEDGERIGHT 02 /* constant to right edge */
2524 #define TOEDGETOP 04 /* constant to top edge */
2525 #define TOEDGEBOT 010 /* constant to bottom edge */
2526 #define FROMCENTX 020 /* constant in X to center */
2527 #define FROMCENTY 040 /* constant in Y to center */
2528 #define RATIOCENTX 0100 /* fixed ratio from X center to edge */
2529 #define RATIOCENTY 0200 /* fixed ratio from Y center to edge */
2530
us_tecedmakeprim(EXAMPLE * nelist,NODEPROTO * np,TECHNOLOGY * tech,TECH_NODES * tlist,INTBIG lambda)2531 BOOLEAN us_tecedmakeprim(EXAMPLE *nelist, NODEPROTO *np, TECHNOLOGY *tech, TECH_NODES *tlist, INTBIG lambda)
2532 {
2533 REGISTER SAMPLE *ns, *nso, *hs;
2534 REGISTER EXAMPLE *ne;
2535 REGISTER INTBIG total, count, newcount, i, truecount, multixs, multiys, multiindent, multisep;
2536 REGISTER INTBIG *newrule, r, dist;
2537 XARRAY trans;
2538 REGISTER CHAR *str;
2539 REGISTER VARIABLE *var, *var2, *var3;
2540 REGISTER NODEINST *ni;
2541
2542 /* look at every sample "ns" in the main example "nelist" */
2543 for(ns = nelist->firstsample; ns != NOSAMPLE; ns = ns->nextsample)
2544 {
2545 /* ignore grab point specification */
2546 if (ns->layer == gen_cellcenterprim) continue;
2547
2548 /* if there is only one example: make sample scale with edge */
2549 if (nelist->nextexample == NOEXAMPLE)
2550 {
2551 /* if a multicut separation was given and this is a cut, add the rule */
2552 if (tlist->f4 > 0 && ns->layer != NONODEPROTO && ns->layer != gen_portprim)
2553 {
2554 for(i=0; i<us_teclayer_count; i++)
2555 if (namesame(us_teclayer_names[i], &ns->layer->protoname[6]) == 0) break;
2556 if (i < us_teclayer_count)
2557 {
2558 if (layeriscontact(us_teclayer_function[i]))
2559 {
2560 hs = us_tecedneedhighlightlayer(nelist, np);
2561 if (hs == 0) return(TRUE);
2562 multixs = ns->node->highx - ns->node->lowx;
2563 multiys = ns->node->highy - ns->node->lowy;
2564 multiindent = ns->node->lowx - hs->node->lowx;
2565 multisep = muldiv(tlist->f4, lambda, WHOLE);
2566 ns->rule = us_tecedaddmulticutrule(multixs, multiys, multiindent, multisep);
2567 if (ns->rule == 0) return(TRUE);
2568 continue;
2569 }
2570 }
2571 }
2572
2573 /* see if there is polygonal information */
2574 if (ns->node->proto == art_filledpolygonprim ||
2575 ns->node->proto == art_closedpolygonprim ||
2576 ns->node->proto == art_openedpolygonprim ||
2577 ns->node->proto == art_openeddottedpolygonprim ||
2578 ns->node->proto == art_openeddashedpolygonprim ||
2579 ns->node->proto == art_openedthickerpolygonprim)
2580 {
2581 var = gettrace(ns->node);
2582 } else var = NOVARIABLE;
2583 if (var != NOVARIABLE)
2584 {
2585 /* make sure the arrays hold "count" points */
2586 count = getlength(var) / 2;
2587 us_tecedforcearrays(count);
2588
2589 /* fill the array */
2590 makerot(ns->node, trans);
2591 for(i=0; i<count; i++)
2592 {
2593 xform((ns->node->geom->lowx + ns->node->geom->highx)/2 +
2594 ((INTBIG *)var->addr)[i*2],
2595 (ns->node->geom->lowy + ns->node->geom->highy)/2 +
2596 ((INTBIG *)var->addr)[i*2+1], &us_tecedmakepx[i], &us_tecedmakepy[i], trans);
2597 us_tecedmakefactor[i] = FROMCENTX|FROMCENTY;
2598 }
2599 } else
2600 {
2601 /* see if it is an arc of a circle */
2602 count = 2;
2603 if (ns->node->proto == art_circleprim || ns->node->proto == art_thickcircleprim)
2604 {
2605 var = getvalkey((INTBIG)ns->node, VNODEINST, VINTEGER, art_degreeskey);
2606 if (var != NOVARIABLE) count = 3;
2607 } else var = NOVARIABLE;
2608
2609 /* make sure the arrays hold enough points */
2610 us_tecedforcearrays(count);
2611
2612 /* set sample description */
2613 if (var != NOVARIABLE)
2614 {
2615 /* handle circular arc sample */
2616 us_tecedmakepx[0] = (ns->node->geom->lowx + ns->node->geom->highx) / 2;
2617 us_tecedmakepy[0] = (ns->node->geom->lowy + ns->node->geom->highy) / 2;
2618 makerot(ns->node, trans);
2619 dist = ns->node->geom->highx - us_tecedmakepx[0];
2620 xform(us_tecedmakepx[0] + mult(dist, cosine(var->addr)),
2621 us_tecedmakepy[0] + mult(dist, sine(var->addr)), &us_tecedmakepx[1], &us_tecedmakepy[1], trans);
2622 xform(ns->node->geom->highx,
2623 (ns->node->geom->lowy + ns->node->geom->highy) / 2, &us_tecedmakepx[2], &us_tecedmakepy[2], trans);
2624 us_tecedmakefactor[0] = FROMCENTX|FROMCENTY;
2625 us_tecedmakefactor[1] = RATIOCENTX|RATIOCENTY;
2626 us_tecedmakefactor[2] = RATIOCENTX|RATIOCENTY;
2627 } else if (ns->node->proto == art_circleprim || ns->node->proto == art_thickcircleprim ||
2628 ns->node->proto == art_filledcircleprim)
2629 {
2630 /* handle circular sample */
2631 us_tecedmakepx[0] = (ns->node->geom->lowx + ns->node->geom->highx) / 2;
2632 us_tecedmakepy[0] = (ns->node->geom->lowy + ns->node->geom->highy) / 2;
2633 us_tecedmakepx[1] = ns->node->geom->highx;
2634 us_tecedmakepy[1] = (ns->node->geom->lowy + ns->node->geom->highy) / 2;
2635 us_tecedmakefactor[0] = FROMCENTX|FROMCENTY;
2636 us_tecedmakefactor[1] = TOEDGERIGHT|FROMCENTY;
2637 } else
2638 {
2639 /* rectangular sample: get the bounding box in (px, py) */
2640 us_tecedgetbbox(ns->node, &us_tecedmakepx[0], &us_tecedmakepx[1], &us_tecedmakepy[0], &us_tecedmakepy[1]);
2641
2642 /* preset stretch factors to go to the edges of the box */
2643 us_tecedmakefactor[0] = TOEDGELEFT|TOEDGEBOT;
2644 us_tecedmakefactor[1] = TOEDGERIGHT|TOEDGETOP;
2645 }
2646 }
2647
2648 /* add the rule to the collection */
2649 newrule = us_tecedstretchpoints(us_tecedmakepx,us_tecedmakepy, count, us_tecedmakefactor, ns, np,
2650 nelist);
2651 if (newrule == 0) return(TRUE);
2652 var = getvalkey((INTBIG)ns->node, VNODEINST, VSTRING|VISARRAY, art_messagekey);
2653 if (var == NOVARIABLE) str = (CHAR *)0; else
2654 str = ((CHAR **)var->addr)[0];
2655 ns->rule = us_tecedaddrule(newrule, count*4, FALSE, str);
2656 if (ns->rule == NORULE) return(TRUE);
2657 efree((CHAR *)newrule);
2658 continue;
2659 }
2660
2661 /* look at other examples and find samples associated with this */
2662 nelist->studysample = ns;
2663 for(ne = nelist->nextexample; ne != NOEXAMPLE; ne = ne->nextexample)
2664 {
2665 /* count number of samples associated with the main sample */
2666 total = 0;
2667 for(nso = ne->firstsample; nso != NOSAMPLE; nso = nso->nextsample)
2668 if (nso->assoc == ns)
2669 {
2670 ne->studysample = nso;
2671 total++;
2672 }
2673 if (total == 0)
2674 {
2675 us_tecedpointout(ns->node, ns->node->parent);
2676 ttyputerr(_("Still unassociated sample in %s (shouldn't happen)"),
2677 describenodeproto(np));
2678 return(TRUE);
2679 }
2680
2681 /* if there are multiple associations, it must be a contact cut */
2682 if (total > 1)
2683 {
2684 /* make sure the layer is real geometry, not highlight or a port */
2685 if (ns->layer == NONODEPROTO || ns->layer == gen_portprim)
2686 {
2687 us_tecedpointout(ns->node, ns->node->parent);
2688 ttyputerr(_("Only contact layers may be iterated in examples of %s"),
2689 describenodeproto(np));
2690 return(TRUE);
2691 }
2692
2693 /* make sure the contact cut layer is opaque */
2694 for(i=0; i<tech->layercount; i++)
2695 if (namesame(&ns->layer->protoname[6], us_teclayer_names[i]) == 0)
2696 {
2697 if (tech->layers[i]->bits != LAYERO)
2698 {
2699 us_tecedpointout(ns->node, ns->node->parent);
2700 ttyputerr(_("Multiple contact layers must not be transparent in %s"),
2701 describenodeproto(np));
2702 return(TRUE);
2703 }
2704 break;
2705 }
2706
2707 /* add the rule */
2708 if (us_tecedmulticut(ns, nelist, np)) return(TRUE);
2709 break;
2710 }
2711 }
2712 if (ne != NOEXAMPLE) continue;
2713
2714 /* associations done for this sample, now analyze them */
2715 if (ns->node->proto == art_filledpolygonprim ||
2716 ns->node->proto == art_closedpolygonprim ||
2717 ns->node->proto == art_openedpolygonprim ||
2718 ns->node->proto == art_openeddottedpolygonprim ||
2719 ns->node->proto == art_openeddashedpolygonprim ||
2720 ns->node->proto == art_openedthickerpolygonprim)
2721 {
2722 var = gettrace(ns->node);
2723 } else var = NOVARIABLE;
2724 if (var != NOVARIABLE)
2725 {
2726 truecount = count = getlength(var) / 2;
2727
2728 /* make sure the arrays hold "count" points */
2729 us_tecedforcearrays(count);
2730 makerot(ns->node, trans);
2731 for(i=0; i<count; i++)
2732 xform((ns->node->geom->lowx + ns->node->geom->highx)/2 + ((INTBIG *)var->addr)[i*2],
2733 (ns->node->geom->lowy + ns->node->geom->highy)/2 +
2734 ((INTBIG *)var->addr)[i*2+1], &us_tecedmakepx[i], &us_tecedmakepy[i], trans);
2735 } else
2736 {
2737 /* make sure the arrays hold enough points */
2738 count = 2;
2739 if (ns->node->proto == art_circleprim || ns->node->proto == art_thickcircleprim)
2740 {
2741 var3 = getvalkey((INTBIG)ns->node, VNODEINST, VINTEGER, art_degreeskey);
2742 if (var3 != NOVARIABLE) count = 3;
2743 } else var3 = NOVARIABLE;
2744 truecount = count;
2745 if (var3 == NOVARIABLE)
2746 {
2747 var2 = getval((INTBIG)ns->node, VNODEINST, VSTRING, x_("EDTEC_minbox"));
2748 if (var2 != NOVARIABLE) count *= 2;
2749 }
2750 us_tecedforcearrays(count);
2751
2752 /* set sample description */
2753 if (var3 != NOVARIABLE)
2754 {
2755 /* handle circular arc sample */
2756 us_tecedmakepx[0] = (ns->node->geom->lowx + ns->node->geom->highx) / 2;
2757 us_tecedmakepy[0] = (ns->node->geom->lowy + ns->node->geom->highy) / 2;
2758 makerot(ns->node, trans);
2759 dist = ns->node->geom->highx - us_tecedmakepx[0];
2760 xform(us_tecedmakepx[0] + mult(dist, cosine(var3->addr)),
2761 us_tecedmakepy[0] + mult(dist, sine(var3->addr)), &us_tecedmakepx[1], &us_tecedmakepy[1], trans);
2762 xform(ns->node->geom->highx,
2763 (ns->node->geom->lowy + ns->node->geom->highy) / 2, &us_tecedmakepx[2], &us_tecedmakepy[2], trans);
2764 } else if (ns->node->proto == art_circleprim || ns->node->proto == art_thickcircleprim ||
2765 ns->node->proto == art_filledcircleprim)
2766 {
2767 /* handle circular sample */
2768 us_tecedmakepx[0] = (ns->node->geom->lowx + ns->node->geom->highx) / 2;
2769 us_tecedmakepy[0] = (ns->node->geom->lowy + ns->node->geom->highy) / 2;
2770 us_tecedmakepx[1] = ns->node->geom->highx;
2771 us_tecedmakepy[1] = (ns->node->geom->lowy + ns->node->geom->highy) / 2;
2772 } else
2773 {
2774 /* rectangular sample: get the bounding box in (us_tecedmakepx, us_tecedmakepy) */
2775 us_tecedgetbbox(ns->node, &us_tecedmakepx[0], &us_tecedmakepx[1], &us_tecedmakepy[0], &us_tecedmakepy[1]);
2776 }
2777 if (var2 != NOVARIABLE)
2778 {
2779 us_tecedmakepx[2] = us_tecedmakepx[0]; us_tecedmakepy[2] = us_tecedmakepy[0];
2780 us_tecedmakepx[3] = us_tecedmakepx[1]; us_tecedmakepy[3] = us_tecedmakepy[1];
2781 }
2782 }
2783
2784 for(i=0; i<count; i++)
2785 {
2786 us_tecedmakeleftdist[i] = us_tecedmakepx[i] - nelist->lx;
2787 us_tecedmakerightdist[i] = nelist->hx - us_tecedmakepx[i];
2788 us_tecedmakebotdist[i] = us_tecedmakepy[i] - nelist->ly;
2789 us_tecedmaketopdist[i] = nelist->hy - us_tecedmakepy[i];
2790 us_tecedmakecentxdist[i] = us_tecedmakepx[i] - (nelist->lx+nelist->hx)/2;
2791 us_tecedmakecentydist[i] = us_tecedmakepy[i] - (nelist->ly+nelist->hy)/2;
2792 if (nelist->hx == nelist->lx) us_tecedmakeratiox[i] = 0; else
2793 us_tecedmakeratiox[i] = (us_tecedmakepx[i] - (nelist->lx+nelist->hx)/2) * WHOLE / (nelist->hx-nelist->lx);
2794 if (nelist->hy == nelist->ly) us_tecedmakeratioy[i] = 0; else
2795 us_tecedmakeratioy[i] = (us_tecedmakepy[i] - (nelist->ly+nelist->hy)/2) * WHOLE / (nelist->hy-nelist->ly);
2796 if (i < truecount)
2797 us_tecedmakefactor[i] = TOEDGELEFT | TOEDGERIGHT | TOEDGETOP | TOEDGEBOT | FROMCENTX |
2798 FROMCENTY | RATIOCENTX | RATIOCENTY; else
2799 us_tecedmakefactor[i] = FROMCENTX | FROMCENTY;
2800 }
2801 for(ne = nelist->nextexample; ne != NOEXAMPLE; ne = ne->nextexample)
2802 {
2803 ni = ne->studysample->node;
2804 if (ni->proto == art_filledpolygonprim ||
2805 ni->proto == art_closedpolygonprim ||
2806 ni->proto == art_openedpolygonprim ||
2807 ni->proto == art_openeddottedpolygonprim ||
2808 ni->proto == art_openeddashedpolygonprim ||
2809 ni->proto == art_openedthickerpolygonprim)
2810 {
2811 var = gettrace(ni);
2812 } else var = NOVARIABLE;
2813 if (var != NOVARIABLE)
2814 {
2815 newcount = getlength(var) / 2;
2816 makerot(ni, trans);
2817 for(i=0; i<mini(truecount, newcount); i++)
2818 xform((ni->geom->lowx + ni->geom->highx)/2 + ((INTBIG *)var->addr)[i*2],
2819 (ni->geom->lowy + ni->geom->highy)/2 +
2820 ((INTBIG *)var->addr)[i*2+1], &us_tecedmakecx[i], &us_tecedmakecy[i], trans);
2821 } else
2822 {
2823 newcount = 2;
2824 if (ni->proto == art_circleprim || ni->proto == art_thickcircleprim)
2825 {
2826 var3 = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, art_degreeskey);
2827 if (var3 != NOVARIABLE) newcount = 3;
2828 } else var3 = NOVARIABLE;
2829 if (var3 != NOVARIABLE)
2830 {
2831 us_tecedmakecx[0] = (ni->geom->lowx + ni->geom->highx) / 2;
2832 us_tecedmakecy[0] = (ni->geom->lowy + ni->geom->highy) / 2;
2833 makerot(ni, trans);
2834 dist = ni->geom->highx - us_tecedmakecx[0];
2835 xform(us_tecedmakecx[0] + mult(dist, cosine(var3->addr)),
2836 us_tecedmakecy[0] + mult(dist, sine(var3->addr)), &us_tecedmakecx[1], &us_tecedmakecy[1], trans);
2837 xform(ni->geom->highx, (ni->geom->lowy + ni->geom->highy) / 2,
2838 &us_tecedmakecx[2], &us_tecedmakecy[2], trans);
2839 } else if (ni->proto == art_circleprim || ni->proto == art_thickcircleprim ||
2840 ni->proto == art_filledcircleprim)
2841 {
2842 us_tecedmakecx[0] = (ni->geom->lowx + ni->geom->highx) / 2;
2843 us_tecedmakecy[0] = (ni->geom->lowy + ni->geom->highy) / 2;
2844 us_tecedmakecx[1] = ni->geom->highx;
2845 us_tecedmakecy[1] = (ni->geom->lowy + ni->geom->highy) / 2;
2846 } else
2847 {
2848 us_tecedgetbbox(ni, &us_tecedmakecx[0], &us_tecedmakecx[1], &us_tecedmakecy[0], &us_tecedmakecy[1]);
2849 }
2850 }
2851 if (newcount != truecount)
2852 {
2853 us_tecedpointout(ni, ni->parent);
2854 ttyputerr(_("Main example of %s has %ld points but this has %ld in %s"),
2855 us_tecedsamplename(ne->studysample->layer),
2856 truecount, newcount, describenodeproto(np));
2857 return(TRUE);
2858 }
2859
2860 for(i=0; i<truecount; i++)
2861 {
2862 /* see if edges are fixed distance from example edge */
2863 if (us_tecedmakeleftdist[i] != us_tecedmakecx[i] - ne->lx) us_tecedmakefactor[i] &= ~TOEDGELEFT;
2864 if (us_tecedmakerightdist[i] != ne->hx - us_tecedmakecx[i]) us_tecedmakefactor[i] &= ~TOEDGERIGHT;
2865 if (us_tecedmakebotdist[i] != us_tecedmakecy[i] - ne->ly) us_tecedmakefactor[i] &= ~TOEDGEBOT;
2866 if (us_tecedmaketopdist[i] != ne->hy - us_tecedmakecy[i]) us_tecedmakefactor[i] &= ~TOEDGETOP;
2867
2868 /* see if edges are fixed distance from example center */
2869 if (us_tecedmakecentxdist[i] != us_tecedmakecx[i] - (ne->lx+ne->hx)/2) us_tecedmakefactor[i] &= ~FROMCENTX;
2870 if (us_tecedmakecentydist[i] != us_tecedmakecy[i] - (ne->ly+ne->hy)/2) us_tecedmakefactor[i] &= ~FROMCENTY;
2871
2872 /* see if edges are fixed ratio from example center */
2873 if (ne->hx == ne->lx) r = 0; else
2874 r = (us_tecedmakecx[i] - (ne->lx+ne->hx)/2) * WHOLE / (ne->hx-ne->lx);
2875 if (r != us_tecedmakeratiox[i]) us_tecedmakefactor[i] &= ~RATIOCENTX;
2876 if (ne->hy == ne->ly) r = 0; else
2877 r = (us_tecedmakecy[i] - (ne->ly+ne->hy)/2) * WHOLE / (ne->hy-ne->ly);
2878 if (r != us_tecedmakeratioy[i]) us_tecedmakefactor[i] &= ~RATIOCENTY;
2879 }
2880
2881 /* make sure port information is on the primary example */
2882 if (ns->layer != gen_portprim) continue;
2883
2884 /* check port angle */
2885 var = getval((INTBIG)ns->node, VNODEINST, VINTEGER, x_("EDTEC_portangle"));
2886 var2 = getval((INTBIG)ni, VNODEINST, VINTEGER, x_("EDTEC_portangle"));
2887 if (var == NOVARIABLE && var2 != NOVARIABLE)
2888 {
2889 us_tecedpointout(NONODEINST, np);
2890 ttyputerr(_("Warning: moving port angle to main example of %s"),
2891 describenodeproto(np));
2892 (void)setval((INTBIG)ns->node, VNODEINST, x_("EDTEC_portangle"), var2->addr, VINTEGER);
2893 }
2894
2895 /* check port range */
2896 var = getval((INTBIG)ns->node, VNODEINST, VINTEGER, x_("EDTEC_portrange"));
2897 var2 = getval((INTBIG)ni, VNODEINST, VINTEGER, x_("EDTEC_portrange"));
2898 if (var == NOVARIABLE && var2 != NOVARIABLE)
2899 {
2900 us_tecedpointout(NONODEINST, np);
2901 ttyputerr(_("Warning: moving port range to main example of %s"), describenodeproto(np));
2902 (void)setval((INTBIG)ns->node, VNODEINST, x_("EDTEC_portrange"), var2->addr, VINTEGER);
2903 }
2904
2905 /* check connectivity */
2906 var = getval((INTBIG)ns->node, VNODEINST, VNODEPROTO|VISARRAY, x_("EDTEC_connects"));
2907 var2 = getval((INTBIG)ni, VNODEINST, VNODEPROTO|VISARRAY, x_("EDTEC_connects"));
2908 if (var == NOVARIABLE && var2 != NOVARIABLE)
2909 {
2910 us_tecedpointout(NONODEINST, np);
2911 ttyputerr(_("Warning: moving port connections to main example of %s"),
2912 describenodeproto(np));
2913 (void)setval((INTBIG)ns->node, VNODEINST, x_("EDTEC_connects"),
2914 var2->addr, VNODEPROTO|VISARRAY|(getlength(var2)<<VLENGTHSH));
2915 }
2916 }
2917
2918 /* error check for the highlight layer */
2919 if (ns->layer == NONODEPROTO)
2920 for(i=0; i<truecount; i++)
2921 if ((us_tecedmakefactor[i]&(TOEDGELEFT|TOEDGERIGHT)) == 0 ||
2922 (us_tecedmakefactor[i]&(TOEDGETOP|TOEDGEBOT)) == 0)
2923 {
2924 us_tecedpointout(ns->node, ns->node->parent);
2925 ttyputerr(_("Highlight must be constant distance from edge in %s"), describenodeproto(np));
2926 return(TRUE);
2927 }
2928
2929 /* finally, make a rule for this sample */
2930 newrule = us_tecedstretchpoints(us_tecedmakepx, us_tecedmakepy, count, us_tecedmakefactor, ns, np, nelist);
2931 if (newrule == 0) return(TRUE);
2932
2933 /* add the rule to the global list */
2934 var = getvalkey((INTBIG)ns->node, VNODEINST, VSTRING|VISARRAY, art_messagekey);
2935 if (var == NOVARIABLE) str = (CHAR *)0; else
2936 str = ((CHAR **)var->addr)[0];
2937 ns->rule = us_tecedaddrule(newrule, count*4, FALSE, str);
2938 if (ns->rule == NORULE) return(TRUE);
2939 efree((CHAR *)newrule);
2940 }
2941 return(FALSE);
2942 }
2943
2944 /*
2945 * routine to ensure that the 13 global arrays are all at least "want" long.
2946 * Their current size is "us_tecedmakearrlen".
2947 */
us_tecedforcearrays(INTBIG want)2948 void us_tecedforcearrays(INTBIG want)
2949 {
2950 if (us_tecedmakearrlen >= want) return;
2951 if (us_tecedmakearrlen != 0)
2952 {
2953 efree((CHAR *)us_tecedmakepx);
2954 efree((CHAR *)us_tecedmakepy);
2955 efree((CHAR *)us_tecedmakecx);
2956 efree((CHAR *)us_tecedmakecy);
2957 efree((CHAR *)us_tecedmakefactor);
2958 efree((CHAR *)us_tecedmakeleftdist);
2959 efree((CHAR *)us_tecedmakerightdist);
2960 efree((CHAR *)us_tecedmakebotdist);
2961 efree((CHAR *)us_tecedmaketopdist);
2962 efree((CHAR *)us_tecedmakecentxdist);
2963 efree((CHAR *)us_tecedmakecentydist);
2964 efree((CHAR *)us_tecedmakeratiox);
2965 efree((CHAR *)us_tecedmakeratioy);
2966 }
2967 us_tecedmakearrlen = want;
2968 us_tecedmakepx = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2969 if (us_tecedmakepx == 0) return;
2970 us_tecedmakepy = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2971 if (us_tecedmakepy == 0) return;
2972 us_tecedmakecx = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2973 if (us_tecedmakecx == 0) return;
2974 us_tecedmakecy = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2975 if (us_tecedmakecy == 0) return;
2976 us_tecedmakefactor = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2977 if (us_tecedmakefactor == 0) return;
2978 us_tecedmakeleftdist = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2979 if (us_tecedmakeleftdist == 0) return;
2980 us_tecedmakerightdist = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2981 if (us_tecedmakerightdist == 0) return;
2982 us_tecedmakebotdist = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2983 if (us_tecedmakebotdist == 0) return;
2984 us_tecedmaketopdist = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2985 if (us_tecedmaketopdist == 0) return;
2986 us_tecedmakecentxdist = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2987 if (us_tecedmakecentxdist == 0) return;
2988 us_tecedmakecentydist = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2989 if (us_tecedmakecentydist == 0) return;
2990 us_tecedmakeratiox = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2991 if (us_tecedmakeratiox == 0) return;
2992 us_tecedmakeratioy = emalloc((want * SIZEOFINTBIG), us_tool->cluster);
2993 if (us_tecedmakeratioy == 0) return;
2994 }
2995
2996 /*
2997 * routine to adjust the "count"-long array of points in "px" and "py" according
2998 * to the stretch factor bits in "factor" and return an array that describes
2999 * these points. Returns zero on error.
3000 */
us_tecedstretchpoints(INTBIG * px,INTBIG * py,INTBIG count,INTBIG * factor,SAMPLE * ns,NODEPROTO * np,EXAMPLE * nelist)3001 INTBIG *us_tecedstretchpoints(INTBIG *px, INTBIG *py, INTBIG count, INTBIG *factor,
3002 SAMPLE *ns, NODEPROTO *np, EXAMPLE *nelist)
3003 {
3004 REGISTER INTBIG *newrule, lambda;
3005 REGISTER INTBIG i;
3006
3007 newrule = emalloc((count*4*SIZEOFINTBIG), el_tempcluster);
3008 if (newrule == 0) return(0);
3009
3010 lambda = el_curlib->lambda[art_tech->techindex];
3011 for(i=0; i<count; i++)
3012 {
3013 /* determine the X algorithm */
3014 if ((factor[i]&TOEDGELEFT) != 0)
3015 {
3016 /* left edge rule */
3017 newrule[i*4] = -H0;
3018 newrule[i*4+1] = (px[i]-nelist->lx) * WHOLE/lambda;
3019 } else if ((factor[i]&TOEDGERIGHT) != 0)
3020 {
3021 /* right edge rule */
3022 newrule[i*4] = H0;
3023 newrule[i*4+1] = (px[i]-nelist->hx) * WHOLE/lambda;
3024 } else if ((factor[i]&FROMCENTX) != 0)
3025 {
3026 /* center rule */
3027 newrule[i*4] = 0;
3028 newrule[i*4+1] = (px[i]-(nelist->lx+nelist->hx)/2) * WHOLE/lambda;
3029 } else if ((factor[i]&RATIOCENTX) != 0)
3030 {
3031 /* constant stretch rule */
3032 if (nelist->hx == nelist->lx) newrule[i*4] = 0; else
3033 newrule[i*4] = (px[i] - (nelist->lx+nelist->hx)/2) * WHOLE / (nelist->hx-nelist->lx);
3034 newrule[i*4+1] = 0;
3035 } else
3036 {
3037 us_tecedpointout(ns->node, ns->node->parent);
3038 ttyputerr(_("Cannot determine X stretching rule for layer %s in %s"),
3039 us_tecedsamplename(ns->layer), describenodeproto(np));
3040 return(0);
3041 }
3042
3043 /* determine the Y algorithm */
3044 if ((factor[i]&TOEDGEBOT) != 0)
3045 {
3046 /* bottom edge rule */
3047 newrule[i*4+2] = -H0;
3048 newrule[i*4+3] = (py[i]-nelist->ly) * WHOLE/lambda;
3049 } else if ((factor[i]&TOEDGETOP) != 0)
3050 {
3051 /* top edge rule */
3052 newrule[i*4+2] = H0;
3053 newrule[i*4+3] = (py[i]-nelist->hy) * WHOLE/lambda;
3054 } else if ((factor[i]&FROMCENTY) != 0)
3055 {
3056 /* center rule */
3057 newrule[i*4+2] = 0;
3058 newrule[i*4+3] = (py[i]-(nelist->ly+nelist->hy)/2) * WHOLE/lambda;
3059 } else if ((factor[i]&RATIOCENTY) != 0)
3060 {
3061 /* constant stretch rule */
3062 if (nelist->hy == nelist->ly) newrule[i*4+2] = 0; else
3063 newrule[i*4+2] = (py[i] - (nelist->ly+nelist->hy)/2) * WHOLE /
3064 (nelist->hy-nelist->ly);
3065 newrule[i*4+3] = 0;
3066 } else
3067 {
3068 us_tecedpointout(ns->node, ns->node->parent);
3069 ttyputerr(_("Cannot determine Y stretching rule for layer %s in %s"),
3070 us_tecedsamplename(ns->layer), describenodeproto(np));
3071 return(0);
3072 }
3073 }
3074 return(newrule);
3075 }
3076
us_tecedneedhighlightlayer(EXAMPLE * nelist,NODEPROTO * np)3077 SAMPLE *us_tecedneedhighlightlayer(EXAMPLE *nelist, NODEPROTO *np)
3078 {
3079 REGISTER SAMPLE *hs;
3080
3081 /* find the highlight layer */
3082 for(hs = nelist->firstsample; hs != NOSAMPLE; hs = hs->nextsample)
3083 if (hs->layer == NONODEPROTO) return(hs);
3084
3085 us_tecedpointout(NONODEINST, np);
3086 ttyputerr(_("No highlight layer on contact %s"), describenodeproto(np));
3087 if ((us_tool->toolstate&NODETAILS) == 0)
3088 ttyputmsg(_("Use 'place-layer' option to create HIGHLIGHT"));
3089 return(0);
3090 }
3091
3092 /*
3093 * routine to build a rule for multiple contact-cut sample "ns" from the
3094 * overall example list in "nelist". Returns true on error.
3095 */
us_tecedmulticut(SAMPLE * ns,EXAMPLE * nelist,NODEPROTO * np)3096 BOOLEAN us_tecedmulticut(SAMPLE *ns, EXAMPLE *nelist, NODEPROTO *np)
3097 {
3098 REGISTER INTBIG total, i, multixs, multiys, multiindent, multisep;
3099 REGISTER INTBIG xsep, ysep, sepx, sepy;
3100 REGISTER SAMPLE **nslist, *nso, *hs;
3101 REGISTER EXAMPLE *ne;
3102
3103 /* find the highlight layer */
3104 hs = us_tecedneedhighlightlayer(nelist, np);
3105 if (hs == 0) return(TRUE);
3106
3107 /* determine size of each cut */
3108 multixs = ns->node->highx - ns->node->lowx;
3109 multiys = ns->node->highy - ns->node->lowy;
3110
3111 /* determine indentation of cuts */
3112 multiindent = ns->node->lowx - hs->node->lowx;
3113 if (hs->node->highx - ns->node->highx != multiindent ||
3114 ns->node->lowy - hs->node->lowy != multiindent ||
3115 hs->node->highy - ns->node->highy != multiindent)
3116 {
3117 us_tecedpointout(ns->node, ns->node->parent);
3118 ttyputerr(_("Multiple contact cuts must be indented uniformly in %s"),
3119 describenodeproto(np));
3120 return(TRUE);
3121 }
3122
3123 /* look at every example after the first */
3124 xsep = ysep = -1;
3125 for(ne = nelist->nextexample; ne != NOEXAMPLE; ne = ne->nextexample)
3126 {
3127 /* count number of samples equivalent to the main sample */
3128 total = 0;
3129 for(nso = ne->firstsample; nso != NOSAMPLE; nso = nso->nextsample)
3130 if (nso->assoc == ns)
3131 {
3132 /* make sure size is proper */
3133 if (multixs != nso->node->highx - nso->node->lowx ||
3134 multiys != nso->node->highy - nso->node->lowy)
3135 {
3136 us_tecedpointout(nso->node, nso->node->parent);
3137 ttyputerr(_("Multiple contact cuts must not differ in size in %s"),
3138 describenodeproto(np));
3139 return(TRUE);
3140 }
3141 total++;
3142 }
3143
3144 /* allocate space for these samples */
3145 nslist = (SAMPLE **)emalloc((total * (sizeof (SAMPLE *))), el_tempcluster);
3146 if (nslist == 0) return(TRUE);
3147
3148 /* fill the list of samples */
3149 i = 0;
3150 for(nso = ne->firstsample; nso != NOSAMPLE; nso = nso->nextsample)
3151 if (nso->assoc == ns) nslist[i++] = nso;
3152
3153 /* analyze the samples for separation */
3154 for(i=1; i<total; i++)
3155 {
3156 /* find separation */
3157 sepx = abs((nslist[i-1]->node->highx + nslist[i-1]->node->lowx) / 2 -
3158 (nslist[i]->node->highx + nslist[i]->node->lowx) / 2);
3159 sepy = abs((nslist[i-1]->node->highy + nslist[i-1]->node->lowy) / 2 -
3160 (nslist[i]->node->highy + nslist[i]->node->lowy) / 2);
3161
3162 /* check for validity */
3163 if (sepx < multixs && sepy < multiys)
3164 {
3165 us_tecedpointout(nslist[i]->node, nslist[i]->node->parent);
3166 ttyputerr(_("Multiple contact cuts must not overlap in %s"),
3167 describenodeproto(np));
3168 efree((CHAR *)nslist);
3169 return(TRUE);
3170 }
3171
3172 /* accumulate minimum separation */
3173 if (sepx >= multixs)
3174 {
3175 if (xsep < 0) xsep = sepx; else
3176 {
3177 if (xsep > sepx) xsep = sepx;
3178 }
3179 }
3180 if (sepy >= multiys)
3181 {
3182 if (ysep < 0) ysep = sepy; else
3183 {
3184 if (ysep > sepy) ysep = sepy;
3185 }
3186 }
3187 }
3188
3189 /* finally ensure that all separations are multiples of "multisep" */
3190 for(i=1; i<total; i++)
3191 {
3192 /* find X separation */
3193 sepx = abs((nslist[i-1]->node->highx + nslist[i-1]->node->lowx) / 2 -
3194 (nslist[i]->node->highx + nslist[i]->node->lowx) / 2);
3195 sepy = abs((nslist[i-1]->node->highy + nslist[i-1]->node->lowy) / 2 -
3196 (nslist[i]->node->highy + nslist[i]->node->lowy) / 2);
3197 if (sepx / xsep * xsep != sepx)
3198 {
3199 us_tecedpointout(nslist[i]->node, nslist[i]->node->parent);
3200 ttyputerr(_("Multiple contact cut X spacing must be uniform in %s"),
3201 describenodeproto(np));
3202 efree((CHAR *)nslist);
3203 return(TRUE);
3204 }
3205
3206 /* find Y separation */
3207 if (sepy / ysep * ysep != sepy)
3208 {
3209 us_tecedpointout(nslist[i]->node, nslist[i]->node->parent);
3210 ttyputerr(_("Multiple contact cut Y spacing must be uniform in %s"),
3211 describenodeproto(np));
3212 efree((CHAR *)nslist);
3213 return(TRUE);
3214 }
3215 }
3216 efree((CHAR *)nslist);
3217 }
3218 multisep = xsep - multixs;
3219 if (multisep != ysep - multiys)
3220 {
3221 us_tecedpointout(NONODEINST, np);
3222 ttyputerr(_("Multiple contact cut X and Y spacing must be the same in %s"),
3223 describenodeproto(np));
3224 return(TRUE);
3225 }
3226 ns->rule = us_tecedaddmulticutrule(multixs, multiys, multiindent, multisep);
3227 if (ns->rule == 0) return(TRUE);
3228 return(FALSE);
3229 }
3230
us_tecedaddmulticutrule(INTBIG multixs,INTBIG multiys,INTBIG multiindent,INTBIG multisep)3231 RULE *us_tecedaddmulticutrule(INTBIG multixs, INTBIG multiys, INTBIG multiindent, INTBIG multisep)
3232 {
3233 REGISTER RULE *rule;
3234 INTBIG rulearr[8];
3235
3236 rulearr[0] = -H0; rulearr[1] = K1;
3237 rulearr[2] = -H0; rulearr[3] = K1;
3238 rulearr[4] = -H0; rulearr[5] = K3;
3239 rulearr[6] = -H0; rulearr[7] = K3;
3240 rule = us_tecedaddrule(rulearr, 8, TRUE, (CHAR *)0);
3241 if (rule == NORULE) return(0);
3242 rule->multixs = multixs;
3243 rule->multiys = multiys;
3244 rule->multiindent = multiindent;
3245 rule->multisep = multisep;
3246 return(rule);
3247 }
3248
3249 /*
3250 * routine to add the "len"-long list of port connections in "conlist" to
3251 * the list of port connections, and return the port connection entry
3252 * for this one. Returns NOPCON on error
3253 */
us_tecedaddportlist(INTBIG len,INTBIG * conlist)3254 PCON *us_tecedaddportlist(INTBIG len, INTBIG *conlist)
3255 {
3256 REGISTER PCON *pc;
3257 REGISTER INTBIG i, j;
3258
3259 /* find a port connection that is the same */
3260 for(pc = us_tecedfirstpcon; pc != NOPCON; pc = pc->nextpcon)
3261 {
3262 if (pc->total != len) continue;
3263 for(j=0; j<pc->total; j++) pc->assoc[j] = 0;
3264 for(i=0; i<len; i++)
3265 {
3266 for(j=0; j<pc->total; j++) if (pc->connects[j+1] == conlist[i])
3267 {
3268 pc->assoc[j]++;
3269 break;
3270 }
3271 }
3272 for(j=0; j<pc->total; j++) if (pc->assoc[j] == 0) break;
3273 if (j >= pc->total) return(pc);
3274 }
3275
3276 /* not found: add to list */
3277 pc = (PCON *)emalloc((sizeof (PCON)), us_tool->cluster);
3278 if (pc == 0) return(NOPCON);
3279 pc->total = len;
3280 pc->connects = emalloc(((len+5)*SIZEOFINTBIG), us_tool->cluster);
3281 if (pc->connects == 0) return(NOPCON);
3282 pc->assoc = emalloc((len*SIZEOFINTBIG), us_tool->cluster);
3283 if (pc->assoc == 0) return(NOPCON);
3284 for(j=0; j<len; j++) pc->connects[j+1] = conlist[j];
3285 pc->connects[0] = -1;
3286 pc->connects[len+1] = AUNIV;
3287 pc->connects[len+2] = AINVIS;
3288 pc->connects[len+3] = AUNROUTED;
3289 pc->connects[len+4] = -1;
3290 pc->nextpcon = us_tecedfirstpcon;
3291 us_tecedfirstpcon = pc;
3292 return(pc);
3293 }
3294
3295 /*
3296 * routine to get the list of libraries that are used in the construction
3297 * of library "lib". Returns the number of libraries, terminated with "lib",
3298 * and sets the list in "liblist".
3299 */
us_teceditgetdependents(LIBRARY * lib,LIBRARY *** liblist)3300 INTBIG us_teceditgetdependents(LIBRARY *lib, LIBRARY ***liblist)
3301 {
3302 REGISTER VARIABLE *var;
3303 REGISTER INTBIG i, j, total;
3304 REGISTER CHAR *pt;
3305
3306 /* get list of dependent libraries */
3307 var = getval((INTBIG)lib, VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_dependent_libraries"));
3308 if (var == NOVARIABLE) j = 0; else j = getlength(var);
3309 if (j >= us_teceddepliblistsize)
3310 {
3311 if (us_teceddepliblistsize != 0) efree((CHAR *)us_teceddepliblist);
3312 us_teceddepliblist = (LIBRARY **)emalloc((j+1) * (sizeof (LIBRARY *)), us_tool->cluster);
3313 if (us_teceddepliblist == 0) return(0);
3314 us_teceddepliblistsize = j+1;
3315 }
3316
3317 total = 0;
3318 for(i=0; i<j; i++)
3319 {
3320 pt = ((CHAR **)var->addr)[i];
3321 us_teceddepliblist[total++] = getlibrary(pt);
3322 if (us_teceddepliblist[total-1] == NOLIBRARY)
3323 {
3324 ttyputerr(_("Cannot find dependent technology library %s, ignoring"), pt);
3325 total--;
3326 continue;
3327 }
3328 if (us_teceddepliblist[total-1] == lib)
3329 {
3330 ttyputerr(_("Library cannot depend on itself, ignoring dependency"));
3331 total--;
3332 continue;
3333 }
3334 }
3335 us_teceddepliblist[total++] = lib;
3336 *liblist = us_teceddepliblist;
3337 return(total);
3338 }
3339
3340 /*
3341 * general-purpose routine to scan the "dependentlibcount" libraries in "dependentlibs",
3342 * looking for cells that begin with the string "match". It then uses the
3343 * variable "seqname" on the last library to determine an ordering of the cells.
3344 * Then, it returns the cells in the array "sequence" and returns the number of them.
3345 * Returns 0 on error.
3346 */
us_teceditfindsequence(LIBRARY ** dependentlibs,INTBIG dependentlibcount,CHAR * match,CHAR * seqname,NODEPROTO *** sequence)3347 INTBIG us_teceditfindsequence(LIBRARY **dependentlibs, INTBIG dependentlibcount,
3348 CHAR *match, CHAR *seqname, NODEPROTO ***sequence)
3349 {
3350 REGISTER INTBIG total;
3351 REGISTER INTBIG i, j, k, l, npsize, matchcount;
3352 REGISTER NODEPROTO *np, *lnp, **nplist, **newnplist;
3353 REGISTER VARIABLE *var;
3354 REGISTER LIBRARY *olderlib, *laterlib;
3355
3356 /* look backwards through libraries for the appropriate cells */
3357 matchcount = estrlen(match);
3358 total = 0;
3359 npsize = 0;
3360 for(i=dependentlibcount-1; i>=0; i--)
3361 {
3362 olderlib = dependentlibs[i];
3363 for(np = olderlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3364 if (namesamen(np->protoname, match, matchcount) == 0)
3365 {
3366 /* see if this cell is used in a later library */
3367 for(j=i+1; j<dependentlibcount; j++)
3368 {
3369 laterlib = dependentlibs[j];
3370 for(lnp = laterlib->firstnodeproto; lnp != NONODEPROTO; lnp = lnp->nextnodeproto)
3371 if (namesame(lnp->protoname, np->protoname) == 0)
3372 {
3373 /* got older and later version of same cell: check dates */
3374 if (lnp->revisiondate < np->revisiondate)
3375 ttyputmsg(_("Warning: library %s has newer %s than library %s"),
3376 olderlib->libname, np->protoname, laterlib->libname);
3377 break;
3378 }
3379 if (lnp != NONODEPROTO) break;
3380 }
3381
3382 /* if no later library has this, add to total */
3383 if (j >= dependentlibcount)
3384 {
3385 if (total >= npsize)
3386 {
3387 newnplist = (NODEPROTO **)emalloc((npsize+10) * (sizeof (NODEPROTO *)),
3388 el_tempcluster);
3389 if (newnplist == 0) return(0);
3390
3391 /* LINTED "nplist" used in proper order */
3392 for(k=0; k<total; k++) newnplist[k] = nplist[k];
3393 if (npsize != 0) efree((CHAR *)nplist);
3394 nplist = newnplist;
3395 npsize += 10;
3396 }
3397 newnplist[total++] = np;
3398 }
3399 }
3400 }
3401 if (total <= 0) return(0);
3402
3403 /* if there is no sequence, simply return the list */
3404 var = getval((INTBIG)dependentlibs[dependentlibcount-1], VLIBRARY, VSTRING|VISARRAY, seqname);
3405 if (var == NOVARIABLE)
3406 {
3407 *sequence = nplist;
3408 return(total);
3409 }
3410
3411 /* allocate a new list to be built from the sequence */
3412 *sequence = (NODEPROTO **)emalloc(total * (sizeof (NODEPROTO *)), el_tempcluster);
3413 if (*sequence == 0) return(0);
3414
3415 j = getlength(var);
3416 k = 0;
3417 for(i=0; i<j; i++)
3418 {
3419 for(l = 0; l < total; l++)
3420 {
3421 np = nplist[l];
3422 if (np == NONODEPROTO) continue;
3423 if (namesame(&np->protoname[matchcount], ((CHAR **)var->addr)[i]) == 0) break;
3424 }
3425 if (l >= total) continue;
3426 (*sequence)[k++] = np;
3427 nplist[l] = NONODEPROTO;
3428 }
3429 for(l = 0; l < total; l++)
3430 {
3431 np = nplist[l];
3432 if (np != NONODEPROTO) (*sequence)[k++] = np;
3433 }
3434 efree((CHAR *)nplist);
3435 return(total);
3436 }
3437
us_tecedaddrule(INTBIG list[8],INTBIG count,BOOLEAN multcut,CHAR * istext)3438 RULE *us_tecedaddrule(INTBIG list[8], INTBIG count, BOOLEAN multcut, CHAR *istext)
3439 {
3440 REGISTER RULE *r;
3441 REGISTER INTBIG i, textinc;
3442
3443 for(r = us_tecedfirstrule; r != NORULE; r = r->nextrule)
3444 {
3445 if (multcut != r->multicut) continue;
3446 if (istext != 0 && r->istext != 0)
3447 {
3448 if (namesame(istext, (CHAR *)r->value[count]) != 0) continue;
3449 } else if (istext != 0 || r->istext != 0) continue;
3450 if (count != r->count) continue;
3451 for(i=0; i<count; i++) if (r->value[i] != list[i]) break;
3452 if (i >= count) return(r);
3453 }
3454
3455 r = (RULE *)emalloc((sizeof (RULE)), us_tool->cluster);
3456 if (r == 0) return(NORULE);
3457 if (istext != 0) textinc = 1; else textinc = 0;
3458 r->value = emalloc(((count+textinc) * SIZEOFINTBIG), us_tool->cluster);
3459 if (r->value == 0) return(NORULE);
3460 r->count = count;
3461 r->nextrule = us_tecedfirstrule;
3462 r->used = FALSE;
3463 r->multicut = multcut;
3464 us_tecedfirstrule = r;
3465 for(i=0; i<count; i++) r->value[i] = list[i];
3466 r->istext = 0;
3467 if (istext != 0)
3468 {
3469 (void)allocstring((CHAR **)(&r->value[count]), istext, us_tool->cluster);
3470 r->istext = 1;
3471 }
3472 return(r);
3473 }
3474
3475 /*
3476 * Routine to obtain the layer associated with node "ni". Returns 0 if the layer is not
3477 * there or invalid. Returns NONODEPROTO if this is the highlight layer.
3478 */
us_tecedgetlayer(NODEINST * ni)3479 NODEPROTO *us_tecedgetlayer(NODEINST *ni)
3480 {
3481 REGISTER VARIABLE *var;
3482 REGISTER NODEPROTO *np, *onp;
3483
3484 var = getval((INTBIG)ni, VNODEINST, VNODEPROTO, x_("EDTEC_layer"));
3485 if (var == NOVARIABLE) return(0);
3486 np = (NODEPROTO *)var->addr;
3487 if (np != NONODEPROTO)
3488 {
3489 /* validate the reference */
3490 for(onp = ni->parent->lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
3491 if (onp == np) break;
3492 if (onp == NONODEPROTO) return(0);
3493 }
3494 return(np);
3495 }
3496
3497 /****************************** WRITE TECHNOLOGY AS "C" CODE ******************************/
3498
3499 /*
3500 * routine to dump the layer information in technology "tech" to the stream in
3501 * "f".
3502 */
us_teceditdumplayers(FILE * f,TECHNOLOGY * tech,CHAR * techname)3503 void us_teceditdumplayers(FILE *f, TECHNOLOGY *tech, CHAR *techname)
3504 {
3505 CHAR *sym, *colorname, *colorsymbol, date[30];
3506 REGISTER INTBIG i, j, k, l;
3507 REGISTER CHAR *l1, *l2, *l3, *l4, *l5;
3508 REGISTER void *infstr;
3509
3510 /* write information for "tectable.c" */
3511 xprintf(f, x_("#if 0\n"));
3512 xprintf(f, _("/* the next 4 lines belong at the top of 'tectable.c': */\n"));
3513 xprintf(f, x_("extern GRAPHICS *%s_layers[];\n"), us_tecedmakesymbol(techname));
3514 xprintf(f, x_("extern TECH_ARCS *%s_arcprotos[];\n"), us_tecedmakesymbol(techname));
3515 xprintf(f, x_("extern TECH_NODES *%s_nodeprotos[];\n"), us_tecedmakesymbol(techname));
3516 xprintf(f, x_("extern TECH_VARIABLES %s_variables[];\n"), us_tecedmakesymbol(techname));
3517 xprintf(f, x_("\n/* the next 8 lines belong in the 'el_technologylist' array of 'tectable.c': */\n"));
3518 xprintf(f, x_("\t{x_(\"%s\"), 0, %ld, NONODEPROTO,NOARCPROTO,NOVARIABLE,0,NOCOMCOMP,NOCLUSTER,\t/* info */\n"),
3519 us_tecedmakesymbol(techname), tech->deflambda);
3520 xprintf(f, x_("\tN_(\"%s\"),\t/* description */\n"), tech->techdescript);
3521 xprintf(f, x_("\t0, %s_layers,"), us_tecedmakesymbol(techname));
3522 xprintf(f, x_(" 0, %s_arcprotos,"), us_tecedmakesymbol(techname));
3523 xprintf(f, x_(" 0, %s_nodeprotos,"), us_tecedmakesymbol(techname));
3524 xprintf(f, x_(" %s_variables,\t/* tables */\n"), us_tecedmakesymbol(techname));
3525 xprintf(f, x_("\t0, 0, 0, 0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/* control routines */\n"));
3526 xprintf(f, x_("\t0, 0, 0, 0, 0, 0, 0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/* node routines */\n"));
3527 xprintf(f, x_("\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/* port routine */\n"));
3528 xprintf(f, x_("\t0, 0, 0, 0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/* arc routines */\n"));
3529 xprintf(f, x_("\tNOTECHNOLOGY, NONEGATEDARCS|STATICTECHNOLOGY, 0, 0},\t\t\t\t\t\t\t/* miscellaneous */\n"));
3530 xprintf(f, x_("#endif\n"));
3531
3532 /* write legal banner */
3533 xprintf(f, x_("/*\n"));
3534 xprintf(f, x_(" * Electric(tm) VLSI Design System\n"));
3535 xprintf(f, x_(" *\n"));
3536 xprintf(f, x_(" * File: %s.c\n"), techname);
3537 xprintf(f, x_(" * %s technology description\n"), techname);
3538 xprintf(f, x_(" * Generated automatically from a library\n"));
3539 xprintf(f, x_(" *\n"));
3540 estrcpy(date, timetostring(getcurrenttime()));
3541 date[24] = 0;
3542 xprintf(f, x_(" * Copyright (c) %s Static Free Software.\n"), &date[20]);
3543 xprintf(f, x_(" *\n"));
3544 xprintf(f, x_(" * Electric(tm) is free software; you can redistribute it and/or modify\n"));
3545 xprintf(f, x_(" * it under the terms of the GNU General Public License as published by\n"));
3546 xprintf(f, x_(" * the Free Software Foundation; either version 2 of the License, or\n"));
3547 xprintf(f, x_(" * (at your option) any later version.\n"));
3548 xprintf(f, x_(" *\n"));
3549 xprintf(f, x_(" * Electric(tm) is distributed in the hope that it will be useful,\n"));
3550 xprintf(f, x_(" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"));
3551 xprintf(f, x_(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"));
3552 xprintf(f, x_(" * GNU General Public License for more details.\n"));
3553 xprintf(f, x_(" *\n"));
3554 xprintf(f, x_(" * You should have received a copy of the GNU General Public License\n"));
3555 xprintf(f, x_(" * along with Electric(tm); see the file COPYING. If not, write to\n"));
3556 xprintf(f, x_(" * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,\n"));
3557 xprintf(f, x_(" * Boston, Mass 02111-1307, USA.\n"));
3558 xprintf(f, x_(" *\n"));
3559 xprintf(f, x_(" * Static Free Software\n"));
3560 xprintf(f, x_(" * 4119 Alpine Road\n"));
3561 xprintf(f, x_(" * Portola Valley, California 94028\n"));
3562 xprintf(f, x_(" * info@staticfreesoft.com\n"));
3563 xprintf(f, x_(" */\n"));
3564
3565 /* write header */
3566 xprintf(f, x_("#include \"global.h\"\n"));
3567 xprintf(f, x_("#include \"egraphics.h\"\n"));
3568 xprintf(f, x_("#include \"tech.h\"\n"));
3569 xprintf(f, x_("#include \"efunction.h\"\n"));
3570
3571 /* write the layer declarations */
3572 xprintf(f, x_("\n/******************** LAYERS ********************/\n"));
3573 k = 8;
3574 for(i=0; i<tech->layercount; i++) k = maxi(k, estrlen(us_teclayer_iname[i]));
3575 k++;
3576 xprintf(f, x_("\n#define MAXLAYERS"));
3577 for(j=8; j<k; j++) xprintf(f, x_(" "));
3578 xprintf(f, x_("%ld\n"), tech->layercount);
3579 for(i=0; i<tech->layercount; i++)
3580 {
3581 xprintf(f, x_("#define L%s"), us_teclayer_iname[i]);
3582 for(j=estrlen(us_teclayer_iname[i]); j<k; j++) xprintf(f, x_(" "));
3583 xprintf(f, x_("%ld\t\t\t\t/* %s */\n"), i, us_teclayer_names[i]);
3584 }
3585 xprintf(f, x_("\n"));
3586
3587 /* write the layer descriptions */
3588 for(i=0; i<tech->layercount; i++)
3589 {
3590 xprintf(f, x_("static GRAPHICS %s_%s_lay = {"), us_tecedmakesymbol(techname),
3591 us_teclayer_iname[i]);
3592 switch (tech->layers[i]->bits)
3593 {
3594 case LAYERT1: xprintf(f, x_("LAYERT1, ")); break;
3595 case LAYERT2: xprintf(f, x_("LAYERT2, ")); break;
3596 case LAYERT3: xprintf(f, x_("LAYERT3, ")); break;
3597 case LAYERT4: xprintf(f, x_("LAYERT4, ")); break;
3598 case LAYERT5: xprintf(f, x_("LAYERT5, ")); break;
3599 case LAYERO: xprintf(f, x_("LAYERO, ")); break;
3600 }
3601 if (ecolorname(tech->layers[i]->col, &colorname, &colorsymbol)) colorsymbol = x_("unknown");
3602 xprintf(f, x_("%s, "), colorsymbol);
3603 if ((tech->layers[i]->colstyle&NATURE) == SOLIDC) xprintf(f, x_("SOLIDC")); else
3604 {
3605 xprintf(f, x_("PATTERNED"));
3606 if ((tech->layers[i]->colstyle&OUTLINEPAT) != 0) xprintf(f, x_("|OUTLINEPAT"));
3607 }
3608 xprintf(f, x_(", "));
3609 if ((tech->layers[i]->bwstyle&NATURE) == SOLIDC) xprintf(f, x_("SOLIDC")); else
3610 {
3611 xprintf(f, x_("PATTERNED"));
3612 if ((tech->layers[i]->bwstyle&OUTLINEPAT) != 0) xprintf(f, x_("|OUTLINEPAT"));
3613 }
3614 xprintf(f, x_(","));
3615
3616 xprintf(f, x_("\n"));
3617 for(j=0; j<16; j++) if (tech->layers[i]->raster[j] != 0) break;
3618 if (j >= 16)
3619 xprintf(f, x_("\t{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NOVARIABLE, 0};\n")); else
3620 {
3621 for(j=0; j<16; j++)
3622 {
3623 xprintf(f, x_("\t"));
3624 if (j == 0) xprintf(f, x_("{"));
3625 xprintf(f, x_("0x%04x"), tech->layers[i]->raster[j]&0xFFFF);
3626 if (j == 15) xprintf(f, x_("}"));
3627 xprintf(f, x_(","));
3628 if (j > 0 && j < 15) xprintf(f, x_(" "));
3629 xprintf(f, x_(" /* "));
3630 for(k=0; k<16; k++)
3631 if ((tech->layers[i]->raster[j] & (1 << (15-k))) != 0)
3632 xprintf(f, x_("X")); else xprintf(f, x_(" "));
3633 xprintf(f, x_(" */\n"));
3634 }
3635 xprintf(f, x_("\tNOVARIABLE, 0};\n"));
3636 }
3637 }
3638
3639 /* write the aggregation of all layers */
3640 sym = us_tecedmakesymbol(techname);
3641 xprintf(f, x_("\nGRAPHICS *%s_layers[MAXLAYERS+1] = {\n"), sym);
3642 for(i=0; i<tech->layercount; i++)
3643 {
3644 xprintf(f, x_("\t&%s_%s_lay,"), sym, us_teclayer_iname[i]);
3645 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3646 }
3647 xprintf(f, x_("\tNOGRAPHICS\n};\n"));
3648
3649 /* write the layer names */
3650 sym = us_tecedmakesymbol(techname);
3651 l = estrlen(sym) + 40;
3652 xprintf(f, x_("static char *%s_layer_names[MAXLAYERS] = {"), sym);
3653 for(i=0; i<tech->layercount; i++)
3654 {
3655 if (i != 0) { xprintf(f, x_(", ")); l += 2; }
3656 if (us_teclayer_names[i] == 0) sym = x_(""); else sym = us_teclayer_names[i];
3657 if (l + estrlen(sym) + 2 > 80)
3658 {
3659 xprintf(f, x_("\n\t"));
3660 l = 4;
3661 }
3662 xprintf(f, x_("x_(\"%s\")"), sym);
3663 l += estrlen(sym) + 2;
3664 }
3665 xprintf(f, x_("};\n"));
3666
3667 /* write the CIF layer names */
3668 if ((us_tecflags&HASCIF) != 0)
3669 {
3670 xprintf(f, x_("static char *%s_cif_layers[MAXLAYERS] = {\n"), us_tecedmakesymbol(techname));
3671 for(i=0; i<tech->layercount; i++)
3672 {
3673 if (us_teccif_layers[i] == 0) xprintf(f, x_("\tx_(\"\")")); else
3674 xprintf(f, x_("\tx_(\"%s\")"), us_teccif_layers[i]);
3675 if (i != tech->layercount-1) xprintf(f, x_(","));
3676 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3677 }
3678 xprintf(f, x_("};\n"));
3679 }
3680
3681 /* write the DXF layer numbers */
3682 if ((us_tecflags&HASDXF) != 0)
3683 {
3684 xprintf(f, x_("static char *%s_dxf_layers[MAXLAYERS] = {\n"), us_tecedmakesymbol(techname));
3685 for(i=0; i<tech->layercount; i++)
3686 {
3687 xprintf(f, x_("\tx_(\"%s\")"), us_tecdxf_layers[i]);
3688 if (i != tech->layercount-1) xprintf(f, x_(","));
3689 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3690 }
3691 xprintf(f, x_("};\n"));
3692 }
3693
3694 /* write the Calma GDS-II layer number */
3695 if ((us_tecflags&HASGDS) != 0)
3696 {
3697 xprintf(f, x_("static CHAR *%s_gds_layers[MAXLAYERS] = {\n"), us_tecedmakesymbol(techname));
3698 for(i=0; i<tech->layercount; i++)
3699 {
3700 xprintf(f, x_("\tx_(\"%s\")"), us_tecgds_layers[i]);
3701 if (i != tech->layercount-1) xprintf(f, x_(","));
3702 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3703 }
3704 xprintf(f, x_("};\n"));
3705 }
3706
3707 /* write the layer functions */
3708 xprintf(f, x_("static INTBIG %s_layer_function[MAXLAYERS] = {\n"), us_tecedmakesymbol(techname));
3709 for(i=0; i<tech->layercount; i++)
3710 {
3711 infstr = initinfstr();
3712 addstringtoinfstr(infstr, us_teclayer_functions[us_teclayer_function[i]&LFTYPE].constant);
3713 for(j=0; us_teclayer_functions[j].name != 0; j++)
3714 {
3715 if (us_teclayer_functions[j].value <= LFTYPE) continue;
3716 if ((us_teclayer_function[i]&us_teclayer_functions[j].value) != 0)
3717 {
3718 addtoinfstr(infstr, '|');
3719 addstringtoinfstr(infstr, us_teclayer_functions[j].constant);
3720 }
3721 }
3722 if (tech->layers[i]->bits == LAYERT1) addstringtoinfstr(infstr, x_("|LFTRANS1")); else
3723 if (tech->layers[i]->bits == LAYERT2) addstringtoinfstr(infstr, x_("|LFTRANS2")); else
3724 if (tech->layers[i]->bits == LAYERT3) addstringtoinfstr(infstr, x_("|LFTRANS3")); else
3725 if (tech->layers[i]->bits == LAYERT4) addstringtoinfstr(infstr, x_("|LFTRANS4")); else
3726 if (tech->layers[i]->bits == LAYERT5) addstringtoinfstr(infstr, x_("|LFTRANS5"));
3727 xprintf(f, x_("\t%s"), returninfstr(infstr));
3728 if (i != tech->layercount-1) xprintf(f, x_(","));
3729 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3730 }
3731 xprintf(f, x_("};\n"));
3732
3733 /* write the layer letters */
3734 xprintf(f, x_("static char *%s_layer_letters[MAXLAYERS] = {\n"), us_tecedmakesymbol(techname));
3735 for(i=0; i<tech->layercount; i++)
3736 {
3737 if (us_teclayer_letters[i] == 0) xprintf(f, x_("\tx_(\"\")")); else
3738 xprintf(f, x_("\tx_(\"%s\")"), us_teclayer_letters[i]);
3739 if (i != tech->layercount-1) xprintf(f, x_(","));
3740 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3741 }
3742 xprintf(f, x_("};\n"));
3743
3744 /* write the SPICE information */
3745 if ((us_tecflags&HASSPIRES) != 0)
3746 {
3747 xprintf(f, x_("static float %s_sim_spice_resistance[MAXLAYERS] = {\n"),
3748 us_tecedmakesymbol(techname));
3749 for(i=0; i<tech->layercount; i++)
3750 {
3751 xprintf(f, x_("\t%s"), us_tecedmakefloatstring(us_tecspice_res[i]));
3752 if (i != tech->layercount-1) xprintf(f, x_(","));
3753 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3754 }
3755 xprintf(f, x_("};\n"));
3756 }
3757 if ((us_tecflags&HASSPICAP) != 0)
3758 {
3759 xprintf(f, x_("static float %s_sim_spice_capacitance[MAXLAYERS] = {\n"),
3760 us_tecedmakesymbol(techname));
3761 for(i=0; i<tech->layercount; i++)
3762 {
3763 xprintf(f, x_("\t%s"), us_tecedmakefloatstring(us_tecspice_cap[i]));
3764 if (i != tech->layercount-1) xprintf(f, x_(","));
3765 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3766 }
3767 xprintf(f, x_("};\n"));
3768 }
3769 if ((us_tecflags&HASSPIECAP) != 0)
3770 {
3771 xprintf(f, x_("static float %s_sim_spice_edge_cap[MAXLAYERS] = {\n"),
3772 us_tecedmakesymbol(techname));
3773 for(i=0; i<tech->layercount; i++)
3774 {
3775 xprintf(f, x_("\t%s"), us_tecedmakefloatstring(us_tecspice_ecap[i]));
3776 if (i != tech->layercount-1) xprintf(f, x_(","));
3777 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3778 }
3779 xprintf(f, x_("};\n"));
3780 }
3781
3782 /* write the 3D information */
3783 if ((us_tecflags&HAS3DINFO) != 0)
3784 {
3785 xprintf(f, x_("static INTBIG %s_3dheight_layers[MAXLAYERS] = {\n"),
3786 us_tecedmakesymbol(techname));
3787 for(i=0; i<tech->layercount; i++)
3788 {
3789 xprintf(f, x_("\t%ld"), us_tec3d_height[i]);
3790 if (i != tech->layercount-1) xprintf(f, x_(","));
3791 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3792 }
3793 xprintf(f, x_("};\n"));
3794 xprintf(f, x_("static INTBIG %s_3dthick_layers[MAXLAYERS] = {\n"),
3795 us_tecedmakesymbol(techname));
3796 for(i=0; i<tech->layercount; i++)
3797 {
3798 xprintf(f, x_("\t%ld"), us_tec3d_thickness[i]);
3799 if (i != tech->layercount-1) xprintf(f, x_(","));
3800 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3801 }
3802 xprintf(f, x_("};\n"));
3803 }
3804 if ((us_tecflags&HASPRINTCOL) != 0)
3805 {
3806 xprintf(f, x_("static INTBIG %s_printcolors_layers[MAXLAYERS*5] = {\n"),
3807 us_tecedmakesymbol(techname));
3808 for(i=0; i<tech->layercount; i++)
3809 {
3810 xprintf(f, x_("\t%ld,%ld,%ld, %ld,%ld"), us_tecprint_colors[i*5],
3811 us_tecprint_colors[i*5+1], us_tecprint_colors[i*5+2],
3812 us_tecprint_colors[i*5+3], us_tecprint_colors[i*5+4]);
3813 if (i != tech->layercount-1) xprintf(f, x_(","));
3814 xprintf(f, x_("\t\t/* %s */\n"), us_teclayer_names[i]);
3815 }
3816 xprintf(f, x_("};\n"));
3817 }
3818
3819 /* write the color map */
3820 if ((us_tecflags&HASCOLORMAP) != 0)
3821 {
3822 /* determine the five transparent layers */
3823 l1 = l2 = l3 = l4 = l5 = 0;
3824 for(i=0; i<tech->layercount; i++)
3825 {
3826 if (tech->layers[i]->bits == LAYERT1 && l1 == 0)
3827 l1 = us_teclayer_names[i]; else
3828 if (tech->layers[i]->bits == LAYERT2 && l2 == 0)
3829 l2 = us_teclayer_names[i]; else
3830 if (tech->layers[i]->bits == LAYERT3 && l3 == 0)
3831 l3 = us_teclayer_names[i]; else
3832 if (tech->layers[i]->bits == LAYERT4 && l4 == 0)
3833 l4 = us_teclayer_names[i]; else
3834 if (tech->layers[i]->bits == LAYERT5 && l5 == 0)
3835 l5 = us_teclayer_names[i];
3836 }
3837 if (l1 == 0) l1 = x_("layer 1");
3838 if (l2 == 0) l2 = x_("layer 2");
3839 if (l3 == 0) l3 = x_("layer 3");
3840 if (l4 == 0) l4 = x_("layer 4");
3841 if (l5 == 0) l5 = x_("layer 5");
3842 xprintf(f, x_("\nstatic TECH_COLORMAP %s_colmap[32] =\n{\n"), us_tecedmakesymbol(techname));
3843 for(i=0; i<32; i++)
3844 {
3845 xprintf(f, x_("\t{%3d,%3d,%3d}, /* %2d: "), us_teccolmap[i].red,
3846 us_teccolmap[i].green, us_teccolmap[i].blue, i);
3847 if ((i&1) != 0) xprintf(f, x_("%s"), l1); else
3848 for(j=0; j<(INTBIG)estrlen(l1); j++) xprintf(f, x_(" "));
3849 xprintf(f, x_("+"));
3850 if ((i&2) != 0) xprintf(f, x_("%s"), l2); else
3851 for(j=0; j<(INTBIG)estrlen(l2); j++) xprintf(f, x_(" "));
3852 xprintf(f, x_("+"));
3853 if ((i&4) != 0) xprintf(f, x_("%s"), l3); else
3854 for(j=0; j<(INTBIG)estrlen(l3); j++) xprintf(f, x_(" "));
3855 xprintf(f, x_("+"));
3856 if ((i&8) != 0) xprintf(f, x_("%s"), l4); else
3857 for(j=0; j<(INTBIG)estrlen(l4); j++) xprintf(f, x_(" "));
3858 xprintf(f, x_("+"));
3859 if ((i&16) != 0) xprintf(f, x_("%s"), l5); else
3860 for(j=0; j<(INTBIG)estrlen(l5); j++) xprintf(f, x_(" "));
3861 xprintf(f, x_(" */\n"));
3862 }
3863 xprintf(f, x_("};\n"));
3864 }
3865
3866 /* write design rules */
3867 if ((us_tecflags&(HASDRCMINWID|HASCONDRC|HASUNCONDRC|HASCONDRCW|HASUNCONDRCW|HASCONDRCM|HASUNCONDRCM|HASEDGEDRC)) != 0)
3868 {
3869 xprintf(f, x_("\n/******************** DESIGN RULES ********************/\n"));
3870
3871 /* write the DRC minimum width information */
3872 if ((us_tecflags&HASDRCMINWID) != 0)
3873 {
3874 xprintf(f, x_("static INTBIG %s_minimum_width[MAXLAYERS] = {"),
3875 us_tecedmakesymbol(techname));
3876 for(i=0; i<tech->layercount; i++)
3877 {
3878 if (i != 0) xprintf(f, x_(", "));
3879 xprintf(f, x_("%s"), us_tecedmakefract(us_tecdrc_rules->minwidth[i]));
3880 }
3881 xprintf(f, x_("};\n"));
3882 if ((us_tecflags&HASDRCMINWIDR) != 0)
3883 {
3884 xprintf(f, x_("static char *%s_minimum_width_rule[MAXLAYERS] = {"),
3885 us_tecedmakesymbol(techname));
3886 for(i=0; i<tech->layercount; i++)
3887 {
3888 if (i != 0) xprintf(f, x_(", "));
3889 xprintf(f, x_("x_(\"%s\")"), us_tecdrc_rules->minwidthR[i]);
3890 }
3891 xprintf(f, x_("};\n"));
3892 }
3893 }
3894
3895 if ((us_tecflags&HASCONDRC) != 0)
3896 {
3897 xprintf(f, x_("\nstatic INTBIG %s_connectedtable[] = {\n"),
3898 us_tecedmakesymbol(techname));
3899 us_teceditdumpdrctab(f, us_tecdrc_rules->conlist, tech, FALSE);
3900 if ((us_tecflags&HASCONDRCR) != 0)
3901 {
3902 xprintf(f, x_("\nstatic char *%s_connectedtable_rule[] = {\n"),
3903 us_tecedmakesymbol(techname));
3904 us_teceditdumpdrctab(f, us_tecdrc_rules->conlistR, tech, TRUE);
3905 }
3906 }
3907 if ((us_tecflags&HASUNCONDRC) != 0)
3908 {
3909 xprintf(f, x_("\nstatic INTBIG %s_unconnectedtable[] = {\n"),
3910 us_tecedmakesymbol(techname));
3911 us_teceditdumpdrctab(f, us_tecdrc_rules->unconlist, tech, FALSE);
3912 if ((us_tecflags&HASUNCONDRCR) != 0)
3913 {
3914 xprintf(f, x_("\nstatic char *%s_unconnectedtable_rule[] = {\n"),
3915 us_tecedmakesymbol(techname));
3916 us_teceditdumpdrctab(f, us_tecdrc_rules->unconlistR, tech, TRUE);
3917 }
3918 }
3919 if ((us_tecflags&HASCONDRCW) != 0)
3920 {
3921 xprintf(f, x_("\nstatic INTBIG %s_connectedtable_wide[] = {\n"),
3922 us_tecedmakesymbol(techname));
3923 us_teceditdumpdrctab(f, us_tecdrc_rules->conlistW, tech, FALSE);
3924 if ((us_tecflags&HASCONDRCWR) != 0)
3925 {
3926 xprintf(f, x_("\nstatic char *%s_connectedtable_wide_rule[] = {\n"),
3927 us_tecedmakesymbol(techname));
3928 us_teceditdumpdrctab(f, us_tecdrc_rules->conlistWR, tech, TRUE);
3929 }
3930 }
3931 if ((us_tecflags&HASUNCONDRCW) != 0)
3932 {
3933 xprintf(f, x_("\nstatic INTBIG %s_unconnectedtable_wide[] = {\n"),
3934 us_tecedmakesymbol(techname));
3935 us_teceditdumpdrctab(f, us_tecdrc_rules->unconlistW, tech, FALSE);
3936 if ((us_tecflags&HASUNCONDRCWR) != 0)
3937 {
3938 xprintf(f, x_("\nstatic char *%s_unconnectedtable_wide_rule[] = {\n"),
3939 us_tecedmakesymbol(techname));
3940 us_teceditdumpdrctab(f, us_tecdrc_rules->unconlistWR, tech, TRUE);
3941 }
3942 }
3943 if ((us_tecflags&HASCONDRCM) != 0)
3944 {
3945 xprintf(f, x_("\nstatic INTBIG %s_connectedtable_multi[] = {\n"),
3946 us_tecedmakesymbol(techname));
3947 us_teceditdumpdrctab(f, us_tecdrc_rules->conlistM, tech, FALSE);
3948 if ((us_tecflags&HASCONDRCMR) != 0)
3949 {
3950 xprintf(f, x_("\nstatic char *%s_connectedtable_multi_rule[] = {\n"),
3951 us_tecedmakesymbol(techname));
3952 us_teceditdumpdrctab(f, us_tecdrc_rules->conlistMR, tech, TRUE);
3953 }
3954 }
3955 if ((us_tecflags&HASUNCONDRCM) != 0)
3956 {
3957 xprintf(f, x_("\nstatic INTBIG %s_unconnectedtable_multi[] = {\n"),
3958 us_tecedmakesymbol(techname));
3959 us_teceditdumpdrctab(f, us_tecdrc_rules->unconlistM, tech, FALSE);
3960 if ((us_tecflags&HASUNCONDRCMR) != 0)
3961 {
3962 xprintf(f, x_("\nstatic char *%s_unconnectedtable_multi_rule[] = {\n"),
3963 us_tecedmakesymbol(techname));
3964 us_teceditdumpdrctab(f, us_tecdrc_rules->unconlistMR, tech, TRUE);
3965 }
3966 }
3967 if ((us_tecflags&HASEDGEDRC) != 0)
3968 {
3969 xprintf(f, x_("\nstatic INTBIG %s_edgetable[] = {\n"),
3970 us_tecedmakesymbol(techname));
3971 us_teceditdumpdrctab(f, us_tecdrc_rules->edgelist, tech, FALSE);
3972 if ((us_tecflags&HASEDGEDRCR) != 0)
3973 {
3974 xprintf(f, x_("\nstatic char *%s_edgetable_rule[] = {\n"),
3975 us_tecedmakesymbol(techname));
3976 us_teceditdumpdrctab(f, us_tecdrc_rules->edgelistR, tech, TRUE);
3977 }
3978 }
3979 }
3980 }
3981
us_teceditdumpdrctab(FILE * f,void * distances,TECHNOLOGY * tech,BOOLEAN isstring)3982 void us_teceditdumpdrctab(FILE *f, void *distances, TECHNOLOGY *tech, BOOLEAN isstring)
3983 {
3984 REGISTER INTBIG i, j;
3985 REGISTER INTBIG amt, mod, *amtlist;
3986 CHAR shortname[7], *msg, **distlist;
3987
3988 for(i=0; i<6; i++)
3989 {
3990 xprintf(f, x_("/* "));
3991 for(j=0; j<tech->layercount; j++)
3992 {
3993 if ((INTBIG)estrlen(us_teclayer_iname[j]) <= i) xprintf(f, x_(" ")); else
3994 xprintf(f, x_("%c"), us_teclayer_iname[j][i]);
3995 xprintf(f, x_(" "));
3996 }
3997 xprintf(f, x_(" */\n"));
3998 }
3999 if (isstring) distlist = (CHAR **)distances; else
4000 amtlist = (INTBIG *)distances;
4001 for(j=0; j<tech->layercount; j++)
4002 {
4003 (void)estrncpy(shortname, us_teclayer_iname[j], 6);
4004 shortname[6] = 0;
4005 xprintf(f, x_("/* %-6s */ "), shortname);
4006 for(i=0; i<j; i++) xprintf(f, x_(" "));
4007 for(i=j; i<tech->layercount; i++)
4008 {
4009 if (isstring)
4010 {
4011 msg = *distlist++;
4012 xprintf(f, x_("x_(\"%s\")"), msg);
4013 } else
4014 {
4015 amt = *amtlist++;
4016 if (amt < 0) xprintf(f, x_("XX")); else
4017 {
4018 mod = amt % WHOLE;
4019 if (mod == 0) xprintf(f, x_("K%ld"), amt/WHOLE); else
4020 if (mod == WHOLE/2) xprintf(f, x_("H%ld"), amt/WHOLE); else
4021 if (mod == WHOLE/4) xprintf(f, x_("Q%ld"), amt/WHOLE); else
4022 if (mod == WHOLE/4*3) xprintf(f, x_("T%ld"), amt/WHOLE); else
4023 xprintf(f, x_("%ld"), amt);
4024 }
4025 }
4026 if (j != tech->layercount-1 || i != tech->layercount-1)
4027 xprintf(f, x_(","));
4028 }
4029 xprintf(f, x_("\n"));
4030 }
4031 xprintf(f, x_("};\n"));
4032 }
4033
4034 /*
4035 * routine to dump the arc information in technology "tech" to the stream in
4036 * "f".
4037 */
us_teceditdumparcs(FILE * f,TECHNOLOGY * tech,CHAR * techname)4038 void us_teceditdumparcs(FILE *f, TECHNOLOGY *tech, CHAR *techname)
4039 {
4040 REGISTER INTBIG i, j, k;
4041
4042 /* print the header */
4043 xprintf(f, x_("\n/******************** ARCS ********************/\n"));
4044
4045 /* compute the width of the widest arc name */
4046 k = 12;
4047 for(i=0; i<tech->arcprotocount; i++)
4048 k = maxi(k, estrlen(tech->arcprotos[i]->arcname));
4049 k++;
4050
4051 /* write the number of arcs */
4052 xprintf(f, x_("\n#define ARCPROTOCOUNT"));
4053 for(j=12; j<k; j++) xprintf(f, x_(" "));
4054 xprintf(f, x_("%ld\n"), tech->arcprotocount);
4055
4056 /* write defines for each arc */
4057 for(i=0; i<tech->arcprotocount; i++)
4058 {
4059 xprintf(f, x_("#define A%s"), us_tecedmakeupper(tech->arcprotos[i]->arcname));
4060 for(j=estrlen(tech->arcprotos[i]->arcname); j<k; j++)
4061 xprintf(f, x_(" "));
4062 xprintf(f, x_("%ld\t\t\t\t/* %s */\n"), i, tech->arcprotos[i]->arcname);
4063 }
4064
4065 /* now write the arcs */
4066 for(i=0; i<tech->arcprotocount; i++)
4067 {
4068 xprintf(f, x_("\nstatic TECH_ARCLAY %s_al_%ld[] = {"),
4069 us_tecedmakesymbol(techname), i);
4070 for(k=0; k<tech->arcprotos[i]->laycount; k++)
4071 {
4072 if (k != 0) xprintf(f, x_(", "));
4073 xprintf(f, x_("{"));
4074 xprintf(f, x_("L%s,"), us_teclayer_iname[tech->arcprotos[i]->list[k].lay]);
4075 if (tech->arcprotos[i]->list[k].off == 0) xprintf(f, x_("0,")); else
4076 xprintf(f, x_("%s,"), us_tecedmakefract(tech->arcprotos[i]->list[k].off));
4077 if (tech->arcprotos[i]->list[k].style == FILLED) xprintf(f, x_("FILLED}")); else
4078 xprintf(f, x_("CLOSED}"));
4079 }
4080 xprintf(f, x_("};\n"));
4081 xprintf(f, x_("static TECH_ARCS %s_a_%ld = {\n"), us_tecedmakesymbol(techname), i);
4082 xprintf(f, x_("\tx_(\"%s\"), "), tech->arcprotos[i]->arcname);
4083 xprintf(f, x_("%s, "), us_tecedmakefract(tech->arcprotos[i]->arcwidth));
4084 xprintf(f, x_("A%s,NOARCPROTO,\n"), us_tecedmakeupper(tech->arcprotos[i]->arcname));
4085 xprintf(f, x_("\t%d, %s_al_%ld,\n"), tech->arcprotos[i]->laycount,
4086 us_tecedmakesymbol(techname), i);
4087 for(j=0; us_tecarc_functions[j].name != 0; j++)
4088 if (us_tecarc_functions[j].value ==
4089 (INTBIG)((tech->arcprotos[i]->initialbits&AFUNCTION)>>AFUNCTIONSH))
4090 {
4091 xprintf(f, x_("\t(%s<<AFUNCTIONSH)"), us_tecarc_functions[j].constant);
4092 break;
4093 }
4094 if (us_tecarc_functions[j].name == 0) xprintf(f, x_("\t(APUNKNOWN<<AFUNCTIONSH)"));
4095 if ((tech->arcprotos[i]->initialbits&WANTFIXANG) != 0) xprintf(f, x_("|WANTFIXANG"));
4096 if ((tech->arcprotos[i]->initialbits&CANWIPE) != 0) xprintf(f, x_("|CANWIPE"));
4097 if ((tech->arcprotos[i]->initialbits&WANTNOEXTEND) != 0) xprintf(f, x_("|WANTNOEXTEND"));
4098 xprintf(f, x_("|(%ld<<AANGLEINCSH)"), (tech->arcprotos[i]->initialbits&AANGLEINC)>>AANGLEINCSH);
4099 xprintf(f, x_("};\n"));
4100 }
4101
4102 /* print the summary */
4103 xprintf(f, x_("\nTECH_ARCS *%s_arcprotos[ARCPROTOCOUNT+1] = {\n\t"),
4104 us_tecedmakesymbol(techname));
4105 for(i=0; i<tech->arcprotocount; i++)
4106 xprintf(f, x_("&%s_a_%ld, "), us_tecedmakesymbol(techname), i);
4107 xprintf(f, x_("((TECH_ARCS *)-1)};\n"));
4108
4109 /* print the variable with the width offsets */
4110 if ((us_tecflags&HASARCWID) != 0)
4111 {
4112 xprintf(f, x_("\nstatic INTBIG %s_arc_widoff[ARCPROTOCOUNT] = {"),
4113 us_tecedmakesymbol(techname));
4114 for(i=0; i<tech->arcprotocount; i++)
4115 {
4116 if (i != 0) xprintf(f, x_(", "));
4117 if (us_tecarc_widoff[i] == 0) xprintf(f, x_("0")); else
4118 xprintf(f, x_("%s"), us_tecedmakefract(us_tecarc_widoff[i]));
4119 }
4120 xprintf(f, x_("};\n"));
4121 }
4122 }
4123
4124 /*
4125 * routine to dump the node information in technology "tech" to the stream in
4126 * "f".
4127 */
us_teceditdumpnodes(FILE * f,TECHNOLOGY * tech,CHAR * techname)4128 void us_teceditdumpnodes(FILE *f, TECHNOLOGY *tech, CHAR *techname)
4129 {
4130 REGISTER RULE *r;
4131 REGISTER INTBIG i, j, k, l, tot;
4132 CHAR *ab, *sym;
4133 BOOLEAN yaxis;
4134 REGISTER PCON *pc;
4135 REGISTER TECH_POLYGON *plist;
4136 REGISTER TECH_SERPENT *slist;
4137 REGISTER TECH_NODES *nlist;
4138 REGISTER void *infstr;
4139
4140 /* make abbreviations for each node */
4141 for(i=0; i<tech->nodeprotocount; i++)
4142 {
4143 (void)allocstring(&ab, makeabbrev(tech->nodeprotos[i]->nodename, FALSE), el_tempcluster);
4144 tech->nodeprotos[i]->creation = (NODEPROTO *)ab;
4145
4146 /* loop until the name is unique */
4147 for(;;)
4148 {
4149 /* see if a previously assigned abbreviation is the same */
4150 for(j=0; j<i; j++)
4151 if (namesame(ab, (CHAR *)tech->nodeprotos[j]->creation) == 0) break;
4152 if (j == i) break;
4153
4154 /* name conflicts: change it */
4155 l = estrlen(ab);
4156 if (ab[l-1] >= '0' && ab[l-1] <= '8') ab[l-1]++; else
4157 {
4158 infstr = initinfstr();
4159 addstringtoinfstr(infstr, ab);
4160 addtoinfstr(infstr, '0');
4161 (void)reallocstring(&ab, returninfstr(infstr), el_tempcluster);
4162 tech->nodeprotos[i]->creation = (NODEPROTO *)ab;
4163 }
4164 }
4165 }
4166
4167 /* write the port lists */
4168 xprintf(f, x_("\n/******************** PORT CONNECTIONS ********************/\n\n"));
4169 i = 1;
4170 for(pc = us_tecedfirstpcon; pc != NOPCON; pc = pc->nextpcon)
4171 {
4172 pc->pcindex = i++;
4173 xprintf(f, x_("static INTBIG %s_pc_%ld[] = {-1, "),
4174 us_tecedmakesymbol(techname), pc->pcindex);
4175 for(j=0; j<pc->total; j++)
4176 {
4177 k = pc->connects[j+1];
4178 xprintf(f, x_("A%s, "), us_tecedmakeupper(tech->arcprotos[k]->arcname));
4179 }
4180 xprintf(f, x_("ALLGEN, -1};\n"));
4181 }
4182
4183 xprintf(f, x_("\n/******************** RECTANGLE DESCRIPTIONS ********************/"));
4184 xprintf(f, x_("\n\n"));
4185
4186 /* print box information */
4187 i = 1;
4188 for(r = us_tecedfirstrule; r != NORULE; r = r->nextrule)
4189 {
4190 if (!r->used) continue;
4191 r->rindex = i++;
4192 xprintf(f, x_("static INTBIG %s_box%ld[%ld] = {"),
4193 us_tecedmakesymbol(techname), r->rindex, r->count);
4194 for(j=0; j<r->count; j += 2)
4195 {
4196 if (j != 0) xprintf(f, x_(", "));
4197 if ((j%4) == 0) yaxis = FALSE; else yaxis = TRUE;
4198 xprintf(f, x_("%s"), us_tecededgelabel(r->value[j], r->value[j+1], yaxis));
4199 }
4200 if (r->istext != 0)
4201 xprintf(f, x_(", x_(\"%s\")"), (CHAR *)r->value[r->count]);
4202 xprintf(f, x_("};\n"));
4203 }
4204
4205 xprintf(f, x_("\n/******************** NODES ********************/\n"));
4206
4207 /* compute widest node name */
4208 k = 13;
4209 for(i=0; i<tech->nodeprotocount; i++)
4210 k = maxi(k, estrlen((CHAR *)tech->nodeprotos[i]->creation));
4211 k++;
4212
4213 /* write the total define */
4214 xprintf(f, x_("\n#define NODEPROTOCOUNT"));
4215 for(j=13; j<k; j++) xprintf(f, x_(" "));
4216 xprintf(f, x_("%ld\n"), tech->nodeprotocount);
4217
4218 /* write the other defines */
4219 for(i=0; i<tech->nodeprotocount; i++)
4220 {
4221 ab = (CHAR *)tech->nodeprotos[i]->creation;
4222 xprintf(f, x_("#define N%s"), us_tecedmakeupper(ab));
4223 for(j=estrlen(ab); j<k; j++) xprintf(f, x_(" "));
4224 xprintf(f, x_("%ld\t\t\t\t/* %s */\n"), i+1, tech->nodeprotos[i]->nodename);
4225 }
4226
4227 /* print node information */
4228 for(i=0; i<tech->nodeprotocount; i++)
4229 {
4230 /* header comment */
4231 nlist = tech->nodeprotos[i];
4232 ab = (CHAR *)nlist->creation;
4233 xprintf(f, x_("\n/* %s */\n"), nlist->nodename);
4234
4235 /* print ports */
4236 xprintf(f, x_("static TECH_PORTS %s_%s_p[] = {\n"), us_tecedmakesymbol(techname), ab);
4237 for(j=0; j<nlist->portcount; j++)
4238 {
4239 if (j != 0) xprintf(f, x_(",\n"));
4240
4241 /* the name of the connection structure */
4242 for(pc = us_tecedfirstpcon; pc != NOPCON; pc = pc->nextpcon)
4243 if (pc->connects == nlist->portlist[j].portarcs) break;
4244 if (pc != NOPCON)
4245 xprintf(f, x_("\t{%s_pc_%ld, "), us_tecedmakesymbol(techname), pc->pcindex);
4246
4247 /* the port name */
4248 xprintf(f, x_("x_(\"%s\"), NOPORTPROTO, "), nlist->portlist[j].protoname);
4249
4250 /* the port userbits */
4251 xprintf(f, x_("(%ld<<PORTARANGESH)"),
4252 (nlist->portlist[j].initialbits&PORTARANGE)>>PORTARANGESH);
4253 if ((nlist->portlist[j].initialbits&PORTANGLE) != 0)
4254 xprintf(f, x_("|(%ld<<PORTANGLESH)"),
4255 (nlist->portlist[j].initialbits&PORTANGLE)>>PORTANGLESH);
4256 if ((nlist->portlist[j].initialbits&PORTNET) != 0)
4257 xprintf(f, x_("|(%ld<<PORTNETSH)"), (nlist->portlist[j].initialbits&PORTNET)>>PORTNETSH);
4258 xprintf(f, x_(",\n"));
4259
4260 /* the port area */
4261 xprintf(f, x_("\t\t%s, %s, %s, %s}"),
4262 us_tecededgelabel(nlist->portlist[j].lowxmul, nlist->portlist[j].lowxsum, FALSE),
4263 us_tecededgelabel(nlist->portlist[j].lowymul, nlist->portlist[j].lowysum, TRUE),
4264 us_tecededgelabel(nlist->portlist[j].highxmul, nlist->portlist[j].highxsum, FALSE),
4265 us_tecededgelabel(nlist->portlist[j].highymul, nlist->portlist[j].highysum, TRUE));
4266 }
4267 xprintf(f, x_("};\n"));
4268
4269 /* print layers */
4270 for(k=0; k<2; k++)
4271 {
4272 if (nlist->special == SERPTRANS)
4273 {
4274 if (k == 0)
4275 {
4276 xprintf(f, x_("static TECH_SERPENT %s_%s_l[] = {\n"),
4277 us_tecedmakesymbol(techname), ab);
4278 tot = nlist->layercount;
4279 } else
4280 {
4281 xprintf(f, x_("static TECH_SERPENT %s_%sE_l[] = {\n"),
4282 us_tecedmakesymbol(techname), ab);
4283 tot = nlist->layercount + 1;
4284 }
4285 } else
4286 {
4287 if (k != 0) continue;
4288 xprintf(f, x_("static TECH_POLYGON %s_%s_l[] = {\n"),
4289 us_tecedmakesymbol(techname), ab);
4290 tot = nlist->layercount;
4291 }
4292 for(j=0; j<tot; j++)
4293 {
4294 if (j != 0) xprintf(f, x_(",\n"));
4295 xprintf(f, x_("\t"));
4296 if (nlist->special == SERPTRANS)
4297 {
4298 xprintf(f, x_("{"));
4299 if (k == 0) plist = &nlist->gra[j].basics;
4300 else plist = &nlist->ele[j].basics;
4301 } else plist = &nlist->layerlist[j];
4302 xprintf(f, x_("{L%s,"), us_teclayer_iname[plist->layernum]);
4303 xprintf(f, x_(" %d,"), plist->portnum);
4304 xprintf(f, x_(" %d,"), plist->count);
4305 switch (plist->style)
4306 {
4307 case FILLEDRECT: xprintf(f, x_(" FILLEDRECT,")); break;
4308 case CLOSEDRECT: xprintf(f, x_(" CLOSEDRECT,")); break;
4309 case CROSSED: xprintf(f, x_(" CROSSED,")); break;
4310 case FILLED: xprintf(f, x_(" FILLED,")); break;
4311 case CLOSED: xprintf(f, x_(" CLOSED,")); break;
4312 case OPENED: xprintf(f, x_(" OPENED,")); break;
4313 case OPENEDT1: xprintf(f, x_(" OPENEDT1,")); break;
4314 case OPENEDT2: xprintf(f, x_(" OPENEDT2,")); break;
4315 case OPENEDT3: xprintf(f, x_(" OPENEDT3,")); break;
4316 case VECTORS: xprintf(f, x_(" VECTORS,")); break;
4317 case CIRCLE: xprintf(f, x_(" CIRCLE,")); break;
4318 case THICKCIRCLE: xprintf(f, x_(" THICKCIRCLE,")); break;
4319 case DISC: xprintf(f, x_(" DISC,")); break;
4320 case CIRCLEARC: xprintf(f, x_(" CIRCLEARC,")); break;
4321 case THICKCIRCLEARC: xprintf(f, x_(" THICKCIRCLEARC,")); break;
4322 case TEXTCENT: xprintf(f, x_(" TEXTCENT,")); break;
4323 case TEXTTOP: xprintf(f, x_(" TEXTTOP,")); break;
4324 case TEXTBOT: xprintf(f, x_(" TEXTBOT,")); break;
4325 case TEXTLEFT: xprintf(f, x_(" TEXTLEFT,")); break;
4326 case TEXTRIGHT: xprintf(f, x_(" TEXTRIGHT,")); break;
4327 case TEXTTOPLEFT: xprintf(f, x_(" TEXTTOPLEFT,")); break;
4328 case TEXTBOTLEFT: xprintf(f, x_(" TEXTBOTLEFT,")); break;
4329 case TEXTTOPRIGHT: xprintf(f, x_(" TEXTTOPRIGHT,")); break;
4330 case TEXTBOTRIGHT: xprintf(f, x_(" TEXTBOTRIGHT,")); break;
4331 case TEXTBOX: xprintf(f, x_(" TEXTBOX,")); break;
4332 default: xprintf(f, x_(" ????,")); break;
4333 }
4334 switch (plist->representation)
4335 {
4336 case BOX: xprintf(f, x_(" BOX,")); break;
4337 case MINBOX: xprintf(f, x_(" MINBOX,")); break;
4338 case POINTS: xprintf(f, x_(" POINTS,")); break;
4339 default: xprintf(f, x_(" ????,")); break;
4340 }
4341 for(r = us_tecedfirstrule; r != NORULE; r = r->nextrule)
4342 if (r->value == plist->points) break;
4343 if (r != NORULE)
4344 xprintf(f, x_(" %s_box%ld"), us_tecedmakesymbol(techname), r->rindex); else
4345 xprintf(f, x_(" %s_box??"), us_tecedmakesymbol(techname));
4346 xprintf(f, x_("}"));
4347 if (nlist->special == SERPTRANS)
4348 {
4349 if (k == 0) slist = &nlist->gra[j]; else
4350 slist = &nlist->ele[j];
4351 xprintf(f, x_(", %s"), us_tecedmakefract(slist->lwidth));
4352 xprintf(f, x_(", %s"), us_tecedmakefract(slist->rwidth));
4353 xprintf(f, x_(", %s"), us_tecedmakefract(slist->extendt));
4354 xprintf(f, x_(", %s}"), us_tecedmakefract(slist->extendb));
4355 }
4356 }
4357 xprintf(f, x_("};\n"));
4358 }
4359
4360 /* print the node information */
4361 xprintf(f, x_("static TECH_NODES %s_%s = {\n"), us_tecedmakesymbol(techname), ab);
4362 xprintf(f, x_("\tx_(\"%s\"), N%s, NONODEPROTO,\n"), nlist->nodename, us_tecedmakeupper(ab));
4363 xprintf(f, x_("\t%s,"), us_tecedmakefract(nlist->xsize));
4364 xprintf(f, x_(" %s,\n"), us_tecedmakefract(nlist->ysize));
4365 xprintf(f, x_("\t%d, %s_%s_p,\n"), nlist->portcount, us_tecedmakesymbol(techname), ab);
4366 if (nlist->special == SERPTRANS)
4367 xprintf(f, x_("\t%d, (TECH_POLYGON *)0,\n"), nlist->layercount); else
4368 xprintf(f, x_("\t%d, %s_%s_l,\n"), nlist->layercount,
4369 us_tecedmakesymbol(techname), ab);
4370 j = (nlist->initialbits&NFUNCTION)>>NFUNCTIONSH;
4371 if (j < 0 || j >= MAXNODEFUNCTION) j = 0;
4372 xprintf(f, x_("\t(%s<<NFUNCTIONSH)"), nodefunctionconstantname(j));
4373 if ((nlist->initialbits&WIPEON1OR2) != 0) xprintf(f, x_("|WIPEON1OR2"));
4374 if ((nlist->initialbits&HOLDSTRACE) != 0) xprintf(f, x_("|HOLDSTRACE"));
4375 if ((nlist->initialbits&NSQUARE) != 0) xprintf(f, x_("|NSQUARE"));
4376 if ((nlist->initialbits&ARCSWIPE) != 0) xprintf(f, x_("|ARCSWIPE"));
4377 if ((nlist->initialbits&ARCSHRINK) != 0) xprintf(f, x_("|ARCSHRINK"));
4378 if ((nlist->initialbits&NODESHRINK) != 0) xprintf(f, x_("|NODESHRINK"));
4379 if ((nlist->initialbits&LOCKEDPRIM) != 0) xprintf(f, x_("|LOCKEDPRIM"));
4380 xprintf(f, x_(",\n"));
4381 switch (nlist->special)
4382 {
4383 case 0:
4384 xprintf(f, x_("\t0,0,0,0,0,0,0,0,0"));
4385 break;
4386 case SERPTRANS:
4387 xprintf(f, x_("\tSERPTRANS,%d,"), nlist->f1);
4388 xprintf(f, x_("%s,"), us_tecedmakefract(nlist->f2));
4389 xprintf(f, x_("%s,"), us_tecedmakefract(nlist->f3));
4390 xprintf(f, x_("%s,"), us_tecedmakefract(nlist->f4));
4391 xprintf(f, x_("%s,"), us_tecedmakefract(nlist->f5));
4392 xprintf(f, x_("%s,"), us_tecedmakefract(nlist->f6));
4393 xprintf(f, x_("%s_%s_l,"), us_tecedmakesymbol(techname), ab);
4394 xprintf(f, x_("%s_%sE_l"), us_tecedmakesymbol(techname), ab);
4395 break;
4396 case MULTICUT:
4397 xprintf(f, x_("\tMULTICUT,%s,"), us_tecedmakefract(nlist->f1));
4398 xprintf(f, x_("%s,"), us_tecedmakefract(nlist->f2));
4399 xprintf(f, x_("%s,"), us_tecedmakefract(nlist->f3));
4400 xprintf(f, x_("%s,0,0,0,0"), us_tecedmakefract(nlist->f4));
4401 break;
4402 case POLYGONAL:
4403 xprintf(f, x_("\tPOLYGONAL,0,0,0,0,0,0,0,0"));
4404 break;
4405 }
4406 xprintf(f, x_("};\n"));
4407 }
4408
4409 /* print summary of nodes */
4410 xprintf(f, x_("\nTECH_NODES *%s_nodeprotos[NODEPROTOCOUNT+1] = {\n\t"),
4411 us_tecedmakesymbol(techname));
4412 l = 4;
4413 for(i=0; i<tech->nodeprotocount; i++)
4414 {
4415 sym = us_tecedmakesymbol(techname);
4416 if (l + estrlen(sym) + estrlen((CHAR *)tech->nodeprotos[i]->creation) + 4 > 80)
4417 {
4418 xprintf(f, x_("\n\t"));
4419 l = 4;
4420 }
4421 xprintf(f, x_("&%s_%s, "), sym, (CHAR *)tech->nodeprotos[i]->creation);
4422 l += estrlen(sym) + estrlen((CHAR *)tech->nodeprotos[i]->creation) + 4;
4423 }
4424 xprintf(f, x_("((TECH_NODES *)-1)};\n"));
4425
4426 /* print highlight offset information */
4427 xprintf(f, x_("\nstatic INTBIG %s_node_widoff[NODEPROTOCOUNT*4] = {\n\t"),
4428 us_tecedmakesymbol(techname));
4429 l = 4;
4430 for(i=0; i<tech->nodeprotocount; i++)
4431 {
4432 if (i != 0) { xprintf(f, x_(", ")); l += 2; }
4433 infstr = initinfstr();
4434 if (us_tecnode_widoff[i*4] == 0) addtoinfstr(infstr, '0'); else
4435 addstringtoinfstr(infstr, us_tecedmakefract(us_tecnode_widoff[i*4]));
4436 addtoinfstr(infstr, ',');
4437 if (us_tecnode_widoff[i*4+1] == 0) addtoinfstr(infstr, '0'); else
4438 addstringtoinfstr(infstr, us_tecedmakefract(us_tecnode_widoff[i*4+1]));
4439 addtoinfstr(infstr, ',');
4440 if (us_tecnode_widoff[i*4+2] == 0) addtoinfstr(infstr, '0'); else
4441 addstringtoinfstr(infstr, us_tecedmakefract(us_tecnode_widoff[i*4+2]));
4442 addtoinfstr(infstr, ',');
4443 if (us_tecnode_widoff[i*4+3] == 0) addtoinfstr(infstr, '0'); else
4444 addstringtoinfstr(infstr, us_tecedmakefract(us_tecnode_widoff[i*4+3]));
4445 sym = returninfstr(infstr);
4446 l += estrlen(sym);
4447 if (l > 80)
4448 {
4449 xprintf(f, x_("\n\t"));
4450 l = 4;
4451 }
4452 xprintf(f, x_("%s"), sym);
4453 }
4454 xprintf(f, x_("};\n"));
4455
4456 /* print grab point informaton if it exists */
4457 if ((us_tecflags&HASGRAB) != 0 && us_tecnode_grabcount > 0)
4458 {
4459 xprintf(f, x_("\nstatic INTBIG %s_centergrab[] = {\n"), us_tecedmakesymbol(techname));
4460 for(i=0; i<us_tecnode_grabcount; i += 3)
4461 {
4462 ab = (CHAR *)tech->nodeprotos[us_tecnode_grab[i]-1]->creation;
4463 xprintf(f, x_("\tN%s, %ld, %ld"), us_tecedmakeupper(ab), us_tecnode_grab[i+1],
4464 us_tecnode_grab[i+2]);
4465 if (i != us_tecnode_grabcount-3) xprintf(f, x_(",\n"));
4466 }
4467 xprintf(f, x_("\n};\n"));
4468 }
4469
4470 /* print minimum node size informaton if it exists */
4471 if ((us_tecflags&HASMINNODE) != 0)
4472 {
4473 xprintf(f, x_("\nstatic INTBIG %s_node_minsize[NODEPROTOCOUNT*2] = {\n"), us_tecedmakesymbol(techname));
4474 for(i=0; i<tech->nodeprotocount; i++)
4475 {
4476 if (us_tecdrc_rules->minnodesize[i*2] < 0) ab = x_("XX"); else
4477 ab = us_tecedmakefract(us_tecdrc_rules->minnodesize[i*2]);
4478 xprintf(f, x_("\t%s, "), ab);
4479 if (us_tecdrc_rules->minnodesize[i*2+1] < 0) ab = x_("XX"); else
4480 ab = us_tecedmakefract(us_tecdrc_rules->minnodesize[i*2+1]);
4481 xprintf(f, x_("%s"), ab);
4482 if (i == tech->nodeprotocount-1) ab = x_(""); else ab = x_(",");
4483 xprintf(f, x_("%s\t\t/* %s */\n"), ab, tech->nodeprotos[i]->nodename);
4484 }
4485 xprintf(f, x_("};\n"));
4486 }
4487 if ((us_tecflags&HASMINNODER) != 0)
4488 {
4489 xprintf(f, x_("\nstatic char *%s_node_minsize_rule[NODEPROTOCOUNT] = {\n"), us_tecedmakesymbol(techname));
4490 for(i=0; i<tech->nodeprotocount; i++)
4491 {
4492 if (i == tech->nodeprotocount-1) ab = x_(""); else ab = x_(",");
4493 xprintf(f, x_("\tx_(\"%s\")%s\t\t/* %s */\n"), us_tecdrc_rules->minnodesizeR[i], ab,
4494 tech->nodeprotos[i]->nodename);
4495 }
4496 xprintf(f, x_("};\n"));
4497 }
4498
4499 /* clean up */
4500 for(i=0; i<tech->nodeprotocount; i++)
4501 {
4502 efree((CHAR *)tech->nodeprotos[i]->creation);
4503 tech->nodeprotos[i]->creation = NONODEPROTO;
4504 }
4505 }
4506
4507 /*
4508 * routine to dump the variable information in technology "tech" to the stream in
4509 * "f".
4510 */
us_teceditdumpvars(FILE * f,TECHNOLOGY * tech,CHAR * techname)4511 void us_teceditdumpvars(FILE *f, TECHNOLOGY *tech, CHAR *techname)
4512 {
4513 REGISTER INTBIG i, j, k;
4514 REGISTER CHAR *pt;
4515 REGISTER VARIABLE *var;
4516
4517 xprintf(f, x_("\n/******************** VARIABLE AGGREGATION ********************/\n"));
4518
4519 /* write any miscellaneous string array variables */
4520 for(i=0; us_knownvars[i].varname != 0; i++)
4521 {
4522 var = getval((INTBIG)tech, VTECHNOLOGY, -1, us_knownvars[i].varname);
4523 if (var == NOVARIABLE) continue;
4524 if ((var->type&(VTYPE|VISARRAY)) == (VSTRING|VISARRAY))
4525 {
4526 xprintf(f, x_("\nchar *%s_%s[] = {\n"), us_tecedmakesymbol(techname),
4527 us_knownvars[i].varname);
4528 j = getlength(var);
4529 for(k=0; k<j; k++)
4530 {
4531 xprintf(f, x_("\tx_(\""));
4532 for(pt = ((CHAR **)var->addr)[k]; *pt != 0; pt++)
4533 {
4534 if (*pt == '"') xprintf(f, x_("\\"));
4535 xprintf(f, x_("%c"), *pt);
4536 }
4537 xprintf(f, x_("\"),\n"));
4538 }
4539 xprintf(f, x_("\tNOSTRING};\n"));
4540 }
4541 }
4542
4543 xprintf(f, x_("\nTECH_VARIABLES %s_variables[] =\n{\n"), us_tecedmakesymbol(techname));
4544
4545 xprintf(f, x_("\t{x_(\"TECH_layer_names\"), (CHAR *)%s_layer_names, 0.0,\n"),
4546 us_tecedmakesymbol(techname));
4547 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4548
4549 xprintf(f, x_("\t{x_(\"TECH_layer_function\"), (CHAR *)%s_layer_function, 0.0,\n"),
4550 us_tecedmakesymbol(techname));
4551 xprintf(f, x_("\t\tVINTEGER|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4552
4553 xprintf(f, x_("\t{x_(\"TECH_node_width_offset\"), (CHAR *)%s_node_widoff, 0.0,\n"),
4554 us_tecedmakesymbol(techname));
4555 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|((NODEPROTOCOUNT*4)<<VLENGTHSH)},\n"));
4556 if ((us_tecflags&HASGRAB) != 0 && us_tecnode_grabcount > 0)
4557 xprintf(f, x_("\t{x_(\"prototype_center\"), (CHAR *)%s_centergrab, 0.0, %ld},\n"),
4558 us_tecedmakesymbol(techname), us_tecnode_grabcount/3);
4559
4560 if ((us_tecflags&HASMINNODE) != 0)
4561 {
4562 xprintf(f, x_("\t{x_(\"DRC_min_node_size\"), (CHAR *)%s_node_minsize, 0.0,\n"),
4563 us_tecedmakesymbol(techname));
4564 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|((NODEPROTOCOUNT*2)<<VLENGTHSH)},\n"));
4565 }
4566 if ((us_tecflags&HASMINNODER) != 0)
4567 {
4568 xprintf(f, x_("\t{x_(\"DRC_min_node_size_rule\"), (CHAR *)%s_node_minsize_rule, 0.0,\n"),
4569 us_tecedmakesymbol(techname));
4570 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|(NODEPROTOCOUNT<<VLENGTHSH)},\n"));
4571 }
4572
4573 if ((us_tecflags&HASARCWID) != 0)
4574 {
4575 xprintf(f, x_("\t{x_(\"TECH_arc_width_offset\"), (CHAR *)%s_arc_widoff, 0.0,\n"),
4576 us_tecedmakesymbol(techname));
4577 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|(ARCPROTOCOUNT<<VLENGTHSH)},\n"));
4578 }
4579
4580 if ((us_tecflags&HAS3DINFO) != 0)
4581 {
4582 xprintf(f, x_("\t{x_(\"TECH_layer_3dthickness\"), (CHAR *)%s_3dthick_layers, 0.0,\n"),
4583 us_tecedmakesymbol(techname));
4584 xprintf(f, x_("\t\tVINTEGER|VDONTSAVE|VISARRAY|(ARCPROTOCOUNT<<VLENGTHSH)},\n"));
4585 xprintf(f, x_("\t{x_(\"TECH_layer_3dheight\"), (CHAR *)%s_3dheight_layers, 0.0,\n"),
4586 us_tecedmakesymbol(techname));
4587 xprintf(f, x_("\t\tVINTEGER|VDONTSAVE|VISARRAY|(ARCPROTOCOUNT<<VLENGTHSH)},\n"));
4588 }
4589 if ((us_tecflags&HASPRINTCOL) != 0)
4590 {
4591 xprintf(f, x_("\t{x_(\"USER_print_colors\"), (CHAR *)%s_printcolors_layers, 0.0,\n"),
4592 us_tecedmakesymbol(techname));
4593 xprintf(f, x_("\t\tVINTEGER|VDONTSAVE|VISARRAY|((MAXLAYERS*5)<<VLENGTHSH)},\n"));
4594 }
4595
4596 xprintf(f, x_("\t{x_(\"USER_layer_letters\"), (CHAR *)%s_layer_letters, 0.0,\n"),
4597 us_tecedmakesymbol(techname));
4598 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4599
4600 if ((us_tecflags&HASCOLORMAP) != 0)
4601 {
4602 xprintf(f, x_("\t{x_(\"USER_color_map\"), (CHAR *)%s_colmap, 0.0,\n"),
4603 us_tecedmakesymbol(techname));
4604 xprintf(f, x_("\t\tVCHAR|VDONTSAVE|VISARRAY|((sizeof %s_colmap)<<VLENGTHSH)},\n"),
4605 us_tecedmakesymbol(techname));
4606 }
4607
4608 if ((us_tecflags&HASCIF) != 0)
4609 {
4610 xprintf(f, x_("\t{x_(\"IO_cif_layer_names\"), (CHAR *)%s_cif_layers, 0.0,\n"),
4611 us_tecedmakesymbol(techname));
4612 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4613 }
4614
4615 if ((us_tecflags&HASDXF) != 0)
4616 {
4617 xprintf(f, x_("\t{x_(\"IO_dxf_layer_names\"), (CHAR *)%s_dxf_layers, 0.0,\n"),
4618 us_tecedmakesymbol(techname));
4619 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4620 }
4621
4622 if ((us_tecflags&HASGDS) != 0)
4623 {
4624 xprintf(f, x_("\t{x_(\"IO_gds_layer_numbers\"), (CHAR *)%s_gds_layers, 0.0,\n"),
4625 us_tecedmakesymbol(techname));
4626 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4627 }
4628
4629 if ((us_tecflags&HASDRCMINWID) != 0)
4630 {
4631 xprintf(f, x_("\t{x_(\"DRC_min_width\"), (CHAR *)%s_minimum_width, 0.0,\n"),
4632 us_tecedmakesymbol(techname));
4633 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4634 if ((us_tecflags&HASDRCMINWIDR) != 0)
4635 {
4636 xprintf(f, x_("\t{x_(\"DRC_min_width_rule\"), (CHAR *)%s_minimum_width_rule, 0.0,\n"),
4637 us_tecedmakesymbol(techname));
4638 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4639 }
4640 }
4641 if ((us_tecflags&(HASCONDRCW|HASUNCONDRCW)) != 0)
4642 {
4643 xprintf(f, x_("\t{x_(\"DRC_wide_limit\"), (CHAR *)%ld, 0.0,\n"),
4644 us_tecdrc_rules->widelimit);
4645 xprintf(f, x_("\t\tVFRACT|VDONTSAVE},\n"));
4646 }
4647
4648 if ((us_tecflags&HASCONDRC) != 0)
4649 {
4650 xprintf(f, x_("\t{x_(\"DRC_min_connected_distances\"), (CHAR *)%s_connectedtable, 0.0,\n"),
4651 us_tecedmakesymbol(techname));
4652 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|\n"));
4653 xprintf(f, x_("\t\t\t(((sizeof %s_connectedtable)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4654 us_tecedmakesymbol(techname));
4655 if ((us_tecflags&HASCONDRCR) != 0)
4656 {
4657 xprintf(f, x_("\t{x_(\"DRC_min_connected_distances_rule\"), (CHAR *)%s_connectedtable_rule, 0.0,\n"),
4658 us_tecedmakesymbol(techname));
4659 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|\n"));
4660 xprintf(f, x_("\t\t\t(((sizeof %s_connectedtable_rule)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4661 us_tecedmakesymbol(techname));
4662 }
4663 }
4664 if ((us_tecflags&HASUNCONDRC) != 0)
4665 {
4666 xprintf(f, x_("\t{x_(\"DRC_min_unconnected_distances\"), (CHAR *)%s_unconnectedtable, 0.0,\n"),
4667 us_tecedmakesymbol(techname));
4668 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|\n"));
4669 xprintf(f, x_("\t\t (((sizeof %s_unconnectedtable)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4670 us_tecedmakesymbol(techname));
4671 if ((us_tecflags&HASUNCONDRCR) != 0)
4672 {
4673 xprintf(f, x_("\t{x_(\"DRC_min_unconnected_distances_rule\"), (CHAR *)%s_unconnectedtable_rule, 0.0,\n"),
4674 us_tecedmakesymbol(techname));
4675 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|\n"));
4676 xprintf(f, x_("\t\t\t(((sizeof %s_unconnectedtable_rule)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4677 us_tecedmakesymbol(techname));
4678 }
4679 }
4680
4681 if ((us_tecflags&HASCONDRCW) != 0)
4682 {
4683 xprintf(f, x_("\t{x_(\"DRC_min_connected_distances_wide\"), (CHAR *)%s_connectedtable_wide, 0.0,\n"),
4684 us_tecedmakesymbol(techname));
4685 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|\n"));
4686 xprintf(f, x_("\t\t\t(((sizeof %s_connectedtable_wide)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4687 us_tecedmakesymbol(techname));
4688 if ((us_tecflags&HASCONDRCWR) != 0)
4689 {
4690 xprintf(f, x_("\t{x_(\"DRC_min_connected_distances_wide_rule\"), (CHAR *)%s_connectedtable_wide_rule, 0.0,\n"),
4691 us_tecedmakesymbol(techname));
4692 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|\n"));
4693 xprintf(f, x_("\t\t\t(((sizeof %s_connectedtable_wide_rule)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4694 us_tecedmakesymbol(techname));
4695 }
4696 }
4697 if ((us_tecflags&HASUNCONDRCW) != 0)
4698 {
4699 xprintf(f, x_("\t{x_(\"DRC_min_unconnected_distances_wide\"), (CHAR *)%s_unconnectedtable_wide, 0.0,\n"),
4700 us_tecedmakesymbol(techname));
4701 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|\n"));
4702 xprintf(f, x_("\t\t (((sizeof %s_unconnectedtable_wide)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4703 us_tecedmakesymbol(techname));
4704 if ((us_tecflags&HASUNCONDRCWR) != 0)
4705 {
4706 xprintf(f, x_("\t{x_(\"DRC_min_unconnected_distances_wide_rule\"), (CHAR *)%s_unconnectedtable_wide_rule, 0.0,\n"),
4707 us_tecedmakesymbol(techname));
4708 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|\n"));
4709 xprintf(f, x_("\t\t\t(((sizeof %s_unconnectedtable_wide)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4710 us_tecedmakesymbol(techname));
4711 }
4712 }
4713
4714 if ((us_tecflags&HASCONDRCM) != 0)
4715 {
4716 xprintf(f, x_("\t{x_(\"DRC_min_connected_distances_multi\"), (CHAR *)%s_connectedtable_multi, 0.0,\n"),
4717 us_tecedmakesymbol(techname));
4718 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|\n"));
4719 xprintf(f, x_("\t\t\t(((sizeof %s_connectedtable_multi)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4720 us_tecedmakesymbol(techname));
4721 if ((us_tecflags&HASCONDRCMR) != 0)
4722 {
4723 xprintf(f, x_("\t{x_(\"DRC_min_connected_distances_multi_rule\"), (CHAR *)%s_connectedtable_multi_rule, 0.0,\n"),
4724 us_tecedmakesymbol(techname));
4725 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|\n"));
4726 xprintf(f, x_("\t\t\t(((sizeof %s_connectedtable_multi_rule)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4727 us_tecedmakesymbol(techname));
4728 }
4729 }
4730 if ((us_tecflags&HASUNCONDRCM) != 0)
4731 {
4732 xprintf(f, x_("\t{x_(\"DRC_min_unconnected_distances_multi\"), (CHAR *)%s_unconnectedtable_multi, 0.0,\n"),
4733 us_tecedmakesymbol(techname));
4734 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|\n"));
4735 xprintf(f, x_("\t\t (((sizeof %s_unconnectedtable_multi)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4736 us_tecedmakesymbol(techname));
4737 if ((us_tecflags&HASUNCONDRCMR) != 0)
4738 {
4739 xprintf(f, x_("\t{x_(\"DRC_min_unconnected_distances_multi_rule\"), (CHAR *)%s_unconnectedtable_multi_rule, 0.0,\n"),
4740 us_tecedmakesymbol(techname));
4741 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|\n"));
4742 xprintf(f, x_("\t\t\t(((sizeof %s_unconnectedtable_multi)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4743 us_tecedmakesymbol(techname));
4744 }
4745 }
4746 if ((us_tecflags&HASEDGEDRC) != 0)
4747 {
4748 xprintf(f, x_("\t{x_(\"DRC_min_edge_distances\"), (CHAR *)%s_edgetable, 0.0,\n"),
4749 us_tecedmakesymbol(techname));
4750 xprintf(f, x_("\t\tVFRACT|VDONTSAVE|VISARRAY|\n"));
4751 xprintf(f, x_("\t\t (((sizeof %s_edgetable)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4752 us_tecedmakesymbol(techname));
4753 if ((us_tecflags&HASEDGEDRCR) != 0)
4754 {
4755 xprintf(f, x_("\t{x_(\"DRC_min_edge_distances_rule\"), (CHAR *)%s_edgetable_rule, 0.0,\n"),
4756 us_tecedmakesymbol(techname));
4757 xprintf(f, x_("\t\tVSTRING|VDONTSAVE|VISARRAY|\n"));
4758 xprintf(f, x_("\t\t\t(((sizeof %s_edgetable)/SIZEOFINTBIG)<<VLENGTHSH)},\n"),
4759 us_tecedmakesymbol(techname));
4760 }
4761 }
4762
4763 if ((us_tecflags&HASSPIRES) != 0)
4764 {
4765 xprintf(f, x_("\t{x_(\"SIM_spice_resistance\"), (CHAR *)%s_sim_spice_resistance, 0.0,\n"),
4766 us_tecedmakesymbol(techname));
4767 xprintf(f, x_("\t\tVFLOAT|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4768 }
4769 if ((us_tecflags&HASSPICAP) != 0)
4770 {
4771 xprintf(f, x_("\t{x_(\"SIM_spice_capacitance\"), (CHAR *)%s_sim_spice_capacitance, 0.0,\n"),
4772 us_tecedmakesymbol(techname));
4773 xprintf(f, x_("\t\tVFLOAT|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4774 }
4775 if ((us_tecflags&HASSPIECAP) != 0)
4776 {
4777 xprintf(f, x_("\t{x_(\"SIM_spice_edge_capacitance\"), (CHAR *)%s_sim_spice_edge_cap, 0.0,\n"),
4778 us_tecedmakesymbol(techname));
4779 xprintf(f, x_("\t\tVFLOAT|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},\n"));
4780 }
4781
4782 /* throw in pointers to any miscellaneous variables */
4783 for(i=0; us_knownvars[i].varname != 0; i++)
4784 {
4785 var = getval((INTBIG)tech, VTECHNOLOGY, -1, us_knownvars[i].varname);
4786 if (var == NOVARIABLE) continue;
4787 xprintf(f, x_("\t{x_(\"%s\"), "), us_knownvars[i].varname);
4788 switch (var->type&(VTYPE|VISARRAY))
4789 {
4790 case VINTEGER:
4791 xprintf(f, x_("(CHAR *)%ld, 0.0, VINTEGER|VDONTSAVE"), var->addr);
4792 break;
4793 case VFLOAT:
4794 xprintf(f, x_("(CHAR *)0, %g, VFLOAT|VDONTSAVE"), castfloat(var->addr));
4795 break;
4796 case VSTRING:
4797 xprintf(f, x_("x_(\"%s\"), 0.0, VSTRING|VDONTSAVE"), (CHAR *)var->addr);
4798 break;
4799 case VSTRING|VISARRAY:
4800 xprintf(f, x_("(CHAR *)%s_%s, 0.0,\n\t\tVSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)"),
4801 us_tecedmakesymbol(techname), us_knownvars[i].varname);
4802 break;
4803 }
4804 xprintf(f, x_("},\n"));
4805 }
4806
4807 xprintf(f, x_("\t{NULL, NULL, 0.0, 0}\n};\n"));
4808 }
4809
4810 /*
4811 * routine to convert the multiplication and addition factors in "mul" and
4812 * "add" into proper constant names. The "yaxis" is false for X and 1 for Y
4813 */
us_tecededgelabel(INTBIG mul,INTBIG add,BOOLEAN yaxis)4814 CHAR *us_tecededgelabel(INTBIG mul, INTBIG add, BOOLEAN yaxis)
4815 {
4816 CHAR line[20];
4817 REGISTER INTBIG amt;
4818 REGISTER void *infstr;
4819
4820 infstr = initinfstr();
4821
4822 /* handle constant distance from center (handles halves up to 5.5) */
4823 if (mul == 0 && (add%H0) == 0 && abs(add) < K6)
4824 {
4825 addstringtoinfstr(infstr, x_("CENTER"));
4826 if (add == 0) return(returninfstr(infstr));
4827 if (!yaxis)
4828 {
4829 if (add < 0) addtoinfstr(infstr, 'L'); else addtoinfstr(infstr, 'R');
4830 } else
4831 {
4832 if (add < 0) addtoinfstr(infstr, 'D'); else addtoinfstr(infstr, 'U');
4833 }
4834 amt = abs(add);
4835 switch (amt%WHOLE)
4836 {
4837 case 0: (void)esnprintf(line, 20, x_("%ld"), amt/WHOLE); break;
4838 case H0: (void)esnprintf(line, 20, x_("%ldH"), amt/WHOLE); break;
4839 }
4840 addstringtoinfstr(infstr, line);
4841 return(returninfstr(infstr));
4842 }
4843
4844 /* handle constant distance from edge (handles quarters up to 10, halves to 20) */
4845 if ((mul == H0 || mul == -H0) &&
4846 (((add%Q0) == 0 && abs(add) < K10) || ((add%H0) == 0 && abs(add) < K20)))
4847 {
4848 if (!yaxis)
4849 {
4850 if (mul < 0) addstringtoinfstr(infstr, x_("LEFT")); else
4851 addstringtoinfstr(infstr, x_("RIGHT"));
4852 } else
4853 {
4854 if (mul < 0) addstringtoinfstr(infstr, x_("BOT")); else
4855 addstringtoinfstr(infstr, x_("TOP"));
4856 }
4857 if (add == 0) addstringtoinfstr(infstr, x_("EDGE")); else
4858 {
4859 amt = abs(add);
4860 switch (amt%WHOLE)
4861 {
4862 case 0: (void)esnprintf(line, 20, x_("IN%ld"), amt/WHOLE); break;
4863 case Q0: (void)esnprintf(line, 20, x_("IN%ldQ"), amt/WHOLE); break;
4864 case H0: (void)esnprintf(line, 20, x_("IN%ldH"), amt/WHOLE); break;
4865 case T0: (void)esnprintf(line, 20, x_("IN%ldT"), amt/WHOLE); break;
4866 }
4867 addstringtoinfstr(infstr, line);
4868 }
4869 return(returninfstr(infstr));
4870 }
4871
4872 /* generate two-value description */
4873 addstringtoinfstr(infstr, us_tecedmakefract(mul));
4874 addtoinfstr(infstr, ',');
4875 addstringtoinfstr(infstr, us_tecedmakefract(add));
4876 return(returninfstr(infstr));
4877 }
4878
4879 /****************************** WRITE TECHNOLOGY AS "JAVA" CODE ******************************/
4880
4881 /*
4882 * routine to dump the layer information in technology "tech" to the stream in
4883 * "f".
4884 */
us_teceditdumpjavalayers(FILE * f,TECHNOLOGY * tech,CHAR * techname)4885 void us_teceditdumpjavalayers(FILE *f, TECHNOLOGY *tech, CHAR *techname)
4886 {
4887 CHAR date[30], *transparent, *l1, *l2, *l3, *l4, *l5;
4888 REGISTER INTBIG i, j, k, red, green, blue;
4889 REGISTER void *infstr;
4890 float r, c;
4891 REGISTER BOOLEAN extrafunction;
4892 REGISTER VARIABLE *varr, *varc;
4893
4894 /* write legal banner */
4895 xprintf(f, x_("// BE SURE TO INCLUDE THIS TECHNOLOGY IN Technology.initAllTechnologies()\n\n"));
4896 xprintf(f, x_("/* -*- tab-width: 4 -*-\n"));
4897 xprintf(f, x_(" *\n"));
4898 xprintf(f, x_(" * Electric(tm) VLSI Design System\n"));
4899 xprintf(f, x_(" *\n"));
4900 xprintf(f, x_(" * File: %s.java\n"), techname);
4901 xprintf(f, x_(" * %s technology description\n"), techname);
4902 xprintf(f, x_(" * Generated automatically from a library\n"));
4903 xprintf(f, x_(" *\n"));
4904 estrcpy(date, timetostring(getcurrenttime()));
4905 date[24] = 0;
4906 xprintf(f, x_(" * Copyright (c) %s Sun Microsystems and Static Free Software\n"), &date[20]);
4907 xprintf(f, x_(" *\n"));
4908 xprintf(f, x_(" * Electric(tm) is free software; you can redistribute it and/or modify\n"));
4909 xprintf(f, x_(" * it under the terms of the GNU General Public License as published by\n"));
4910 xprintf(f, x_(" * the Free Software Foundation; either version 2 of the License, or\n"));
4911 xprintf(f, x_(" * (at your option) any later version.\n"));
4912 xprintf(f, x_(" *\n"));
4913 xprintf(f, x_(" * Electric(tm) is distributed in the hope that it will be useful,\n"));
4914 xprintf(f, x_(" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"));
4915 xprintf(f, x_(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"));
4916 xprintf(f, x_(" * GNU General Public License for more details.\n"));
4917 xprintf(f, x_(" *\n"));
4918 xprintf(f, x_(" * You should have received a copy of the GNU General Public License\n"));
4919 xprintf(f, x_(" * along with Electric(tm); see the file COPYING. If not, write to\n"));
4920 xprintf(f, x_(" * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,\n"));
4921 xprintf(f, x_(" * Boston, Mass 02111-1307, USA.\n"));
4922 xprintf(f, x_(" */\n"));
4923 xprintf(f, x_("package com.sun.electric.technology.technologies;\n"));
4924 xprintf(f, x_("\n"));
4925
4926 /* write header */
4927 xprintf(f, x_("import com.sun.electric.technology.Technology;\n"));
4928 xprintf(f, x_("import com.sun.electric.technology.Layer;\n"));
4929 xprintf(f, x_("import com.sun.electric.technology.PrimitiveNode;\n"));
4930 xprintf(f, x_("import com.sun.electric.technology.PrimitiveArc;\n"));
4931 xprintf(f, x_("import com.sun.electric.technology.PrimitivePort;\n"));
4932 xprintf(f, x_("import com.sun.electric.technology.EdgeH;\n"));
4933 xprintf(f, x_("import com.sun.electric.technology.EdgeV;\n"));
4934 xprintf(f, x_("import com.sun.electric.technology.SizeOffset;\n"));
4935 xprintf(f, x_("import com.sun.electric.database.geometry.EGraphics;\n"));
4936 xprintf(f, x_("import com.sun.electric.database.geometry.Poly;\n"));
4937 xprintf(f, x_("import com.sun.electric.database.prototype.ArcProto;\n"));
4938 xprintf(f, x_("import com.sun.electric.database.prototype.PortProto;\n"));
4939 xprintf(f, x_("import com.sun.electric.database.prototype.NodeProto;\n"));
4940 xprintf(f, x_("import com.sun.electric.tool.drc.DRC;\n"));
4941 xprintf(f, x_("\n"));
4942 xprintf(f, x_("import java.awt.Color;\n"));
4943 xprintf(f, x_("\n"));
4944
4945 xprintf(f, x_("/**\n"));
4946 xprintf(f, x_(" * This is the %s Technology.\n"), tech->techdescript);
4947 xprintf(f, x_(" */\n"));
4948 xprintf(f, x_("public class %s extends Technology\n"), techname);
4949 xprintf(f, x_("{\n"), techname);
4950 xprintf(f, x_("\t/** the %s Technology object. */ public static final %s tech = new %s();\n"),
4951 tech->techdescript, techname, techname);
4952 if ((us_tecflags&(HASCONDRC|HASUNCONDRC)) != 0)
4953 {
4954 xprintf(f, x_("\tprivate static final double XX = -1;\n"));
4955 xprintf(f, x_("\tprivate double [] conDist, unConDist;\n"));
4956 }
4957 xprintf(f, x_("\n"));
4958
4959 xprintf(f, x_("\t// -------------------- private and protected methods ------------------------\n"));
4960 xprintf(f, x_("\tprivate %s()\n"), techname);
4961 xprintf(f, x_("\t{\n"));
4962 xprintf(f, x_("\t\tsetTechName(\"%s\");\n"), techname);
4963 xprintf(f, x_("\t\tsetTechDesc(\"%s\");\n"), tech->techdescript);
4964 xprintf(f, x_("\t\tsetFactoryScale(%ld, true); // in nanometers: really %g microns\n"),
4965 tech->deflambda / 2, (float)tech->deflambda / 2000.0);
4966 xprintf(f, x_("\t\tsetNoNegatedArcs();\n"));
4967 xprintf(f, x_("\t\tsetStaticTechnology();\n"));
4968
4969 /* write the color map */
4970 if ((us_tecflags&HASCOLORMAP) != 0)
4971 {
4972 /* determine the five transparent layers */
4973 l1 = x_("layer 1");
4974 l2 = x_("layer 2");
4975 l3 = x_("layer 3");
4976 l4 = x_("layer 4");
4977 l5 = x_("layer 5");
4978 for(i=0; i<tech->layercount; i++)
4979 {
4980 if (tech->layers[i]->bits == LAYERT1 && l1 == 0)
4981 l1 = us_teclayer_names[i]; else
4982 if (tech->layers[i]->bits == LAYERT2 && l2 == 0)
4983 l2 = us_teclayer_names[i]; else
4984 if (tech->layers[i]->bits == LAYERT3 && l3 == 0)
4985 l3 = us_teclayer_names[i]; else
4986 if (tech->layers[i]->bits == LAYERT4 && l4 == 0)
4987 l4 = us_teclayer_names[i]; else
4988 if (tech->layers[i]->bits == LAYERT5 && l5 == 0)
4989 l5 = us_teclayer_names[i];
4990 }
4991 xprintf(f, x_("\t\tsetNumTransparentLayers(5);\n"));
4992 xprintf(f, x_("\t\tsetFactoryTransparentLayers(new Color []\n"));
4993 xprintf(f, x_("\t\t{\n"));
4994 xprintf(f, x_("\t\t\tnew Color(%3d,%3d,%3d), // %s\n"),
4995 us_teccolmap[1].red, us_teccolmap[1].green, us_teccolmap[1].blue, l1);
4996 xprintf(f, x_("\t\t\tnew Color(%3d,%3d,%3d), // %s\n"),
4997 us_teccolmap[2].red, us_teccolmap[2].green, us_teccolmap[2].blue, l2);
4998 xprintf(f, x_("\t\t\tnew Color(%3d,%3d,%3d), // %s\n"),
4999 us_teccolmap[4].red, us_teccolmap[4].green, us_teccolmap[4].blue, l3);
5000 xprintf(f, x_("\t\t\tnew Color(%3d,%3d,%3d), // %s\n"),
5001 us_teccolmap[8].red, us_teccolmap[8].green, us_teccolmap[8].blue, l4);
5002 xprintf(f, x_("\t\t\tnew Color(%3d,%3d,%3d), // %s\n"),
5003 us_teccolmap[16].red, us_teccolmap[16].green, us_teccolmap[16].blue, l5);
5004 xprintf(f, x_("\t\t});\n"));
5005 }
5006 xprintf(f, x_("\n"));
5007
5008 /* write the layer declarations */
5009 xprintf(f, x_("\t\t//**************************************** LAYERS ****************************************\n\n"));
5010 for(i=0; i<tech->layercount; i++)
5011 {
5012 xprintf(f, x_("\t\t/** %s layer */\n"), us_teclayer_iname[i]);
5013 xprintf(f, x_("\t\tLayer %s_lay = Layer.newInstance(this, \"%s\",\n"), us_teclayer_iname[i],
5014 us_teclayer_names[i]);
5015 xprintf(f, x_("\t\t\tnew EGraphics("));
5016 if ((tech->layers[i]->colstyle&NATURE) == SOLIDC) xprintf(f, x_("EGraphics.SOLID")); else
5017 {
5018 if ((tech->layers[i]->colstyle&OUTLINEPAT) == 0)
5019 xprintf(f, x_("EGraphics.PATTERNED")); else
5020 xprintf(f, x_("EGraphics.OUTLINEPAT"));
5021 }
5022 xprintf(f, x_(", "));
5023 if ((tech->layers[i]->bwstyle&NATURE) == SOLIDC) xprintf(f, x_("EGraphics.SOLID")); else
5024 {
5025 if ((tech->layers[i]->bwstyle&OUTLINEPAT) == 0)
5026 xprintf(f, x_("EGraphics.PATTERNED")); else
5027 xprintf(f, x_("EGraphics.OUTLINEPAT"));
5028 }
5029 transparent = "0";
5030 switch (tech->layers[i]->bits)
5031 {
5032 case LAYERT1: transparent = "EGraphics.TRANSPARENT_1"; break;
5033 case LAYERT2: transparent = "EGraphics.TRANSPARENT_2"; break;
5034 case LAYERT3: transparent = "EGraphics.TRANSPARENT_3"; break;
5035 case LAYERT4: transparent = "EGraphics.TRANSPARENT_4"; break;
5036 case LAYERT5: transparent = "EGraphics.TRANSPARENT_5"; break;
5037 }
5038 red = us_teccolmap[tech->layers[i]->col].red;
5039 green = us_teccolmap[tech->layers[i]->col].green;
5040 blue = us_teccolmap[tech->layers[i]->col].blue;
5041 if (red < 0 || red > 255) red = 0;
5042 if (green < 0 || green > 255) green = 0;
5043 if (blue < 0 || blue > 255) blue = 0;
5044 xprintf(f, x_(", %s, %ld,%ld,%ld,0.8,1,\n"), transparent, red, green, blue);
5045
5046 for(j=0; j<16; j++) if (tech->layers[i]->raster[j] != 0) break;
5047 if (j >= 16)
5048 xprintf(f, x_("\t\t\tnew int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}));\n\n")); else
5049 {
5050 for(j=0; j<16; j++)
5051 {
5052 xprintf(f, x_("\t\t\t"));
5053 if (j == 0) xprintf(f, x_("new int[] { ")); else
5054 xprintf(f, x_("\t\t\t"));
5055 xprintf(f, x_("0x%04x"), tech->layers[i]->raster[j]&0xFFFF);
5056 if (j == 15) xprintf(f, x_("}));")); else
5057 xprintf(f, x_(", "));
5058
5059 xprintf(f, x_("// "));
5060 for(k=0; k<16; k++)
5061 if ((tech->layers[i]->raster[j] & (1 << (15-k))) != 0)
5062 xprintf(f, x_("X")); else xprintf(f, x_(" "));
5063 xprintf(f, x_("\n"));
5064 }
5065 xprintf(f, x_("\n"));
5066 }
5067 }
5068
5069 /* write the layer functions */
5070 xprintf(f, x_("\t\t// The layer functions\n"));
5071 for(i=0; i<tech->layercount; i++)
5072 {
5073 k = us_teclayer_function[i];
5074 infstr = initinfstr();
5075 formatinfstr(infstr, x_("%s_lay.setFunction(Layer.Function."), us_teclayer_iname[i]);
5076 if ((k&(LFTYPE|LFPTYPE)) == (LFDIFF|LFPTYPE))
5077 {
5078 addstringtoinfstr(infstr, "DIFFP");
5079 k &= ~LFPTYPE;
5080 } else if ((k&(LFTYPE|LFNTYPE)) == (LFDIFF|LFNTYPE))
5081 {
5082 addstringtoinfstr(infstr, "DIFFN");
5083 k &= ~LFNTYPE;
5084 } else if ((k&(LFTYPE|LFPTYPE)) == (LFWELL|LFPTYPE))
5085 {
5086 addstringtoinfstr(infstr, "WELLP");
5087 k &= ~LFPTYPE;
5088 } else if ((k&(LFTYPE|LFNTYPE)) == (LFWELL|LFNTYPE))
5089 {
5090 addstringtoinfstr(infstr, "WELLN");
5091 k &= ~LFNTYPE;
5092 } else if ((k&(LFTYPE|LFPTYPE)) == (LFIMPLANT|LFPTYPE))
5093 {
5094 addstringtoinfstr(infstr, "IMPLANTP");
5095 k &= ~LFPTYPE;
5096 } else if ((k&(LFTYPE|LFNTYPE)) == (LFIMPLANT|LFNTYPE))
5097 {
5098 addstringtoinfstr(infstr, "IMPLANTN");
5099 k &= ~LFNTYPE;
5100 } else if ((k&(LFTYPE|LFINTRANS)) == (LFPOLY1|LFINTRANS))
5101 {
5102 addstringtoinfstr(infstr, "GATE");
5103 k &= ~LFINTRANS;
5104 } else
5105 {
5106 addstringtoinfstr(infstr, &us_teclayer_functions[k&LFTYPE].constant[2]);
5107 }
5108 extrafunction = FALSE;
5109 for(j=0; us_teclayer_functions[j].name != 0; j++)
5110 {
5111 if (us_teclayer_functions[j].value <= LFTYPE) continue;
5112 if ((k&us_teclayer_functions[j].value) != 0)
5113 {
5114 if (extrafunction) addstringtoinfstr(infstr, "|"); else
5115 addstringtoinfstr(infstr, ", ");
5116 addstringtoinfstr(infstr, "Layer.Function.");
5117 addstringtoinfstr(infstr, &us_teclayer_functions[j].constant[2]);
5118 extrafunction = TRUE;
5119 }
5120 }
5121 addstringtoinfstr(infstr, ");");
5122 xprintf(f, x_("\t\t%s"), returninfstr(infstr));
5123 xprintf(f, x_("\t\t// %s\n"), us_teclayer_names[i]);
5124 }
5125
5126 /* write the CIF layer names */
5127 if ((us_tecflags&HASCIF) != 0)
5128 {
5129 xprintf(f, x_("\n\t\t// The CIF names\n"));
5130 for(i=0; i<tech->layercount; i++)
5131 {
5132 xprintf(f, x_("\t\t%s_lay.setFactoryCIFLayer(\""), us_teclayer_iname[i]);
5133 if (us_teccif_layers[i] != 0) xprintf(f, x_("%s"), us_teccif_layers[i]);
5134 xprintf(f, x_("\");\t\t// %s\n"), us_teclayer_names[i]);
5135 }
5136 }
5137
5138 /* write the DXF layer numbers */
5139 if ((us_tecflags&HASDXF) != 0)
5140 {
5141 xprintf(f, x_("\n\t\t// The DXF names\n"));
5142 for(i=0; i<tech->layercount; i++)
5143 {
5144 xprintf(f, x_("\t\t%s_lay.setFactoryDXFLayer(\""), us_teclayer_iname[i]);
5145 xprintf(f, x_("%s"), us_tecdxf_layers[i]);
5146 xprintf(f, x_("\");\t\t// %s\n"), us_teclayer_names[i]);
5147 }
5148 }
5149
5150 /* write the Calma GDS-II layer number */
5151 if ((us_tecflags&HASGDS) != 0)
5152 {
5153 xprintf(f, x_("\n\t\t// The GDS names\n"));
5154 for(i=0; i<tech->layercount; i++)
5155 {
5156 xprintf(f, x_("\t\t%s_lay.setFactoryGDSLayer(\""), us_teclayer_iname[i]);
5157 xprintf(f, x_("%s"), us_tecgds_layers[i]);
5158 xprintf(f, x_("\");\t\t// %s\n"), us_teclayer_names[i]);
5159 }
5160 }
5161
5162 /* write the 3D information */
5163 if ((us_tecflags&HAS3DINFO) != 0)
5164 {
5165 xprintf(f, x_("\n\t\t// The layer height\n"));
5166 for(i=0; i<tech->layercount; i++)
5167 {
5168 xprintf(f, x_("\t\t%s_lay.setFactory3DInfo("), us_teclayer_iname[i]);
5169 xprintf(f, x_("%ld, %ld"), us_tec3d_thickness[i], us_tec3d_height[i]);
5170 xprintf(f, x_(");\t\t// %s\n"), us_teclayer_names[i]);
5171 }
5172 }
5173
5174 /* write the SPICE information */
5175 if ((us_tecflags&(HASSPIRES|HASSPICAP|HASSPIECAP)) != 0)
5176 {
5177 xprintf(f, x_("\n\t\t// The SPICE information\n"));
5178 for(i=0; i<tech->layercount; i++)
5179 {
5180 xprintf(f, x_("\t\t%s_lay.setFactoryParasitics("), us_teclayer_iname[i]);
5181 if ((us_tecflags&HASSPIRES) == 0) xprintf(f, x_("0, ")); else
5182 xprintf(f, x_("%s, "), us_tecedmakefloatstring(us_tecspice_res[i]));
5183 if ((us_tecflags&HASSPICAP) == 0) xprintf(f, x_("0, ")); else
5184 xprintf(f, x_("%s, "), us_tecedmakefloatstring(us_tecspice_cap[i]));
5185 if ((us_tecflags&HASSPIECAP) == 0) xprintf(f, x_("0")); else
5186 xprintf(f, x_("%s"), us_tecedmakefloatstring(us_tecspice_ecap[i]));
5187 xprintf(f, x_(");\t\t// %s\n"), us_teclayer_names[i]);
5188 }
5189 }
5190 varr = getval((INTBIG)tech, VTECHNOLOGY, -1, x_("SIM_spice_min_resistance"));
5191 varc = getval((INTBIG)tech, VTECHNOLOGY, -1, x_("SIM_spice_min_capacitance"));
5192 if (varr != NOVARIABLE || varc != NOVARIABLE)
5193 {
5194 if (varr != NOVARIABLE) r = castfloat(varr->addr); else r = 0.0;
5195 if (varc != NOVARIABLE) c = castfloat(varr->addr); else c = 0.0;
5196 xprintf(f, x_("\t\tsetFactoryParasitics(%g, %g);\n"), r, c);
5197 }
5198
5199 /* write design rules */
5200 if ((us_tecflags&(HASCONDRC|HASUNCONDRC)) != 0)
5201 {
5202 xprintf(f, x_("\n\t\t//******************** DESIGN RULES ********************\n"));
5203
5204 if ((us_tecflags&HASCONDRC) != 0)
5205 {
5206 xprintf(f, x_("\n\t\tconDist = new double[]\n"));
5207 us_teceditdumpjavadrctab(f, us_tecdrc_rules->conlist, tech, FALSE);
5208 }
5209 if ((us_tecflags&HASUNCONDRC) != 0)
5210 {
5211 xprintf(f, x_("\n\t\tunConDist = new double[]\n"));
5212 us_teceditdumpjavadrctab(f, us_tecdrc_rules->unconlist, tech, FALSE);
5213 }
5214 }
5215 }
5216
us_teceditdumpjavadrctab(FILE * f,void * distances,TECHNOLOGY * tech,BOOLEAN isstring)5217 void us_teceditdumpjavadrctab(FILE *f, void *distances, TECHNOLOGY *tech, BOOLEAN isstring)
5218 {
5219 REGISTER INTBIG i, j;
5220 REGISTER INTBIG amt, *amtlist;
5221 CHAR shortname[7], *msg, **distlist;
5222
5223 for(i=0; i<6; i++)
5224 {
5225 xprintf(f, x_("\t\t\t// "));
5226 for(j=0; j<tech->layercount; j++)
5227 {
5228 if ((INTBIG)estrlen(us_teclayer_iname[j]) <= i) xprintf(f, x_(" ")); else
5229 xprintf(f, x_("%c"), us_teclayer_iname[j][i]);
5230 xprintf(f, x_(" "));
5231 }
5232 xprintf(f, x_("\n"));
5233 }
5234 if (isstring) distlist = (CHAR **)distances; else
5235 amtlist = (INTBIG *)distances;
5236 for(j=0; j<tech->layercount; j++)
5237 {
5238 (void)estrncpy(shortname, us_teclayer_iname[j], 6);
5239 shortname[6] = 0;
5240 xprintf(f, x_("\t\t\t/* %-6s */ "), shortname);
5241 for(i=0; i<j; i++) xprintf(f, x_(" "));
5242 for(i=j; i<tech->layercount; i++)
5243 {
5244 if (isstring)
5245 {
5246 msg = *distlist++;
5247 xprintf(f, x_("x_(\"%s\")"), msg);
5248 } else
5249 {
5250 amt = *amtlist++;
5251 if (amt < 0) xprintf(f, x_("XX")); else
5252 {
5253 xprintf(f, x_("%g"), (float)amt/WHOLE);
5254 }
5255 }
5256 if (j != tech->layercount-1 || i != tech->layercount-1)
5257 xprintf(f, x_(","));
5258 }
5259 xprintf(f, x_("\n"));
5260 }
5261 xprintf(f, x_("\t\t};\n"));
5262 }
5263
5264 /*
5265 * routine to dump the arc information in technology "tech" to the stream in
5266 * "f".
5267 */
us_teceditdumpjavaarcs(FILE * f,TECHNOLOGY * tech,CHAR * techname)5268 void us_teceditdumpjavaarcs(FILE *f, TECHNOLOGY *tech, CHAR *techname)
5269 {
5270 REGISTER INTBIG i, j, k;
5271
5272 /* print the header */
5273 xprintf(f, x_("\n\t\t//******************** ARCS ********************\n"));
5274
5275 /* now write the arcs */
5276 for(i=0; i<tech->arcprotocount; i++)
5277 {
5278 xprintf(f, x_("\n\t\t/** %s arc */\n"), tech->arcprotos[i]->arcname);
5279 xprintf(f, x_("\t\tPrimitiveArc %s_arc = PrimitiveArc.newInstance(this, \"%s\", %g, new Technology.ArcLayer []\n"),
5280 us_teceditconverttojava(tech->arcprotos[i]->arcname), tech->arcprotos[i]->arcname, (float)tech->arcprotos[i]->arcwidth/WHOLE);
5281 xprintf(f, x_("\t\t{\n"));
5282 for(k=0; k<tech->arcprotos[i]->laycount; k++)
5283 {
5284 xprintf(f, x_("\t\t\tnew Technology.ArcLayer(%s_lay, "),
5285 us_teclayer_iname[tech->arcprotos[i]->list[k].lay]);
5286 if (tech->arcprotos[i]->list[k].off == 0) xprintf(f, x_("0,")); else
5287 xprintf(f, x_("%g,"), (float)tech->arcprotos[i]->list[k].off/WHOLE);
5288 if (tech->arcprotos[i]->list[k].style == FILLED) xprintf(f, x_(" Poly.Type.FILLED)")); else
5289 xprintf(f, x_(" Poly.Type.CLOSED)"));
5290 if (k+1 < tech->arcprotos[i]->laycount) xprintf(f, x_(","));
5291 xprintf(f, x_("\n"));
5292 }
5293 xprintf(f, x_("\t\t});\n"));
5294 for(j=0; us_tecarc_functions[j].name != 0; j++)
5295 if (us_tecarc_functions[j].value ==
5296 (INTBIG)((tech->arcprotos[i]->initialbits&AFUNCTION)>>AFUNCTIONSH))
5297 {
5298 xprintf(f, x_("\t\t%s_arc.setFunction(PrimitiveArc.Function.%s);\n"),
5299 us_teceditconverttojava(tech->arcprotos[i]->arcname), &us_tecarc_functions[j].constant[2]);
5300 break;
5301 }
5302 if (us_tecarc_functions[j].name == 0)
5303 xprintf(f, x_("\t\t%s_arc.setFunction(PrimitiveArc.Function.UNKNOWN);\n"), us_teceditconverttojava(tech->arcprotos[i]->arcname));
5304 if ((tech->arcprotos[i]->initialbits&CANWIPE) != 0)
5305 xprintf(f, x_("\t\t%s_arc.setWipable();\n"), us_teceditconverttojava(tech->arcprotos[i]->arcname));
5306 if ((us_tecflags&HASARCWID) != 0 && us_tecarc_widoff[i] != 0)
5307 {
5308 xprintf(f, x_("\t\t%s_arc.setWidthOffset(%ld);\n"), us_teceditconverttojava(tech->arcprotos[i]->arcname),
5309 (float)us_tecarc_widoff[i]/WHOLE);
5310 }
5311
5312 if ((tech->arcprotos[i]->initialbits&WANTFIXANG) != 0)
5313 xprintf(f, x_("\t\t%s_arc.setFactoryFixedAngle(true);\n"), us_teceditconverttojava(tech->arcprotos[i]->arcname));
5314 if ((tech->arcprotos[i]->initialbits&WANTNOEXTEND) != 0)
5315 xprintf(f, x_("\t\t%s_arc.setFactoryExtended(false);\n"), us_teceditconverttojava(tech->arcprotos[i]->arcname));
5316 xprintf(f, x_("\t\t%s_arc.setFactoryAngleIncrement(%ld);\n"), us_teceditconverttojava(tech->arcprotos[i]->arcname),
5317 (tech->arcprotos[i]->initialbits&AANGLEINC)>>AANGLEINCSH);
5318
5319 }
5320 }
5321
5322 /*
5323 * routine to dump the node information in technology "tech" to the stream in
5324 * "f".
5325 */
us_teceditdumpjavanodes(FILE * f,TECHNOLOGY * tech,CHAR * techname)5326 void us_teceditdumpjavanodes(FILE *f, TECHNOLOGY *tech, CHAR *techname)
5327 {
5328 REGISTER RULE *r;
5329 REGISTER INTBIG i, j, k, l, tot;
5330 CHAR *ab;
5331 REGISTER PCON *pc;
5332 REGISTER BOOLEAN yaxis;
5333 REGISTER TECH_POLYGON *plist;
5334 REGISTER TECH_NODES *nlist;
5335 REGISTER void *infstr;
5336
5337 /* make abbreviations for each node */
5338 for(i=0; i<tech->nodeprotocount; i++)
5339 {
5340 (void)allocstring(&ab, makeabbrev(tech->nodeprotos[i]->nodename, FALSE), el_tempcluster);
5341 tech->nodeprotos[i]->creation = (NODEPROTO *)ab;
5342
5343 /* loop until the name is unique */
5344 for(;;)
5345 {
5346 /* see if a previously assigned abbreviation is the same */
5347 for(j=0; j<i; j++)
5348 if (namesame(ab, (CHAR *)tech->nodeprotos[j]->creation) == 0) break;
5349 if (j == i) break;
5350
5351 /* name conflicts: change it */
5352 l = estrlen(ab);
5353 if (ab[l-1] >= '0' && ab[l-1] <= '8') ab[l-1]++; else
5354 {
5355 infstr = initinfstr();
5356 addstringtoinfstr(infstr, ab);
5357 addtoinfstr(infstr, '0');
5358 (void)reallocstring(&ab, returninfstr(infstr), el_tempcluster);
5359 tech->nodeprotos[i]->creation = (NODEPROTO *)ab;
5360 }
5361 }
5362 }
5363
5364 xprintf(f, x_("\n\t\t//******************** RECTANGLE DESCRIPTIONS ********************"));
5365 xprintf(f, x_("\n\n"));
5366
5367 /* print box information */
5368 i = 1;
5369 for(r = us_tecedfirstrule; r != NORULE; r = r->nextrule)
5370 {
5371 if (!r->used) continue;
5372 r->rindex = i++;
5373 xprintf(f, x_("\t\tTechnology.TechPoint [] box_%ld = new Technology.TechPoint[] {\n"),
5374 r->rindex);
5375 for(j=0; j<r->count; j += 2)
5376 {
5377 if ((j%4) == 0)
5378 {
5379 yaxis = FALSE;
5380 xprintf(f, x_("\t\t\tnew Technology.TechPoint("));
5381 } else
5382 {
5383 yaxis = TRUE;
5384 }
5385 xprintf(f, x_("%s"), us_tecededgelabeljava(r->value[j], r->value[j+1], yaxis));
5386 if ((j%4) == 0) xprintf(f, x_(", ")); else
5387 {
5388 xprintf(f, x_(")"));
5389 if (j+1 < r->count) xprintf(f, x_(","));
5390 xprintf(f, x_("\n"));
5391 }
5392 }
5393 xprintf(f, x_("\t\t};\n"));
5394 }
5395
5396 xprintf(f, x_("\n\t\t//******************** NODES ********************\n"));
5397
5398 /* print node information */
5399 for(i=0; i<tech->nodeprotocount; i++)
5400 {
5401 /* header comment */
5402 nlist = tech->nodeprotos[i];
5403 ab = (CHAR *)nlist->creation;
5404 xprintf(f, x_("\n\t\t/** %s */\n"), nlist->nodename);
5405
5406 xprintf(f, x_("\t\tPrimitiveNode %s_node = PrimitiveNode.newInstance(\"%s\", this, %g, %g, "),
5407 ab, nlist->nodename, (float)nlist->xsize/WHOLE, (float)nlist->ysize/WHOLE);
5408 if (us_tecnode_widoff[i*4] != 0 || us_tecnode_widoff[i*4+1] != 0 ||
5409 us_tecnode_widoff[i*4+2] != 0 || us_tecnode_widoff[i*4+3] != 0)
5410 {
5411 xprintf(f, x_("new SizeOffset(%g, %g, %g, %g),\n"),
5412 (float)us_tecnode_widoff[i*4] / WHOLE, (float)us_tecnode_widoff[i*4+1] / WHOLE,
5413 (float)us_tecnode_widoff[i*4+2] / WHOLE, (float)us_tecnode_widoff[i*4+3] / WHOLE);
5414 } else
5415 {
5416 xprintf(f, x_("null,\n"));
5417 }
5418
5419 /* print layers */
5420 xprintf(f, x_("\t\t\tnew Technology.NodeLayer []\n"));
5421 xprintf(f, x_("\t\t\t{\n"));
5422 tot = nlist->layercount;
5423 for(j=0; j<tot; j++)
5424 {
5425 if (nlist->special == SERPTRANS) plist = &nlist->gra[j].basics; else
5426 plist = &nlist->layerlist[j];
5427 xprintf(f, x_("\t\t\t\tnew Technology.NodeLayer(%s_lay, %ld, Poly.Type."),
5428 us_teclayer_iname[plist->layernum], plist->portnum);
5429 switch (plist->style)
5430 {
5431 case FILLEDRECT: xprintf(f, x_("FILLED,")); break;
5432 case CLOSEDRECT: xprintf(f, x_("CLOSED,")); break;
5433 case CROSSED: xprintf(f, x_("CROSSED,")); break;
5434 case FILLED: xprintf(f, x_("FILLED,")); break;
5435 case CLOSED: xprintf(f, x_("CLOSED,")); break;
5436 case OPENED: xprintf(f, x_("OPENED,")); break;
5437 case OPENEDT1: xprintf(f, x_("OPENEDT1,")); break;
5438 case OPENEDT2: xprintf(f, x_("OPENEDT2,")); break;
5439 case OPENEDT3: xprintf(f, x_("OPENEDT3,")); break;
5440 case VECTORS: xprintf(f, x_("VECTORS,")); break;
5441 case CIRCLE: xprintf(f, x_("CIRCLE,")); break;
5442 case THICKCIRCLE: xprintf(f, x_("THICKCIRCLE,")); break;
5443 case DISC: xprintf(f, x_("DISC,")); break;
5444 case CIRCLEARC: xprintf(f, x_("CIRCLEARC,")); break;
5445 case THICKCIRCLEARC: xprintf(f, x_("THICKCIRCLEARC,")); break;
5446 case TEXTCENT: xprintf(f, x_("TEXTCENT,")); break;
5447 case TEXTTOP: xprintf(f, x_("TEXTTOP,")); break;
5448 case TEXTBOT: xprintf(f, x_("TEXTBOT,")); break;
5449 case TEXTLEFT: xprintf(f, x_("TEXTLEFT,")); break;
5450 case TEXTRIGHT: xprintf(f, x_("TEXTRIGHT,")); break;
5451 case TEXTTOPLEFT: xprintf(f, x_("TEXTTOPLEFT,")); break;
5452 case TEXTBOTLEFT: xprintf(f, x_("TEXTBOTLEFT,")); break;
5453 case TEXTTOPRIGHT: xprintf(f, x_("TEXTTOPRIGHT,")); break;
5454 case TEXTBOTRIGHT: xprintf(f, x_("TEXTBOTRIGHT,")); break;
5455 case TEXTBOX: xprintf(f, x_("TEXTBOX,")); break;
5456 default: xprintf(f, x_("????,")); break;
5457 }
5458 switch (plist->representation)
5459 {
5460 case BOX: xprintf(f, x_(" Technology.NodeLayer.BOX,")); break;
5461 case MINBOX: xprintf(f, x_(" Technology.NodeLayer.MINBOX,")); break;
5462 case POINTS: xprintf(f, x_(" Technology.NodeLayer.POINTS,")); break;
5463 default: xprintf(f, x_(" Technology.NodeLayer.????,")); break;
5464 }
5465 for(r = us_tecedfirstrule; r != NORULE; r = r->nextrule)
5466 if (r->value == plist->points) break;
5467 if (r != NORULE)
5468 {
5469 xprintf(f, x_(" box_%ld"), r->rindex);
5470 } else
5471 xprintf(f, x_(" box??"));
5472 if (nlist->special == SERPTRANS)
5473 {
5474 xprintf(f, x_(", %g, %g, %g, %g"),
5475 nlist->gra[j].lwidth / (float)WHOLE, nlist->gra[j].rwidth / (float)WHOLE,
5476 nlist->gra[j].extendb / (float)WHOLE, nlist->gra[j].extendt / (float)WHOLE);
5477 }
5478 xprintf(f, x_(")"));
5479 if (j+1 < tot) xprintf(f, x_(","));
5480 xprintf(f, x_("\n"));
5481 }
5482 xprintf(f, x_("\t\t\t});\n"));
5483
5484 /* print ports */
5485 xprintf(f, x_("\t\t%s_node.addPrimitivePorts(new PrimitivePort[]\n"), ab);
5486 xprintf(f, x_("\t\t\t{\n"));
5487 for(j=0; j<nlist->portcount; j++)
5488 {
5489 xprintf(f, x_(" \t\t\tPrimitivePort.newInstance(this, %s_node, new ArcProto [] {"), ab);
5490 for(pc = us_tecedfirstpcon; pc != NOPCON; pc = pc->nextpcon)
5491 if (pc->connects == nlist->portlist[j].portarcs) break;
5492 if (pc != NOPCON)
5493 {
5494 for(l=0; l<pc->total; l++)
5495 {
5496 k = pc->connects[l+1];
5497 xprintf(f, x_("%s_arc"), us_teceditconverttojava(tech->arcprotos[k]->arcname));
5498 if (l+1 < pc->total) xprintf(f, x_(", "));
5499 }
5500 }
5501 xprintf(f, x_("}, \"%s\", %ld,%ld, %ld, PortProto.Characteristic.UNKNOWN,\n"),
5502 nlist->portlist[j].protoname,
5503 (nlist->portlist[j].initialbits&PORTANGLE)>>PORTANGLESH,
5504 (nlist->portlist[j].initialbits&PORTARANGE)>>PORTARANGESH,
5505 (nlist->portlist[j].initialbits&PORTNET)>>PORTNETSH);
5506 xprintf(f, x_("\t\t\t\t\t%s, %s, %s, %s)"),
5507 us_tecededgelabeljava(nlist->portlist[j].lowxmul, nlist->portlist[j].lowxsum, FALSE),
5508 us_tecededgelabeljava(nlist->portlist[j].lowymul, nlist->portlist[j].lowysum, TRUE),
5509 us_tecededgelabeljava(nlist->portlist[j].highxmul, nlist->portlist[j].highxsum, FALSE),
5510 us_tecededgelabeljava(nlist->portlist[j].highymul, nlist->portlist[j].highysum, TRUE));
5511
5512 if (j+1 < nlist->portcount) xprintf(f, x_(","));
5513 xprintf(f, x_("\n"));
5514 }
5515 xprintf(f, x_("\t\t\t});\n"));
5516
5517 /* print the node information */
5518 j = (nlist->initialbits&NFUNCTION)>>NFUNCTIONSH;
5519 if (j < 0 || j >= MAXNODEFUNCTION) j = 0;
5520 xprintf(f, x_("\t\t%s_node.setFunction(NodeProto.Function.%s);\n"), ab, &nodefunctionconstantname(j)[2]);
5521
5522 if ((nlist->initialbits&WIPEON1OR2) != 0)
5523 xprintf(f, x_("\t\t%s_node.setWipeOn1or2();\n"), ab);
5524 if ((nlist->initialbits&HOLDSTRACE) != 0)
5525 xprintf(f, x_("\t\t%s_node.setHoldsOutline();\n"), ab);
5526 if ((nlist->initialbits&NSQUARE) != 0)
5527 xprintf(f, x_("\t\t%s_node.setSquare();\n"), ab);
5528 if ((nlist->initialbits&ARCSWIPE) != 0)
5529 xprintf(f, x_("\t\t%s_node.setArcsWipe();\n"), ab);
5530 if ((nlist->initialbits&ARCSHRINK) != 0)
5531 xprintf(f, x_("\t\t%s_node.setArcsShrink();\n"), ab);
5532 if ((nlist->initialbits&NODESHRINK) != 0)
5533 xprintf(f, x_("\t\t%s_node.setCanShrink();\n"), ab);
5534 if ((nlist->initialbits&LOCKEDPRIM) != 0)
5535 xprintf(f, x_("\t\t%s_node.setLockedPrim();\n"), ab);
5536 if (nlist->special != 0)
5537 {
5538 switch (nlist->special)
5539 {
5540 case SERPTRANS:
5541 xprintf(f, x_("\t\t%s_node.setSpecialType(PrimitiveNode.SERPTRANS);\n"), ab);
5542 xprintf(f, x_("\t\t%s_node.setSpecialValues(new double [] {%g, %g, %g, %g, %g, %g});\n"),
5543 ab, (float)nlist->f1/WHOLE, (float)nlist->f2/WHOLE, (float)nlist->f3/WHOLE,
5544 (float)nlist->f4/WHOLE, (float)nlist->f5/WHOLE, (float)nlist->f6/WHOLE);
5545 break;
5546 case POLYGONAL:
5547 xprintf(f, x_("\t\t%s_node.setSpecialType(PrimitiveNode.POLYGONAL);\n"), ab);
5548 break;
5549 case MULTICUT:
5550 xprintf(f, x_("\t\t%s_node.setSpecialType(PrimitiveNode.MULTICUT);\n"), ab);
5551 xprintf(f, x_("\t\t%s_node.setSpecialValues(new double [] {%g, %g, %g, %g});\n"),
5552 ab, (float)nlist->f1/WHOLE, (float)nlist->f2/WHOLE, (float)nlist->f3/WHOLE,
5553 (float)nlist->f4/WHOLE);
5554 break;
5555 }
5556 }
5557 }
5558
5559 /* write the pure-layer associations */
5560 xprintf(f, x_("\n\t\t// The pure layer nodes\n"));
5561 for(i=0; i<tech->layercount; i++)
5562 {
5563 if ((us_teclayer_function[i]&LFPSEUDO) != 0) continue;
5564
5565 /* find the pure layer node */
5566 for(j=0; j<tech->nodeprotocount; j++)
5567 {
5568 nlist = tech->nodeprotos[j];
5569 if (((nlist->initialbits&NFUNCTION)>>NFUNCTIONSH) != NPNODE) continue;
5570 plist = &nlist->layerlist[0];
5571 if (plist->layernum == i) break;
5572 }
5573 if (j >= tech->nodeprotocount) continue;
5574 ab = (CHAR *)tech->nodeprotos[j]->creation;
5575 xprintf(f, x_("\t\t%s_lay.setPureLayerNode("), us_teclayer_iname[i]);
5576 xprintf(f, x_("%s_node"), ab);
5577 xprintf(f, x_(");\t\t// %s\n"), us_teclayer_names[i]);
5578 }
5579
5580 xprintf(f, x_("\t};\n"));
5581
5582 #if 0
5583 /* print grab point informaton if it exists */
5584 if ((us_tecflags&HASGRAB) != 0 && us_tecnode_grabcount > 0)
5585 {
5586 xprintf(f, x_("\nstatic INTBIG %s_centergrab[] = {\n"), us_tecedmakesymbol(techname));
5587 for(i=0; i<us_tecnode_grabcount; i += 3)
5588 {
5589 ab = (CHAR *)tech->nodeprotos[us_tecnode_grab[i]-1]->creation;
5590 xprintf(f, x_("\tN%s, %ld, %ld"), us_tecedmakeupper(ab), us_tecnode_grab[i+1],
5591 us_tecnode_grab[i+2]);
5592 if (i != us_tecnode_grabcount-3) xprintf(f, x_(",\n"));
5593 }
5594 xprintf(f, x_("\n};\n"));
5595 }
5596
5597 /* print minimum node size informaton if it exists */
5598 if ((us_tecflags&HASMINNODE) != 0)
5599 {
5600 xprintf(f, x_("\nstatic INTBIG %s_node_minsize[NODEPROTOCOUNT*2] = {\n"), us_tecedmakesymbol(techname));
5601 for(i=0; i<tech->nodeprotocount; i++)
5602 {
5603 if (us_tecdrc_rules->minnodesize[i*2] < 0) ab = x_("XX"); else
5604 ab = us_tecedmakefract(us_tecdrc_rules->minnodesize[i*2]);
5605 xprintf(f, x_("\t%s, "), ab);
5606 if (us_tecdrc_rules->minnodesize[i*2+1] < 0) ab = x_("XX"); else
5607 ab = us_tecedmakefract(us_tecdrc_rules->minnodesize[i*2+1]);
5608 xprintf(f, x_("%s"), ab);
5609 if (i == tech->nodeprotocount-1) ab = x_(""); else ab = x_(",");
5610 xprintf(f, x_("%s\t\t/* %s */\n"), ab, tech->nodeprotos[i]->nodename);
5611 }
5612 xprintf(f, x_("};\n"));
5613 }
5614 if ((us_tecflags&HASMINNODER) != 0)
5615 {
5616 xprintf(f, x_("\nstatic char *%s_node_minsize_rule[NODEPROTOCOUNT] = {\n"), us_tecedmakesymbol(techname));
5617 for(i=0; i<tech->nodeprotocount; i++)
5618 {
5619 if (i == tech->nodeprotocount-1) ab = x_(""); else ab = x_(",");
5620 xprintf(f, x_("\tx_(\"%s\")%s\t\t/* %s */\n"), us_tecdrc_rules->minnodesizeR[i], ab,
5621 tech->nodeprotos[i]->nodename);
5622 }
5623 xprintf(f, x_("};\n"));
5624 }
5625 #endif
5626
5627 /* write method to reset rules */
5628 if ((us_tecflags&(HASCONDRC|HASUNCONDRC)) != 0)
5629 {
5630 CHAR *conword, *unconword;
5631 if ((us_tecflags&HASCONDRC) != 0) conword = "conDist"; else conword = "null";
5632 if ((us_tecflags&HASUNCONDRC) != 0) unconword = "unConDist"; else unconword = "null";
5633 xprintf(f, x_("\tpublic DRC.Rules getFactoryDesignRules()\n"));
5634 xprintf(f, x_("\t{\n"));
5635 xprintf(f, x_("\t\treturn DRC.makeSimpleRules(this, %s, %s);\n"), conword, unconword);
5636 xprintf(f, x_("\t}\n"));
5637 }
5638
5639 /* clean up */
5640 for(i=0; i<tech->nodeprotocount; i++)
5641 {
5642 efree((CHAR *)tech->nodeprotos[i]->creation);
5643 tech->nodeprotos[i]->creation = NONODEPROTO;
5644 }
5645 }
5646
5647 /*
5648 * Routine to remove illegal Java charcters from "string".
5649 */
us_teceditconverttojava(CHAR * string)5650 CHAR *us_teceditconverttojava(CHAR *string)
5651 {
5652 REGISTER void *infstr;
5653 REGISTER CHAR *pt;
5654
5655 infstr = initinfstr();
5656 for(pt = string; *pt != 0; pt++)
5657 {
5658 if (*pt == '-') addtoinfstr(infstr, '_'); else
5659 addtoinfstr(infstr, *pt);
5660 }
5661 return(returninfstr(infstr));
5662 }
5663
5664 /*
5665 * routine to convert the multiplication and addition factors in "mul" and
5666 * "add" into proper constant names. The "yaxis" is false for X and 1 for Y
5667 */
us_tecededgelabeljava(INTBIG mul,INTBIG add,BOOLEAN yaxis)5668 CHAR *us_tecededgelabeljava(INTBIG mul, INTBIG add, BOOLEAN yaxis)
5669 {
5670 REGISTER INTBIG amt;
5671 REGISTER void *infstr;
5672
5673 infstr = initinfstr();
5674
5675 /* handle constant distance from center */
5676 if (mul == 0)
5677 {
5678 if (yaxis) addstringtoinfstr(infstr, "EdgeV."); else
5679 addstringtoinfstr(infstr, "EdgeH.");
5680 if (add == 0)
5681 {
5682 addstringtoinfstr(infstr, x_("makeCenter()"));
5683 } else
5684 {
5685 formatinfstr(infstr, x_("fromCenter(%g)"), (float)add/WHOLE);
5686 }
5687 return(returninfstr(infstr));
5688 }
5689
5690 /* handle constant distance from edge */
5691 if ((mul == H0 || mul == -H0))
5692 {
5693 if (yaxis) addstringtoinfstr(infstr, "EdgeV."); else
5694 addstringtoinfstr(infstr, "EdgeH.");
5695 amt = abs(add);
5696 if (!yaxis)
5697 {
5698 if (mul < 0)
5699 {
5700 if (add == 0) addstringtoinfstr(infstr, x_("makeLeftEdge()")); else
5701 formatinfstr(infstr, x_("fromLeft(%g)"), (float)amt/WHOLE);
5702 } else
5703 {
5704 if (add == 0) addstringtoinfstr(infstr, x_("makeRightEdge()")); else
5705 formatinfstr(infstr, x_("fromRight(%g)"), (float)amt/WHOLE);
5706 }
5707 } else
5708 {
5709 if (mul < 0)
5710 {
5711 if (add == 0) addstringtoinfstr(infstr, x_("makeBottomEdge()")); else
5712 formatinfstr(infstr, x_("fromBottom(%g)"), (float)amt/WHOLE);
5713 } else
5714 {
5715 if (add == 0) addstringtoinfstr(infstr, x_("makeTopEdge()")); else
5716 formatinfstr(infstr, x_("fromTop(%g)"), (float)amt/WHOLE);
5717 }
5718 }
5719 return(returninfstr(infstr));
5720 }
5721
5722 /* generate two-value description */
5723 if (!yaxis)
5724 formatinfstr(infstr, x_("new EdgeH(%g, %g)"), (float)mul/WHOLE, (float)add/WHOLE); else
5725 formatinfstr(infstr, x_("new EdgeV(%g, %g)"), (float)mul/WHOLE, (float)add/WHOLE);
5726 return(returninfstr(infstr));
5727 }
5728
5729 /****************************** SUPPORT FOR SOURCE-CODE GENERATION ******************************/
5730
5731 /*
5732 * Routine to return a string representation of the floating point value "v".
5733 * The letter "f" is added to the end if appropriate.
5734 */
us_tecedmakefloatstring(float v)5735 CHAR *us_tecedmakefloatstring(float v)
5736 {
5737 static CHAR retstr[50];
5738 REGISTER CHAR *pt;
5739
5740 esnprintf(retstr, 50, x_("%g"), v);
5741 if (estrcmp(retstr, x_("0")) == 0) return(retstr);
5742 for(pt = retstr; *pt != 0; pt++)
5743 if (*pt == '.') break;
5744 if (*pt == 0) estrcat(retstr, x_(".0"));
5745 estrcat(retstr, x_("f"));
5746 return(retstr);
5747 }
5748
5749 /*
5750 * routine to convert the fractional value "amt" to a technology constant.
5751 * The presumption is that quarter values exist from K0 to K10, that
5752 * half values exist up to K20, that whole values exist up to K30, and
5753 * that other values are not necessarily defined in "tech.h".
5754 */
us_tecedmakefract(INTBIG amt)5755 CHAR *us_tecedmakefract(INTBIG amt)
5756 {
5757 static CHAR line[21];
5758 REGISTER INTBIG whole;
5759 REGISTER CHAR *pt;
5760
5761 pt = line;
5762 if (amt < 0)
5763 {
5764 *pt++ = '-';
5765 amt = -amt;
5766 }
5767 whole = amt/WHOLE;
5768 switch (amt%WHOLE)
5769 {
5770 case 0:
5771 if (whole <= 30) (void)esnprintf(pt, 20, x_("K%ld"), whole); else
5772 (void)esnprintf(pt, 20, x_("%ld"), amt);
5773 break;
5774 case Q0:
5775 if (whole <= 10) (void)esnprintf(pt, 20, x_("Q%ld"), whole); else
5776 (void)esnprintf(pt, 20, x_("%ld"), amt);
5777 break;
5778 case H0:
5779 if (whole <= 20) (void)esnprintf(pt, 20, x_("H%ld"), whole); else
5780 (void)esnprintf(pt, 20, x_("%ld"), amt);
5781 break;
5782 case T0:
5783 if (whole <= 10) (void)esnprintf(pt, 20, x_("T%ld"), whole); else
5784 (void)esnprintf(pt, 20, x_("%ld"), amt);
5785 break;
5786 default:
5787 (void)esnprintf(pt, 20, x_("%ld"), amt);
5788 break;
5789 }
5790 return(line);
5791 }
5792
5793 /*
5794 * routine to convert all characters in string "str" to upper case and to
5795 * change any nonalphanumeric characters to a "_"
5796 */
us_tecedmakeupper(CHAR * str)5797 CHAR *us_tecedmakeupper(CHAR *str)
5798 {
5799 REGISTER CHAR ch;
5800 REGISTER void *infstr;
5801
5802 infstr = initinfstr();
5803 while (*str != 0)
5804 {
5805 ch = *str++;
5806 if (islower(ch)) ch = toupper(ch);
5807 if (!isalnum(ch)) ch = '_';
5808 addtoinfstr(infstr, ch);
5809 }
5810 return(returninfstr(infstr));
5811 }
5812
5813 /*
5814 * routine to change any nonalphanumeric characters in string "str" to a "_"
5815 */
us_tecedmakesymbol(CHAR * str)5816 CHAR *us_tecedmakesymbol(CHAR *str)
5817 {
5818 REGISTER CHAR ch;
5819 REGISTER void *infstr;
5820
5821 infstr = initinfstr();
5822 while (*str != 0)
5823 {
5824 ch = *str++;
5825 if (!isalnum(ch)) ch = '_';
5826 addtoinfstr(infstr, ch);
5827 }
5828 return(returninfstr(infstr));
5829 }
5830
5831 /*
5832 * Routine to find the parameter value in a string that has been stored as a message
5833 * on a node. These parameters always have the form "name: value". This returns a pointer
5834 * to the "value" part.
5835 */
us_teceditgetparameter(VARIABLE * var)5836 CHAR *us_teceditgetparameter(VARIABLE *var)
5837 {
5838 REGISTER CHAR *str, *orig;
5839
5840 orig = str = (CHAR *)var->addr;
5841 while (*str != 0 && *str != ':') str++;
5842 if (*str == 0) return(orig);
5843 *str++;
5844 while (*str == ' ') str++;
5845 return(str);
5846 }
5847
5848 /*
5849 * Routine to return the name of the technology-edit port on node "ni". Typically,
5850 * this is stored on the "EDTEC_portname" variable, but it may also be the node's name.
5851 */
us_tecedgetportname(NODEINST * ni)5852 CHAR *us_tecedgetportname(NODEINST *ni)
5853 {
5854 REGISTER VARIABLE *var;
5855
5856 var = getval((INTBIG)ni, VNODEINST, VSTRING, x_("EDTEC_portname"));
5857 if (var != NOVARIABLE) return((CHAR *)var->addr);
5858 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key);
5859 if (var != NOVARIABLE) return((CHAR *)var->addr);
5860 return(0);
5861 }
5862