2
* Electric(tm) VLSI Design System
5
* Generic technology description
6
* Written by: Steven M. Rubin, Static Free Software
8
* Copyright (c) 2000 Static Free Software.
10
* Electric(tm) is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* Electric(tm) is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with Electric(tm); see the file COPYING. If not, write to
22
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23
* Boston, Mass 02111-1307, USA.
25
* Static Free Software
27
* Portola Valley, California 94028
28
* info@staticfreesoft.com
32
#include "egraphics.h"
34
#include "efunction.h"
39
NODEPROTO *gen_univpinprim, *gen_invispinprim, *gen_unroutedpinprim, *gen_facetcenterprim,
40
*gen_portprim, *gen_drcprim;
41
ARCPROTO *gen_universalarc, *gen_invisiblearc, *gen_unroutedarc;
42
ARCPROTO **gen_upconn = 0;
44
/* prototypes for local routines */
45
static void gen_makeunivlist(void);
47
/******************** LAYERS ********************/
49
#define MAXLAYERS 5 /* total layers below */
50
#define LUNIV 0 /* universal layer (connects all) */
51
#define LINVIS 1 /* invisible layer (nonelectrical) */
52
#define LUNROUTED 2 /* unrouted layer (for routers) */
53
#define LGLYPH 3 /* glyph layer (for menu icons) */
54
#define LDRC 4 /* drc ignore layer */
56
static GRAPHICS gen_un_lay = {LAYERO, MENTXT, SOLIDC, SOLIDC,
57
/* univ */ {0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
58
static GRAPHICS gen_in_lay = {LAYERO, GRAY, SOLIDC, SOLIDC,
59
/* invis */ {0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
60
static GRAPHICS gen_int_lay = {LAYERO, BLACK, SOLIDC, SOLIDC,
61
/* invis text */ {0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
62
static GRAPHICS gen_ur_lay = {LAYERO, DGRAY, SOLIDC, SOLIDC,
63
/* unrouted */ {0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
64
static GRAPHICS gen_gl_lay = {LAYERO, MENGLY, SOLIDC, SOLIDC,
65
/* glyph */ {0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
66
static GRAPHICS gen_dr_lay = {LAYERO, ORANGE, SOLIDC, SOLIDC,
67
/* drc */ {0,0,0,0,0,0,0,0}, NOVARIABLE, 0};
69
/* these tables must be updated togehter */
70
GRAPHICS *gen_layers[MAXLAYERS+1] = {&gen_un_lay, &gen_in_lay,
71
&gen_ur_lay, &gen_gl_lay, &gen_dr_lay, NOGRAPHICS};
72
static char *gen_layer_names[MAXLAYERS] = {"Universal", "Invisible",
73
"Unrouted", "Glyph", "DRC"};
74
static char *gen_cif_layers[MAXLAYERS] = {"", "", "", "", "DRC"};
75
static INTBIG gen_layer_function[MAXLAYERS] = {LFUNKNOWN, LFUNKNOWN|LFNONELEC,
76
LFUNKNOWN, LFART|LFNONELEC, LFART|LFNONELEC};
77
static char *gen_layer_letters[MAXLAYERS] = {"u", "i", "r", "g", "d"};
79
/******************** ARCS ********************/
81
#define ARCPROTOCOUNT 3
84
#define GENAUNROUTED 2
87
static TECH_ARCLAY gen_al_u[] = {{LUNIV,0,FILLED}};
88
static TECH_ARCS gen_a_u = {
89
"Universal",0,GENAUNIV,NOARCPROTO, /* name */
90
1,gen_al_u, /* layers */
91
(APUNKNOWN<<AFUNCTIONSH)|WANTFIXANG|(45<<AANGLEINCSH)}; /* userbits */
94
static TECH_ARCLAY gen_al_i[] = {{LINVIS,0,FILLED}};
95
static TECH_ARCS gen_a_i = {
96
"Invisible",0,GENAINVIS,NOARCPROTO, /* name */
97
1,gen_al_i, /* layers */
98
(APNONELEC<<AFUNCTIONSH)|WANTFIXANG|(45<<AANGLEINCSH)}; /* userbits */
101
static TECH_ARCLAY gen_al_r[] = {{LUNROUTED,0,FILLED}};
102
static TECH_ARCS gen_a_r = {
103
"Unrouted",0,GENAUNROUTED,NOARCPROTO, /* name */
104
1,gen_al_r, /* layers */
105
(APUNROUTED<<AFUNCTIONSH)|(0<<AANGLEINCSH)}; /* userbits */
107
TECH_ARCS *gen_arcprotos[ARCPROTOCOUNT+1] = {
108
&gen_a_u, &gen_a_i, &gen_a_r, ((TECH_ARCS *)-1)};
110
/******************** PORT CONNECTIONS **************************/
112
/* these values are replaced with actual arcproto addresses */
113
static INTBIG gen_pc_iu[] = {-1, GENAINVIS, GENAUNIV, -1};
114
static INTBIG gen_pc_riu[] = {-1, GENAUNROUTED, GENAINVIS, GENAUNIV, -1};
116
/******************** NODES ********************/
118
#define NODEPROTOCOUNT 6
119
#define NUNIV 1 /* universal pin */
120
#define NINVIS 2 /* invisible pin */
121
#define NUNROUTED 3 /* unrouted pin */
122
#define NCENTER 4 /* facet center */
123
#define NPORT 5 /* port declaration (for tech edit) */
124
#define NDRC 6 /* drc ignore mask (for ECAD's DRC) */
126
static INTBIG gen_fullbox[] = {LEFTEDGE, BOTEDGE, RIGHTEDGE, TOPEDGE};
127
static INTBIG gen_disccenter[] = {CENTER, CENTER, RIGHTEDGE, CENTER};
128
static INTBIG gen_in2box[] = {LEFTIN2, BOTIN2, RIGHTIN2, TOPIN2};
129
static INTBIG gen_center_lc[] = {LEFTEDGE, BOTEDGE, LEFTEDGE, BOTEDGE};
130
static INTBIG gen_portabox[] = {CENTER, CENTER, CENTER, CENTER,
134
static TECH_PORTS gen_u_p[] = { /* ports */
135
{(INTBIG *)0, "univ", NOPORTPROTO, (180<<PORTARANGESH),
136
CENTER, CENTER, CENTER, CENTER}};
137
static TECH_POLYGON gen_u_l[] = { /* layers */
138
{LUNIV, 0, 2, DISC, POINTS, gen_disccenter}};
139
static TECH_NODES gen_u = {
140
"Universal-Pin",NUNIV,NONODEPROTO, /* name */
142
1,gen_u_p, /* ports */
143
1,gen_u_l, /* layers */
144
(NPPIN<<NFUNCTIONSH)|HOLDSTRACE|WIPEON1OR2, /* userbits */
145
0,0,0,0,0,0,0,0,0}; /* characteristics */
148
static TECH_PORTS gen_i_p[] = {{ /* ports */
149
gen_pc_iu, "center", NOPORTPROTO, (180<<PORTARANGESH),
150
CENTER, CENTER, CENTER, CENTER}};
151
static TECH_POLYGON gen_i_l[] = { /* layers */
152
{LINVIS, 0, 4, CLOSEDRECT, BOX, gen_fullbox}};
153
static TECH_NODES gen_i = {
154
"Invisible-Pin",NINVIS,NONODEPROTO, /* name */
156
1,gen_i_p, /* ports */
157
1,gen_i_l, /* layers */
158
(NPPIN<<NFUNCTIONSH)|WIPEON1OR2, /* userbits */
159
0,0,0,0,0,0,0,0,0}; /* characteristics */
162
static TECH_PORTS gen_r_p[] = {{ /* ports */
163
gen_pc_riu, "unrouted", NOPORTPROTO, (180<<PORTARANGESH),
164
CENTER, CENTER, CENTER, CENTER}};
165
static TECH_POLYGON gen_r_l[] = { /* layers */
166
{LUNROUTED, 0, 2, DISC, POINTS, gen_disccenter}};
167
static TECH_NODES gen_r = {
168
"Unrouted-Pin",NUNROUTED,NONODEPROTO, /* name */
170
1,gen_r_p, /* ports */
171
1,gen_r_l, /* layers */
172
(NPPIN<<NFUNCTIONSH)|WIPEON1OR2, /* userbits */
173
0,0,0,0,0,0,0,0,0}; /* characteristics */
176
static TECH_PORTS gen_c_p[] = {{ /* ports */
177
gen_pc_iu, "center", NOPORTPROTO, (180<<PORTARANGESH),
178
LEFTEDGE, BOTEDGE, LEFTEDGE, BOTEDGE}};
179
static TECH_POLYGON gen_c_l[] = { /* layers */
180
{LGLYPH, 0, 4, CLOSED, BOX, gen_fullbox},
181
{LGLYPH, 0, 2, BIGCROSS, POINTS, gen_center_lc}};
182
static TECH_NODES gen_c = {
183
"Facet-Center",NCENTER,NONODEPROTO, /* name */
185
1,gen_c_p, /* ports */
186
2,gen_c_l, /* layers */
187
(NPART<<NFUNCTIONSH), /* userbits */
188
0,0,0,0,0,0,0,0,0}; /* characteristics */
191
static TECH_PORTS gen_p_p[] = {{ /* ports */
192
gen_pc_iu, "center", NOPORTPROTO, (180<<PORTARANGESH),
193
CENTER, CENTER, CENTER, CENTER}};
194
static TECH_POLYGON gen_p_l[] = { /* layers */
195
{LGLYPH, 0, 4, CLOSED, BOX, gen_in2box},
196
{LGLYPH, 0, 3, OPENED, POINTS, gen_portabox}};
197
static TECH_NODES gen_p = {
198
"Port",NPORT,NONODEPROTO, /* name */
200
1,gen_p_p, /* ports */
201
2,gen_p_l, /* layers */
202
(NPART<<NFUNCTIONSH), /* userbits */
203
0,0,0,0,0,0,0,0,0}; /* characteristics */
206
static TECH_PORTS gen_d_p[] = {{ /* ports */
207
gen_pc_iu, "center", NOPORTPROTO, (180<<PORTARANGESH),
208
CENTER, CENTER, CENTER, CENTER}};
209
static TECH_POLYGON gen_d_l[] = { /* layers */
210
{LDRC, 0, 4, CLOSEDRECT, BOX, gen_fullbox}};
211
static TECH_NODES gen_d = {
212
"DRC-Node",NDRC,NONODEPROTO, /* name */
214
1,gen_d_p, /* ports */
215
1,gen_d_l, /* layers */
216
(NPNODE<<NFUNCTIONSH)|HOLDSTRACE, /* userbits */
217
POLYGONAL,0,0,0,0,0,0,0,0}; /* characteristics */
219
TECH_NODES *gen_nodeprotos[NODEPROTOCOUNT+1] = {&gen_u, &gen_i,
220
&gen_r, &gen_c, &gen_p, &gen_d, ((TECH_NODES *)-1)};
222
static INTBIG gen_node_widoff[NODEPROTOCOUNT*4] = {0,0,0,0, 0,0,0,0, 0,0,0,0,
223
0,0,0,0, K2,K2,K2,K2, 0,0,0,0};
225
/******************** VARIABLE AGGREGATION ********************/
227
TECH_VARIABLES gen_variables[] =
229
/* set general information about the technology */
230
{"TECH_layer_names", (char *)gen_layer_names, 0.0,
231
VSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
232
{"TECH_layer_function", (char *)gen_layer_function, 0.0,
233
VINTEGER|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
234
{"TECH_node_width_offset", (char *)gen_node_widoff, 0.0,
235
VFRACT|VDONTSAVE|VISARRAY|((NODEPROTOCOUNT*4)<<VLENGTHSH)},
237
/* set information for the I/O tool */
238
{"IO_cif_layer_names", (char *)gen_cif_layers, 0.0,
239
VSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
241
/* set information for the USER tool */
242
{"USER_layer_letters", (char *)gen_layer_letters, 0.0,
243
VSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
247
/******************** ROUTINES ********************/
249
BOOLEAN gen_initprocess(TECHNOLOGY *tech, INTBIG pass)
254
/* initialize the technology variable */
259
/* create list of ALL arcs (now and when technologies change) */
260
registertechnologycache(gen_makeunivlist, 0, 0);
262
gen_univpinprim = getnodeproto("Generic:Universal-Pin");
263
gen_invispinprim = getnodeproto("Generic:Invisible-Pin");
264
gen_unroutedpinprim = getnodeproto("Generic:Unrouted-Pin");
265
gen_facetcenterprim = getnodeproto("Generic:Facet-Center");
266
gen_portprim = getnodeproto("Generic:Port");
267
gen_drcprim = getnodeproto("Generic:DRC-Node");
269
gen_universalarc = getarcproto("Generic:Universal");
270
gen_invisiblearc = getarcproto("Generic:Invisible");
271
gen_unroutedarc = getarcproto("Generic:Unrouted");
275
/* set colors properly */
276
gen_gl_lay.col = el_colmengly;
282
void gen_termprocess(void)
284
if (gen_upconn != 0) efree((char *)gen_upconn);
288
* routine to update the connecitivity list for universal and invisible pins so that
289
* they can connect to ALL arcs. This is called at initialization and again
290
* whenever the number of technologies changes
292
void gen_makeunivlist(void)
295
REGISTER ARCPROTO *ap;
296
REGISTER TECHNOLOGY *t;
297
static BOOLEAN first = TRUE;
299
/* count the number of arcs in all technologies */
301
for(t = el_technologies; t != NOTECHNOLOGY; t = t->nexttechnology)
303
for(ap = t->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto) tot++;
306
/* make an array for each arc */
307
if (gen_upconn != 0) efree((char *)gen_upconn);
308
gen_upconn = (ARCPROTO **)emalloc(((tot+2) * (sizeof (ARCPROTO *))), gen_tech->cluster);
309
if (gen_upconn == 0) return;
314
gen_upconn[tot++] = (ARCPROTO *)0;
315
for(t = el_technologies; t != NOTECHNOLOGY; t = t->nexttechnology)
317
for(ap = t->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
318
gen_upconn[tot++] = ap;
320
gen_upconn[tot] = NOARCPROTO;
322
/* store the array in this technology */
325
/* on first entry, load the local descriptor */
326
gen_u_p[0].portarcs = (INTBIG *)gen_upconn;
327
gen_i_p[0].portarcs = (INTBIG *)gen_upconn;
330
/* after initialization, simply change the connection array */
331
gen_univpinprim->firstportproto->connects = gen_upconn;
332
gen_invispinprim->firstportproto->connects = gen_upconn;
337
INTBIG gen_nodepolys(NODEINST *ni, INTBIG *reasonable, WINDOWPART *win)
339
REGISTER INTBIG pindex, count;
340
REGISTER INTBIG start, end;
341
REGISTER INTBIG lambda;
342
static INTBIG portanglekey = 0, portrangekey = 0;
343
REGISTER VARIABLE *var, *var2;
345
pindex = ni->proto->primindex;
346
count = gen_nodeprotos[pindex-1]->layercount;
347
if (pindex == NUNIV || pindex == NINVIS || pindex == NUNROUTED)
349
if (tech_pinusecount(ni, win)) count = 0;
350
if (pindex == NINVIS)
352
gen_in_lay.bits = LAYERO;
353
gen_in_lay.col = GRAY;
354
gen_int_lay.bits = LAYERO;
355
gen_int_lay.col = BLACK;
356
var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, art_colorkey);
357
if (var != NOVARIABLE)
361
case LAYERT1: gen_in_lay.col = COLORT1; gen_in_lay.bits = LAYERT1; break;
362
case LAYERT2: gen_in_lay.col = COLORT2; gen_in_lay.bits = LAYERT2; break;
363
case LAYERT3: gen_in_lay.col = COLORT3; gen_in_lay.bits = LAYERT3; break;
364
case LAYERT4: gen_in_lay.col = COLORT4; gen_in_lay.bits = LAYERT4; break;
365
case LAYERT5: gen_in_lay.col = COLORT5; gen_in_lay.bits = LAYERT5; break;
367
if ((var->addr&(LAYERG|LAYERH|LAYEROE)) == LAYEROE)
368
gen_in_lay.bits = LAYERO; else
369
gen_in_lay.bits = LAYERA;
370
gen_in_lay.col = var->addr;
373
gen_int_lay.bits = gen_in_lay.bits;
374
gen_int_lay.col = gen_in_lay.col;
377
} else if (pindex == NPORT)
379
if (portanglekey == 0) portanglekey = makekey("EDTEC_portangle");
380
if (portrangekey == 0) portrangekey = makekey("EDTEC_portrange");
382
/* port node becomes a cross when it is 1x1 */
383
lambda = lambdaofnode(ni);
384
if (ni->highx-ni->lowx == lambda*2 && ni->highy-ni->lowy == lambda*2)
385
gen_p_l[0].style = CROSS; else gen_p_l[0].style = CLOSED;
387
var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, portanglekey);
388
var2 = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, portrangekey);
389
if (var == NOVARIABLE || var2 == NOVARIABLE) count--; else
391
start = (var->addr - var2->addr) * 10;
392
end = (var->addr + var2->addr) * 10;
393
while (start < 0) start += 3600;
394
while (start > 3600) start -= 3600;
395
while (end < 0) end += 3600;
396
while (end > 3600) end -= 3600;
397
gen_portabox[1] = mult(cosine(start), K2);
398
gen_portabox[3] = mult(sine(start), K2);
399
gen_portabox[9] = mult(cosine(end), K2);
400
gen_portabox[11] = mult(sine(end), K2);
404
/* add in displayable variables */
405
tech_realpolys = count;
406
count += tech_displayablenvars(ni, tech_curwindowpart);
407
if (reasonable != 0) *reasonable = count;
411
void gen_shapenodepoly(NODEINST *ni, INTBIG box, POLYGON *poly)
413
REGISTER TECH_POLYGON *lay;
414
REGISTER INTBIG pindex, count, i, j;
415
REGISTER INTBIG x, y, xoff, yoff, cross, lambda;
416
REGISTER VARIABLE *var;
418
/* handle displayable variables */
419
pindex = ni->proto->primindex;
420
if (box >= tech_realpolys)
422
(void)tech_filldisplayablenvar(ni, poly, tech_curwindowpart, 0);
423
if (pindex == NINVIS) poly->desc = &gen_int_lay;
427
lambda = lambdaofnode(ni);
428
lay = &gen_nodeprotos[pindex - 1]->layerlist[box];
429
if (lay->portnum < 0) poly->portproto = NOPORTPROTO; else
430
poly->portproto = ni->proto->tech->nodeprotos[pindex-1]->portlist[lay->portnum].addr;
432
/* universal pins may have trace information */
435
var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER|VISARRAY, el_trace_key);
436
if (var != NOVARIABLE)
438
/* make sure polygon can hold this description */
439
count = getlength(var) / 2;
440
j = count*4 + (count-1)*2;
441
if (poly->limit < j) (void)extendpolygon(poly, j);
443
/* fill the polygon */
444
xoff = (ni->highx + ni->lowx) / 2;
445
yoff = (ni->highy + ni->lowy) / 2;
448
for(i=0; i<count; i++)
450
x = ((INTBIG *)var->addr)[i*2];
451
y = ((INTBIG *)var->addr)[i*2+1];
452
poly->xv[j] = x-cross+xoff;
453
poly->yv[j] = y-cross+yoff; j++;
454
poly->xv[j] = x+cross+xoff;
455
poly->yv[j] = y+cross+yoff; j++;
456
poly->xv[j] = x-cross+xoff;
457
poly->yv[j] = y+cross+yoff; j++;
458
poly->xv[j] = x+cross+xoff;
459
poly->yv[j] = y-cross+yoff; j++;
461
for(i=1; i<count; i++)
463
poly->xv[j] = ((INTBIG *)var->addr)[(i-1)*2]+xoff;
464
poly->yv[j] = ((INTBIG *)var->addr)[(i-1)*2+1]+yoff; j++;
465
poly->xv[j] = ((INTBIG *)var->addr)[i*2]+xoff;
466
poly->yv[j] = ((INTBIG *)var->addr)[i*2+1]+yoff; j++;
469
/* add in peripheral information */
470
poly->layer = lay->layernum;
471
poly->style = VECTORS;
473
poly->desc = gen_layers[poly->layer];
478
/* nontrace pins draw the normal way */
479
tech_fillpoly(poly, lay, ni, lambda, FILLED);
480
poly->desc = gen_layers[poly->layer];
483
void gen_shapeportpoly(NODEINST *ni, PORTPROTO *pp, POLYGON *poly, XARRAY trans,
486
REGISTER INTBIG pindex;
488
pindex = ni->proto->primindex;
489
tech_fillportpoly(ni, pp, poly, trans, gen_nodeprotos[pindex-1], OPENED);
492
INTBIG gen_arcpolys(ARCINST *ai, WINDOWPART *win)
496
i = gen_arcprotos[ai->proto->arcindex]->laycount;
498
/* add in displayable variables */
500
i += tech_displayableavars(ai, win);
504
void gen_shapearcpoly(ARCINST *ai, INTBIG box, POLYGON *poly)
506
REGISTER INTBIG aindex;
507
REGISTER TECH_ARCLAY *thista;
509
/* handle displayable variables */
510
if (box >= tech_realpolys)
512
(void)tech_filldisplayableavar(ai, poly, tech_curwindowpart, 0);
516
aindex = ai->proto->arcindex;
517
thista = &gen_arcprotos[aindex]->list[box];
518
makearcpoly(ai->length, ai->width-thista->off*lambdaofarc(ai)/WHOLE, ai, poly, thista->style);
519
poly->layer = thista->lay;
520
poly->desc = gen_layers[poly->layer];