1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: tecgen.c
6  * Generic technology description
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 "tech.h"
35 #include "efunction.h"
36 #include "tecgen.h"
37 #include "tecart.h"
38 
39 typedef struct
40 {
41 	INTBIG incol,  inbits;
42 	INTBIG intcol, intbits;
43 	INTBIG portbox1, portbox3, portbox9, portbox11;
44 } GENPOLYLOOP;
45 
46 static GENPOLYLOOP gen_oneprocpolyloop;
47 
48 TECHNOLOGY *gen_tech;
49 NODEPROTO  *gen_univpinprim, *gen_invispinprim, *gen_unroutedpinprim, *gen_cellcenterprim,
50 	*gen_portprim, *gen_drcprim, *gen_essentialprim, *gen_simprobeprim;
51 ARCPROTO   *gen_universalarc, *gen_invisiblearc, *gen_unroutedarc;
52 ARCPROTO  **gen_upconn = 0;
53 
54 /* prototypes for local routines */
55 static void gen_makeunivlist(void);
56 static INTBIG gen_intnodepolys(NODEINST *ni, INTBIG *reasonable, WINDOWPART *win, POLYLOOP *pl,
57 			GENPOLYLOOP *genpl);
58 static void gen_intshapenodepoly(NODEINST *ni, INTBIG box, POLYGON *poly, POLYLOOP *pl, GENPOLYLOOP *genpl);
59 
60 /******************** LAYERS ********************/
61 
62 #define MAXLAYERS       6		/* total layers below */
63 #define LUNIV           0		/* universal layer (connects all) */
64 #define LINVIS          1		/* invisible layer (nonelectrical) */
65 #define LUNROUTED       2		/* unrouted layer (for routers) */
66 #define LGLYPH          3		/* glyph layer (for menu icons) */
67 #define LDRC            4		/* drc ignore layer */
68 #define LSIMPROBE       5		/* simulation probe layer */
69 
70 static GRAPHICS gen_un_lay = {LAYERO, MENTXT, SOLIDC, SOLIDC,
71 /* univ */					{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
72 static GRAPHICS gen_in_lay = {LAYERO, GRAY,  SOLIDC, SOLIDC,
73 /* invis */					{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
74 static GRAPHICS gen_int_lay = {LAYERO, BLACK,  SOLIDC, SOLIDC,
75 /* invis text */			{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
76 static GRAPHICS gen_ur_lay = {LAYERO, DGRAY, SOLIDC, SOLIDC,
77 /* unrouted */				{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
78 static GRAPHICS gen_gl_lay = {LAYERO, MENGLY, SOLIDC, SOLIDC,
79 /* glyph */					{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
80 static GRAPHICS gen_dr_lay = {LAYERO, ORANGE, SOLIDC, SOLIDC,
81 /* drc */					{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
82 static GRAPHICS gen_sp_lay = {LAYERO, GREEN, SOLIDC, SOLIDC,
83 /* sim probe */				{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
84 
85 /* these tables must be updated togehter */
86 GRAPHICS *gen_layers[MAXLAYERS+1] = {&gen_un_lay, &gen_in_lay,
87 	&gen_ur_lay, &gen_gl_lay, &gen_dr_lay, &gen_sp_lay, NOGRAPHICS};
88 static CHAR *gen_layer_names[MAXLAYERS] = {x_("Universal"), x_("Invisible"),
89 	x_("Unrouted"), x_("Glyph"), x_("DRC"), x_("Sim-Probe")};
90 static CHAR *gen_cif_layers[MAXLAYERS] = {x_(""), x_(""), x_(""), x_(""), x_("DRC"), x_("")};
91 static INTBIG gen_layer_function[MAXLAYERS] = {LFUNKNOWN, LFUNKNOWN|LFNONELEC,
92 	LFUNKNOWN, LFART|LFNONELEC, LFART|LFNONELEC, LFART|LFNONELEC};
93 static CHAR *gen_layer_letters[MAXLAYERS] = {x_("u"), x_("i"), x_("r"), x_("g"), x_("d"), x_("s")};
94 
95 /******************** ARCS ********************/
96 
97 #define ARCPROTOCOUNT     3
98 #define GENAUNIV          0
99 #define GENAINVIS         1
100 #define GENAUNROUTED      2
101 
102 /* universal arc */
103 static TECH_ARCLAY gen_al_u[] = {{LUNIV,0,FILLED}};
104 static TECH_ARCS gen_a_u = {
105 	x_("Universal"),0,GENAUNIV,NOARCPROTO,					/* name */
106 	1,gen_al_u,												/* layers */
107 	(APUNKNOWN<<AFUNCTIONSH)|WANTFIXANG|(45<<AANGLEINCSH)};	/* userbits */
108 
109 /* invisible arc */
110 static TECH_ARCLAY gen_al_i[] = {{LINVIS,0,FILLED}};
111 static TECH_ARCS gen_a_i = {
112 	x_("Invisible"),0,GENAINVIS,NOARCPROTO,					/* name */
113 	1,gen_al_i,												/* layers */
114 	(APNONELEC<<AFUNCTIONSH)|WANTFIXANG|(45<<AANGLEINCSH)};	/* userbits */
115 
116 /* unrouted arc */
117 static TECH_ARCLAY gen_al_r[] = {{LUNROUTED,0,FILLED}};
118 static TECH_ARCS gen_a_r = {
119 	x_("Unrouted"),0,GENAUNROUTED,NOARCPROTO,				/* name */
120 	1,gen_al_r,												/* layers */
121 	(APUNROUTED<<AFUNCTIONSH)|(0<<AANGLEINCSH)};			/* userbits */
122 
123 TECH_ARCS *gen_arcprotos[ARCPROTOCOUNT+1] = {
124 	&gen_a_u, &gen_a_i, &gen_a_r, ((TECH_ARCS *)-1)};
125 
126 /******************** PORT CONNECTIONS **************************/
127 
128 /* these values are replaced with actual arcproto addresses */
129 static INTBIG gen_pc_iu[]  = {-1, GENAINVIS, GENAUNIV, -1};
130 static INTBIG gen_pc_riu[] = {-1, GENAUNROUTED, GENAINVIS, GENAUNIV, -1};
131 
132 /******************** NODES ********************/
133 
134 #define NODEPROTOCOUNT     8
135 #define NUNIV              1		/* universal pin */
136 #define NINVIS             2		/* invisible pin */
137 #define NUNROUTED          3		/* unrouted pin */
138 #define NCENTER            4		/* cell center */
139 #define NPORT              5		/* port declaration (for tech edit) */
140 #define NDRC               6		/* drc ignore mask (for ECAD's DRC) */
141 #define NESSENTIAL         7		/* essential bounds marker */
142 #define NSIMPROBE          8		/* simulation probe */
143 
144 static INTBIG gen_fullbox[]    = {LEFTEDGE, BOTEDGE, RIGHTEDGE, TOPEDGE};
145 static INTBIG gen_disccenter[] = {CENTER,   CENTER,  RIGHTEDGE, CENTER};
146 static INTBIG gen_in2box[]     = {LEFTIN2,  BOTIN2,  RIGHTIN2,  TOPIN2};
147 static INTBIG gen_center_lc[]  = {LEFTEDGE, BOTEDGE, LEFTEDGE,  BOTEDGE};
148 static INTBIG gen_portabox[]   = {CENTER,   CENTER,  CENTER,    CENTER,
149 								  CENTER,   CENTER};
150 static INTBIG gen_essentiall[] = {CENTERL1, CENTER,  CENTER,    CENTER,
151 								  CENTER,   CENTERD1};
152 /* Universal pin */
153 static TECH_PORTS gen_u_p[] = {						/* ports */
154 	{(INTBIG *)0, x_("univ"), NOPORTPROTO, (180<<PORTARANGESH),
155 		CENTER, CENTER, CENTER, CENTER}};
156 static TECH_POLYGON gen_u_l[] = {					/* layers */
157 	{LUNIV, 0, 2, DISC, POINTS, gen_disccenter}};
158 static TECH_NODES gen_u = {
159 	x_("Universal-Pin"),NUNIV,NONODEPROTO,			/* name */
160 	K1,K1,											/* size */
161 	1,gen_u_p,										/* ports */
162 	1,gen_u_l,										/* layers */
163 	(NPPIN<<NFUNCTIONSH)|HOLDSTRACE|WIPEON1OR2,		/* userbits */
164 	0,0,0,0,0,0,0,0,0};								/* characteristics */
165 
166 /* Invisible Pin */
167 static TECH_PORTS gen_i_p[] = {{					/* ports */
168 	gen_pc_iu, x_("center"), NOPORTPROTO, (180<<PORTARANGESH),
169 		CENTER, CENTER, CENTER, CENTER}};
170 static TECH_POLYGON gen_i_l[] = {					/* layers */
171 	{LINVIS, 0, 4, CLOSEDRECT, BOX, gen_fullbox}};
172 static TECH_NODES gen_i = {
173 	x_("Invisible-Pin"),NINVIS,NONODEPROTO,			/* name */
174 	K1,K1,											/* size */
175 	1,gen_i_p,										/* ports */
176 	1,gen_i_l,										/* layers */
177 	(NPPIN<<NFUNCTIONSH)|WIPEON1OR2,				/* userbits */
178 	0,0,0,0,0,0,0,0,0};								/* characteristics */
179 
180 /* Unrouted Pin */
181 static TECH_PORTS gen_r_p[] = {{					/* ports */
182 	gen_pc_riu, x_("unrouted"), NOPORTPROTO, (180<<PORTARANGESH),
183 		CENTER, CENTER, CENTER, CENTER}};
184 static TECH_POLYGON gen_r_l[] = {					/* layers */
185 	{LUNROUTED, 0, 2, DISC, POINTS, gen_disccenter}};
186 static TECH_NODES gen_r = {
187 	x_("Unrouted-Pin"),NUNROUTED,NONODEPROTO,		/* name */
188 	K1,K1,											/* size */
189 	1,gen_r_p,										/* ports */
190 	1,gen_r_l,										/* layers */
191 	(NPPIN<<NFUNCTIONSH)|WIPEON1OR2,				/* userbits */
192 	0,0,0,0,0,0,0,0,0};								/* characteristics */
193 
194 /* Cell Center */
195 static TECH_PORTS gen_c_p[] = {{					/* ports */
196 	gen_pc_iu, x_("center"), NOPORTPROTO, (180<<PORTARANGESH),
197 		LEFTEDGE, BOTEDGE, LEFTEDGE, BOTEDGE}};
198 static TECH_POLYGON gen_c_l[] = {					/* layers */
199 	{LGLYPH, 0, 4, CLOSED,   BOX,    gen_fullbox},
200 	{LGLYPH, 0, 2, BIGCROSS, POINTS, gen_center_lc}};
201 static TECH_NODES gen_c = {
202 	x_("Facet-Center"),NCENTER,NONODEPROTO,			/* name */
203 	K0,K0,											/* size */
204 	1,gen_c_p,										/* ports */
205 	2,gen_c_l,										/* layers */
206 	(NPART<<NFUNCTIONSH),							/* userbits */
207 	0,0,0,0,0,0,0,0,0};								/* characteristics */
208 
209 /* Port */
210 static TECH_PORTS gen_p_p[] = {{					/* ports */
211 	gen_pc_iu, x_("center"), NOPORTPROTO, (180<<PORTARANGESH),
212 		CENTER, CENTER, CENTER, CENTER}};
213 static TECH_POLYGON gen_p_l[] = {					/* layers */
214 	{LGLYPH, 0,         4, CLOSED,   BOX,    gen_in2box},
215 	{LGLYPH, 0,         3, OPENED,   POINTS, gen_portabox}};
216 static TECH_NODES gen_p = {
217 	x_("Port"),NPORT,NONODEPROTO,					/* name */
218 	K6,K6,											/* size */
219 	1,gen_p_p,										/* ports */
220 	2,gen_p_l,										/* layers */
221 	(NPART<<NFUNCTIONSH),							/* userbits */
222 	0,0,0,0,0,0,0,0,0};								/* characteristics */
223 
224 /* DRC Node */
225 static TECH_PORTS gen_d_p[] = {{					/* ports */
226 	gen_pc_iu, x_("center"), NOPORTPROTO, (180<<PORTARANGESH),
227 		CENTER, CENTER, CENTER, CENTER}};
228 static TECH_POLYGON gen_d_l[] = {					/* layers */
229 	{LDRC, 0, 4, CLOSEDRECT, BOX, gen_fullbox}};
230 static TECH_NODES gen_d = {
231 	x_("DRC-Node"),NDRC,NONODEPROTO,				/* name */
232 	K2,K2,											/* size */
233 	1,gen_d_p,										/* ports */
234 	1,gen_d_l,										/* layers */
235 	(NPNODE<<NFUNCTIONSH)|HOLDSTRACE,				/* userbits */
236 	POLYGONAL,0,0,0,0,0,0,0,0};						/* characteristics */
237 
238 /* Essential Bounds marker */
239 static TECH_PORTS gen_e_p[] = {{					/* ports */
240 	gen_pc_iu, x_("center"), NOPORTPROTO, (180<<PORTARANGESH),
241 		LEFTEDGE, BOTEDGE, LEFTEDGE, BOTEDGE}};
242 static TECH_POLYGON gen_e_l[] = {					/* layers */
243 	{LGLYPH, 0, 3, OPENED, POINTS, gen_essentiall}};
244 static TECH_NODES gen_e = {
245 	x_("Essential-Bounds"),NESSENTIAL,NONODEPROTO,	/* name */
246 	K0,K0,											/* size */
247 	1,gen_e_p,										/* ports */
248 	1,gen_e_l,										/* layers */
249 	(NPART<<NFUNCTIONSH),							/* userbits */
250 	0,0,0,0,0,0,0,0,0};								/* characteristics */
251 
252 /* Simulation Probe node */
253 static TECH_PORTS gen_s_p[] = {{					/* ports */
254 	gen_pc_riu, x_("center"), NOPORTPROTO, (180<<PORTARANGESH),
255 		LEFTEDGE, BOTEDGE, RIGHTEDGE, TOPEDGE}};
256 static TECH_POLYGON gen_s_l[] = {					/* layers */
257 	{LSIMPROBE, 0, 4, FILLEDRECT, BOX, gen_fullbox}};
258 static TECH_NODES gen_s = {
259 	x_("Simulation-Probe"),NSIMPROBE,NONODEPROTO,	/* name */
260 	K10,K10,										/* size */
261 	1,gen_s_p,										/* ports */
262 	1,gen_s_l,										/* layers */
263 	(NPART<<NFUNCTIONSH)|HOLDSTRACE,				/* userbits */
264 	0,0,0,0,0,0,0,0,0};								/* characteristics */
265 
266 TECH_NODES *gen_nodeprotos[NODEPROTOCOUNT+1] = {&gen_u, &gen_i,
267 	&gen_r, &gen_c, &gen_p, &gen_d, &gen_e, &gen_s, ((TECH_NODES *)-1)};
268 
269 static INTBIG gen_node_widoff[NODEPROTOCOUNT*4] = {0,0,0,0, 0,0,0,0, 0,0,0,0,
270 	0,0,0,0, K2,K2,K2,K2, 0,0,0,0, 0,0,0,0, 0,0,0,0};
271 
272 /******************** VARIABLE AGGREGATION ********************/
273 
274 TECH_VARIABLES gen_variables[] =
275 {
276 	/* set general information about the technology */
277 	{x_("TECH_layer_names"), (CHAR *)gen_layer_names, 0.0,
278 		VSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
279 	{x_("TECH_layer_function"), (CHAR *)gen_layer_function, 0.0,
280 		VINTEGER|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
281 	{x_("TECH_node_width_offset"), (CHAR *)gen_node_widoff, 0.0,
282 		VFRACT|VDONTSAVE|VISARRAY|((NODEPROTOCOUNT*4)<<VLENGTHSH)},
283 
284 	/* set information for the I/O tool */
285 	{x_("IO_cif_layer_names"), (CHAR *)gen_cif_layers, 0.0,
286 		VSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
287 
288 	/* set information for the USER tool */
289 	{x_("USER_layer_letters"), (CHAR *)gen_layer_letters, 0.0,
290 		VSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
291 	{NULL, NULL, 0.0, 0}
292 };
293 
294 /******************** ROUTINES ********************/
295 
gen_initprocess(TECHNOLOGY * tech,INTBIG pass)296 BOOLEAN gen_initprocess(TECHNOLOGY *tech, INTBIG pass)
297 {
298 	switch (pass)
299 	{
300 		case 0:
301 			/* initialize the technology variable */
302 			gen_tech = tech;
303 			break;
304 
305 		case 1:
306 			/* create list of ALL arcs (now and when technologies change) */
307 			registertechnologycache(gen_makeunivlist, 0, 0);
308 
309 			gen_univpinprim = getnodeproto(x_("Generic:Universal-Pin"));
310 			gen_invispinprim = getnodeproto(x_("Generic:Invisible-Pin"));
311 			gen_unroutedpinprim = getnodeproto(x_("Generic:Unrouted-Pin"));
312 			gen_cellcenterprim = getnodeproto(x_("Generic:Facet-Center"));
313 			gen_portprim = getnodeproto(x_("Generic:Port"));
314 			gen_drcprim = getnodeproto(x_("Generic:DRC-Node"));
315 			gen_essentialprim = getnodeproto(x_("Generic:Essential-Bounds"));
316 			gen_simprobeprim = getnodeproto(x_("Generic:Simulation-Probe"));
317 
318 			gen_universalarc = getarcproto(x_("Generic:Universal"));
319 			gen_invisiblearc = getarcproto(x_("Generic:Invisible"));
320 			gen_unroutedarc = getarcproto(x_("Generic:Unrouted"));
321 			break;
322 
323 		case 2:
324 			/* set colors properly */
325 			gen_gl_lay.col = el_colmengly;
326 			break;
327 	}
328 	return(FALSE);
329 }
330 
gen_termprocess(void)331 void gen_termprocess(void)
332 {
333 	if (gen_upconn != 0) efree((CHAR *)gen_upconn);
334 }
335 
336 /*
337  * routine to update the connecitivity list for universal and invisible pins so that
338  * they can connect to ALL arcs.  This is called at initialization and again
339  * whenever the number of technologies changes
340  */
gen_makeunivlist(void)341 void gen_makeunivlist(void)
342 {
343 	REGISTER INTBIG tot;
344 	REGISTER ARCPROTO *ap;
345 	REGISTER TECHNOLOGY *t;
346 	static BOOLEAN first = TRUE;
347 
348 	/* count the number of arcs in all technologies */
349 	tot = 0;
350 	for(t = el_technologies; t != NOTECHNOLOGY; t = t->nexttechnology)
351 	{
352 		for(ap = t->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto) tot++;
353 	}
354 
355 	/* make an array for each arc */
356 	if (gen_upconn != 0) efree((CHAR *)gen_upconn);
357 	gen_upconn = (ARCPROTO **)emalloc(((tot+2) * (sizeof (ARCPROTO *))), gen_tech->cluster);
358 	if (gen_upconn == 0) return;
359 
360 	/* fill the array */
361 	tot = 0;
362 	if (first)
363 		gen_upconn[tot++] = (ARCPROTO *)0;
364 	for(t = el_technologies; t != NOTECHNOLOGY; t = t->nexttechnology)
365 	{
366 		for(ap = t->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
367 			gen_upconn[tot++] = ap;
368 	}
369 	gen_upconn[tot] = NOARCPROTO;
370 
371 	/* store the array in this technology */
372 	if (first)
373 	{
374 		/* on first entry, load the local descriptor */
375 		gen_u_p[0].portarcs = (INTBIG *)gen_upconn;
376 		gen_i_p[0].portarcs = (INTBIG *)gen_upconn;
377 	} else
378 	{
379 		/* after initialization, simply change the connection array */
380 		gen_univpinprim->firstportproto->connects = gen_upconn;
381 		gen_invispinprim->firstportproto->connects = gen_upconn;
382 	}
383 	first = FALSE;
384 }
385 
gen_nodepolys(NODEINST * ni,INTBIG * reasonable,WINDOWPART * win)386 INTBIG gen_nodepolys(NODEINST *ni, INTBIG *reasonable, WINDOWPART *win)
387 {
388 	return(gen_intnodepolys(ni, reasonable, win, &tech_oneprocpolyloop, &gen_oneprocpolyloop));
389 }
390 
gen_intnodepolys(NODEINST * ni,INTBIG * reasonable,WINDOWPART * win,POLYLOOP * pl,GENPOLYLOOP * genpl)391 INTBIG gen_intnodepolys(NODEINST *ni, INTBIG *reasonable, WINDOWPART *win, POLYLOOP *pl,
392 	GENPOLYLOOP *genpl)
393 {
394 	REGISTER INTBIG pindex, count;
395 	REGISTER INTBIG start, end;
396 	REGISTER INTBIG lambda;
397 	static INTBIG portanglekey = 0, portrangekey = 0;
398 	REGISTER VARIABLE *var, *var2;
399 
400 	pindex = ni->proto->primindex;
401 	count = gen_nodeprotos[pindex-1]->layercount;
402 	if (pindex == NUNIV || pindex == NINVIS || pindex == NUNROUTED)
403 	{
404 		if (tech_pinusecount(ni, win)) count = 0;
405 		if (pindex == NINVIS)
406 		{
407 			genpl->inbits = LAYERO;
408 			genpl->incol = GRAY;
409 			genpl->intbits = LAYERO;
410 			genpl->intcol = BLACK;
411 			var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, art_colorkey);
412 			if (var != NOVARIABLE)
413 			{
414 				switch (var->addr)
415 				{
416 					case LAYERT1: genpl->incol = COLORT1;  genpl->inbits = LAYERT1;  break;
417 					case LAYERT2: genpl->incol = COLORT2;  genpl->inbits = LAYERT2;  break;
418 					case LAYERT3: genpl->incol = COLORT3;  genpl->inbits = LAYERT3;  break;
419 					case LAYERT4: genpl->incol = COLORT4;  genpl->inbits = LAYERT4;  break;
420 					case LAYERT5: genpl->incol = COLORT5;  genpl->inbits = LAYERT5;  break;
421 					default:
422 						if ((var->addr&(LAYERG|LAYERH|LAYEROE)) == LAYEROE)
423 							genpl->inbits = LAYERO; else
424 								genpl->inbits = LAYERA;
425 						genpl->incol = var->addr;
426 						break;
427 				}
428 				genpl->intbits = genpl->inbits;
429 				genpl->intcol = genpl->incol;
430 			}
431 		}
432 	} else if (pindex == NPORT)
433 	{
434 		if (portanglekey == 0) portanglekey = makekey(x_("EDTEC_portangle"));
435 		if (portrangekey == 0) portrangekey = makekey(x_("EDTEC_portrange"));
436 
437 		/* port node becomes a cross when it is 1x1 */
438 		lambda = lambdaofnode(ni);
439 		if (ni->highx-ni->lowx == lambda*2 && ni->highy-ni->lowy == lambda*2)
440 			gen_p_l[0].style = CROSS; else gen_p_l[0].style = CLOSED;
441 
442 		var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, portanglekey);
443 		var2 = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, portrangekey);
444 		if (var == NOVARIABLE || var2 == NOVARIABLE) count--; else
445 		{
446 			start = (var->addr - var2->addr) * 10;
447 			end = (var->addr + var2->addr) * 10;
448 			while (start < 0) start += 3600;
449 			while (start > 3600) start -= 3600;
450 			while (end < 0) end += 3600;
451 			while (end > 3600) end -= 3600;
452 			genpl->portbox1 = mult(cosine(start), K2);
453 			genpl->portbox3 = mult(sine(start), K2);
454 			genpl->portbox9 = mult(cosine(end), K2);
455 			genpl->portbox11 = mult(sine(end), K2);
456 		}
457 	}
458 
459 	/* add in displayable variables */
460 	pl->realpolys = count;
461 	count += tech_displayablenvars(ni, pl->curwindowpart, pl);
462 	if (reasonable != 0) *reasonable = count;
463 	return(count);
464 }
465 
gen_shapenodepoly(NODEINST * ni,INTBIG box,POLYGON * poly)466 void gen_shapenodepoly(NODEINST *ni, INTBIG box, POLYGON *poly)
467 {
468 	gen_intshapenodepoly(ni, box, poly, &tech_oneprocpolyloop, &gen_oneprocpolyloop);
469 }
470 
gen_intshapenodepoly(NODEINST * ni,INTBIG box,POLYGON * poly,POLYLOOP * pl,GENPOLYLOOP * genpl)471 void gen_intshapenodepoly(NODEINST *ni, INTBIG box, POLYGON *poly, POLYLOOP *pl, GENPOLYLOOP *genpl)
472 {
473 	REGISTER TECH_POLYGON *lay;
474 	REGISTER INTBIG pindex, count, i, j;
475 	REGISTER INTBIG x, y, xoff, yoff, cross, lambda;
476 	REGISTER VARIABLE *var;
477 
478 	/* handle displayable variables */
479 	pindex = ni->proto->primindex;
480 	if (box >= pl->realpolys)
481 	{
482 		(void)tech_filldisplayablenvar(ni, poly, pl->curwindowpart, 0, pl);
483 		if (pindex == NINVIS)
484 		{
485 			/* code cannot be called by multiple procesors: uses globals */
486 			NOT_REENTRANT;
487 
488 			gen_int_lay.bits = genpl->intbits;
489 			gen_int_lay.col = genpl->intcol;
490 			poly->desc = &gen_int_lay;
491 		}
492 		return;
493 	}
494 
495 	lambda = lambdaofnode(ni);
496 	lay = &gen_nodeprotos[pindex - 1]->layerlist[box];
497 	if (lay->portnum < 0) poly->portproto = NOPORTPROTO; else
498 		poly->portproto = ni->proto->tech->nodeprotos[pindex-1]->portlist[lay->portnum].addr;
499 
500 	switch (pindex)
501 	{
502 		case NINVIS:
503 			/* code cannot be called by multiple procesors: uses globals */
504 			NOT_REENTRANT;
505 
506 			/* invisible pins take programmable appearance */
507 			gen_in_lay.bits = genpl->inbits;
508 			gen_in_lay.col = genpl->incol;
509 			break;
510 
511 		case NPORT:
512 			/* code cannot be called by multiple procesors: uses globals */
513 			NOT_REENTRANT;
514 
515 			/* ports take precomputed range indicators */
516 			gen_portabox[1] = genpl->portbox1;
517 			gen_portabox[3] = genpl->portbox3;
518 			gen_portabox[9] = genpl->portbox9;
519 			gen_portabox[11] = genpl->portbox11;
520 			break;
521 
522 		case NUNIV:
523 			/* universal pins may have trace information */
524 			var = gettrace(ni);
525 			if (var != NOVARIABLE)
526 			{
527 				/* make sure polygon can hold this description */
528 				count = getlength(var) / 2;
529 				j = count*4 + (count-1)*2;
530 				if (poly->limit < j) (void)extendpolygon(poly, j);
531 
532 				/* fill the polygon */
533 				xoff = (ni->highx + ni->lowx) / 2;
534 				yoff = (ni->highy + ni->lowy) / 2;
535 				cross = lambda / 4;
536 				j = 0;
537 				for(i=0; i<count; i++)
538 				{
539 					x = ((INTBIG *)var->addr)[i*2];
540 					y = ((INTBIG *)var->addr)[i*2+1];
541 					poly->xv[j] = x-cross+xoff;
542 					poly->yv[j] = y-cross+yoff;   j++;
543 					poly->xv[j] = x+cross+xoff;
544 					poly->yv[j] = y+cross+yoff;   j++;
545 					poly->xv[j] = x-cross+xoff;
546 					poly->yv[j] = y+cross+yoff;   j++;
547 					poly->xv[j] = x+cross+xoff;
548 					poly->yv[j] = y-cross+yoff;   j++;
549 				}
550 				for(i=1; i<count; i++)
551 				{
552 					poly->xv[j] = ((INTBIG *)var->addr)[(i-1)*2]+xoff;
553 					poly->yv[j] = ((INTBIG *)var->addr)[(i-1)*2+1]+yoff;   j++;
554 					poly->xv[j] = ((INTBIG *)var->addr)[i*2]+xoff;
555 					poly->yv[j] = ((INTBIG *)var->addr)[i*2+1]+yoff;   j++;
556 				}
557 
558 				/* add in peripheral information */
559 				poly->layer = lay->layernum;
560 				poly->style = VECTORS;
561 				poly->count = j;
562 				poly->desc = gen_layers[poly->layer];
563 				return;
564 			}
565 			break;
566 	}
567 
568 	/* nontrace pins draw the normal way */
569 	tech_fillpoly(poly, lay, ni, lambda, FILLED);
570 	poly->desc = gen_layers[poly->layer];
571 }
572 
gen_allnodepolys(NODEINST * ni,POLYLIST * plist,WINDOWPART * win,BOOLEAN onlyreasonable)573 INTBIG gen_allnodepolys(NODEINST *ni, POLYLIST *plist, WINDOWPART *win, BOOLEAN onlyreasonable)
574 {
575 	REGISTER INTBIG tot, j;
576 	INTBIG reasonable;
577 	REGISTER NODEPROTO *np;
578 	REGISTER POLYGON *poly;
579 	POLYLOOP mypl;
580 	GENPOLYLOOP mygenpl;
581 
582 	np = ni->proto;
583 	mypl.curwindowpart = win;
584 	tot = gen_intnodepolys(ni, &reasonable, win, &mypl, &mygenpl);
585 	if (onlyreasonable) tot = reasonable;
586 	if (mypl.realpolys < tot) tot = mypl.realpolys;
587 	if (ensurepolylist(plist, tot, db_cluster)) return(-1);
588 	for(j = 0; j < tot; j++)
589 	{
590 		poly = plist->polygons[j];
591 		poly->tech = gen_tech;
592 		gen_intshapenodepoly(ni, j, poly, &mypl, &mygenpl);
593 	}
594 	return(tot);
595 }
596 
gen_shapeportpoly(NODEINST * ni,PORTPROTO * pp,POLYGON * poly,XARRAY trans,BOOLEAN purpose)597 void gen_shapeportpoly(NODEINST *ni, PORTPROTO *pp, POLYGON *poly, XARRAY trans,
598 	BOOLEAN purpose)
599 {
600 	REGISTER INTBIG pindex, style;
601 	Q_UNUSED( purpose );
602 
603 	pindex = ni->proto->primindex;
604 	if (pindex == NSIMPROBE) style = FILLED; else
605 		style = OPENED;
606 	tech_fillportpoly(ni, pp, poly, trans, gen_nodeprotos[pindex-1], style, lambdaofnode(ni));
607 }
608