1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: netextract.c
6 * Network tool: module for node extraction
7 * Written by: David Groulx and Brett Bissinger, Harvey Mudd College
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 * Things to do:
32 * Detect transistors
33 * Remove the well/select layers
34 * Find implicit connections created by PL nodes that cross or end in a "T"
35 */
36 #include "global.h"
37 #include "network.h"
38 #include "efunction.h"
39 #include "usr.h"
40 #include "tecgen.h"
41
42 static void build_node_arc_list( NODEINST**, INTBIG*, TECHNOLOGY*, INTBIG*, ARCINST**, NODEINST**, NODEPROTO* );
43 static void add_node( NODEINST* node, NODEINST** list );
44 static void remove_node( NODEINST*, NODEINST** list, INTBIG *count );
45 static void add_arc( ARCINST* arc, ARCINST** list );
46 static void via_to_contact( NODEINST**, INTBIG*, TECHNOLOGY*, INTBIG*, ARCINST**, NODEINST**, NODEPROTO* );
47 static BOOLEAN contains_node( NODEINST*, NODEINST* );
48
49 /*
50 * Routine to convert cell "cell" from pure-layer nodes to real nodes and arcs.
51 */
net_conv_to_internal(NODEPROTO * cell)52 void net_conv_to_internal( NODEPROTO *cell )
53 {
54 NODEINST *nodes; /* head of the new node list */
55 ARCINST *arcs; /* head of the new arc list */
56 NODEINST *db_node; /* for editing arcs to point to inst in the databade, also for */
57 /* call to endchangeobject */
58 NODEINST *nodelooper, **plnodelist, *ni;
59 NODEINST node;
60 NODEPROTO *prim;
61 static POLYGON *poly = NOPOLYGON;
62 ARCINST *arclooper;
63 ARCINST *db_arc; /* store return of newarcinst(), use in call to endchangeobject() */
64 INTBIG nodecounter, *equivlayers, i, j;
65 VARIABLE *var;
66 CHAR **ciflayers;
67 TECHNOLOGY *tech;
68
69 /* count the number of PL nodes */
70 tech = NOTECHNOLOGY;
71 nodecounter = 0;
72 for(nodelooper = cell->firstnodeinst; nodelooper != NONODEINST; nodelooper = nodelooper->nextnodeinst)
73 {
74 if (((nodelooper->proto->userbits & NFUNCTION) >> NFUNCTIONSH) != NPNODE) continue;
75 nodecounter++;
76 if (tech == NOTECHNOLOGY) tech = nodelooper->proto->tech; else
77 {
78 if (tech != nodelooper->proto->tech)
79 {
80 ttyputerr(_("Cannot determine technology to use (found %s and %s)"),
81 tech->techname, nodelooper->proto->tech->techname);
82 return;
83 }
84 }
85 }
86 if (nodecounter == 0)
87 {
88 ttyputmsg(_("There are no pure-layer nodes to convert"));
89 return;
90 }
91
92 /* save the PL nodes in a list */
93 plnodelist = (NODEINST **)emalloc(nodecounter * (sizeof (NODEINST *)), net_tool->cluster);
94 if (plnodelist == 0) return;
95 nodecounter = 0;
96 for(nodelooper = cell->firstnodeinst; nodelooper != NONODEINST; nodelooper = nodelooper->nextnodeinst)
97 {
98 if (((nodelooper->proto->userbits & NFUNCTION) >> NFUNCTIONSH) != NPNODE) continue;
99 plnodelist[nodecounter++] = nodelooper;
100 }
101 ttyputmsg(_("There are %ld pure-layer nodes"), nodecounter);
102
103 /* setup equivalent layers to handle CIF layer unification */
104 equivlayers = (INTBIG *)emalloc(tech->layercount * SIZEOFINTBIG, net_tool->cluster);
105 if (equivlayers == 0) return;
106 var = getval((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, x_("IO_cif_layer_names"));
107 if (var == NOVARIABLE) ciflayers = 0; else
108 ciflayers = (CHAR **)var->addr;
109 for(i=0; i<tech->layercount; i++)
110 {
111 equivlayers[i] = i;
112 if (ciflayers != 0)
113 {
114 for(j=0; j<i; j++)
115 {
116 if (namesame(ciflayers[j], ciflayers[i]) != 0) continue;
117 equivlayers[i] = j;
118 break;
119 }
120 }
121 }
122
123 /* precache the layer number in each pure-layer node prototype */
124 (void)needstaticpolygon(&poly, 4, net_tool->cluster);
125 for(prim = tech->firstnodeproto; prim != NONODEPROTO; prim = prim->nextnodeproto)
126 {
127 if (((prim->userbits&NFUNCTION) >> NFUNCTIONSH) != NPNODE) continue;
128 ni = &node; initdummynode(ni);
129 ni->proto = prim;
130 ni->lowx = 0; ni->highx = 100;
131 ni->lowy = 0; ni->highy = 100;
132 (void)nodepolys(ni, 0, NOWINDOWPART);
133 shapenodepoly(ni, 0, poly);
134 prim->temp1 = equivlayers[poly->layer];
135 }
136
137 /* initialize list of new nodes and arcs */
138 nodes = NONODEINST;
139 arcs = NOARCINST;
140
141 /* find contacts */
142 via_to_contact( plnodelist, &nodecounter,
143 tech,
144 equivlayers,
145 &arcs,
146 &nodes,
147 cell );
148
149 /* convert to arcs and pins */
150 build_node_arc_list( plnodelist, &nodecounter,
151 tech,
152 equivlayers,
153 &arcs,
154 &nodes,
155 cell );
156
157 #if 0 /* not handling this yet */
158 arc_crossings( &arcs, &nodes, cell );
159
160 t_crossings( &arcs, &nodes, cell );
161 #endif
162
163 /* create all the nodes in the lists, and store the pointers */
164 /* in a new list for use in the arcs */
165 for( ; nodes != NONODEINST; nodes = nodes->nextnodeinst )
166 {
167 db_node = newnodeinst( nodes->proto,
168 nodes->lowx,
169 nodes->highx,
170 nodes->lowy,
171 nodes->highy,
172 nodes->transpose,
173 nodes->rotation,
174 nodes->parent );
175 if (db_node == NONODEINST) continue;
176 endobjectchange( (INTBIG)db_node, VNODEINST );
177
178 /* search through all arcs and change their ends to point */
179 /* to NODEINST*'s in the database */
180 arclooper = arcs;
181 for( ; arclooper != NOARCINST; arclooper = arclooper->nextarcinst )
182 {
183 if( arclooper->end[0].nodeinst == nodes )
184 {
185 arclooper->end[0].nodeinst = db_node;
186 }
187
188 if( arclooper->end[1].nodeinst == nodes )
189 {
190 arclooper->end[1].nodeinst = db_node;
191 }
192 }
193 }
194
195 /* create arc insts */
196 for( ; arcs != NOARCINST; arcs = arcs->nextarcinst )
197 {
198 db_arc = newarcinst( arcs->proto,
199 arcs->width,
200 arcs->userbits,
201 arcs->end[0].nodeinst,
202 arcs->end[0].nodeinst->proto->firstportproto,
203 arcs->end[0].xpos,
204 arcs->end[0].ypos,
205 arcs->end[1].nodeinst,
206 arcs->end[1].nodeinst->proto->firstportproto,
207 arcs->end[1].xpos,
208 arcs->end[1].ypos,
209 arcs->parent );
210 if (db_arc == NOARCINST)
211 {
212 ttyputerr(_("Error creating %s arc"), arcs->proto->protoname);
213 continue;
214 }
215 endobjectchange( (INTBIG)db_arc, VARCINST );
216 }
217
218 /* deallocate the list of pure-layer nodes */
219 efree((CHAR *)plnodelist);
220 efree((CHAR *)equivlayers);
221 }
222
223 /********************************** EXTRACTION CASES **********************************/
224
225 #define MAXORIGLAYERS 10
226
227 typedef struct
228 {
229 INTBIG cutlayer; /* the layer number of the cut */
230 INTBIG otherlayercount; /* number of other layers associated with contact */
231 INTBIG otherlayers[MAXORIGLAYERS]; /* other contact layers */
232 NODEPROTO *propercontact; /* contact primitive */
233 } CONTACT;
234
via_to_contact(NODEINST ** parselist,INTBIG * parselistcount,TECHNOLOGY * tech,INTBIG * equivlayers,ARCINST ** arcs,NODEINST ** nodes,NODEPROTO * cell)235 void via_to_contact( NODEINST** parselist, INTBIG *parselistcount,
236 TECHNOLOGY *tech,
237 INTBIG *equivlayers,
238 ARCINST** arcs,
239 NODEINST** nodes,
240 NODEPROTO* cell )
241 {
242 /* locate vias an turn them into nodes, removing them from the parselist */
243 NODEINST *looper;
244 NODEINST node;
245 NODEINST *contact_search;
246 NODEINST *contact;
247 NODEINST *type[MAXORIGLAYERS], *ni;
248 NODEPROTO *thisismycontact, *prim;
249 CONTACT *contactlist;
250 INTBIG i, j, k, fun, thiscontact, lx, hx, ly, hy, lowx, highx, lowy, highy,
251 contactcount, totlayers, otherlayercount, typeindex[MAXORIGLAYERS];
252 static POLYGON *poly = NOPOLYGON;
253 Q_UNUSED( arcs );
254
255 /* allocate a polygon */
256 (void)needstaticpolygon(&poly, 4, net_tool->cluster);
257
258 /* make a catalog of the contacts and their layers */
259 contactcount = 0;
260 for(prim = tech->firstnodeproto; prim != NONODEPROTO; prim = prim->nextnodeproto)
261 {
262 fun = (prim->userbits&NFUNCTION) >> NFUNCTIONSH;
263 if (fun != NPCONTACT && fun != NPWELL && fun != NPSUBSTRATE) continue;
264 contactcount++;
265 }
266 if (contactcount == 0) return;
267 contactlist = (CONTACT *)emalloc(contactcount * (sizeof (CONTACT)), net_tool->cluster);
268 if (contactlist == 0) return;
269 contactcount = 0;
270 for(prim = tech->firstnodeproto; prim != NONODEPROTO; prim = prim->nextnodeproto)
271 {
272 fun = (prim->userbits&NFUNCTION) >> NFUNCTIONSH;
273 if (fun != NPCONTACT && fun != NPWELL && fun != NPSUBSTRATE) continue;
274 ni = &node; initdummynode(ni);
275 ni->proto = prim;
276 ni->lowx = prim->lowx; ni->highx = prim->highx;
277 ni->lowy = prim->lowy; ni->highy = prim->highy;
278 totlayers = nodepolys(ni, 0, NOWINDOWPART);
279 otherlayercount = 0;
280 for(i=0; i<totlayers; i++)
281 {
282 shapenodepoly(ni, i, poly);
283 if (poly->tech != tech) continue;
284 fun = layerfunction(tech, poly->layer) & LFTYPE;
285 if (!layeriscontact(fun)) contactlist[contactcount].cutlayer = equivlayers[poly->layer]; else
286 {
287 if (otherlayercount >= MAXORIGLAYERS) continue;
288 contactlist[contactcount].otherlayers[otherlayercount] = equivlayers[poly->layer];
289 otherlayercount++;
290 }
291 }
292 contactlist[contactcount].propercontact = prim;
293 contactlist[contactcount].otherlayercount = otherlayercount;
294 contactcount++;
295 }
296
297 /* loop though looking for nodes that are of cut type */
298 for(i=0; i < (*parselistcount); i++)
299 {
300 looper = parselist[i];
301
302 /* look for layers that match one of the contact descriptions */
303 for(thiscontact=0; thiscontact<contactcount; thiscontact++)
304 {
305 /* current node must match the cut layer */
306 if (looper->proto->temp1 != contactlist[thiscontact].cutlayer)
307 continue;
308
309 /* find other layers near the cut, store them in "type" */
310 for(k=0; k<contactlist[thiscontact].otherlayercount; k++)
311 type[k] = NONODEINST;
312 for(j=0; j < (*parselistcount); j++)
313 {
314 contact_search = parselist[j];
315 for(k=0; k<contactlist[thiscontact].otherlayercount; k++)
316 {
317 if (contact_search->proto->temp1 != contactlist[thiscontact].otherlayers[k])
318 continue;
319 if (contains_node(contact_search, looper))
320 {
321 if (type[k] != NONODEINST)
322 {
323 /* want the smallest enclosing PL node on this layer */
324 if ((type[k]->highx-type[k]->lowx) * (type[k]->highy-type[k]->lowy) <
325 (contact_search->highx-contact_search->lowx) * (contact_search->highy-contact_search->lowy))
326 continue;
327 }
328 type[k] = contact_search;
329 typeindex[k] = j;
330 }
331 }
332 }
333
334 /* see if all other layers were found */
335 for(k=0; k<contactlist[thiscontact].otherlayercount; k++)
336 if (type[k] == NONODEINST) break;
337 if (k >= contactlist[thiscontact].otherlayercount) break;
338 }
339 if (thiscontact >= contactcount) continue;
340
341 /* find the correct contact proto */
342 thisismycontact = contactlist[thiscontact].propercontact;
343
344 /* the contact size is the size of the largest non-well layer */
345 j = 0;
346 for(k=0; k<contactlist[thiscontact].otherlayercount; k++)
347 {
348 fun = layerfunction(tech, type[k]->proto->temp1) & LFTYPE;
349 if (fun == LFWELL || fun == LFIMPLANT) continue;
350 if (j == 0)
351 {
352 lowx = type[k]->lowx;
353 highx = type[k]->highx;
354 lowy = type[k]->lowy;
355 highy = type[k]->highy;
356 } else
357 {
358 if (type[k]->lowx < lowx) lowx = type[k]->lowx;
359 if (type[k]->highx > highx) highx = type[k]->highx;
360 if (type[k]->lowy < lowy) lowy = type[k]->lowy;
361 if (type[k]->highy > highy) highy = type[k]->highy;
362 }
363 j++;
364 }
365
366 /* create the new contact */
367 contact = allocnodeinst(cell->lib->cluster);
368 nodeprotosizeoffset(thisismycontact, &lx, &ly, &hx, &hy, cell);
369 contact->highx = highx + hx;
370 contact->lowx = lowx - lx;
371 contact->highy = highy + hy;
372 contact->lowy = lowy - ly;
373 contact->parent = cell;
374 contact->proto = thisismycontact;
375
376 /* insert it into nodes */
377 add_node( contact, nodes );
378
379 /* remove PL nodes from the list */
380 for(k=0; k<contactlist[thiscontact].otherlayercount; k++)
381 {
382 fun = layerfunction(tech, type[k]->proto->temp1) & LFTYPE;
383 if (fun == LFWELL || fun == LFIMPLANT) continue;
384 remove_node(type[k], parselist, parselistcount);
385 if (typeindex[k] < i) i--;
386 }
387
388 /* remove looper from parselist */
389 remove_node(looper, parselist, parselistcount);
390
391 /* kill infinite loop by putting looper back to where it was before the contact */
392 i--;
393 } /*outside of for */
394 }
395
396
397 typedef struct
398 {
399 INTBIG layercount; /* number of layers associated with arc */
400 INTBIG layers[MAXORIGLAYERS]; /* arc layers */
401 ARCPROTO *properarc; /* arc prototype */
402 } ARCDESC;
403
404 /* break down each PL node into 2 nodes and 1 arc. */
build_node_arc_list(NODEINST ** parselist,INTBIG * parselistcount,TECHNOLOGY * tech,INTBIG * equivlayers,ARCINST ** arcs,NODEINST ** nodes,NODEPROTO * cell)405 void build_node_arc_list( NODEINST** parselist,
406 INTBIG *parselistcount,
407 TECHNOLOGY *tech,
408 INTBIG *equivlayers,
409 ARCINST** arcs,
410 NODEINST** nodes,
411 NODEPROTO* cell )
412 {
413 /* data that will be created and added to the list */
414 NODEINST* nodeinst1;
415 NODEINST* nodeinst2, *arc_search;
416 ARCINST* arcinst1, *ai;
417 ARCINST arc;
418 INTBIG lowx1, highx1, lowy1, highy1, px1, py1;
419 INTBIG lowx2, highx2, lowy2, highy2, px2, py2;
420 INTBIG width, hx, lx, hy, ly;
421 ARCPROTO* arctech, *ap;
422 NODEPROTO* nodetech;
423 NODEINST *thisPLnode, *type[MAXORIGLAYERS];
424 PORTPROTO *pp1, *pp2;
425 INTBIG i, j, k, arccount, thisarc, totlayers, layercount;
426 ARCDESC *arclist;
427 static POLYGON *poly = NOPOLYGON;
428
429 /* allocate a polygon */
430 (void)needstaticpolygon(&poly, 4, net_tool->cluster);
431
432 /* make a catalog of the arcs and their layers */
433 arccount = 0;
434 for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
435 arccount++;
436 arclist = (ARCDESC *)emalloc(arccount * (sizeof (ARCDESC)), net_tool->cluster);
437 if (arclist == 0) return;
438 arccount = 0;
439 for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
440 {
441 ai = &arc; initdummyarc(ai);
442 ai->proto = ap;
443 totlayers = arcpolys(ai, NOWINDOWPART);
444 layercount = 0;
445 for(i=0; i<totlayers; i++)
446 {
447 shapearcpoly(ai, i, poly);
448 if (poly->tech != tech) continue;
449 if (layercount >= MAXORIGLAYERS) continue;
450 arclist[arccount].layers[layercount] = equivlayers[poly->layer];
451 layercount++;
452 }
453 arclist[arccount].properarc = ap;
454 arclist[arccount].layercount = layercount;
455 arccount++;
456 }
457
458 for(i=0; i < *parselistcount; i++)
459 {
460 thisPLnode = parselist[i];
461 /* parsing a normal node */
462
463 /* find this layer in the list */
464 for(thisarc = 0; thisarc < arccount; thisarc++)
465 {
466 /* must match the first layer of the arc */
467 if (thisPLnode->proto->temp1 != arclist[thisarc].layers[0]) continue;
468
469 /* found first layer: see if there are others */
470 for(k=1; k<arclist[thisarc].layercount; k++) type[k] = NONODEINST;
471 type[0] = thisPLnode;
472 for(k=1; k<arclist[thisarc].layercount; k++)
473 {
474 for(j=0; j < (*parselistcount); j++)
475 {
476 arc_search = parselist[j];
477 if (arc_search->proto->temp1 != arclist[thisarc].layers[k])
478 continue;
479 if (contains_node(arc_search, thisPLnode))
480 type[k] = arc_search;
481 }
482 }
483 for(k=1; k<arclist[thisarc].layercount; k++)
484 if (type[k] == NONODEINST) break;
485 if (k >= arclist[thisarc].layercount) break;
486 }
487 if (thisarc >= arccount) continue;
488
489 /* determine if the node is horizontal or vertical */
490 if( thisPLnode->highx - thisPLnode->lowx > thisPLnode->highy - thisPLnode->lowy )
491 {
492 /* horizontal node, new nodes at left and right */
493
494 /* arc */
495 width = thisPLnode->highy - thisPLnode->lowy;
496
497 /* left node */
498 lowx1 = thisPLnode->lowx;
499 highx1 = thisPLnode->lowx +
500 ( thisPLnode->highy - thisPLnode->lowy );
501 lowy1 = thisPLnode->lowy;
502 highy1 = thisPLnode->highy;
503
504 /* right node */
505 lowx2 = thisPLnode->highx -
506 ( thisPLnode->highy - thisPLnode->lowy );
507 highx2 = thisPLnode->highx;
508 lowy2 = thisPLnode->lowy;
509 highy2 = thisPLnode->highy;
510 }
511 else
512 {
513 /* vertical node, new nodes at top and bottom */
514
515 /* arc */
516 width = thisPLnode->highx - thisPLnode->lowx;
517
518 /* top node */
519 lowx1 = thisPLnode->lowx;
520 highx1 = thisPLnode->highx;
521 lowy1 = thisPLnode->highy -
522 ( thisPLnode->highx - thisPLnode->lowx );
523 highy1 = thisPLnode->highy;
524
525 /* bottom node */
526 lowx2 = thisPLnode->lowx;
527 highx2 = thisPLnode->highx;
528 lowy2 = thisPLnode->lowy;
529 highy2 = thisPLnode->lowy +
530 ( thisPLnode->highx - thisPLnode->lowx );
531 }
532
533 /* determine the arc technology */
534 arctech = arclist[thisarc].properarc;
535
536 /* determine the pin technology */
537 nodetech = getpinproto(arctech);
538 if (nodetech == NONODEPROTO) continue;
539
540 /* fill in data */
541 px1 = (lowx1+highx1)/2;
542 py1 = (lowy1+highy1)/2;
543 for(nodeinst1 = *nodes; nodeinst1 != NONODEINST; nodeinst1 = nodeinst1->nextnodeinst)
544 {
545 for(pp1 = nodeinst1->proto->firstportproto; pp1 != NOPORTPROTO; pp1 = pp1->nextportproto)
546 {
547 shapeportpoly(nodeinst1, pp1, poly, FALSE);
548 if (isinside(px1, py1, poly)) break;
549 }
550 if (pp1 != NOPORTPROTO) break;
551 }
552 if (nodeinst1 == NONODEINST)
553 {
554 nodeinst1 = allocnodeinst(cell->lib->cluster);
555 nodeprotosizeoffset(nodetech, &lx, &ly, &hx, &hy, cell);
556 nodeinst1->highx = highx1 + hx;
557 nodeinst1->lowx = lowx1 - lx;
558 nodeinst1->highy = highy1 + hy;
559 nodeinst1->lowy = lowy1 - ly;
560 nodeinst1->proto = nodetech;
561 nodeinst1->parent = cell;
562 pp1 = nodetech->firstportproto;
563
564 add_node(nodeinst1, nodes);
565 }
566
567 px2 = (lowx2+highx2)/2;
568 py2 = (lowy2+highy2)/2;
569 for(nodeinst2 = *nodes; nodeinst2 != NONODEINST; nodeinst2 = nodeinst2->nextnodeinst)
570 {
571 for(pp2 = nodeinst2->proto->firstportproto; pp2 != NOPORTPROTO; pp2 = pp2->nextportproto)
572 {
573 shapeportpoly(nodeinst2, pp2, poly, FALSE);
574 if (isinside(px2, py2, poly)) break;
575 }
576 if (pp2 != NOPORTPROTO) break;
577 }
578 if (nodeinst2 == NONODEINST)
579 {
580 nodeinst2 = allocnodeinst(cell->lib->cluster);
581 nodeprotosizeoffset(nodetech, &lx, &ly, &hx, &hy, cell);
582 nodeinst2->highx = highx2 + hx;
583 nodeinst2->lowx = lowx2 - lx;
584 nodeinst2->highy = highy2 + hy;
585 nodeinst2->lowy = lowy2 - ly;
586 nodeinst2->proto = nodetech;
587 nodeinst2->parent = cell;
588 pp2 = nodetech->firstportproto;
589
590 add_node(nodeinst2, nodes);
591 }
592
593 /* allocate space for new things */
594 arcinst1 = allocarcinst(cell->lib->cluster);
595
596 arcinst1->width = width + arcprotowidthoffset(arctech);
597 arcinst1->end[0].nodeinst = nodeinst1;
598 arcinst1->end[0].xpos = px1;
599 arcinst1->end[0].ypos = py1;
600 arcinst1->end[1].nodeinst = nodeinst2;
601 arcinst1->end[1].xpos = px2;
602 arcinst1->end[1].ypos = py2;
603 arcinst1->proto = arctech;
604 arcinst1->userbits = us_makearcuserbits(arctech);
605 arcinst1->parent = cell;
606
607 add_arc( arcinst1, arcs );
608
609 remove_node(thisPLnode, parselist, parselistcount);
610 i--;
611 }
612
613 /* free arc structure */
614 efree((CHAR *)arclist);
615 }
616
617 /*********************************** NOT YET USED ***********************************/
618
619 #if 0 /* not used yet */
620
621 NODEINST* arc_to_PL( ARCINST* arc, NODEPROTO* cell )
622 {
623 /* create a new node to return */
624 NODEINST* newnode;
625
626 newnode = allocnodeinst(cell->lib->cluster);
627
628 /* get the max x */
629 if( arc->end[0].nodeinst->highx >= arc->end[1].nodeinst->highx )
630 {
631 newnode->highx = arc->end[0].nodeinst->highx;
632 }
633 else
634 {
635 newnode->highx = arc->end[1].nodeinst->highx;
636 }
637
638 /* get the low x */
639 if( arc->end[0].nodeinst->lowx <= arc->end[1].nodeinst->lowx )
640 {
641 newnode->lowx = arc->end[0].nodeinst->lowx;
642 }
643 else
644 {
645 newnode->lowx = arc->end[1].nodeinst->lowx;
646 }
647
648 /* get the max y */
649 if( arc->end[0].nodeinst->highy >= arc->end[1].nodeinst->highy )
650 {
651 newnode->highy = arc->end[0].nodeinst->highy;
652 }
653 else
654 {
655 newnode->highy = arc->end[1].nodeinst->highy;
656 }
657
658 /* get the low y */
659 if( arc->end[0].nodeinst->lowy <= arc->end[1].nodeinst->lowy )
660 {
661 newnode->lowy = arc->end[0].nodeinst->lowy;
662 }
663 else
664 {
665 newnode->lowy = arc->end[1].nodeinst->lowy;
666 }
667
668 return newnode;
669 }
670
671 void arc_crossings( ARCINST** arcs, NODEINST** nodes, NODEPROTO* cell )
672 {
673 ARCINST* a1;
674 ARCINST* a2;
675 NODEINST* n1; /* new PL associated with a1 */
676 NODEINST* n2; /* associated new PL for a2 */
677 NODEINST* newnode;
678 ARCINST* newarc1;
679 ARCINST* newarc2;
680 ARCINST* newarc3;
681 ARCINST* newarc4;
682 INTBIG newxpos;
683 INTBIG newypos;
684 BOOLEAN cross_found;
685
686 ARCINST* delete_arc_list = NOARCINST;
687
688
689 for( a1 = *arcs; a1 != NOARCINST; a1 = a1->nextarcinst )
690 {
691 for( a2 = a1->nextarcinst; a2 != NOARCINST; a2 = a2->nextarcinst )
692 {
693 /* check if the arcs are of the same type */
694 if( a1->proto == a2->proto )
695 {
696 cross_found = FALSE;
697
698 /* calculate coords of each, store them like pl nodes for comparison */
699 n1 = arc_to_PL( a1, cell );
700 n2 = arc_to_PL( a2, cell );
701
702
703 /* n1 horizontal, n2 vertical */
704 if( n1->highx > n2->highx &&
705 n1->lowx < n2->lowx &&
706 n2->highy > n1->highy &&
707 n2->lowy < n1->lowy )
708 {
709
710 ttyputmsg(_("overlap condition met"));
711 /* create the new node */
712 newnode = allocnodeinst(cell->lib->cluster);
713
714 newnode->highx = n2->highx;
715 newnode->lowx = n2->lowx;
716 newnode->highy = n1->highy;
717 newnode->lowy = n1->lowy;
718 newnode->transpose = 0;
719 newnode->rotation = 0;
720 newnode->parent = a1->parent;
721 newnode->proto = a1->end[0].nodeinst->proto;
722 cross_found = TRUE;
723 }
724
725
726 /* n1 vertical, n2 horizontal */
727 else if( n2->highx > n1->highx &&
728 n2->lowx < n1->lowx &&
729 n1->highy > n2->highy &&
730 n1->lowy < n2->lowy )
731 {
732 ttyputmsg(_("overlap condition met"));
733
734
735
736 /* create the new node */
737 newnode = allocnodeinst(cell->lib->cluster);
738
739 newnode->highx = n1->highx;
740 newnode->lowx = n1->lowx;
741 newnode->highy = n2->highy;
742 newnode->lowy = n2->lowy;
743 newnode->transpose = 0;
744 newnode->rotation = 0;
745 newnode->parent = a1->parent;
746 newnode->proto = a1->end[0].nodeinst->proto;
747 cross_found = TRUE;
748 } /* if( n1 instersects n2 ) */
749
750 if( cross_found )
751 {
752 /* create 4 new arcs and delete these 2 */
753 newarc1 = allocarcinst(cell->lib->cluster);
754 newarc2 = allocarcinst(cell->lib->cluster);
755 newarc3 = allocarcinst(cell->lib->cluster);
756 newarc4 = allocarcinst(cell->lib->cluster);
757
758
759 /* fill out the new arcs */
760 newxpos = ( newnode->highx + newnode->lowx ) / 2;
761 newypos = ( newnode->highy + newnode->lowy ) / 2;
762
763 newarc1->parent = a1->parent;
764 newarc2->parent = a1->parent;
765 newarc3->parent = a1->parent;
766 newarc4->parent = a1->parent;
767
768 newarc1->proto = a1->proto;
769 newarc2->proto = a1->proto;
770 newarc3->proto = a1->proto;
771 newarc4->proto = a1->proto;
772
773 newarc1->end[0] = a1->end[0];
774 newarc1->end[1].nodeinst = newnode;
775 newarc1->end[1].xpos = newxpos;
776 newarc1->end[1].ypos = newypos;
777
778 newarc2->end[0] = a1->end[1];
779 newarc2->end[1].nodeinst = newnode;
780 newarc2->end[1].xpos = newxpos;
781 newarc2->end[1].ypos = newypos;
782
783 newarc3->end[0] = a2->end[0];
784 newarc3->end[1].nodeinst = newnode;
785 newarc3->end[1].xpos = newxpos;
786 newarc3->end[1].ypos = newypos;
787
788 newarc4->end[0] = a2->end[1];
789 newarc4->end[1].nodeinst = newnode;
790 newarc4->end[1].xpos = newxpos;
791 newarc4->end[1].ypos = newypos;
792
793
794 newarc1->width = newarc1->end[0].nodeinst->highx -
795 newarc1->end[0].nodeinst->lowx;
796 newarc2->width = newarc2->end[0].nodeinst->highx -
797 newarc2->end[0].nodeinst->lowx;
798 newarc3->width = newarc3->end[0].nodeinst->highx -
799 newarc3->end[0].nodeinst->lowx;
800 newarc4->width = newarc4->end[0].nodeinst->highx -
801 newarc4->end[0].nodeinst->lowx;
802
803
804 /* add arcs to the remove list */
805
806 /*add_arc( a1, &delete_arc_list ); */
807 /*add_arc( a2, &delete_arc_list ); */
808
809
810 /* add the new node and the 4 arcs to the beginnings of the lists */
811 newarc1->prevarcinst = NOARCINST;
812 newarc1->nextarcinst = newarc2;
813 newarc2->prevarcinst = newarc1;
814 newarc2->nextarcinst = newarc3;
815 newarc3->prevarcinst = newarc2;
816 newarc3->nextarcinst = newarc4;
817 newarc4->prevarcinst = newarc3;
818 newarc4->nextarcinst = *arcs;
819
820 if( *arcs != NOARCINST )
821 {
822 (*arcs)->prevarcinst = newarc4;
823 }
824
825 *arcs = newarc1;
826
827
828 if( *nodes == NONODEINST )
829 {
830 newnode->prevnodeinst = NONODEINST;
831 newnode->nextnodeinst = NONODEINST;
832 *nodes = newnode;
833 }
834 else
835 {
836 newnode->prevnodeinst = NONODEINST;
837 newnode->nextnodeinst = *nodes;
838 (*nodes)->prevnodeinst = newnode;
839 (*nodes) = newnode;
840 }
841
842
843 cross_found = FALSE;
844 }
845
846
847 } /* if( same proto ) */
848 } /* for a2 */
849 } /* for a1 */
850
851 /* loop through arcs list and remove all the arcs in the delete list */
852 if( delete_arc_list == NOARCINST )
853 {
854 /* should delete arc list here */
855 }
856
857 for( ; delete_arc_list != NOARCINST; delete_arc_list = delete_arc_list->nextarcinst )
858 {
859 /* remove_arc( delete_arc_list, arcs ); */
860 }
861 }
862
863 void make_arc_geom( ARCINST** arcs, NODEPROTO* cell )
864 {
865 GEOM* geom;
866 ARCINST* arcinst;
867
868 for(arcinst = *arcs ; arcinst != NOARCINST; arcinst = arcinst->nextarcinst )
869 {
870 geom = allocgeom(cell->lib->cluster);
871
872 /* find the high x */
873 if( arcinst->end[0].nodeinst->highx > arcinst->end[1].nodeinst->highx )
874 {
875 geom->highx = arcinst->end[0].nodeinst->highx;
876 }
877 else
878 {
879 geom->highx = arcinst->end[1].nodeinst->highx;
880 }
881
882 /* find the low x */
883 if( arcinst->end[0].nodeinst->lowx < arcinst->end[1].nodeinst->lowx )
884 {
885 geom->lowx = arcinst->end[0].nodeinst->lowx;
886 }
887 else
888 {
889 geom->lowx = arcinst->end[1].nodeinst->lowx;
890 }
891
892 /* find the high y */
893 if( arcinst->end[0].nodeinst->highy > arcinst->end[1].nodeinst->highy )
894 {
895 geom->highy = arcinst->end[0].nodeinst->highy;
896 }
897 else
898 {
899 geom->highy = arcinst->end[1].nodeinst->highy;
900 }
901
902 /* find the low y */
903 if( arcinst->end[0].nodeinst->lowy < arcinst->end[1].nodeinst->lowy )
904 {
905 geom->lowy = arcinst->end[0].nodeinst->lowy;
906 }
907 else
908 {
909 geom->lowy = arcinst->end[1].nodeinst->lowy;
910 }
911
912
913 /* store in the arc */
914 arcinst->geom = geom;
915 }
916 }
917
918 void t_crossings( ARCINST** arcs, NODEINST** nodes, NODEPROTO* cell )
919 {
920 ARCINST* looper;
921 ARCINST* comparearc;
922 NODEINST* newnode;
923 ARCINST* newarc1;
924 ARCINST* newarc2;
925 ARCINST* newarc3;
926 INTBIG xpos;
927 INTBIG ypos;
928
929 /* since geometries are null in the arcs currently, create them for all of them */
930 make_arc_geom( arcs, cell );
931
932 /* for each arc, run through every node and see if any are intersecting part of the arcs body */
933 for( comparearc = *arcs; comparearc != NOARCINST; comparearc = comparearc->nextarcinst )
934 {
935 for( looper = *arcs; looper != NOARCINST; looper = looper->nextarcinst )
936 {
937 if( comparearc->proto == looper->proto )
938 {
939 /* check both nodes of looper to see if any lie within comparearc */
940
941 /* check if comparearc is horizontal or vertical */
942 if( ( comparearc->geom->highx - comparearc->geom->lowx ) >
943 ( comparearc->geom->highy - comparearc->geom->lowy ) )
944 {
945 /* comparearc horizontal */
946
947
948 if( ( looper->end[0].nodeinst->highy < comparearc->geom->highy ) &&
949 ( looper->end[0].nodeinst->lowy > comparearc->geom->lowy ) )
950 {
951 newnode = allocnodeinst(cell->lib->cluster);
952 newarc1 = allocarcinst(cell->lib->cluster);
953 newarc2 = allocarcinst(cell->lib->cluster);
954 newarc3 = allocarcinst(cell->lib->cluster);
955
956 newnode->highx = looper->geom->highx;
957 newnode->lowx = looper->geom->lowx;
958 newnode->highy = comparearc->geom->highy;
959 newnode->lowy = comparearc->geom->lowy;
960
961 xpos = ( newnode->highx + newnode->lowx ) / 2;
962 ypos = ( newnode->highy + newnode->lowy ) / 2;
963
964 /* connect up new arcs */
965 newarc1->end[0] = comparearc->end[0];
966 newarc1->end[1].nodeinst = newnode;
967 newarc1->end[1].xpos = xpos;
968 newarc1->end[1].ypos = ypos;
969 newarc2->end[0] = comparearc->end[1];
970 newarc2->end[1].nodeinst = newnode;
971 newarc2->end[1].xpos = xpos;
972 newarc2->end[1].ypos = ypos;
973 newarc3->end[0] = looper->end[1];
974 newarc3->end[1].nodeinst = newnode;
975 newarc3->end[1].xpos = xpos;
976 newarc3->end[1].ypos = ypos;
977
978
979 /* add to the current lists */
980 add_node( newnode, nodes );
981 add_arc( newarc1, arcs );
982 add_arc( newarc2, arcs );
983 add_arc( newarc3, arcs );
984 }
985
986 else if( ( looper->end[1].nodeinst->highy < comparearc->geom->highy ) &&
987 ( looper->end[1].nodeinst->lowy > comparearc->geom->lowy ) )
988 {
989 newnode = allocnodeinst(cell->lib->cluster);
990 newarc1 = allocarcinst(cell->lib->cluster);
991 newarc2 = allocarcinst(cell->lib->cluster);
992 newarc3 = allocarcinst(cell->lib->cluster);
993
994 newnode->highx = looper->geom->highx;
995 newnode->lowx = looper->geom->lowx;
996 newnode->highy = comparearc->geom->highy;
997 newnode->lowy = looper->geom->lowy;
998
999 xpos = ( newnode->highx + newnode->lowx ) / 2;
1000 ypos = ( newnode->highy + newnode->lowy ) / 2;
1001
1002 /* connect up new arcs */
1003 newarc1->end[0] = comparearc->end[0];
1004 newarc1->end[1].nodeinst = newnode;
1005 newarc1->end[1].xpos = xpos;
1006 newarc1->end[1].ypos = ypos;
1007 newarc2->end[0] = comparearc->end[1];
1008 newarc2->end[1].nodeinst = newnode;
1009 newarc2->end[1].xpos = xpos;
1010 newarc2->end[1].ypos = ypos;
1011 newarc3->end[0] = looper->end[1];
1012 newarc3->end[1].nodeinst = newnode;
1013 newarc3->end[1].xpos = xpos;
1014 newarc3->end[1].ypos = ypos;
1015
1016
1017 /* add to the current lists */
1018 add_node( newnode, nodes );
1019 add_arc( newarc1, arcs );
1020 add_arc( newarc2, arcs );
1021 add_arc( newarc3, arcs );
1022 }
1023 }
1024 else
1025 {
1026 /* comparearc vertical */
1027 if( ( looper->end[0].nodeinst->highx < comparearc->geom->highx ) &&
1028 ( looper->end[0].nodeinst->lowx > comparearc->geom->lowx ) )
1029 {
1030 newnode = allocnodeinst(cell->lib->cluster);
1031 newarc1 = allocarcinst(cell->lib->cluster);
1032 newarc2 = allocarcinst(cell->lib->cluster);
1033 newarc3 = allocarcinst(cell->lib->cluster);
1034
1035 newnode->highx = comparearc->geom->highx;
1036 newnode->lowx = comparearc->geom->lowx;
1037 newnode->highy = looper->geom->highy;
1038 newnode->lowy = looper->geom->lowy;
1039
1040 xpos = ( newnode->highx + newnode->lowx ) / 2;
1041 ypos = ( newnode->highy + newnode->lowy ) / 2;
1042
1043 /* connect up new arcs */
1044 newarc1->end[0] = comparearc->end[0];
1045 newarc1->end[1].nodeinst = newnode;
1046 newarc1->end[1].xpos = xpos;
1047 newarc1->end[1].ypos = ypos;
1048 newarc2->end[0] = comparearc->end[1];
1049 newarc2->end[1].nodeinst = newnode;
1050 newarc2->end[1].xpos = xpos;
1051 newarc2->end[1].ypos = ypos;
1052 newarc3->end[0] = looper->end[1];
1053 newarc3->end[1].nodeinst = newnode;
1054 newarc3->end[1].xpos = xpos;
1055 newarc3->end[1].ypos = ypos;
1056
1057 /* add to the current lists */
1058 add_node( newnode, nodes );
1059 add_arc( newarc1, arcs );
1060 add_arc( newarc2, arcs );
1061 add_arc( newarc3, arcs );
1062 }
1063
1064 else if( ( looper->end[1].nodeinst->highx < comparearc->geom->highx ) &&
1065 ( looper->end[1].nodeinst->lowx > comparearc->geom->lowx ) )
1066 {
1067 newnode = allocnodeinst(cell->lib->cluster);
1068 newarc1 = allocarcinst(cell->lib->cluster);
1069 newarc2 = allocarcinst(cell->lib->cluster);
1070 newarc3 = allocarcinst(cell->lib->cluster);
1071
1072 newnode->highx = comparearc->geom->highx;
1073 newnode->lowx = comparearc->geom->lowx;
1074 newnode->highy = looper->geom->highy;
1075 newnode->lowy = looper->geom->lowy;
1076
1077 xpos = ( newnode->highx + newnode->lowx ) / 2;
1078 ypos = ( newnode->highy + newnode->lowy ) / 2;
1079
1080 /* connect up new arcs */
1081 newarc1->end[0] = comparearc->end[0];
1082 newarc1->end[1].nodeinst = newnode;
1083 newarc1->end[1].xpos = xpos;
1084 newarc1->end[1].ypos = ypos;
1085 newarc2->end[0] = comparearc->end[1];
1086 newarc2->end[1].nodeinst = newnode;
1087 newarc2->end[1].xpos = xpos;
1088 newarc2->end[1].ypos = ypos;
1089 newarc3->end[0] = looper->end[1];
1090 newarc3->end[1].nodeinst = newnode;
1091 newarc3->end[1].xpos = xpos;
1092 newarc3->end[1].ypos = ypos;
1093
1094 /* add to the current lists */
1095 add_node( newnode, nodes );
1096 add_arc( newarc1, arcs );
1097 add_arc( newarc2, arcs );
1098 add_arc( newarc3, arcs );
1099 }
1100 }
1101 } /* same tech */
1102 } /* for looping nodes */
1103 } /* looping arcs */
1104 }
1105
1106 void remove_arc( ARCINST* arc, ARCINST** list )
1107 {
1108 ARCINST* looper;
1109 looper = *list;
1110
1111 for( ; looper != NOARCINST; looper = looper->nextarcinst )
1112 {
1113 ttyputmsg(_("in the for loop"));
1114
1115 if( arc == looper )
1116 {
1117 /* case 1: list has only one member */
1118 if( looper->prevarcinst == NOARCINST &&
1119 looper->nextarcinst == NOARCINST )
1120 {
1121 *list = NOARCINST;
1122 }
1123
1124 /* case 2: node is at the beginning of the list */
1125 if( looper->prevarcinst == NOARCINST )
1126 {
1127 looper->nextarcinst->prevarcinst = NOARCINST;
1128 *list = looper->nextarcinst;
1129 }
1130
1131 /* case 3: node is at the end of the list */
1132 else if( looper->nextarcinst == NOARCINST )
1133 {
1134 looper->prevarcinst->nextarcinst = NOARCINST;
1135 }
1136
1137 /* case 4: node is in the middle of the list */
1138 else
1139 {
1140 looper->prevarcinst->nextarcinst =
1141 looper->nextarcinst;
1142 looper->nextarcinst->prevarcinst =
1143 looper->prevarcinst;
1144 }
1145 return;
1146 }
1147 }
1148 }
1149
1150 #endif
1151
1152 /********************************** SUPPORT **********************************/
1153
add_arc(ARCINST * arc,ARCINST ** list)1154 void add_arc( ARCINST* arc, ARCINST** list )
1155 {
1156 arc->nextarcinst = *list;
1157 *list = arc;
1158 }
1159
1160
add_node(NODEINST * node,NODEINST ** list)1161 void add_node( NODEINST* node, NODEINST** list )
1162 {
1163 node->nextnodeinst = *list;
1164 *list = node;
1165 }
1166
1167
remove_node(NODEINST * node,NODEINST ** list,INTBIG * count)1168 void remove_node( NODEINST* node, NODEINST** list, INTBIG *count)
1169 {
1170 INTBIG i, j;
1171
1172 for(i=0; i < *count; i++)
1173 if (list[i] == node) break;
1174 if (i < *count)
1175 {
1176 (*count)--;
1177 for(j=i; j < *count; j++) list[j] = list[j+1];
1178 startobjectchange((INTBIG)node, VNODEINST);
1179 (void)killnodeinst(node);
1180 }
1181 }
1182
1183
contains_node(NODEINST * outside,NODEINST * inside)1184 BOOLEAN contains_node( NODEINST* outside, NODEINST* inside )
1185 {
1186 if (outside->highx > inside->highx &&
1187 outside->lowx < inside->lowx &&
1188 outside->lowy < inside->lowy &&
1189 outside->highy > inside->highy )
1190 {
1191 return (TRUE);
1192 }
1193 return (FALSE);
1194 }
1195