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