1 /*--------------------------------------------------------------*/
2 /*  antenna.c -- Compute the metal area to gate area for all	*/
3 /*  routes and determine where antenna violations occur.  Then,	*/
4 /*  resolve the violations by routing from each violation to an	*/
5 /*  antenna tap.						*/
6 /*								*/
7 /*  To be done:  If there are no antenna cells placed, or if	*/
8 /*  the antenna route fails, or if the antenna violation is	*/
9 /*  close to the limit, see if the route can be adjusted by	*/
10 /*  moving the route to a higher layer near the gate.		*/
11 /*--------------------------------------------------------------*/
12 /* Written by Tim Edwards, May 2018                           	*/
13 /*--------------------------------------------------------------*/
14 
15 #include <ctype.h>
16 #include <stdio.h>
17 #include <math.h>
18 #include <stdarg.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <regex.h>
24 #include <assert.h>
25 
26 /* This entire file is dependent on the Tcl/Tk version */
27 #ifdef TCL_QROUTER
28 #include <tk.h>
29 
30 #include "qrouter.h"
31 #include "qconfig.h"
32 #include "mask.h"
33 #include "maze.h"
34 #include "node.h"
35 #include "lef.h"
36 #include "def.h"
37 #include "point.h"
38 
39 /* Node Hash Table routines taken from delay.c */
40 extern GATE FindGateNode(Tcl_HashTable *, NODE, int *);
41 extern void FreeNodeTable(Tcl_HashTable *);
42 
43 extern int TotalRoutes;
44 
45 /* Structure to hold information about an antenna error. */
46 
47 typedef struct antennainfo_  *ANTENNAINFO;
48 
49 struct antennainfo_ {
50    ANTENNAINFO next;	/* Next antenna violation in the list.	*/
51    NET net;		/* The net violating an antenna rule	*/
52    NODE node;		/* A gate-end node that is in violation */
53    ROUTE route;		/* A route that is part of the antenna	*/
54    int layer;		/* Uppermost metal layer of the antenna */
55 };
56 
57 /* Keep the list as a global variable so it can be accessed	*/
58 /* from doroute() (in qrouter.c)				*/
59 
60 ANTENNAINFO AntennaList;
61 
62 typedef struct annotateinfo_  *ANNOTATEINFO;
63 
64 struct annotateinfo_ {
65     ANNOTATEINFO next;
66     NET net;
67     char *instance;
68     char *pin;
69     int flag;		/* Flag for checking output status	*/
70 };
71 
72 ANNOTATEINFO AnnotateList = NULL;
73 
74 #define ANNO_INIT 0
75 #define ANNO_OUTPUT 1
76 
77 /*----------------------------------------------------------------------*/
78 /* Report connection of a fixed antenna violation, given the net.	*/
79 /*----------------------------------------------------------------------*/
80 
get_annotate_info(NET net,char ** pinptr)81 char *get_annotate_info(NET net, char **pinptr)
82 {
83     ANNOTATEINFO annotate;
84 
85     for (annotate = AnnotateList; annotate; annotate = annotate->next) {
86 	if (annotate->net->netnum == net->netnum) {
87 	    if (annotate->flag == ANNO_INIT) {
88 		annotate->flag = ANNO_OUTPUT;	    /* Mark as having been output */
89 		*pinptr = annotate->pin;
90 		return annotate->instance;
91 	    }
92 	}
93     }
94     *pinptr = NULL;
95     return NULL;
96 }
97 
98 /*--------------------------------------------------------------*/
99 /* Regular expression matching of the given string in		*/
100 /* "antennacell" to the string "strtest".  If the regular	*/
101 /* expression matches and the result is in the first character	*/
102 /* position of the string, then return TRUE (match), otherwise	*/
103 /* return FALSE (no match).					*/
104 /*--------------------------------------------------------------*/
105 
106 u_char
string_match(char * antennacell,char * strtest)107 string_match(char *antennacell, char *strtest)
108 {
109     regex_t regex;
110     regmatch_t pmatch;
111     int reti;
112 
113     /* Compile regular expression */
114     reti = regcomp(&regex, antennacell, 0);
115     if (reti) {
116 	/* Assume this is not a regular expression and just run */
117 	/* a straight string match.				*/
118 	if (!strcasecmp(antennacell, strtest))
119 	    return TRUE;
120 	else
121 	    return FALSE;
122     }
123 
124     /* Execute regular expression */
125     reti = regexec(&regex, strtest, 1, &pmatch, 0);
126     regfree(&regex);
127 
128     if (!reti) {
129 	if (pmatch.rm_so == 0)	/* Must match beginning of string */
130 	    return TRUE;
131 	else
132 	    return FALSE;
133     }
134     else
135 	return FALSE;
136 }
137 
138 /*--------------------------------------------------------------*/
139 /* Find free antenna cells, and collect all the antenna taps	*/
140 /* into a single net, much like VDD_NET or GND_NET.		*/
141 /*								*/
142 /* Return the number of free antenna taps available in the	*/
143 /* layout.							*/
144 /*								*/
145 /* If the name of the antennacell ends in '*', then assume a	*/
146 /* wildcard character and match to any string beginning with 	*/
147 /* the substring of antennacell.				*/
148 /*--------------------------------------------------------------*/
149 
150 void
find_free_antenna_taps(char * antennacell)151 find_free_antenna_taps(char *antennacell)
152 {
153     int numtaps;
154     GATE ginst;
155     GATE gateginfo;
156     NODE noderec;
157     int netnum, i;
158 
159     if (antennacell == NULL) {
160 	Fprintf(stderr, "No antenna cell defined!\n");
161 	return;
162     }
163     numtaps = 0;
164     for (ginst = Nlgates; ginst; ginst = ginst->next) {
165 	gateginfo = ginst->gatetype;
166 
167 	if (string_match(antennacell, gateginfo->gatename)) {
168 	    /* Find an unassigned node.  If there is not one,	*/
169 	    /* this is probably a routed (not free) cell.	*/
170 	    for (i = 0; i < ginst->nodes; i++) {
171 		netnum = ginst->netnum[i];
172 		noderec = ginst->noderec[i];
173 		if ((netnum == 0) && (noderec == NULL)) {
174 		    ginst->netnum[i] = ANTENNA_NET;
175 		    ginst->noderec[i] = (NODE)calloc(1, sizeof(struct node_));
176 		    ginst->noderec[i]->netnum = ANTENNA_NET;
177 		}
178 	    }
179 	}
180     }
181 }
182 
183 /*--------------------------------------------------------------*/
184 /* Similar to the routine above, but just count the free taps.	*/
185 /*--------------------------------------------------------------*/
186 
187 int
count_free_antenna_taps(char * antennacell)188 count_free_antenna_taps(char *antennacell)
189 {
190     int numtaps;
191     GATE ginst;
192     GATE gateginfo;
193     int netnum, i;
194 
195     numtaps = 0;
196     for (ginst = Nlgates; ginst; ginst = ginst->next) {
197 	gateginfo = ginst->gatetype;
198 
199 	if (string_match(antennacell, gateginfo->gatename)) {
200 	    /* Find an unassigned node.  If there is not one,	*/
201 	    /* this is probably a routed (not free) cell.	*/
202 	    for (i = 0; i < ginst->nodes; i++) {
203 		netnum = ginst->netnum[i];
204 		if (netnum == ANTENNA_NET)
205 		    numtaps++;
206 	    }
207 	}
208     }
209     return numtaps;
210 }
211 
212 /*--------------------------------------------------------------*/
213 /* After routing, the free antenna taps are all marked with the	*/
214 /* net number of the net just routed.  To make them free again,	*/
215 /* change all but the one that was routed back to ANTENNA_NET.	*/
216 /* Identify the unused taps by finding the OBSVAL record with	*/
217 /* net set to netnum but not connected to the same node.	*/
218 /*--------------------------------------------------------------*/
219 
revert_antenna_taps(int netnum,NODE node)220 void revert_antenna_taps(int netnum, NODE node)
221 {
222     int x, y, lay;
223     PROUTE *Pr;
224     NODEINFO lnode = NULL;
225 
226     /* Clear all targets except for the one just routed */
227 
228     for (lay = 0; lay < Num_layers; lay++)
229 	for (x = 0; x < NumChannelsX; x++)
230 	    for (y = 0; y < NumChannelsY; y++)
231 		if ((OBSVAL(x, y, lay) & NETNUM_MASK) == netnum) {
232 		    Pr = &OBS2VAL(x, y, lay);
233 		    if (Pr->flags & PR_TARGET) {
234 			lnode = NODEIPTR(x, y, lay);
235 			if ((lnode == NULL) || (lnode->nodesav != node)) {
236 			    OBSVAL(x, y, lay) &= ~(NETNUM_MASK | ROUTED_NET);
237 			    OBSVAL(x, y, lay) |= ANTENNA_NET;
238 			}
239 		    }
240 		}
241 }
242 
243 /*--------------------------------------------------------------*/
244 /* States to track nodes as they are processed:			*/
245 /*								*/
246 /*	NOT_VISITED :  Node has not yet been processed.		*/
247 /*	VISITED :  Node was counted on this pass.		*/
248 /*	PROCESSED :  Node was counted on a previous pass.	*/
249 /*	ANCHOR :  Node is a source/drain connection.		*/
250 /*--------------------------------------------------------------*/
251 
252 enum visit_states {NOT_VISITED = 0, VISITED, PROCESSED, ANCHOR};
253 
254 /* Forward declarations */
255 float get_route_area_reverse(NET, ROUTE, int, u_char *, u_char,
256 		Tcl_HashTable *, struct routeinfo_ *);
257 float get_route_area_forward(NET, ROUTE, int, u_char *, u_char,
258 		Tcl_HashTable *, struct routeinfo_ *);
259 float get_route_area_reverse_fromseg(NET, ROUTE, SEG, int, u_char *, u_char,
260 		Tcl_HashTable *, struct routeinfo_ *);
261 
262 /*--------------------------------------------------------------*/
263 /* Determine the amount of metal in the route, starting at the	*/
264 /* route start point, and not moving past any point that is 	*/
265 /* above "layer".  Check all other unvisited routes in net to	*/
266 /* see if any connect to "rt".  If so, check if they connect	*/
267 /* to a point that is part of the subnet below or at "layer".	*/
268 /* If they do, recursively run get_route_area_forward on that	*/
269 /* route.  When done, return the total area of the subnet.	*/
270 /*--------------------------------------------------------------*/
271 
272 float
get_route_area_forward_fromseg(NET net,ROUTE rt,SEG nseg,int layer,u_char * visited,u_char method,Tcl_HashTable * NodeTable,struct routeinfo_ * iroute)273 get_route_area_forward_fromseg(NET net, ROUTE rt, SEG nseg, int layer,
274 		u_char *visited, u_char method, Tcl_HashTable *NodeTable,
275 		struct routeinfo_ *iroute)
276 {
277     float area, length, width, thick;
278     int x, y, l, compat;
279     SEG seg, iseg, chkseg;
280     ROUTE rt2;
281     u_char found;
282 
283     if (rt->flags & RT_VISITED) return 0.0;
284     rt->flags |= RT_VISITED;
285     area = 0.0;
286 
287     /* If nseg is NULL then check from the beginning. */
288     if (nseg == NULL) nseg = rt->segments;
289 
290     /* Check if the route beginning is a node */
291     if (nseg == rt->segments) {
292 	if (rt->flags & RT_START_NODE) {
293 	    NODE node;
294 	    GATE g;
295 	    int i;
296 
297 	    node = rt->start.node;
298 
299 	    if (visited) {
300 
301 		/* If more than one route is connected to the node,	*/
302 		/* then this node may have been visited already.	*/
303 
304 		if (visited[node->nodenum] == NOT_VISITED) {
305 		    g = FindGateNode(NodeTable, node, &i);
306 		    if (g->area[i] == 0.0) {
307 			/* There's a diffusion diode here! */
308 			visited[node->nodenum] = ANCHOR;
309 			return 0.0;
310 		    } else {
311 			/* Add this node to the list of nodes with gates	*/
312 			/* attached to this antenna area.			*/
313 			visited[node->nodenum] = VISITED;
314 		    }
315 		}
316 	    }
317 	    else if ((method == ANTENNA_ROUTE) && (iroute != NULL)) {
318 		set_node_to_net(node, PR_SOURCE, &iroute->glist[0], &iroute->bbox, 0);
319 	    }
320 
321 	    /* Walk all other routes that start or end on this node */
322 
323 	    for (rt2 = net->routes; rt2; rt2 = rt2->next) {
324 		if (rt2->flags & RT_VISITED) continue;
325 
326 		if ((rt2->flags & RT_START_NODE) && (rt2->start.node == node)) {
327 		    /* The start point of rt2 connects to the same node */
328 		    area += get_route_area_forward(net, rt2, layer, visited,
329 				method, NodeTable, NULL);
330 		}
331 		else if ((rt2->flags & RT_END_NODE) && (rt2->end.node == node)) {
332 		    /* The end point of rt2 connects to the same node */
333 		    for (iseg = rt2->segments; iseg && iseg->next; iseg = iseg->next);
334 		    area += get_route_area_reverse(net, rt2, layer, visited,
335 				method, NodeTable, NULL);
336 		}
337 	    }
338 	}
339     }
340 
341     for (seg = rt->segments; seg && (seg != nseg); seg = seg->next);
342     if (seg == NULL) return 0.0;
343 
344     for (; seg; seg = seg->next) {
345 
346 	/* Once the layer goes above the current check layer, the search stops. */
347 	if (method != ANTENNA_DISABLE)
348 	    if (seg->layer > layer) break;
349 
350 	/* Vias don't contribute to area, at least for now. */
351 	if (seg->segtype & ST_VIA) continue;
352 
353 	/* For non-cumulative methods, only count area for	*/
354 	/* those segments which are on the given check layer.	*/
355 
356 	if ((method == CALC_AREA) || (method == CALC_SIDEAREA))
357 	    if (seg->layer != layer)
358 		continue;
359 
360 	/* method ANTENNA_ROUTE indicates that this routine was	*/
361 	/* called as part of antenna routing.  So set up this	*/
362 	/* part of the route in a manner similar to the		*/
363 	/* set_route_to_net() routine.				*/
364 
365 	if ((method == ANTENNA_ROUTE) && (iroute != NULL)) {
366 	    PROUTE *Pr;
367 	    POINT gpoint;
368 
369 	    l = seg->layer;
370 	    x = seg->x1;
371 	    y = seg->y1;
372 	    while (1) {
373 		Pr = &OBS2VAL(x, y, l);
374 		Pr->flags = PR_SOURCE;
375 		Pr->prdata.cost = 0;
376 
377 		if (~(Pr->flags & PR_ON_STACK)) {
378 		    Pr->flags |= PR_ON_STACK;
379 		    gpoint = allocPOINT();
380 		    gpoint->x1 = x;
381 		    gpoint->y1 = y;
382 		    gpoint->layer = l;
383 		    gpoint->next = iroute->glist[0];
384 		    iroute->glist[0] = gpoint;
385 		}
386 
387 		if (x < iroute->bbox.x1) iroute->bbox.x1 = x;
388 		if (x > iroute->bbox.x2) iroute->bbox.x2 = x;
389 		if (y < iroute->bbox.y1) iroute->bbox.y1 = y;
390 		if (y > iroute->bbox.y2) iroute->bbox.y2 = y;
391 
392 		// Move to next grid position in the segment
393 		if (x == seg->x2 && y == seg->y2) break;
394 		if (seg->x2 > seg->x1) x++;
395 		else if (seg->x2 < seg->x1) x--;
396 		if (seg->y2 > seg->y1) y++;
397 		else if (seg->y2 < seg->y1) y--;
398 	    }
399 	}
400 	else if (method == ANTENNA_DISABLE) {
401 	    PROUTE *Pr;
402 
403 	    l = seg->layer;
404 	    x = seg->x1;
405 	    y = seg->y1;
406 	    while (1) {
407 		Pr = &OBS2VAL(x, y, l);
408 		Pr->prdata.net = MAXNETNUM;
409 		Pr->flags &= ~(PR_SOURCE | PR_TARGET | PR_COST);
410 
411 		// Move to next grid position in the segment
412 		if (x == seg->x2 && y == seg->y2) break;
413 		if (seg->x2 > seg->x1) x++;
414 		else if (seg->x2 < seg->x1) x--;
415 		if (seg->y2 > seg->y1) y++;
416 		else if (seg->y2 < seg->y1) y--;
417 	    }
418 	}
419 	if ((method != ANTENNA_ROUTE) && (method != ANTENNA_DISABLE)) {
420 
421 	    /* Note that one of x or y is zero, depending on segment orientation */
422 	    x = (seg->x2 - seg->x1);
423 	    y = (seg->y2 - seg->y1);
424 	    if (x < 0) x = -x;
425 	    if (y < 0) y = -y;
426 
427 	    /* Note that "l" is a unitless grid dimension */
428 	    if (x == 0)
429 		length = (float)y * (float)PitchY;
430 	    else
431 		length = (float)x * (float)PitchX;
432 
433 	    /* area is either the total top surface of the metal, */
434 	    /* or the total side surface of the metal (in um^2)	  */
435 
436 	    width = LefGetRouteWidth(seg->layer);
437 	    if ((method == CALC_AREA) || (method == CALC_AGG_AREA))
438 		area += (float)(length * width);
439 	    else if ((method == CALC_SIDEAREA) || (method == CALC_AGG_SIDEAREA)) {
440 		thick = LefGetRouteThickness(seg->layer);
441 		area += thick * 2.0 * (length + width);
442 	    }
443 	}
444     }
445 
446     /* Check other routes for intersection with this route */
447 
448     for (rt2 = net->routes; rt2; rt2 = rt2->next) {
449 	if (rt2->flags & RT_VISITED) continue;
450 
451 	if (!(rt2->flags & RT_START_NODE) && (rt2->start.route == rt)) {
452 	    /* The start point of rt2 connects somewhere on rt */
453 	    iseg = rt2->segments;
454 	    x = iseg->x1;
455 	    y = iseg->y1;
456 	    l = iseg->layer;
457 	    if (l > layer) continue;
458 	}
459 	else if (!(rt2->flags & RT_END_NODE) && (rt2->end.route == rt)) {
460 	    /* The end point of rt2 connects somewhere on rt */
461 	    for (iseg = rt2->segments; iseg && iseg->next; iseg = iseg->next);
462 	    x = iseg->x2;
463 	    y = iseg->y2;
464 	    l = iseg->layer;
465 	    if (l > layer) continue;
466 	}
467 	else
468 	    continue;
469 
470 	/* Must determine if rt2 intersects rt within the antenna area */
471 
472 	found = (u_char)0;
473 	for (chkseg = rt->segments; chkseg && chkseg != seg; chkseg = chkseg->next) {
474 	    if (chkseg->segtype & ST_WIRE) {
475 		if (iseg->segtype & ST_WIRE) {
476 		    compat = (l == chkseg->layer);
477 		}
478 		else {
479 		    compat = (l == chkseg->layer) || (l + 1 == chkseg->layer);
480 		}
481 	    }
482 	    else {
483 		if (iseg->segtype & ST_WIRE) {
484 		    compat = (l == chkseg->layer) || (l == chkseg->layer + 1);
485 		}
486 		else {
487 		    compat = (l == chkseg->layer) || (l == chkseg->layer + 1) ||
488 				(l + 1 == chkseg->layer);
489 		}
490 	    }
491 	    if (!compat) continue;
492 
493 	    if (chkseg->segtype & ST_VIA) {
494 		if ((chkseg->x1 == x) && (chkseg->y1 == y)) {
495 		    found = (u_char)1;
496 		    break;
497 		}
498 	    }
499 	    else if (chkseg->x1 < chkseg->x2) {
500 		if (chkseg->y1 == y) {
501 		    if ((chkseg->x1 <= x) && (chkseg->x2 >= x)) {
502 			found = (u_char)1;
503 			break;
504 		    }
505 		}
506 	    }
507 	    else if (chkseg->x1 > chkseg->x2) {
508 		if (chkseg->y1 == y) {
509 		    if ((chkseg->x1 >= x) && (chkseg->x2 <= x)) {
510 			found = (u_char)1;
511 			break;
512 		    }
513 		}
514 	    }
515 	    else if (chkseg->y1 < chkseg->y2) {
516 		if (chkseg->x1 == x) {
517 		    if ((chkseg->y1 <= y) && (chkseg->y2 >= y)) {
518 			found = (u_char)1;
519 			break;
520 		    }
521 		}
522 	    }
523 	    else if (chkseg->y1 > chkseg->y2) {
524 		if (chkseg->x1 == x) {
525 		    if ((chkseg->y1 >= y) && (chkseg->y2 <= y)) {
526 			found = (u_char)1;
527 			break;
528 		    }
529 		}
530 	    }
531 	}
532 	if (found == (u_char)1) {
533 	    if (rt2->start.route == rt)
534 		area += get_route_area_forward(net, rt2, layer, visited,
535 				method, NodeTable, iroute);
536 	    else
537 		area += get_route_area_reverse(net, rt2, layer, visited,
538 				method, NodeTable, iroute);
539 	}
540     }
541 
542     /* The end of this route may be a node (so record it in visited) or	*/
543     /* a route (so walk it).						*/
544 
545     if (seg == NULL) {	/* If seg != NULL then we didn't reach the route end */
546 	if (rt->flags & RT_END_NODE) {
547 	    NODE node;
548 	    GATE g;
549 	    int i;
550 
551 	    node = rt->end.node;
552 
553 	    /* Walk all other routes that start or end on this node */
554 
555 	    for (rt2 = net->routes; rt2; rt2 = rt2->next) {
556 		if (rt2->flags & RT_VISITED) continue;
557 
558 		if ((rt2->flags & RT_START_NODE) && (rt2->start.node == node)) {
559 		    /* The start point of rt2 connects to the same node */
560 		    area += get_route_area_forward(net, rt2, layer, visited,
561 				method, NodeTable, NULL);
562 		}
563 		else if ((rt2->flags & RT_END_NODE) && (rt2->end.node == node)) {
564 		    /* The end point of rt2 connects to the same node */
565 		    for (iseg = rt2->segments; iseg && iseg->next; iseg = iseg->next);
566 		    area += get_route_area_reverse(net, rt2, layer, visited,
567 				method, NodeTable, NULL);
568 		}
569 	    }
570 
571 	    g = FindGateNode(NodeTable, node, &i);
572 	    if (g == NULL) {
573 		/* This should not happen */
574 	 	Fprintf(stderr, "Error: net %s route end marked as node, but"
575 			" no node found!\n", net->netname);
576 		return 0.0;
577 	    }
578 	    if (g->area[i] == 0.0) {
579 		/* There's a diffusion diode here! */
580 		if (visited) visited[node->nodenum] = ANCHOR;
581 		return 0.0;
582 	    } else {
583 		/* Add this node to the list of nodes with gates	*/
584 		/* attached to this antenna area.			*/
585 		if (visited) visited[node->nodenum] = VISITED;
586 	    }
587 	    if ((method == ANTENNA_ROUTE) && (iroute != NULL)) {
588 		set_node_to_net(node, PR_SOURCE, &iroute->glist[0], &iroute->bbox, 0);
589 	    }
590 	}
591 	else {
592 	    SEG rseg;
593 
594 	    /* Back up seg to point to the last segment of the route */
595 	    for (seg = rt->segments; seg && seg->next; seg = seg->next);
596 	    x = seg->x2;
597 	    y = seg->y2;
598 	    l = seg->layer;
599 
600 	    /* Find where on rt2 the segment lands, then search rt2 for	*/
601 	    /* antenna area forward and reverse from that segment.	*/
602 
603 	    rt2 = rt->end.route;
604             assert( rt2 != NULL ) ;
605 
606 	    for (rseg = rt2->segments; rseg; rseg = rseg->next) {
607 		if (rseg->segtype & ST_WIRE) {
608 		    if (seg->segtype & ST_WIRE) {
609 			compat = (l == rseg->layer);
610 		    }
611 		    else {
612 			compat = (l == rseg->layer) || (l + 1 == rseg->layer);
613 		    }
614 		}
615 		else {
616 		    if (seg->segtype & ST_WIRE) {
617 			compat = (l == rseg->layer) || (l == rseg->layer + 1);
618 		    }
619 		    else {
620 			compat = (l == rseg->layer) || (l == rseg->layer + 1) ||
621 				(l + 1 == rseg->layer);
622 		    }
623 		}
624 		if (compat) {
625 		    if (rseg->segtype & ST_VIA) {
626 			if ((rseg->x2 == seg->x2) && (rseg->y2 == seg->y2))
627 			    break;
628 		    }
629 		    else if (rseg->x1 < rseg->x2) {
630 			if (rseg->y2 == seg->y2) {
631 			    if ((rseg->x1 <= seg->x2) && (rseg->x2 >= seg->x2))
632 				break;
633 			}
634 		    }
635 		    else if (rseg->x1 > rseg->x2) {
636 			if (rseg->y2 == seg->y2) {
637 			    if ((rseg->x1 >= seg->x2) && (rseg->x2 <= seg->x2))
638 				break;
639 			}
640 		    }
641 		    else if (rseg->y1 < rseg->y2) {
642 			if (rseg->x2 == seg->x2) {
643 			    if ((rseg->y1 <= seg->y2) && (rseg->y2 >= seg->y2))
644 				break;
645 			}
646 		    }
647 		    else if (rseg->y1 > rseg->y2) {
648 			if (rseg->x2 == seg->x2) {
649 			    if ((rseg->y1 >= seg->y2) && (rseg->y2 <= seg->y2))
650 				break;
651 			}
652 		    }
653 		}
654 	    }
655             assert( rseg != NULL ) ;
656 
657 	    if (rseg->next != NULL)
658 	        area += get_route_area_forward_fromseg(net, rt2, rseg->next,
659 			layer, visited, method, NodeTable, iroute);
660 	    area += get_route_area_reverse_fromseg(net, rt2, rseg, layer,
661 			visited, method, NodeTable, iroute);
662 	}
663     }
664     return area;
665 }
666 
667 /*--------------------------------------------------------------*/
668 /* Check route antenna forward from the beginning of the route.	*/
669 /*--------------------------------------------------------------*/
670 
671 float
get_route_area_forward(NET net,ROUTE rt,int layer,u_char * visited,u_char method,Tcl_HashTable * NodeTable,struct routeinfo_ * iroute)672 get_route_area_forward(NET net, ROUTE rt, int layer, u_char *visited,
673 	u_char method, Tcl_HashTable *NodeTable, struct routeinfo_ *iroute)
674 {
675     float area;
676 
677     area = get_route_area_forward_fromseg(net, rt, NULL, layer, visited,
678 		method, NodeTable, iroute);
679     return area;
680 }
681 
682 /*--------------------------------------------------------------*/
683 /* This is the same as get_route_area_forward_fromseg, but is	*/
684 /* searching the path from end to beginning, so reverse the	*/
685 /* route first and then call get_route_area_forward_fromseg().	*/
686 /*--------------------------------------------------------------*/
687 
688 float
get_route_area_reverse_fromseg(NET net,ROUTE rt,SEG nseg,int layer,u_char * visited,u_char method,Tcl_HashTable * NodeTable,struct routeinfo_ * iroute)689 get_route_area_reverse_fromseg(NET net, ROUTE rt, SEG nseg, int layer,
690 	u_char *visited, u_char method, Tcl_HashTable *NodeTable,
691 	struct routeinfo_ *iroute)
692 {
693     SEG seg, dseg, newseg, firstseg, saveseg;
694     NODE savestartnode, saveendnode;
695     float area;
696     u_char saveflags;
697 
698     firstseg = NULL;
699 
700     /* Reverse the route */
701     for (seg = rt->segments; seg; seg = seg->next) {
702 	newseg = (SEG)malloc(sizeof(struct seg_));
703 	newseg->layer = seg->layer;
704 	newseg->x1 = seg->x2;
705 	newseg->x2 = seg->x1;
706 	newseg->y1 = seg->y2;
707 	newseg->y2 = seg->y1;
708 	newseg->segtype = seg->segtype;
709 	newseg->next = firstseg;
710 	firstseg = newseg;
711     }
712 
713     saveseg = rt->segments;
714 
715     /* Replace the route segment with the reversed route */
716     rt->segments = firstseg;
717 
718     /* Reverse the endpoint information */
719     savestartnode = rt->start.node;
720     saveendnode = rt->end.node;
721     rt->start.node = saveendnode;
722     rt->end.node = savestartnode;
723 
724     /* Reverse the start/end flags */
725     saveflags = rt->flags & (RT_START_NODE | RT_END_NODE);
726     rt->flags &= ~(RT_START_NODE | RT_END_NODE);
727     if (saveflags & RT_START_NODE) rt->flags |= RT_END_NODE;
728     if (saveflags & RT_END_NODE) rt->flags |= RT_START_NODE;
729 
730     area = get_route_area_forward_fromseg(net, rt, nseg, layer, visited,
731 		method, NodeTable, iroute);
732 
733     /* Replace the route segment with the original route */
734     rt->segments = saveseg;
735 
736     /* Revert the endpoint information */
737     rt->start.node = savestartnode;
738     rt->end.node = saveendnode;
739 
740     /* Revert the start/end flags */
741     rt->flags &= ~(RT_START_NODE | RT_END_NODE);
742     rt->flags |= saveflags;
743 
744     /* Free the reversed route */
745     for (seg = firstseg; seg; ) {
746 	dseg = seg->next;
747 	free(seg);
748 	seg = dseg;
749     }
750     return area;
751 }
752 
753 /*--------------------------------------------------------------*/
754 /* Walk a route in reverse from end to start.			*/
755 /*--------------------------------------------------------------*/
756 
757 float
get_route_area_reverse(NET net,ROUTE rt,int layer,u_char * visited,u_char method,Tcl_HashTable * NodeTable,struct routeinfo_ * iroute)758 get_route_area_reverse(NET net, ROUTE rt, int layer, u_char *visited,
759 		u_char method, Tcl_HashTable *NodeTable,
760 		struct routeinfo_ *iroute)
761 {
762     float area;
763     area = get_route_area_reverse_fromseg(net, rt, NULL, layer, visited,
764 		method, NodeTable, iroute);
765     return area;
766 }
767 
768 /*--------------------------------------------------------------*/
769 /* Find all antenna violations at a specific metal layer	*/
770 /*--------------------------------------------------------------*/
771 
find_layer_antenna_violations(int layer,Tcl_HashTable * NodeTable)772 int find_layer_antenna_violations(int layer, Tcl_HashTable *NodeTable)
773 {
774     int numerrors, n, nn, numroutes, i, j, new, neterrors;
775     u_char *visited, method;
776     float antenna_ratio, thick;
777     GATE g;
778     NET net;
779     ROUTE rt, saveroute;
780     NODEINFO nodeptr;
781     NODE node, tnode;
782     SEG seg;
783     ANTENNAINFO newantenna;
784     float gate_area, metal_area, ratio, save_gate, save_metal, max_ratio;
785 
786     numerrors = 0;
787 
788     /* Get the metal layer record for this layer and find the metal	*/
789     /* area ratio limit and the method to be used for calculating	*/
790     /* metal area.							*/
791 
792     method = LefGetRouteAntennaMethod(layer);
793     if (method == CALC_NONE) return 0;	/* No antenna information in tech */
794     antenna_ratio = (float)LefGetRouteAreaRatio(layer);
795     thick = (float)LefGetRouteThickness(layer);
796     if (((method == CALC_SIDEAREA) || (method == CALC_AGG_SIDEAREA)) && (thick == 0.0))
797 	return 0;	/* Insufficient antenna information in tech */
798 
799     /* Make a pass through all nets to find antenna violations */
800 
801     for (n = 0; n < Numnets; n++) {
802 	net = Nlnets[n];
803 
804 	if ((net->netnum == VDD_NET) || (net->netnum == GND_NET) ||
805 		(net->netnum == ANTENNA_NET)) continue;
806 
807 	/* Ignore nets with no routes */
808 	numroutes = 0;
809 	for (rt = net->routes; rt; rt = rt->next) numroutes++;
810 	if (numroutes == 0) continue;
811 
812 	/* Consider each terminal as a separate sub-net calculation.	*/
813 	/* But if multiple terminals belong to the same sub-net, they	*/
814 	/* are marked visited and ignored on subsequent calculations.	*/
815 
816 	visited = (u_char *)malloc(net->numnodes * sizeof(u_char));
817 	for (node = net->netnodes; node != NULL; node = node->next) {
818 	    nn = node->nodenum;
819 	    visited[nn] = NOT_VISITED;
820 	}
821 
822 	/* Make a pass through all nodes of the net.  Where they are	*/
823 	/* not connected together at "layer", these are individual	*/
824 	/* sub-nets.							*/
825 
826 	neterrors = 0;
827 	max_ratio = 0.0;	/* For diagnostics only */
828 	for (node = net->netnodes; node != NULL; node = node->next) {
829 	    nn = node->nodenum;
830 	    if (visited[nn] >= PROCESSED) continue; 	/* Already seen */
831 
832 	    /* Find the gate area of this node */
833 	    g = FindGateNode(NodeTable, node, &i);
834 	    metal_area = 0.0;
835 
836 	    if (g->area[i] == 0.0) {
837 		visited[nn] = ANCHOR;	/* Mark as S/D connection */
838 		continue;		/* No gate, so no violation */
839 	    }
840 	    else
841 		visited[nn] = VISITED;
842 
843 	    /* Clear visited flags for routes */
844 
845 	    for (rt = net->routes; rt; rt = rt->next)
846 		rt->flags &= ~RT_VISITED;
847 
848 	    /* Find the route or routes that connect to this node */
849 
850 	    for (rt = net->routes; rt; rt = rt->next) {
851 		if ((rt->flags & RT_START_NODE) && (rt->start.node == node)) {
852 		    saveroute = rt;
853 		    metal_area += get_route_area_forward(net, rt, layer, visited,
854 				method, NodeTable, NULL);
855 		}
856 		else if ((rt->flags & RT_END_NODE) && (rt->end.node == node)) {
857 		    saveroute = rt;
858 		    metal_area += get_route_area_reverse(net, rt, layer, visited,
859 				method, NodeTable, NULL);
860 		}
861 		else continue;
862 	    }
863 
864 	    /* Gate area is combined area of gates visited */
865 
866 	    gate_area = 0.0;
867 	    for (tnode = net->netnodes; tnode != NULL; tnode = tnode->next) {
868 		j = tnode->nodenum;
869 		if (visited[j] == VISITED) {
870 		    g = FindGateNode(NodeTable, tnode, &i);
871 		    if (g->area[i] == 0.0) {
872 			visited[j] = ANCHOR;
873 			gate_area = 0.0;
874 			break;
875 		    }
876 		    else
877 			gate_area += g->area[i];
878 		}
879 
880 	    }
881 
882 	    if (gate_area > 0.0) {
883 		ratio = metal_area / gate_area;
884 		if (ratio > max_ratio) {
885 		    max_ratio = ratio;
886 		    save_gate = gate_area;
887 		    save_metal = metal_area;
888 		}
889 
890 		if (ratio > antenna_ratio) {
891 
892 		    /* Record and report the violation */
893 
894 		    numerrors++;
895 		    neterrors++;
896 		    if (Verbose > 1) {
897 			Fprintf(stderr,
898 				"Antenna violation on node %d of net %s at metal%d\n",
899 				nn, net->netname, layer + 1);
900 		    }
901 		    if (Verbose > 2) {
902 			Fprintf(stderr, "Metal area = %f, Gate area = %f, Ratio = %f\n",
903 				metal_area, gate_area, ratio);
904 		    }
905 		    newantenna = (ANTENNAINFO)malloc(sizeof(struct antennainfo_));
906 		    newantenna->net = net;
907 		    newantenna->node = node;
908 		    newantenna->layer = layer;
909 		    newantenna->route = saveroute;
910 		    newantenna->next = AntennaList;
911 		    AntennaList = newantenna;
912 		}
913 	    }
914 
915 	    /* Mark gates as visited on previous pass */
916 	    for (tnode = net->netnodes; tnode != NULL; tnode = tnode->next) {
917 		j = tnode->nodenum;
918 		if (visited[j] == VISITED) visited[j] = PROCESSED;
919 	    }
920 	}
921 	free(visited);
922 
923 	if (Verbose > 3) {
924 	    /* Diagnostic */
925 	    if (neterrors == 0) {
926 		if (max_ratio > 0.0)
927 		    Fprintf(stderr, "Worst case:  Metal area = %f, Gate area = %f, "
928 			"Ratio = %f\n", save_metal, save_gate, max_ratio);
929 	    }
930 	}
931 
932 	/* Clear route visited flags */
933 	for (rt = net->routes; rt; rt = rt->next)
934 	    rt->flags &= ~RT_VISITED;
935     }
936     return numerrors;
937 }
938 
939 /*--------------------------------------------------------------*/
940 /* This routine is a combination of set_node_to_net(),		*/
941 /* set_routes_to_net(), and disable_node_nets() (see qrouter.c	*/
942 /* and maze.c), but walks the routes in the same manner used	*/
943 /* for finding the antenna violations.  Set the antenna part of	*/
944 /* the net as SOURCE, the free antenna taps as TARGET, and the	*/
945 /* non-antenna portion of the net to an unused net number,	*/
946 /* which can be converted back after routing.			*/
947 /*--------------------------------------------------------------*/
948 
set_antenna_to_net(int newflags,struct routeinfo_ * iroute,u_char stage,ANTENNAINFO violation,Tcl_HashTable * NodeTable)949 int set_antenna_to_net(int newflags, struct routeinfo_ *iroute,
950 		u_char stage, ANTENNAINFO violation, Tcl_HashTable *NodeTable)
951 {
952     int x, y, lay, rval, layer;
953     PROUTE *Pr;
954     ROUTE rt, clrrt;
955     NODE node;
956     NET net;
957 
958     /* Set the node and connected antenna metal routes to PR_SOURCE.	*/
959 
960     rt = violation->route;
961     node = violation->node;
962     net = violation->net;
963     layer = violation->layer;
964 
965     if ((rt->flags & RT_START_NODE) && (rt->start.node == node))
966 	get_route_area_forward(net, rt, layer, NULL, ANTENNA_ROUTE, NodeTable,
967 		iroute);
968     else if ((rt->flags & RT_END_NODE) && (rt->end.node == node))
969 	get_route_area_reverse(net, rt, layer, NULL, ANTENNA_ROUTE, NodeTable,
970 		iroute);
971     else {
972 	/* This should not happen */
973 	Fprintf(stderr, "Error:  Antenna route and node do not connect!\n");
974 	return 1;
975     }
976 
977     /* Clear route visited flags for next pass */
978     for (clrrt = iroute->net->routes; clrrt; clrrt = clrrt->next)
979 	clrrt->flags &= ~RT_VISITED;
980 
981     /* Disable the remainder of the route */
982 
983     if ((rt->flags & RT_START_NODE) && (rt->start.node == node))
984 	get_route_area_forward(net, rt, layer, NULL, ANTENNA_DISABLE, NodeTable,
985 		iroute);
986     else if ((rt->flags & RT_END_NODE) && (rt->end.node == node))
987 	get_route_area_reverse(net, rt, layer, NULL, ANTENNA_DISABLE, NodeTable,
988 		iroute);
989     else {
990 	/* This should not happen */
991 	Fprintf(stderr, "Error:  Antenna route and node do not connect!\n");
992 	return 1;
993     }
994 
995     /* Done checking routes;  clear route visited flags */
996     for (clrrt = iroute->net->routes; clrrt; clrrt = clrrt->next)
997 	clrrt->flags &= ~RT_VISITED;
998 
999     /* Set the antenna taps to the net number.		*/
1000     /* Routine is similar to set_powerbus_to_net().	*/
1001 
1002     rval = 0;
1003     for (lay = 0; lay < Num_layers; lay++)
1004 	for (x = 0; x < NumChannelsX; x++)
1005 	    for (y = 0; y < NumChannelsY; y++)
1006 		if ((OBSVAL(x, y, lay) & NETNUM_MASK) == ANTENNA_NET) {
1007 		    Pr = &OBS2VAL(x, y, lay);
1008 		    // Skip locations that have been purposefully disabled
1009 		    if (!(Pr->flags & PR_COST) && (Pr->prdata.net == MAXNETNUM))
1010 			continue;
1011 		    else if (!(Pr->flags & PR_SOURCE)) {
1012 			Pr->flags |= (PR_TARGET | PR_COST);
1013 			Pr->prdata.cost = MAXRT;
1014 			rval = 1;
1015 			OBSVAL(x, y, lay) &= ~NETNUM_MASK;
1016 			OBSVAL(x, y, lay) |= net->netnum;
1017 		    }
1018 		}
1019 
1020     return rval;
1021 }
1022 
1023 /*--------------------------------------------------------------*/
1024 /* This routine is similar to route_setup() for the normal	*/
1025 /* stage routes, with changes for the antenna routing.		*/
1026 /* Set the node in the "violation" record to source, and set	*/
1027 /* all free antenna taps to destination.  Add existing routes	*/
1028 /* to the source in the same manner as was used to find the	*/
1029 /* antenna violation in the first place (this is a subnet of	*/
1030 /* the complete net).  Disable the remainder of the net.	*/
1031 /* Set all free antenna taps to the net number being routed,	*/
1032 /* then route like stage 1 power routing.			*/
1033 /*--------------------------------------------------------------*/
1034 
antenna_setup(struct routeinfo_ * iroute,ANTENNAINFO violation,Tcl_HashTable * NodeTable)1035 int antenna_setup(struct routeinfo_ *iroute, ANTENNAINFO violation,
1036 	Tcl_HashTable *NodeTable)
1037 {
1038     int i, j, netnum, rval;
1039     PROUTE *Pr;
1040 
1041     for (i = 0; i < Num_layers; i++) {
1042 	for (j = 0; j < NumChannelsX * NumChannelsY; j++) {
1043 	    netnum = Obs[i][j] & (~BLOCKED_MASK);
1044 	    Pr = &Obs2[i][j];
1045 	    if (netnum != 0) {
1046 		Pr->flags = 0;            // Clear all flags
1047 		if (netnum == DRC_BLOCKAGE)
1048 		    Pr->prdata.net = netnum;
1049 		else
1050 		    Pr->prdata.net = netnum & NETNUM_MASK;
1051 	    } else {
1052 		Pr->flags = PR_COST;              // This location is routable
1053 		Pr->prdata.cost = MAXRT;
1054 	    }
1055 	}
1056     }
1057 
1058     // Fill out route information record
1059 
1060     iroute->net = violation->net;
1061     iroute->rt = NULL;
1062     for (i = 0; i < 6; i++)
1063 	iroute->glist[i] = NULL;
1064     iroute->nsrc = violation->node;
1065     iroute->nsrctap = iroute->nsrc->taps;
1066     iroute->maxcost = MAXRT;
1067     iroute->do_pwrbus = TRUE;
1068     iroute->pwrbus_src = 0;
1069 
1070     iroute->bbox.x2 = iroute->bbox.y2 = 0;
1071     iroute->bbox.x1 = NumChannelsX;
1072     iroute->bbox.y1 = NumChannelsY;
1073 
1074     rval = set_antenna_to_net(PR_SOURCE, iroute, 0, violation, NodeTable);
1075 
1076     /* Unlikely that MASK_BBOX would be useful, since one does	*/
1077     /* not know if an antenna tap is inside the box or not.	*/
1078     /* Maybe if bounding box is expanded to encompass some	*/
1079     /* number of taps. . .					*/
1080 
1081     // if (maskMode == MASK_NONE)
1082 	   fillMask((u_char)0);
1083     // else if (maskMode == MASK_BBOX)
1084     //	   createBboxMask(iroute->net, (u_char)Numpasses);
1085 
1086     iroute->maxcost = 20;
1087     return rval;
1088 }
1089 
1090 /*--------------------------------------------------------------*/
1091 /* The simplest way to fix an antenna violation is to find	*/
1092 /* a place in the antenna metal to break the antenna and pull	*/
1093 /* it up to a higher level of metal.  Depending on the severity	*/
1094 /* of the antenna violation, this may need to be done more than	*/
1095 /* once.  If no place to break the antenna is found, return -1	*/
1096 /* for failure.							*/
1097 /*--------------------------------------------------------------*/
1098 
simpleantennafix(ANTENNAINFO violation,Tcl_HashTable * NodeTable)1099 int simpleantennafix(ANTENNAINFO violation, Tcl_HashTable *NodeTable)
1100 {
1101     return -1;		/* Antenna was not fixed */
1102 }
1103 
1104 /*--------------------------------------------------------------*/
1105 /* Route from nets with antenna violations to the nearest	*/
1106 /* routable antenna cell tap.					*/
1107 /*								*/
1108 /* This routine is essentially the same as doroute() but with	*/
1109 /* some special handling related to the antenna taps, which	*/
1110 /* have much in common with VDD and GND taps but significant	*/
1111 /* differences as well.						*/
1112 /*--------------------------------------------------------------*/
1113 
doantennaroute(ANTENNAINFO violation,Tcl_HashTable * NodeTable)1114 int doantennaroute(ANTENNAINFO violation, Tcl_HashTable *NodeTable)
1115 {
1116     NET net;
1117     NODE node;
1118     ROUTE rt1, lrt;
1119     int layer, i, result, savelayers;
1120     struct routeinfo_ iroute;
1121 
1122     net = violation->net;
1123     node = violation->node;
1124     layer = violation->layer;
1125 
1126     result = antenna_setup(&iroute, violation, NodeTable);
1127 
1128     rt1 = createemptyroute();
1129     rt1->netnum = net->netnum;
1130     iroute.rt = rt1;
1131 
1132     /* Force routing to be done at or below the antenna check layer.	*/
1133 
1134     savelayers = Num_layers;
1135     Num_layers = violation->layer + 1;
1136 
1137     result = route_segs(&iroute, 0, (u_char)0);
1138 
1139     Num_layers = savelayers;
1140 
1141     if (result < 0) {
1142 	/* To do:  Handle failures? */
1143 	Fprintf(stderr, "Antenna anchoring route failed.\n");
1144 	free(rt1);
1145     }
1146     else {
1147 	TotalRoutes++;
1148 	if (net->routes) {
1149 	    for (lrt = net->routes; lrt->next; lrt = lrt->next);
1150 	    lrt->next = rt1;
1151 	}
1152 	else {
1153 	    /* This should not happen */
1154 	    Fprintf(stderr, "Error:  Net has no routes!\n");
1155 	    net->routes = rt1;
1156 	}
1157     }
1158 
1159     /* For power-bus-type routing, glist is not empty after routing */
1160     free_glist(&iroute);
1161 
1162     /* Put free taps back to ANTENNA_NET */
1163     revert_antenna_taps(net->netnum, rt1->start.node);
1164 
1165     return result;
1166 }
1167 
1168 /*--------------------------------------------------------------*/
1169 /* Top level routine called from tclqrouter.c			*/
1170 /*--------------------------------------------------------------*/
1171 
1172 void
resolve_antenna(char * antennacell,u_char do_fix)1173 resolve_antenna(char *antennacell, u_char do_fix)
1174 {
1175     FILE *fout;
1176     int numtaps, numerrors, numfixed, result;
1177     int layererrors;
1178     int layer, i, new;
1179     Tcl_HashTable NodeTable;
1180     Tcl_HashEntry *entry;
1181     GATE g;
1182     NET net;
1183     ROUTE rt;
1184     ANTENNAINFO nextviolation, FixedList = NULL, BadList = NULL;
1185 
1186     numtaps = count_free_antenna_taps(antennacell);
1187     if (Verbose > 3) {
1188 	Fprintf(stdout, "Number of free antenna taps = %d\n", numtaps);
1189     }
1190 
1191     AntennaList = NULL;
1192     numerrors = 0;
1193     numfixed = 0;
1194 
1195     /* Build a hash table of nodes, so the gate area can be found	*/
1196     /* quickly for any node by hash lookup.				*/
1197 
1198     Tcl_InitHashTable(&NodeTable, TCL_ONE_WORD_KEYS);
1199 
1200     for (g = Nlgates; g; g = g->next) {
1201 	for (i = 0; i < g->nodes; i++) {
1202 	    GATENODE gn;
1203 	    gn = (GATENODE)malloc(sizeof(struct gatenode_));
1204 	    gn->idx = i;
1205 	    gn->gate = g;
1206 	    entry = Tcl_CreateHashEntry(&NodeTable, (char *)(*(g->noderec + i)), &new);
1207 	    Tcl_SetHashValue(entry, gn);
1208 	}
1209     }
1210 
1211     /* Working from the 1nd layer metal to the top, compute	*/
1212     /* route metal to gate area ratios.  Mark each one when	*/
1213     /* done, as an antenna violation that has been fixed at, 	*/
1214     /* say, metal2 can no longer be a violation on any higer	*/
1215     /* layer of metal.						*/
1216 
1217     for (layer = 0; layer < Num_layers; layer++) {
1218 	layererrors = find_layer_antenna_violations(layer, &NodeTable);
1219 	numerrors += layererrors;
1220 	if (Verbose > 2) {
1221 	    Fprintf(stdout, "Number of antenna errors on metal%d = %d\n",
1222 			layer + 1, layererrors);
1223 	}
1224 
1225 	/* Fix the violations found on this layer before moving	*/
1226 	/* on to the next layer.				*/
1227 
1228 	while (AntennaList != NULL) {
1229 	    nextviolation = AntennaList->next;
1230 
1231 	    if (do_fix) {
1232 		result = simpleantennafix(AntennaList, &NodeTable);
1233 		if (result == 0) {
1234 		    /* No antenna cell involved, so no backannotation	*/
1235 		    /* required.  Remove the "route" record. */
1236 		    AntennaList->route = NULL;
1237 		}
1238 		else
1239 		    result = doantennaroute(AntennaList, &NodeTable);
1240 		if (result >= 0) numfixed++;
1241 	    }
1242 
1243 	    /* Move the error information to either the Fixed or Bad lists */
1244 	    if (result >= 0) {
1245 		AntennaList->next = FixedList;
1246 		FixedList = AntennaList;
1247 		if (AntennaList->route != NULL) {
1248 		    /* Replace the route record with the last route	*/
1249 		    /* of the net, which was the route added to fix.	*/
1250 		    /* If the net requires more than one antenna 	*/
1251 		    /* anchor, then routes won't be confused.		*/
1252 		    for (rt = AntennaList->net->routes; rt && rt->next; rt = rt->next);
1253 		    AntennaList->route = rt;
1254 		}
1255 	    }
1256 	    else {
1257 		AntennaList->next = BadList;
1258 		BadList = AntennaList;
1259 	    }
1260 	    AntennaList = nextviolation;
1261 	}
1262     }
1263 
1264     if (Verbose > 0) {
1265 	Fprintf(stdout, "Total number of antenna errors found = %d\n", numerrors);
1266 	if (do_fix)
1267 	    Fprintf(stdout, "Total number of antenna errors fixed = %d\n", numfixed);
1268     }
1269     if (numtaps < numerrors) {
1270 	if (numtaps == 0)
1271 	    Fprintf(stderr, "There are no antenna taps to use to correct "
1272 			"antenna errors!\n");
1273 	else {
1274 	    Fprintf(stderr, "There are not enough antenna taps to use to "
1275 			"correct antenna errors!\n");
1276 	    Fprintf(stderr, "Number of errors = %d, number of taps = %d\n",
1277 			numerrors, numtaps);
1278 	    Fprintf(stderr, "Increate the amount of unallocated antenna cells"
1279 			" in the design.\n");
1280 	}
1281 	/* To do:  Replace the error message with an ad-hoc solution to	*/
1282 	/* pull routes up to a higher metal layer near the gate causing	*/
1283 	/* the error.							*/
1284     }
1285 
1286     /* Output the violation lists.  The fixed violations need to be	*/
1287     /* known so that the additional connection to the net can be added	*/
1288     /* to the netlist for verification purposes.  The unfixed		*/
1289     /* violations need to be reported so they can be tracked down and	*/
1290     /* fixed by hand.							*/
1291 
1292     if ((FixedList != NULL) || (BadList != NULL))
1293 	fout = fopen("antenna.out", "w");
1294 
1295     /* Clear any existing list of instance connections (annotations) */
1296 
1297     if (AnnotateList) {
1298 	ANNOTATEINFO nextannotate;
1299 	while (AnnotateList != NULL) {
1300 	    nextannotate = AnnotateList->next;
1301 	    free(AnnotateList);
1302 	    AnnotateList = nextannotate;
1303 	}
1304     }
1305 
1306     if (FixedList != NULL) {
1307 	ROUTE rt;
1308 	ANNOTATEINFO newannotate;
1309 	fprintf(fout, "Revised netlist: New antenna anchor connections\n");
1310 
1311 	for (nextviolation = FixedList; nextviolation;
1312 			nextviolation = nextviolation->next) {
1313 	    // NOTE:  nextviolation->route was changed from the route that
1314 	    // connects to the gate in violation, to the route that fixes
1315 	    // the antenna error.
1316 	    g = FindGateNode(&NodeTable, nextviolation->route->start.node, &i);
1317 	    fprintf(fout, "Net=%s Instance=%s Cell=%s Pin=%s\n",
1318 			nextviolation->net->netname, g->gatename,
1319 			g->gatetype->gatename, g->gatetype->node[i]);
1320 
1321 	    // Create an annotation entry for this fixed violation
1322 
1323 	    newannotate = (ANNOTATEINFO)malloc(sizeof(struct annotateinfo_));
1324 	    newannotate->net = nextviolation->net;
1325 	    newannotate->instance = g->gatename;
1326 	    newannotate->pin = g->gatetype->node[i];
1327 	    newannotate->flag = ANNO_INIT;
1328 	    newannotate->next = AnnotateList;
1329 	    AnnotateList = newannotate;
1330 	}
1331 	fprintf(fout, "\n");
1332     }
1333 
1334     if (BadList != NULL) {
1335 	fprintf(fout, "Unfixed antenna errors:\n");
1336 
1337 	for (nextviolation = BadList; nextviolation;
1338 			nextviolation = nextviolation->next) {
1339 	    g = FindGateNode(&NodeTable, nextviolation->node, &i);
1340 	    fprintf(fout, "Net=%s Instance=%s Cell=%s Pin=%s error on Metal%d\n",
1341 			nextviolation->net->netname,
1342 			g->gatename, g->gatetype->gatename,
1343 			g->gatetype->node[i], nextviolation->layer + 1);
1344 	}
1345     }
1346 
1347     if ((FixedList != NULL) || (BadList != NULL)) fclose(fout);
1348 
1349     /* Free up the node hash table */
1350 
1351     FreeNodeTable(&NodeTable);
1352     Tcl_DeleteHashTable(&NodeTable);
1353 
1354     /* Free up the violation lists */
1355 
1356     if (FixedList != NULL) {
1357 	while (FixedList != NULL) {
1358 	    nextviolation = FixedList->next;
1359 	    free(FixedList);
1360 	    FixedList = nextviolation;
1361 	}
1362     }
1363     while (BadList != NULL) {
1364 	nextviolation = BadList->next;
1365 	free(BadList);
1366 	BadList = nextviolation;
1367     }
1368 }
1369 
1370 #endif	/* TCL_QROUTER */
1371 
1372 /* end of antenna.c */
1373