1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usredtecg.c
6 * User interface technology editor: conversion from technology to library
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 SPECIALTEXTDESCR us_tecedmisctexttable[] =
43 {
44 {NONODEINST, 0, 0, 6000, TECHLAMBDA},
45 {NONODEINST, 0, 0, 0, TECHDESCRIPT},
46 {NONODEINST, 0, 0, 0, 0},
47 };
48
49 SPECIALTEXTDESCR us_tecedlayertexttable[] =
50 {
51 {NONODEINST, 0, 28000, 18000, LAYERSTYLE},
52 {NONODEINST, 0, 28000, 12000, LAYERCIF},
53 {NONODEINST, 0, 28000, 6000, LAYERDXF},
54 {NONODEINST, 0, 28000, 0, LAYERGDS},
55 {NONODEINST, 0, 28000, -6000, LAYERFUNCTION},
56 {NONODEINST, 0, 28000, -12000, LAYERLETTERS},
57 {NONODEINST, 0, 28000, -18000, LAYERSPIRES},
58 {NONODEINST, 0, 28000, -24000, LAYERSPICAP},
59 {NONODEINST, 0, 28000, -30000, LAYERSPIECAP},
60 {NONODEINST, 0, 28000, -36000, LAYER3DHEIGHT},
61 {NONODEINST, 0, 28000, -42000, LAYER3DTHICK},
62 {NONODEINST, 0, 28000, -48000, LAYERPRINTCOL},
63 {NONODEINST, 0, 0, 0, 0},
64 };
65
66 SPECIALTEXTDESCR us_tecedarctexttable[] =
67 {
68 {NONODEINST, 0, 0, 30000, ARCFUNCTION},
69 {NONODEINST, 0, 0, 24000, ARCFIXANG},
70 {NONODEINST, 0, 0, 18000, ARCWIPESPINS},
71 {NONODEINST, 0, 0, 12000, ARCNOEXTEND},
72 {NONODEINST, 0, 0, 6000, ARCINC},
73 {NONODEINST, 0, 0, 0, 0},
74 };
75
76 SPECIALTEXTDESCR us_tecednodetexttable[] =
77 {
78 {NONODEINST, 0, 0, 36000, NODEFUNCTION},
79 {NONODEINST, 0, 0, 30000, NODESERPENTINE},
80 {NONODEINST, 0, 0, 24000, NODESQUARE},
81 {NONODEINST, 0, 0, 18000, NODEWIPES},
82 {NONODEINST, 0, 0, 12000, NODELOCKABLE},
83 {NONODEINST, 0, 0, 6000, NODEMULTICUT},
84 {NONODEINST, 0, 0, 0, 0},
85 };
86
87 /* prototypes for local routines */
88 static NODEINST *us_tecedplacegeom(POLYGON*, NODEPROTO*);
89 static void us_tecedsetlist(NODEINST*, POLYGON*, INTBIG, INTBIG, INTBIG, INTBIG);
90 static void us_tecedcreatespecialtext(NODEPROTO *np, SPECIALTEXTDESCR *table);
91
92 /*
93 * convert technology "tech" into a library and return that library.
94 * Returns NOLIBRARY on error
95 */
us_tecedmakelibfromtech(TECHNOLOGY * tech)96 LIBRARY *us_tecedmakelibfromtech(TECHNOLOGY *tech)
97 {
98 REGISTER CHAR *lay, *dxf, **sequence, **varnames, *fname, *gds;
99 REGISTER INTBIG i, j, k, e, xs, ys, oldlam, *newmap, *mapptr, *minnodesize,
100 tcon, func, nodexpos, bits, layertotal, arctotal, nodetotal, multicutsep,
101 height3d, thick3d, lambda, min2x, min2y, nlx, nhx, nly, nhy, wid, xoff,
102 *printcolors, *colors;
103 INTBIG lx, hx, ly, hy, xpos[4], ypos[4], xsc[4], ysc[4], lxo, hxo, lyo, hyo,
104 lxp, hxp, lyp, hyp, blx, bhx, bly, bhy;
105 REGISTER BOOLEAN serp, square, wipes, lockable, first;
106 float spires, spicap, spiecap;
107 CHAR gdsbuf[50];
108 REGISTER void *infstr;
109 REGISTER NODEPROTO *np, **nplist, *pnp, **aplist;
110 REGISTER VARIABLE *var, *var2, *var3, *var5, *var6, *var7, *var8,
111 *var10, *var11, *varred, *vargreen, *varblue;
112 REGISTER LIBRARY *lib;
113 REGISTER NODEINST *ni, *oni, *nni;
114 REGISTER ARCINST *ai;
115 REGISTER PORTPROTO *pp, *opp;
116 REGISTER ARCPROTO *ap;
117 REGISTER GRAPHICS *desc;
118 static POLYGON *poly = NOPOLYGON;
119 REGISTER DRCRULES *rules;
120 REGISTER TECH_POLYGON *ll;
121 REGISTER TECH_NODES *techn;
122 REGISTER TECH_COLORMAP *colmap;
123 NODEINST node;
124 ARCINST arc;
125
126 /* make sure network tool is on */
127 if ((net_tool->toolstate&TOOLON) == 0)
128 {
129 ttyputerr(_("Network tool must be running...turning it on"));
130 toolturnon(net_tool);
131 ttyputerr(_("...now reissue the technology editing command"));
132 return(NOLIBRARY);
133 }
134
135 /* get polygon */
136 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
137
138 lib = newlibrary(tech->techname, tech->techname);
139 if (lib == NOLIBRARY)
140 {
141 ttyputerr(_("Cannot create library %s"), tech->techname);
142 return(NOLIBRARY);
143 }
144 ttyputmsg(_("Created library %s..."), tech->techname);
145
146 /* create the information node */
147 np = newnodeproto(x_("factors"), lib);
148 if (np == NONODEPROTO) return(NOLIBRARY);
149 np->userbits |= TECEDITCELL;
150
151 /* modify this technology's lambda value to match the current one */
152 oldlam = lib->lambda[tech->techindex];
153 lambda = lib->lambda[art_tech->techindex];
154 lib->lambda[tech->techindex] = lambda;
155
156 /* create the miscellaneous info cell (called "factors") */
157 us_tecedmakeinfo(np, oldlam, tech->techdescript);
158
159 /* copy any miscellaneous variables and make a list of their names */
160 j = 0;
161 for(i=0; us_knownvars[i].varname != 0; i++)
162 {
163 us_knownvars[i].ival = 0;
164 var = getval((INTBIG)tech, VTECHNOLOGY, -1, us_knownvars[i].varname);
165 if (var == NOVARIABLE) continue;
166 us_knownvars[i].ival = 1;
167 j++;
168 (void)setval((INTBIG)lib, VLIBRARY, us_knownvars[i].varname, var->addr, var->type);
169 }
170 if (j > 0)
171 {
172 varnames = (CHAR **)emalloc(j * (sizeof (CHAR *)), el_tempcluster);
173 if (varnames == 0) return(NOLIBRARY);
174 j = 0;
175 for(i=0; us_knownvars[i].varname != 0; i++)
176 if (us_knownvars[i].ival != 0) varnames[j++] = us_knownvars[i].varname;
177 (void)setval((INTBIG)lib, VLIBRARY, x_("EDTEC_variable_list"), (INTBIG)varnames,
178 VSTRING|VISARRAY|(j<<VLENGTHSH));
179 efree((CHAR *)varnames);
180 }
181
182 /* create the layer node names */
183 layertotal = tech->layercount;
184 nplist = (NODEPROTO **)emalloc((layertotal * (sizeof (NODEPROTO *))), el_tempcluster);
185 if (nplist == 0) return(NOLIBRARY);
186
187 /* create the layer nodes */
188 ttyputmsg(_("Creating the layers..."));
189 var2 = getval((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, x_("IO_cif_layer_names"));
190 var3 = getval((INTBIG)tech, VTECHNOLOGY, -1, x_("IO_gds_layer_numbers"));
191 var8 = getval((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, x_("IO_dxf_layer_names"));
192 var5 = getval((INTBIG)tech, VTECHNOLOGY, VFLOAT|VISARRAY, x_("SIM_spice_resistance"));
193 var6 = getval((INTBIG)tech, VTECHNOLOGY, VFLOAT|VISARRAY, x_("SIM_spice_capacitance"));
194 var7 = getval((INTBIG)tech, VTECHNOLOGY, VFLOAT|VISARRAY, x_("SIM_spice_edge_capacitance"));
195 var10 = getval((INTBIG)tech, VTECHNOLOGY, VINTEGER|VISARRAY, x_("TECH_layer_3dheight"));
196 var11 = getval((INTBIG)tech, VTECHNOLOGY, VINTEGER|VISARRAY, x_("TECH_layer_3dthickness"));
197 printcolors = us_getprintcolors(tech);
198 for(i=0; i<layertotal; i++)
199 {
200 desc = tech->layers[i];
201 infstr = initinfstr();
202 addstringtoinfstr(infstr, x_("layer-"));
203 addstringtoinfstr(infstr, layername(tech, i));
204 fname = returninfstr(infstr);
205
206 /* make sure the layer doesn't exist */
207 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
208 if (namesame(fname, np->protoname) == 0)
209 {
210 ttyputerr(_("Warning: multiple layers named '%s'"), fname);
211 break;
212 }
213
214 np = newnodeproto(fname, lib);
215 if (np == NONODEPROTO) return(NOLIBRARY);
216 np->userbits |= TECEDITCELL;
217 nplist[i] = np;
218
219 /* compute foreign file formats */
220 if (var2 == NOVARIABLE) lay = x_(""); else
221 lay = ((CHAR **)var2->addr)[i];
222 gds = x_("");
223 if (var3 != NOVARIABLE && (var3->type&VISARRAY) != 0)
224 {
225 if ((var3->type&VTYPE) == VSTRING) gds = ((CHAR **)var3->addr)[i]; else
226 {
227 j = ((INTBIG *)var3->addr)[i];
228 if (j >= 0)
229 {
230 esnprintf(gdsbuf, 50, x_("%ld"), j);
231 gds = gdsbuf;
232 }
233 }
234 }
235 if (var8 == NOVARIABLE) dxf = x_(""); else
236 dxf = ((CHAR **)var8->addr)[i];
237
238 /* compute the SPICE information */
239 if (var5 == NOVARIABLE) spires = 0.0; else
240 spires = ((float *)var5->addr)[i];
241 if (var6 == NOVARIABLE) spicap = 0.0; else
242 spicap = ((float *)var6->addr)[i];
243 if (var7 == NOVARIABLE) spiecap = 0.0; else
244 spiecap = ((float *)var7->addr)[i];
245
246 /* compute the 3D information */
247 if (var10 == NOVARIABLE) height3d = 0; else
248 height3d = ((INTBIG *)var10->addr)[i];
249 if (var11 == NOVARIABLE) thick3d = 0; else
250 thick3d = ((INTBIG *)var11->addr)[i];
251
252 /* get the print colors */
253 if (printcolors == 0) colors = 0; else
254 colors = &printcolors[i*5];
255
256 /* build the layer cell */
257 us_tecedmakelayer(np, desc->col, desc->raster,
258 desc->colstyle&(NATURE|OUTLINEPAT), lay, layerfunction(tech, i),
259 us_layerletters(tech, i), dxf, gds, spires, spicap, spiecap,
260 height3d, thick3d, colors);
261 }
262
263 /* save the layer sequence */
264 sequence = (CHAR **)emalloc(layertotal * (sizeof (CHAR *)), el_tempcluster);
265 if (sequence == 0) return(NOLIBRARY);
266 i = 0;
267 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
268 if (namesamen(np->protoname, x_("layer-"), 6) == 0)
269 sequence[i++] = &np->protoname[6];
270 (void)setval((INTBIG)lib, VLIBRARY, x_("EDTEC_layersequence"), (INTBIG)sequence,
271 VSTRING|VISARRAY|(layertotal<<VLENGTHSH));
272 efree((CHAR *)sequence);
273
274 /* create the arc cells */
275 ttyputmsg(_("Creating the arcs..."));
276 arctotal = 0;
277 for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
278 {
279 ap->temp1 = (INTBIG)NONODEPROTO;
280 if ((ap->userbits&ANOTUSED) != 0) continue;
281 infstr = initinfstr();
282 addstringtoinfstr(infstr, x_("arc-"));
283 addstringtoinfstr(infstr, ap->protoname);
284 fname = returninfstr(infstr);
285
286 /* make sure the arc doesn't exist */
287 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
288 if (namesame(fname, np->protoname) == 0)
289 {
290 ttyputerr(_("Warning: multiple arcs named '%s'"), fname);
291 break;
292 }
293
294 np = newnodeproto(fname, lib);
295 if (np == NONODEPROTO) return(NOLIBRARY);
296 np->userbits |= TECEDITCELL;
297 ap->temp1 = (INTBIG)np;
298 var = getvalkey((INTBIG)ap, VARCPROTO, VINTEGER, us_arcstylekey);
299 if (var != NOVARIABLE) bits = var->addr; else
300 bits = ap->userbits;
301 us_tecedmakearc(np, (ap->userbits&AFUNCTION)>>AFUNCTIONSH,
302 bits&WANTFIXANG, ap->userbits&CANWIPE, bits&WANTNOEXTEND,
303 (ap->userbits&AANGLEINC)>>AANGLEINCSH);
304
305 /* now create the arc layers */
306 ai = &arc; initdummyarc(ai);
307 ai->proto = ap;
308 ai->width = defaultarcwidth(ap);
309 wid = ai->width - arcwidthoffset(ai);
310 ai->end[0].xpos = wid*2;
311 ai->end[0].ypos = 0;
312 ai->end[1].xpos = -wid*2;
313 ai->end[1].ypos = 0;
314 ai->length = computedistance(ai->end[0].xpos, ai->end[0].ypos, ai->end[1].xpos, ai->end[1].ypos);
315 j = arcpolys(ai, NOWINDOWPART);
316 xoff = wid*2 + wid/2 + arcwidthoffset(ai)/2;
317 for(i=0; i<j; i++)
318 {
319 shapearcpoly(ai, i, poly);
320 if (poly->layer < 0) continue;
321 desc = tech->layers[poly->layer];
322 if (desc->bits == LAYERN) continue;
323
324 /* scale the arc geometry appropriately */
325 for(k=0; k<poly->count; k++)
326 {
327 poly->xv[k] = muldiv(poly->xv[k] - xoff, lambda, oldlam) - 40000;
328 poly->yv[k] = muldiv(poly->yv[k], lambda, oldlam) - 10000;
329 }
330
331 /* create the node to describe this layer */
332 ni = us_tecedplacegeom(poly, np);
333 if (ni == NONODEINST) continue;
334
335 /* get graphics for this layer */
336 us_teceditsetpatch(ni, desc);
337 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_layer"), (INTBIG)nplist[poly->layer], VNODEPROTO);
338 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERPATCH, VINTEGER);
339 }
340 i = muldiv(arcwidthoffset(ai) / 2, lambda, oldlam);
341 wid = muldiv(wid, lambda, oldlam);
342 ni = newnodeinst(art_boxprim, -40000 - wid*5 - i, -40000-i,
343 -10000-wid/2, -10000+wid/2, 0, 0, np);
344 if (ni == NONODEINST) return(NOLIBRARY);
345 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, HIGHLIT, VINTEGER);
346 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_layer"), (INTBIG)NONODEPROTO, VNODEPROTO);
347 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERPATCH, VINTEGER);
348 endobjectchange((INTBIG)ni, VNODEINST);
349 arctotal++;
350
351 /* compact it accordingly */
352 us_tecedcompact(np);
353 }
354
355 /* save the arc sequence */
356 sequence = (CHAR **)emalloc(arctotal * (sizeof (CHAR *)), el_tempcluster);
357 if (sequence == 0) return(NOLIBRARY);
358 i = 0;
359 for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
360 {
361 if ((ap->userbits&ANOTUSED) != 0) continue;
362 sequence[i++] = &((NODEPROTO *)ap->temp1)->protoname[4];
363 }
364 (void)setval((INTBIG)lib, VLIBRARY, x_("EDTEC_arcsequence"), (INTBIG)sequence,
365 VSTRING|VISARRAY|(arctotal<<VLENGTHSH));
366 efree((CHAR *)sequence);
367
368 /* create the node cells */
369 ttyputmsg(_("Creating the nodes..."));
370 nodetotal = 0;
371 for(pnp = tech->firstnodeproto; pnp != NONODEPROTO; pnp = pnp->nextnodeproto)
372 if ((pnp->userbits&NNOTUSED) == 0) nodetotal++;
373 minnodesize = (INTBIG *)emalloc(nodetotal*2*SIZEOFINTBIG, el_tempcluster);
374 if (minnodesize == 0) return(NOLIBRARY);
375 nodetotal = 0;
376 for(pnp = tech->firstnodeproto; pnp != NONODEPROTO; pnp = pnp->nextnodeproto)
377 {
378 pnp->temp1 = 0;
379 if ((pnp->userbits&NNOTUSED) != 0) continue;
380 first = TRUE;
381
382 /* create the node layers */
383 oni = &node; initdummynode(oni);
384 oni->proto = pnp;
385 xs = (pnp->highx - pnp->lowx) * 2;
386 ys = (pnp->highy - pnp->lowy) * 2;
387 if (xs < 5000) xs = 5000;
388 if (ys < 5000) ys = 5000;
389 nodexpos = -xs*2;
390 xpos[0] = nodexpos - xs;
391 xpos[1] = nodexpos + xs;
392 xpos[2] = nodexpos - xs;
393 xpos[3] = nodexpos + xs;
394 ypos[0] = -10000 + ys;
395 ypos[1] = -10000 + ys;
396 ypos[2] = -10000 - ys;
397 ypos[3] = -10000 - ys;
398 nodesizeoffset(oni, &lxp, &lyp, &hxp, &hyp);
399 xs = (pnp->highx - pnp->lowx) - lxp - hxp;
400 ys = (pnp->highy - pnp->lowy) - lyp - hyp;
401 xsc[0] = xs*1; ysc[0] = ys*1;
402 xsc[1] = xs*2; ysc[1] = ys*1;
403 xsc[2] = xs*1; ysc[2] = ys*2;
404 xsc[3] = xs*2; ysc[3] = ys*2;
405
406 /* for multicut contacts, make large size be just right for 2 cuts */
407 techn = tech->nodeprotos[pnp->primindex-1];
408 if (techn->special == MULTICUT)
409 {
410 min2x = (techn->f1*2 + techn->f3*2 + techn->f4) * oldlam / WHOLE;
411 min2y = (techn->f2*2 + techn->f3*2 + techn->f4) * oldlam / WHOLE;
412 xsc[1] = min2x;
413 xsc[3] = min2x;
414 ysc[2] = min2y;
415 ysc[3] = min2y;
416 }
417 for(e=0; e<4; e++)
418 {
419 /* do not create node if main example had no polygons */
420 if (e != 0 && first) continue;
421
422 /* square nodes have only two examples */
423 if ((pnp->userbits&NSQUARE) != 0 && (e == 1 || e == 2)) continue;
424 oni->lowx = xpos[e] - xsc[e]/2 - lxp;
425 oni->lowy = ypos[e] - ysc[e]/2 - lyp;
426 oni->highx = xpos[e] + xsc[e]/2 + hxp;
427 oni->highy = ypos[e] + ysc[e]/2 + hyp;
428
429 /* place the layers */
430 j = nodepolys(oni, 0, NOWINDOWPART);
431 for(i=0; i<j; i++)
432 {
433 shapenodepoly(oni, i, poly);
434 if (poly->layer < 0) continue;
435 desc = tech->layers[poly->layer];
436 if (desc->bits == LAYERN) continue;
437
438 for(k=0; k<poly->count; k++)
439 {
440 poly->xv[k] = poly->xv[k] * lambda / oldlam;
441 poly->yv[k] = poly->yv[k] * lambda / oldlam;
442 }
443 /* accumulate total size of main example */
444 if (e == 0)
445 {
446 getbbox(poly, &blx, &bhx, &bly, &bhy);
447 if (i == 0)
448 {
449 nlx = blx; nhx = bhx;
450 nly = bly; nhy = bhy;
451 } else
452 {
453 if (blx < nlx) nlx = blx;
454 if (bhx > nhx) nhx = bhx;
455 if (bly < nly) nly = bly;
456 if (bhy > nhy) nhy = bhy;
457 }
458 }
459
460 /* create the node cell on the first valid layer */
461 if (first)
462 {
463 first = FALSE;
464 infstr = initinfstr();
465 addstringtoinfstr(infstr, x_("node-"));
466 addstringtoinfstr(infstr, pnp->protoname);
467 fname = returninfstr(infstr);
468
469 /* make sure the node doesn't exist */
470 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
471 if (namesame(fname, np->protoname) == 0)
472 {
473 ttyputerr(_("Warning: multiple nodes named '%s'"), fname);
474 break;
475 }
476
477 np = newnodeproto(fname, lib);
478 if (np == NONODEPROTO) return(NOLIBRARY);
479 np->userbits |= TECEDITCELL;
480 func = (pnp->userbits&NFUNCTION)>>NFUNCTIONSH;
481 serp = FALSE;
482 if ((func == NPTRANMOS || func == NPTRAPMOS || func == NPTRADMOS) &&
483 (pnp->userbits&HOLDSTRACE) != 0)
484 serp = TRUE;
485 if ((pnp->userbits&NSQUARE) != 0) square = TRUE; else
486 square = FALSE;
487 if ((pnp->userbits&WIPEON1OR2) != 0) wipes = TRUE; else
488 wipes = FALSE;
489 if ((pnp->userbits&LOCKEDPRIM) != 0) lockable = TRUE; else
490 lockable = FALSE;
491 if (techn->special == MULTICUT) multicutsep = techn->f4; else
492 multicutsep = 0;
493 us_tecedmakenode(np, func, serp, square, wipes, lockable, multicutsep);
494 pnp->temp1 = (INTBIG)np;
495 }
496
497 /* create the node to describe this layer */
498 ni = us_tecedplacegeom(poly, np);
499 if (ni == NONODEINST) return(NOLIBRARY);
500
501 /* get graphics for this layer */
502 us_teceditsetpatch(ni, desc);
503 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_layer"),
504 (INTBIG)nplist[poly->layer], VNODEPROTO);
505 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERPATCH, VINTEGER);
506
507 /* set minimum polygon factor on smallest example */
508 if (e != 0) continue;
509 if (i >= tech->nodeprotos[pnp->primindex-1]->layercount) continue;
510 ll = tech->nodeprotos[pnp->primindex-1]->layerlist;
511 if (ll == 0) continue;
512 if (ll[i].representation != MINBOX) continue;
513 var = setval((INTBIG)ni, VNODEINST, x_("EDTEC_minbox"), (INTBIG)x_("MIN"), VSTRING|VDISPLAY);
514 if (var != NOVARIABLE)
515 defaulttextsize(3, var->textdescript);
516 }
517 if (first) continue;
518
519 /* create the highlight node */
520 lx = (xpos[e]-xsc[e]/2) * lambda / oldlam;
521 hx = (xpos[e]+xsc[e]/2) * lambda / oldlam;
522 ly = (ypos[e]-ysc[e]/2) * lambda / oldlam;
523 hy = (ypos[e]+ysc[e]/2) * lambda / oldlam;
524 ni = newnodeinst(art_boxprim, lx, hx, ly, hy, 0, 0, np);
525 if (ni == NONODEINST) return(NOLIBRARY);
526 (void)setvalkey((INTBIG)ni, VNODEINST, art_colorkey, HIGHLIT, VINTEGER);
527 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_layer"), (INTBIG)NONODEPROTO, VNODEPROTO);
528 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERPATCH, VINTEGER);
529 endobjectchange((INTBIG)ni, VNODEINST);
530
531 /* create a grab node (only in main example) */
532 if (e == 0)
533 {
534 var = getvalkey((INTBIG)pnp, VNODEPROTO, VINTEGER|VISARRAY, el_prototype_center_key);
535 if (var != NOVARIABLE)
536 {
537 lx = hx = xpos[0] + ((INTBIG *)var->addr)[0];
538 ly = hy = ypos[0] + ((INTBIG *)var->addr)[1];
539 lx = lx * lambda / oldlam;
540 hx = hx * lambda / oldlam;
541 ly = ly * lambda / oldlam;
542 hy = hy * lambda / oldlam;
543 nodeprotosizeoffset(gen_cellcenterprim, &lxo, &lyo, &hxo, &hyo, np);
544 ni = newnodeinst(gen_cellcenterprim, lx-lxo, hx+hxo, ly-lyo, hy+hyo, 0, 0, np);
545 if (ni == NONODEINST) return(NOLIBRARY);
546 endobjectchange((INTBIG)ni, VNODEINST);
547 }
548 }
549
550 /* also draw ports */
551 for(pp = pnp->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
552 {
553 shapeportpoly(oni, pp, poly, FALSE);
554 getbbox(poly, &lx, &hx, &ly, &hy);
555 lx = lx * lambda / oldlam;
556 hx = hx * lambda / oldlam;
557 ly = ly * lambda / oldlam;
558 hy = hy * lambda / oldlam;
559 nodeprotosizeoffset(gen_portprim, &lxo, &lyo, &hxo, &hyo, np);
560 ni = newnodeinst(gen_portprim, lx-lxo, hx+hxo, ly-lyo, hy+hyo, 0, 0, np);
561 if (ni == NONODEINST) return(NOLIBRARY);
562 pp->temp1 = (INTBIG)ni;
563 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERPATCH, VINTEGER);
564 var = setval((INTBIG)ni, VNODEINST, x_("EDTEC_portname"), (INTBIG)pp->protoname,
565 VSTRING|VDISPLAY);
566 if (var != NOVARIABLE)
567 defaulttextsize(3, var->textdescript);
568 endobjectchange((INTBIG)ni, VNODEINST);
569
570 /* on the first sample, also show angle and connection */
571 if (e != 0) continue;
572 if (((pp->userbits&PORTANGLE)>>PORTANGLESH) != 0 ||
573 ((pp->userbits&PORTARANGE)>>PORTARANGESH) != 180)
574 {
575 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_portangle"),
576 (pp->userbits&PORTANGLE)>>PORTANGLESH, VINTEGER);
577 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_portrange"),
578 (pp->userbits&PORTARANGE)>>PORTARANGESH, VINTEGER);
579 }
580
581 /* add in the "local" port connections (from this tech) */
582 for(tcon=i=0; pp->connects[i] != NOARCPROTO; i++)
583 if (pp->connects[i]->tech == tech) tcon++;
584 if (tcon != 0)
585 {
586 aplist = (NODEPROTO **)emalloc((tcon * (sizeof (NODEPROTO *))), el_tempcluster);
587 if (aplist == 0) return(NOLIBRARY);
588 for(j=i=0; pp->connects[i] != NOARCPROTO; i++)
589 {
590 if (pp->connects[i]->tech != tech) continue;
591 aplist[j] = (NODEPROTO *)pp->connects[i]->temp1;
592 if (aplist[j] != NONODEPROTO) j++;
593 }
594 (void)setval((INTBIG)ni, VNODEINST, x_("EDTEC_connects"),
595 (INTBIG)aplist, VNODEPROTO|VISARRAY|(j<<VLENGTHSH));
596 efree((CHAR *)aplist);
597 }
598
599 /* connect the connected ports */
600 for(opp = pnp->firstportproto; opp != pp; opp = opp->nextportproto)
601 {
602 if (opp->network != pp->network) continue;
603 nni = (NODEINST *)opp->temp1;
604 if (nni == NONODEINST) continue;
605 if (newarcinst(gen_universalarc, 0, 0, ni, ni->proto->firstportproto,
606 (ni->highx+ni->lowx)/2, (ni->highy+ni->lowy)/2, nni,
607 nni->proto->firstportproto, (nni->highx+nni->lowx)/2,
608 (nni->highy+nni->lowy)/2, np) == NOARCINST) return(NOLIBRARY);
609 break;
610 }
611 }
612 }
613 minnodesize[nodetotal*2] = (nhx - nlx) * WHOLE / lambda;
614 minnodesize[nodetotal*2+1] = (nhy - nly) * WHOLE / lambda;
615 nodetotal++;
616
617 /* compact it accordingly */
618 us_tecedcompact(np);
619 }
620
621 /* save the node sequence */
622 sequence = (CHAR **)emalloc(nodetotal * (sizeof (CHAR *)), el_tempcluster);
623 if (sequence == 0) return(NOLIBRARY);
624 i = 0;
625 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
626 if (np->temp1 != 0)
627 sequence[i++] = &((NODEPROTO *)np->temp1)->protoname[5];
628 (void)setval((INTBIG)lib, VLIBRARY, x_("EDTEC_nodesequence"), (INTBIG)sequence,
629 VSTRING|VISARRAY|(i<<VLENGTHSH));
630 efree((CHAR *)sequence);
631
632 /* create the color map information */
633 ttyputmsg(_("Adding color map and design rules..."));
634 var2 = getval((INTBIG)tech, VTECHNOLOGY, VCHAR|VISARRAY, x_("USER_color_map"));
635 varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
636 vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
637 varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
638 if (varred != NOVARIABLE && vargreen != NOVARIABLE && varblue != NOVARIABLE &&
639 var2 != NOVARIABLE)
640 {
641 newmap = emalloc((256*3*SIZEOFINTBIG), el_tempcluster);
642 if (newmap == 0) return(NOLIBRARY);
643 mapptr = newmap;
644 colmap = (TECH_COLORMAP *)var2->addr;
645 for(i=0; i<256; i++)
646 {
647 *mapptr++ = ((INTBIG *)varred->addr)[i];
648 *mapptr++ = ((INTBIG *)vargreen->addr)[i];
649 *mapptr++ = ((INTBIG *)varblue->addr)[i];
650 }
651 for(i=0; i<32; i++)
652 {
653 newmap[(i<<2)*3] = colmap[i].red;
654 newmap[(i<<2)*3+1] = colmap[i].green;
655 newmap[(i<<2)*3+2] = colmap[i].blue;
656 }
657 (void)setval((INTBIG)lib, VLIBRARY, x_("EDTEC_colormap"), (INTBIG)newmap,
658 VINTEGER|VISARRAY|((256*3)<<VLENGTHSH));
659 efree((CHAR *)newmap);
660 }
661
662 /* create the design rule information */
663 rules = dr_allocaterules(layertotal, nodetotal, tech->techname);
664 if (rules == NODRCRULES) return(NOLIBRARY);
665 for(i=0; i<layertotal; i++)
666 (void)allocstring(&rules->layernames[i], layername(tech, i), el_tempcluster);
667 i = 0;
668 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
669 if (np->temp1 != 0)
670 (void)allocstring(&rules->nodenames[i++], &((NODEPROTO *)np->temp1)->protoname[5],
671 el_tempcluster);
672 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_min_widthkey);
673 if (var != NOVARIABLE)
674 for(i=0; i<rules->numlayers; i++) rules->minwidth[i] = ((INTBIG *)var->addr)[i];
675 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_min_width_rulekey);
676 if (var != NOVARIABLE)
677 for(i=0; i<rules->numlayers; i++)
678 (void)reallocstring(&rules->minwidthR[i], ((CHAR **)var->addr)[i], el_tempcluster);
679 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_connected_distanceskey);
680 if (var != NOVARIABLE)
681 for(i=0; i<rules->utsize; i++) rules->conlist[i] = ((INTBIG *)var->addr)[i];
682 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_connected_distances_rulekey);
683 if (var != NOVARIABLE)
684 for(i=0; i<rules->utsize; i++)
685 (void)reallocstring(&rules->conlistR[i], ((CHAR **)var->addr)[i], el_tempcluster);
686 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_unconnected_distanceskey);
687 if (var != NOVARIABLE)
688 for(i=0; i<rules->utsize; i++) rules->unconlist[i] = ((INTBIG *)var->addr)[i];
689 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_unconnected_distances_rulekey);
690 if (var != NOVARIABLE)
691 for(i=0; i<rules->utsize; i++)
692 (void)reallocstring(&rules->unconlistR[i], ((CHAR **)var->addr)[i], el_tempcluster);
693 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_connected_distancesWkey);
694 if (var != NOVARIABLE)
695 for(i=0; i<rules->utsize; i++) rules->conlistW[i] = ((INTBIG *)var->addr)[i];
696 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_connected_distancesW_rulekey);
697 if (var != NOVARIABLE)
698 for(i=0; i<rules->utsize; i++)
699 (void)reallocstring(&rules->conlistWR[i], ((CHAR **)var->addr)[i], el_tempcluster);
700 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_unconnected_distancesWkey);
701 if (var != NOVARIABLE)
702 for(i=0; i<rules->utsize; i++) rules->unconlistW[i] = ((INTBIG *)var->addr)[i];
703 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_unconnected_distancesW_rulekey);
704 if (var != NOVARIABLE)
705 for(i=0; i<rules->utsize; i++)
706 (void)reallocstring(&rules->unconlistWR[i], ((CHAR **)var->addr)[i], el_tempcluster);
707 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_connected_distancesMkey);
708 if (var != NOVARIABLE)
709 for(i=0; i<rules->utsize; i++) rules->conlistM[i] = ((INTBIG *)var->addr)[i];
710 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_connected_distancesM_rulekey);
711 if (var != NOVARIABLE)
712 for(i=0; i<rules->utsize; i++)
713 (void)reallocstring(&rules->conlistMR[i], ((CHAR **)var->addr)[i], el_tempcluster);
714 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_unconnected_distancesMkey);
715 if (var != NOVARIABLE)
716 for(i=0; i<rules->utsize; i++) rules->unconlistM[i] = ((INTBIG *)var->addr)[i];
717 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_unconnected_distancesM_rulekey);
718 if (var != NOVARIABLE)
719 for(i=0; i<rules->utsize; i++)
720 (void)reallocstring(&rules->unconlistMR[i], ((CHAR **)var->addr)[i], el_tempcluster);
721 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_edge_distanceskey);
722 if (var != NOVARIABLE)
723 for(i=0; i<rules->utsize; i++) rules->edgelist[i] = ((INTBIG *)var->addr)[i];
724 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_edge_distances_rulekey);
725 if (var != NOVARIABLE)
726 for(i=0; i<rules->utsize; i++)
727 (void)reallocstring(&rules->edgelistR[i], ((CHAR **)var->addr)[i], el_tempcluster);
728 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT, dr_wide_limitkey);
729 if (var != NOVARIABLE) rules->widelimit = var->addr;
730 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VFRACT|VISARRAY, dr_min_node_sizekey);
731 if (var != NOVARIABLE)
732 {
733 i = j = 0;
734 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
735 {
736 if (np->temp1 != 0)
737 {
738 rules->minnodesize[i*2] = ((INTBIG *)var->addr)[j*2];
739 rules->minnodesize[i*2+1] = ((INTBIG *)var->addr)[j*2+1];
740
741 /* if rule is valid, make sure it is no larger than actual size */
742 if (rules->minnodesize[i*2] > 0 && rules->minnodesize[i*2+1] > 0)
743 {
744 if (rules->minnodesize[i*2] > minnodesize[i*2])
745 rules->minnodesize[i*2] = minnodesize[i*2];
746 if (rules->minnodesize[i*2+1] > minnodesize[i*2+1])
747 rules->minnodesize[i*2+1] = minnodesize[i*2+1];
748 }
749 i++;
750 }
751 j++;
752 }
753 }
754 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, dr_min_node_size_rulekey);
755 if (var != NOVARIABLE)
756 {
757 i = j = 0;
758 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
759 {
760 if (np->temp1 != 0)
761 {
762 reallocstring(&rules->minnodesizeR[i], ((CHAR **)var->addr)[j], el_tempcluster);
763 i++;
764 }
765 j++;
766 }
767 }
768
769 us_tecedloaddrcmessage(rules, lib);
770 dr_freerules(rules);
771
772 /* clean up */
773 ttyputmsg(_("Done."));
774 efree((CHAR *)nplist);
775 efree((CHAR *)minnodesize);
776 lib->lambda[tech->techindex] = oldlam;
777 return(lib);
778 }
779
780 /*************************** CELL CREATION HELPERS ***************************/
781
782 /*
783 * routine to build the appropriate descriptive information for the information
784 * cell "np".
785 */
us_tecedmakeinfo(NODEPROTO * np,INTBIG lambda,CHAR * description)786 void us_tecedmakeinfo(NODEPROTO *np, INTBIG lambda, CHAR *description)
787 {
788 REGISTER INTBIG i;
789
790 /* load up the structure with the current values */
791 for(i=0; us_tecedmisctexttable[i].funct != 0; i++)
792 {
793 switch (us_tecedmisctexttable[i].funct)
794 {
795 case TECHLAMBDA:
796 us_tecedmisctexttable[i].value = (void *)lambda;
797 break;
798 case TECHDESCRIPT:
799 us_tecedmisctexttable[i].value = (void *)description;
800 break;
801 }
802 }
803
804 /* now create those text objects */
805 us_tecedcreatespecialtext(np, us_tecedmisctexttable);
806 }
807
808 /*
809 * routine to build the appropriate descriptive information for a layer into
810 * cell "np". The color is "colorindex"; the stipple array is in "stip"; the
811 * layer style is in "style", the CIF layer is in "ciflayer"; the function is
812 * in "functionindex"; the layer letters are in "layerletters"; the DXF layer name(s)
813 * are "dxf"; the Calma GDS-II layer is in "gds"; the SPICE resistance is in "spires",
814 * the SPICE capacitance is in "spicap", the SPICE edge capacitance is in "spiecap",
815 * the 3D height is in "height3d", and the 3D thickness is in "thick3d".
816 */
us_tecedmakelayer(NODEPROTO * np,INTBIG colorindex,UINTSML stip[16],INTBIG style,CHAR * ciflayer,INTBIG functionindex,CHAR * layerletters,CHAR * dxf,CHAR * gds,float spires,float spicap,float spiecap,INTBIG height3d,INTBIG thick3d,INTBIG * printcolors)817 void us_tecedmakelayer(NODEPROTO *np, INTBIG colorindex, UINTSML stip[16], INTBIG style,
818 CHAR *ciflayer, INTBIG functionindex, CHAR *layerletters, CHAR *dxf,
819 CHAR *gds, float spires, float spicap, float spiecap,
820 INTBIG height3d, INTBIG thick3d, INTBIG *printcolors)
821 {
822 REGISTER NODEINST *nicolor, *ni, *laypatcontrol, *laycolor, *laystipple;
823 REGISTER INTBIG i, x, y;
824 REGISTER VARIABLE *var;
825 CHAR *colorname, *colorsymbol, *newname;
826 UINTBIG pattern[16];
827 UINTSML spattern[16];
828 REGISTER void *infstr;
829
830 laycolor = laystipple = laypatcontrol = NONODEINST;
831 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
832 {
833 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
834 if (var == NOVARIABLE) continue;
835 switch (var->addr)
836 {
837 case LAYERCOLOR: laycolor = ni; break;
838 case LAYERPATTERN: laystipple = ni; break;
839 case LAYERPATCONT: laypatcontrol = ni; break;
840 }
841 }
842
843 /* create the color information if it is not there */
844 if (laycolor == NONODEINST)
845 {
846 /* create the graphic color object */
847 nicolor = newnodeinst(art_filledboxprim, -20000, -10000, 10000, 20000, 0, 0, np);
848 if (nicolor == NONODEINST) return;
849 (void)setvalkey((INTBIG)nicolor, VNODEINST, art_colorkey, colorindex, VINTEGER);
850 (void)setval((INTBIG)np, VNODEPROTO, x_("EDTEC_colornode"), (INTBIG)nicolor, VNODEINST);
851 if ((style&NATURE) == PATTERNED)
852 {
853 if ((style&OUTLINEPAT) == 0)
854 {
855 for(i=0; i<16; i++) pattern[i] = stip[i];
856 (void)setvalkey((INTBIG)nicolor, VNODEINST, art_patternkey, (INTBIG)pattern,
857 VINTEGER|VISARRAY|(16<<VLENGTHSH));
858 } else
859 {
860 for(i=0; i<16; i++) spattern[i] = stip[i];
861 (void)setvalkey((INTBIG)nicolor, VNODEINST, art_patternkey, (INTBIG)spattern,
862 VSHORT|VISARRAY|(16<<VLENGTHSH));
863 }
864 }
865 endobjectchange((INTBIG)nicolor, VNODEINST);
866
867 /* create the text color object */
868 ni = newnodeinst(gen_invispinprim, 20000, 20000, 24000, 24000, 0, 0, np);
869 if (ni == NONODEINST) return;
870 infstr = initinfstr();
871 addstringtoinfstr(infstr, TECEDNODETEXTCOLOR);
872 if (ecolorname(colorindex, &colorname, &colorsymbol)) colorname = x_("unknown");
873 addstringtoinfstr(infstr, colorname);
874 allocstring(&newname, returninfstr(infstr), el_tempcluster);
875 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)newname,
876 VSTRING|VDISPLAY);
877 efree(newname);
878 if (var != NOVARIABLE)
879 defaulttextsize(2, var->textdescript);
880 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERCOLOR, VINTEGER);
881 endobjectchange((INTBIG)ni, VNODEINST);
882 }
883
884 /* create the stipple pattern objects if none are there */
885 if (laystipple == NONODEINST)
886 {
887 for(x=0; x<16; x++) for(y=0; y<16; y++)
888 {
889 if ((stip[y] & (1 << (15-x))) != 0)
890 {
891 ni = newnodeinst(art_filledboxprim, x*2000-40000, x*2000-38000,
892 4000-y*2000, 6000-y*2000, 0, 0, np);
893 } else
894 {
895 ni = newnodeinst(art_filledboxprim, x*2000-40000, x*2000-38000, 4000-y*2000,
896 6000-y*2000, 0, 0, np);
897 for(i=0; i<16; i++) spattern[i] = 0;
898 (void)setvalkey((INTBIG)ni, VNODEINST, art_patternkey, (INTBIG)spattern,
899 VSHORT|VISARRAY|(16<<VLENGTHSH));
900 }
901 if (ni == NONODEINST) return;
902 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERPATTERN, VINTEGER);
903 endobjectchange((INTBIG)ni, VNODEINST);
904 }
905 ni = newnodeinst(gen_invispinprim, -24000, -24000, 7000, 7000, 0, 0, np);
906 if (ni == NONODEINST) return;
907 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)x_("Stipple Pattern"),
908 VSTRING|VDISPLAY);
909 if (var != NOVARIABLE)
910 TDSETSIZE(var->textdescript, TXTSETQLAMBDA(2));
911 endobjectchange((INTBIG)ni, VNODEINST);
912 }
913
914 /* create the patch control object */
915 if (laypatcontrol == NONODEINST)
916 {
917 ni = newnodeinst(gen_invispinprim, 16000-40000, 16000-40000, 4000-16*2000, 4000-16*2000, 0, 0, np);
918 if (ni == NONODEINST) return;
919 infstr = initinfstr();
920 addstringtoinfstr(infstr, _("Stipple Pattern Operations"));
921 allocstring(&newname, returninfstr(infstr), el_tempcluster);
922 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)newname, VSTRING|VDISPLAY);
923 efree(newname);
924 if (var != NOVARIABLE)
925 defaulttextsize(2, var->textdescript);
926 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, LAYERPATCONT, VINTEGER);
927 endobjectchange((INTBIG)ni, VNODEINST);
928 }
929
930 /* load up the structure with the current values */
931 for(i=0; us_tecedlayertexttable[i].funct != 0; i++)
932 {
933 switch (us_tecedlayertexttable[i].funct)
934 {
935 case LAYERSTYLE:
936 us_tecedlayertexttable[i].value = (void *)style;
937 break;
938 case LAYERCIF:
939 us_tecedlayertexttable[i].value = (void *)ciflayer;
940 break;
941 case LAYERDXF:
942 us_tecedlayertexttable[i].value = (void *)dxf;
943 break;
944 case LAYERGDS:
945 us_tecedlayertexttable[i].value = (void *)gds;
946 break;
947 case LAYERFUNCTION:
948 us_tecedlayertexttable[i].value = (void *)functionindex;
949 break;
950 case LAYERLETTERS:
951 us_tecedlayertexttable[i].value = (void *)layerletters;
952 break;
953 case LAYERSPIRES:
954 us_tecedlayertexttable[i].value = (void *)castint(spires);
955 break;
956 case LAYERSPICAP:
957 us_tecedlayertexttable[i].value = (void *)castint(spicap);
958 break;
959 case LAYERSPIECAP:
960 us_tecedlayertexttable[i].value = (void *)castint(spiecap);
961 break;
962 case LAYER3DHEIGHT:
963 us_tecedlayertexttable[i].value = (void *)height3d;
964 break;
965 case LAYER3DTHICK:
966 us_tecedlayertexttable[i].value = (void *)thick3d;
967 break;
968 case LAYERPRINTCOL:
969 us_tecedlayertexttable[i].value = (void *)printcolors;
970 break;
971 }
972 }
973
974 /* now create those text objects */
975 us_tecedcreatespecialtext(np, us_tecedlayertexttable);
976 }
977
978 /*
979 * routine to build the appropriate descriptive information for an arc into
980 * cell "np". The function is in "func"; the arc is fixed-angle if "fixang"
981 * is nonzero; the arc wipes pins if "wipes" is nonzero; and the arc does
982 * not extend its ends if "noextend" is nonzero. The angle increment is
983 * in "anginc".
984 */
us_tecedmakearc(NODEPROTO * np,INTBIG func,INTBIG fixang,INTBIG wipes,INTBIG noextend,INTBIG anginc)985 void us_tecedmakearc(NODEPROTO *np, INTBIG func, INTBIG fixang, INTBIG wipes, INTBIG noextend,
986 INTBIG anginc)
987 {
988 REGISTER INTBIG i;
989
990 /* load up the structure with the current values */
991 for(i=0; us_tecedarctexttable[i].funct != 0; i++)
992 {
993 switch (us_tecedarctexttable[i].funct)
994 {
995 case ARCFUNCTION:
996 us_tecedarctexttable[i].value = (void *)func;
997 break;
998 case ARCFIXANG:
999 us_tecedarctexttable[i].value = (void *)fixang;
1000 break;
1001 case ARCWIPESPINS:
1002 us_tecedarctexttable[i].value = (void *)wipes;
1003 break;
1004 case ARCNOEXTEND:
1005 us_tecedarctexttable[i].value = (void *)noextend;
1006 break;
1007 case ARCINC:
1008 us_tecedarctexttable[i].value = (void *)anginc;
1009 break;
1010 }
1011 }
1012
1013 /* now create those text objects */
1014 us_tecedcreatespecialtext(np, us_tecedarctexttable);
1015 }
1016
1017 /*
1018 * routine to build the appropriate descriptive information for a node into
1019 * cell "np". The function is in "func", the serpentine transistor factor
1020 * is in "serp", the node is square if "square" is true, the node
1021 * is invisible on 1 or 2 arcs if "wipes" is true, and the node is lockable
1022 * if "lockable" is true.
1023 */
us_tecedmakenode(NODEPROTO * np,INTBIG func,BOOLEAN serp,BOOLEAN square,BOOLEAN wipes,BOOLEAN lockable,INTBIG multicutsep)1024 void us_tecedmakenode(NODEPROTO *np, INTBIG func, BOOLEAN serp, BOOLEAN square, BOOLEAN wipes,
1025 BOOLEAN lockable, INTBIG multicutsep)
1026 {
1027 REGISTER INTBIG i;
1028
1029 /* load up the structure with the current values */
1030 for(i=0; us_tecednodetexttable[i].funct != 0; i++)
1031 {
1032 switch (us_tecednodetexttable[i].funct)
1033 {
1034 case NODEFUNCTION:
1035 us_tecednodetexttable[i].value = (void *)func;
1036 break;
1037 case NODESERPENTINE:
1038 us_tecednodetexttable[i].value = (void *)((INTBIG)serp);
1039 break;
1040 case NODESQUARE:
1041 us_tecednodetexttable[i].value = (void *)((INTBIG)square);
1042 break;
1043 case NODEWIPES:
1044 us_tecednodetexttable[i].value = (void *)((INTBIG)wipes);
1045 break;
1046 case NODELOCKABLE:
1047 us_tecednodetexttable[i].value = (void *)((INTBIG)lockable);
1048 break;
1049 case NODEMULTICUT:
1050 us_tecednodetexttable[i].value = (void *)multicutsep;
1051 break;
1052 }
1053 }
1054
1055 /* now create those text objects */
1056 us_tecedcreatespecialtext(np, us_tecednodetexttable);
1057 }
1058
1059 /*
1060 * routine to add the text corresponding to the layer function in "func"
1061 * to the current infinite string
1062 */
us_tecedaddfunstring(void * infstr,INTBIG func)1063 void us_tecedaddfunstring(void *infstr, INTBIG func)
1064 {
1065 REGISTER INTBIG i;
1066
1067 addstringtoinfstr(infstr, us_teclayer_functions[func&LFTYPE].name);
1068 for(i=0; us_teclayer_functions[i].name != 0; i++)
1069 {
1070 if (us_teclayer_functions[i].value <= LFTYPE) continue;
1071 if ((func&us_teclayer_functions[i].value) == 0) continue;
1072 func &= ~us_teclayer_functions[i].value;
1073 addtoinfstr(infstr, ',');
1074 addstringtoinfstr(infstr, us_teclayer_functions[i].name);
1075 }
1076 }
1077
1078 /*
1079 * Routine to create special text geometry described by "table" in cell "np".
1080 */
us_tecedcreatespecialtext(NODEPROTO * np,SPECIALTEXTDESCR * table)1081 void us_tecedcreatespecialtext(NODEPROTO *np, SPECIALTEXTDESCR *table)
1082 {
1083 REGISTER NODEINST *ni;
1084 REGISTER INTBIG i, *pc;
1085 CHAR line[50], *allocatedname, *str;
1086 REGISTER VARIABLE *var;
1087 REGISTER void *infstr;
1088
1089 us_tecedfindspecialtext(np, table);
1090 for(i=0; table[i].funct != 0; i++)
1091 {
1092 ni = table[i].ni;
1093 if (ni == NONODEINST)
1094 {
1095 ni = newnodeinst(gen_invispinprim, table[i].x, table[i].x,
1096 table[i].y, table[i].y, 0, 0, np);
1097 if (ni == NONODEINST) return;
1098 allocatedname = 0;
1099 switch (table[i].funct)
1100 {
1101 case TECHLAMBDA:
1102 (void)esnprintf(line, 50, x_("Lambda: %ld"), (INTBIG)table[i].value);
1103 str = line;
1104 break;
1105 case TECHDESCRIPT:
1106 infstr = initinfstr();
1107 formatinfstr(infstr, x_("Description: %s"), (CHAR *)table[i].value);
1108 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1109 str = allocatedname;
1110 break;
1111 case LAYERSTYLE:
1112 infstr = initinfstr();
1113 addstringtoinfstr(infstr, TECEDNODETEXTSTYLE);
1114 if (((INTBIG)table[i].value&NATURE) == SOLIDC) addstringtoinfstr(infstr, x_("solid")); else
1115 {
1116 if (((INTBIG)table[i].value&OUTLINEPAT) != 0)
1117 addstringtoinfstr(infstr, x_("patterned/outlined")); else
1118 addstringtoinfstr(infstr, x_("patterned"));
1119 }
1120 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1121 str = allocatedname;
1122 break;
1123 case LAYERCIF:
1124 infstr = initinfstr();
1125 formatinfstr(infstr, x_("%s%s"), TECEDNODETEXTCIF, (CHAR *)table[i].value);
1126 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1127 str = allocatedname;
1128 break;
1129 case LAYERDXF:
1130 infstr = initinfstr();
1131 formatinfstr(infstr, x_("%s%s"), TECEDNODETEXTDXF, (CHAR *)table[i].value);
1132 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1133 str = allocatedname;
1134 break;
1135 case LAYERGDS:
1136 infstr = initinfstr();
1137 formatinfstr(infstr, x_("%s%s"), TECEDNODETEXTGDS, (CHAR *)table[i].value);
1138 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1139 str = allocatedname;
1140 break;
1141 case LAYERFUNCTION:
1142 infstr = initinfstr();
1143 addstringtoinfstr(infstr, TECEDNODETEXTFUNCTION);
1144 us_tecedaddfunstring(infstr, (INTBIG)table[i].value);
1145 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1146 str = allocatedname;
1147 break;
1148 case LAYERLETTERS:
1149 infstr = initinfstr();
1150 formatinfstr(infstr, x_("%s%s"), TECEDNODETEXTLETTERS, (CHAR *)table[i].value);
1151 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1152 str = allocatedname;
1153 break;
1154 case LAYERSPIRES:
1155 infstr = initinfstr();
1156 formatinfstr(infstr, x_("%s%g"), TECEDNODETEXTSPICERES, castfloat((INTBIG)table[i].value));
1157 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1158 str = allocatedname;
1159 break;
1160 case LAYERSPICAP:
1161 infstr = initinfstr();
1162 formatinfstr(infstr, x_("%s%g"), TECEDNODETEXTSPICECAP, castfloat((INTBIG)table[i].value));
1163 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1164 str = allocatedname;
1165 break;
1166 case LAYERSPIECAP:
1167 infstr = initinfstr();
1168 formatinfstr(infstr, x_("%s%g"), TECEDNODETEXTSPICEECAP, castfloat((INTBIG)table[i].value));
1169 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1170 str = allocatedname;
1171 break;
1172 case LAYER3DHEIGHT:
1173 infstr = initinfstr();
1174 formatinfstr(infstr, x_("%s%ld"), TECEDNODETEXT3DHEIGHT, (INTBIG)table[i].value);
1175 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1176 str = allocatedname;
1177 break;
1178 case LAYER3DTHICK:
1179 infstr = initinfstr();
1180 formatinfstr(infstr, x_("%s%ld"), TECEDNODETEXT3DTHICK, (INTBIG)table[i].value);
1181 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1182 str = allocatedname;
1183 break;
1184 case LAYERPRINTCOL:
1185 infstr = initinfstr();
1186 pc = (INTBIG *)table[i].value;
1187 formatinfstr(infstr, x_("%s%ld,%ld,%ld, %ld,%s"), TECEDNODETEXTPRINTCOL,
1188 pc[0], pc[1], pc[2], pc[3], (pc[4]==0 ? x_("off") : x_("on")));
1189 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1190 str = allocatedname;
1191 break;
1192 case ARCFUNCTION:
1193 infstr = initinfstr();
1194 formatinfstr(infstr, x_("%s%s"), TECEDNODETEXTFUNCTION,
1195 us_tecarc_functions[(INTBIG)table[i].value].name);
1196 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1197 str = allocatedname;
1198 break;
1199 case ARCFIXANG:
1200 if ((INTBIG)table[i].value != 0) str = x_("Fixed-angle: Yes"); else
1201 str = x_("Fixed-angle: No");
1202 break;
1203 case ARCWIPESPINS:
1204 if ((INTBIG)table[i].value != 0) str = x_("Wipes pins: Yes"); else
1205 str = x_("Wipes pins: No");
1206 break;
1207 case ARCNOEXTEND:
1208 if ((INTBIG)table[i].value == 0) str = x_("Extend arcs: Yes"); else
1209 str = x_("Extend arcs: No");
1210 break;
1211 case ARCINC:
1212 (void)esnprintf(line, 50, x_("Angle increment: %ld"), (INTBIG)table[i].value);
1213 str = line;
1214 break;
1215 case NODEFUNCTION:
1216 infstr = initinfstr();
1217 formatinfstr(infstr, x_("%s%s"), TECEDNODETEXTFUNCTION,
1218 nodefunctionname((INTBIG)table[i].value, NONODEINST));
1219 allocstring(&allocatedname, returninfstr(infstr), el_tempcluster);
1220 str = allocatedname;
1221 break;
1222 case NODESERPENTINE:
1223 if (table[i].value) str = x_("Serpentine transistor: yes"); else
1224 str = x_("Serpentine transistor: no");
1225 break;
1226 case NODESQUARE:
1227 if (table[i].value) str = x_("Square node: yes"); else
1228 str = x_("Square node: no");
1229 break;
1230 case NODEWIPES:
1231 if (table[i].value) str = x_("Invisible with 1 or 2 arcs: yes"); else
1232 str = x_("Invisible with 1 or 2 arcs: no");
1233 break;
1234 case NODELOCKABLE:
1235 if (table[i].value) str = x_("Lockable: yes"); else
1236 str = x_("Lockable: no");
1237 break;
1238 case NODEMULTICUT:
1239 esnprintf(line, 100, _("Multicut separation: %s"), frtoa((INTBIG)table[i].value));
1240 str = line;
1241 break;
1242 }
1243 var = setvalkey((INTBIG)ni, VNODEINST, art_messagekey, (INTBIG)str, VSTRING|VDISPLAY);
1244 if (var != NOVARIABLE)
1245 defaulttextsize(2, var->textdescript);
1246 (void)setvalkey((INTBIG)ni, VNODEINST, us_edtec_option_key, table[i].funct, VINTEGER);
1247 endobjectchange((INTBIG)ni, VNODEINST);
1248 if (allocatedname != 0) efree(allocatedname);
1249 }
1250 }
1251 }
1252
1253 /*
1254 * Routine to locate the nodes with the special node-cell text. In cell "np", finds
1255 * the relevant text nodes in "table" and loads them into the structure.
1256 */
us_tecedfindspecialtext(NODEPROTO * np,SPECIALTEXTDESCR * table)1257 void us_tecedfindspecialtext(NODEPROTO *np, SPECIALTEXTDESCR *table)
1258 {
1259 REGISTER NODEINST *ni;
1260 REGISTER INTBIG i;
1261 REGISTER VARIABLE *var;
1262
1263 /* clear the node assignments */
1264 for(i=0; table[i].funct != 0; i++)
1265 table[i].ni = NONODEINST;
1266
1267 /* determine the number of special texts here */
1268 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1269 {
1270 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
1271 if (var == NOVARIABLE) continue;
1272 for(i=0; table[i].funct != 0; i++)
1273 {
1274 if (var->addr != table[i].funct) continue;
1275 table[i].ni = ni;
1276 break;
1277 }
1278 }
1279 }
1280
us_tecedplacegeom(POLYGON * poly,NODEPROTO * np)1281 NODEINST *us_tecedplacegeom(POLYGON *poly, NODEPROTO *np)
1282 {
1283 INTBIG lx, hx, ly, hy, dummy;
1284 REGISTER NODEINST *nni;
1285 REGISTER VARIABLE *var;
1286
1287 getbbox(poly, &lx, &hx, &ly, &hy);
1288 switch (poly->style)
1289 {
1290 case FILLED:
1291 if (!isbox(poly, &dummy, &dummy, &dummy, &dummy))
1292 {
1293 nni = newnodeinst(art_filledpolygonprim, lx, hx, ly, hy, 0, 0, np);
1294 if (nni == NONODEINST) return(NONODEINST);
1295 us_tecedsetlist(nni, poly, lx, hx, ly, hy);
1296 endobjectchange((INTBIG)nni, VNODEINST);
1297 return(nni);
1298 }
1299 /* FALLTHROUGH */
1300 case FILLEDRECT:
1301 nni = newnodeinst(art_filledboxprim, lx, hx, ly, hy, 0, 0, np);
1302 if (nni == NONODEINST) return(NONODEINST);
1303 endobjectchange((INTBIG)nni, VNODEINST);
1304 return(nni);
1305 case CLOSED:
1306 if (!isbox(poly, &dummy, &dummy, &dummy, &dummy))
1307 {
1308 nni = newnodeinst(art_closedpolygonprim, lx, hx, ly, hy, 0, 0, np);
1309 if (nni == NONODEINST) return(NONODEINST);
1310 us_tecedsetlist(nni, poly, lx, hx, ly, hy);
1311 endobjectchange((INTBIG)nni, VNODEINST);
1312 return(nni);
1313 }
1314 /* FALLTHROUGH */
1315 case CLOSEDRECT:
1316 nni = newnodeinst(art_boxprim, lx, hx, ly, hy, 0, 0, np);
1317 if (nni == NONODEINST) return(NONODEINST);
1318 endobjectchange((INTBIG)nni, VNODEINST);
1319 return(nni);
1320 case CROSSED:
1321 nni = newnodeinst(art_crossedboxprim, lx, hx, ly, hy, 0,0, np);
1322 if (nni == NONODEINST) return(NONODEINST);
1323 endobjectchange((INTBIG)nni, VNODEINST);
1324 return(nni);
1325 case OPENED:
1326 nni = newnodeinst(art_openedpolygonprim, lx, hx, ly, hy, 0, 0, np);
1327 if (nni == NONODEINST) return(NONODEINST);
1328 us_tecedsetlist(nni, poly, lx, hx, ly, hy);
1329 endobjectchange((INTBIG)nni, VNODEINST);
1330 return(nni);
1331 case OPENEDT1:
1332 nni = newnodeinst(art_openeddottedpolygonprim, lx, hx, ly, hy, 0, 0, np);
1333 if (nni == NONODEINST) return(NONODEINST);
1334 us_tecedsetlist(nni, poly, lx, hx, ly, hy);
1335 endobjectchange((INTBIG)nni, VNODEINST);
1336 return(nni);
1337 case OPENEDT2:
1338 nni = newnodeinst(art_openeddashedpolygonprim, lx, hx, ly, hy, 0, 0, np);
1339 if (nni == NONODEINST) return(NONODEINST);
1340 us_tecedsetlist(nni, poly, lx, hx, ly, hy);
1341 endobjectchange((INTBIG)nni, VNODEINST);
1342 return(nni);
1343 case OPENEDT3:
1344 nni = newnodeinst(art_openedthickerpolygonprim, lx, hx, ly, hy, 0, 0, np);
1345 if (nni == NONODEINST) return(NONODEINST);
1346 us_tecedsetlist(nni, poly, lx, hx, ly, hy);
1347 endobjectchange((INTBIG)nni, VNODEINST);
1348 return(nni);
1349 case CIRCLE:
1350 nni = newnodeinst(art_circleprim, lx, hx, ly, hy, 0, 0, np);
1351 if (nni == NONODEINST) return(NONODEINST);
1352 endobjectchange((INTBIG)nni, VNODEINST);
1353 return(nni);
1354 case THICKCIRCLE:
1355 nni = newnodeinst(art_thickcircleprim, lx, hx, ly, hy, 0, 0, np);
1356 if (nni == NONODEINST) return(NONODEINST);
1357 endobjectchange((INTBIG)nni, VNODEINST);
1358 return(nni);
1359 case DISC:
1360 nni = newnodeinst(art_filledcircleprim, lx, hx, ly, hy, 0, 0, np);
1361 if (nni == NONODEINST) return(NONODEINST);
1362 endobjectchange((INTBIG)nni, VNODEINST);
1363 return(nni);
1364 case CIRCLEARC:
1365 nni = newnodeinst(art_circleprim, lx, hx, ly, hy, 0, 0, np);
1366 if (nni == NONODEINST) return(NONODEINST);
1367 setarcdegrees(nni, 0.0, 45.0*EPI/180.0);
1368 endobjectchange((INTBIG)nni, VNODEINST);
1369 return(nni);
1370 case THICKCIRCLEARC:
1371 nni = newnodeinst(art_thickcircleprim, lx, hx, ly, hy, 0, 0, np);
1372 if (nni == NONODEINST) return(NONODEINST);
1373 setarcdegrees(nni, 0.0, 45.0*EPI/180.0);
1374 endobjectchange((INTBIG)nni, VNODEINST);
1375 return(nni);
1376 case TEXTCENT:
1377 nni = newnodeinst(gen_invispinprim, lx, hx, ly, hy, 0, 0, np);
1378 if (nni == NONODEINST) return(NONODEINST);
1379 var = setvalkey((INTBIG)nni, VNODEINST, art_messagekey,
1380 (INTBIG)poly->string, VSTRING|VDISPLAY);
1381 if (var != NOVARIABLE) TDSETPOS(var->textdescript, VTPOSCENT);
1382 endobjectchange((INTBIG)nni, VNODEINST);
1383 return(nni);
1384 case TEXTBOTLEFT:
1385 nni = newnodeinst(gen_invispinprim, lx, hx, ly, hy, 0, 0, np);
1386 if (nni == NONODEINST) return(NONODEINST);
1387 var = setvalkey((INTBIG)nni, VNODEINST, art_messagekey,
1388 (INTBIG)poly->string, VSTRING|VDISPLAY);
1389 if (var != NOVARIABLE) TDSETPOS(var->textdescript, VTPOSUPRIGHT);
1390 endobjectchange((INTBIG)nni, VNODEINST);
1391 return(nni);
1392 case TEXTBOTRIGHT:
1393 nni = newnodeinst(gen_invispinprim, lx, hx, ly, hy, 0, 0, np);
1394 if (nni == NONODEINST) return(NONODEINST);
1395 var = setvalkey((INTBIG)nni, VNODEINST, art_messagekey,
1396 (INTBIG)poly->string, VSTRING|VDISPLAY);
1397 if (var != NOVARIABLE) TDSETPOS(var->textdescript, VTPOSUPLEFT);
1398 endobjectchange((INTBIG)nni, VNODEINST);
1399 return(nni);
1400 case TEXTBOX:
1401 nni = newnodeinst(gen_invispinprim, lx, hx, ly, hy, 0, 0, np);
1402 if (nni == NONODEINST) return(NONODEINST);
1403 var = setvalkey((INTBIG)nni, VNODEINST, art_messagekey,
1404 (INTBIG)poly->string, VSTRING|VDISPLAY);
1405 if (var != NOVARIABLE) TDSETPOS(var->textdescript, VTPOSBOXED);
1406 endobjectchange((INTBIG)nni, VNODEINST);
1407 return(nni);
1408 }
1409 return(NONODEINST);
1410 }
1411
us_tecedsetlist(NODEINST * ni,POLYGON * poly,INTBIG lx,INTBIG hx,INTBIG ly,INTBIG hy)1412 void us_tecedsetlist(NODEINST *ni, POLYGON *poly, INTBIG lx, INTBIG hx, INTBIG ly, INTBIG hy)
1413 {
1414 REGISTER INTBIG *list;
1415 REGISTER INTBIG i;
1416
1417 list = emalloc((poly->count*2*SIZEOFINTBIG), el_tempcluster);
1418 if (list == 0) return;
1419 for(i=0; i<poly->count; i++)
1420 {
1421 list[i*2] = poly->xv[i] - (hx+lx)/2;
1422 list[i*2+1] = poly->yv[i] - (hy+ly)/2;
1423 }
1424 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)list,
1425 VINTEGER|VISARRAY|((poly->count*2)<<VLENGTHSH));
1426 efree((CHAR *)list);
1427 }
1428