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