1 /*
2 * mzSubrs.c --
3 *
4 * Misc. surport routines for the Maze router.
5 *
6 * *********************************************************************
7 * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the *
8 * * University of California. *
9 * * Permission to use, copy, modify, and distribute this *
10 * * software and its documentation for any purpose and without *
11 * * fee is hereby granted, provided that the above copyright *
12 * * notice appear in all copies. The University of California *
13 * * makes no representations about the suitability of this *
14 * * software for any purpose. It is provided "as is" without *
15 * * express or implied warranty. Export of this software outside *
16 * * of the United States of America may require an export license. *
17 * *********************************************************************
18 */
19
20 #ifndef lint
21 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzSubrs.c,v 1.2 2008/06/01 18:37:44 tim Exp $";
22 #endif /* not lint */
23
24 #include <stdio.h>
25
26 #include "utils/magic.h"
27 #include "utils/geometry.h"
28 #include "tiles/tile.h"
29 #include "utils/hash.h"
30 #include "database/database.h"
31 #include "drc/drc.h"
32 #include "select/select.h"
33 #include "utils/signals.h"
34 #include "textio/textio.h"
35 #include "windows/windows.h"
36 #include "dbwind/dbwind.h"
37 #include "utils/styles.h"
38 #include "debug/debug.h"
39 #include "utils/undo.h"
40 #include "textio/txcommands.h"
41 #include "utils/malloc.h"
42 #include "utils/main.h"
43 #include "utils/geofast.h"
44 #include "utils/list.h"
45 #include "utils/touchingtypes.h"
46 #include "utils/heap.h"
47 #include "mzrouter/mzrouter.h"
48 #include "mzrouter/mzInternal.h"
49
50
51
52 /*
53 * ----------------------------------------------------------------------------
54 *
55 * mzComputeDerivedParms --
56 *
57 * Processes current parms deriving some parameters from others.
58 *
59 * Results:
60 * None
61 *
62 * Side effects:
63 * Modifies current parms.
64 *
65 * ----------------------------------------------------------------------------
66 */
67
68 void
mzComputeDerivedParms()69 mzComputeDerivedParms()
70 {
71 RouteContact *rC;
72 RouteLayer *rL;
73 RouteType *rT;
74
75 /* Compute active routelayer list */
76 mzActiveRLs = NULL;
77 for(rL=mzRouteLayers; rL!=NULL; rL=rL->rl_next)
78 {
79 if(rL->rl_routeType.rt_active)
80 {
81 rL->rl_nextActive = mzActiveRLs;
82 mzActiveRLs = rL;
83 }
84 }
85
86 /* Compute active routetype list */
87 mzActiveRTs = NULL;
88 for(rT=mzRouteTypes; rT!=NULL; rT=rT->rt_next)
89 {
90 if(rT->rt_active)
91 {
92 rT->rt_nextActive = mzActiveRTs;
93 mzActiveRTs = rT;
94 }
95 }
96
97 /* Compute bloats and effWidth for route layers.
98 * Since we are routing bottom left edge of wires:
99 * bloat to bottom = spacing + width - 1;
100 * bloat to top = spacing
101 */
102 for(rL=mzRouteLayers; rL!=NULL; rL=rL->rl_next)
103 {
104 RouteType *rT = &(rL->rl_routeType);
105 int i;
106
107 rT->rt_effWidth = rT->rt_width;
108
109 for(i=0;i<=TT_MAXTYPES;i++)
110 {
111 if(rT->rt_spacing[i]>=0)
112 {
113 rT->rt_bloatBot[i] = rT->rt_width + rT->rt_spacing[i] - 1;
114 rT->rt_bloatTop[i] = rT->rt_spacing[i];
115 }
116 else
117 {
118 rT->rt_bloatBot[i] = -1;
119 rT->rt_bloatTop[i] = -1;
120 }
121 }
122 }
123
124 /* contact widths and bloats are max of components */
125 for(rC=mzRouteContacts; rC!=NULL; rC=rC->rc_next)
126 {
127 RouteType *rT = &(rC->rc_routeType);
128 RouteType *rT1 = &(rC->rc_rLayer1->rl_routeType);
129 RouteType *rT2 = &(rC->rc_rLayer2->rl_routeType);
130 int i;
131
132 rT->rt_effWidth = MAX(MAX(rT1->rt_width,rT2->rt_width),rT->rt_width);
133
134 for(i=0;i<=TT_MAXTYPES;i++)
135 {
136 int bot, bot1, bot2;
137 int top, top1, top2;
138
139 if(rT->rt_spacing[i]>=0)
140 {
141 bot = rT->rt_width + rT->rt_spacing[i] - 1;
142 top = rT->rt_spacing[i];
143 }
144 else
145 {
146 bot = -1;
147 top = -1;
148 }
149
150 if(rT1->rt_spacing[i]>=0)
151 {
152 bot1 = rT1->rt_width + rT1->rt_spacing[i] - 1;
153 top1 = rT1->rt_spacing[i];
154 }
155 else
156 {
157 bot1 = -1;
158 top1 = -1;
159 }
160
161 if(rT2->rt_spacing[i]>=0)
162 {
163 bot2 = rT2->rt_width + rT2->rt_spacing[i] - 1;
164 top2 = rT2->rt_spacing[i];
165 }
166 else
167 {
168 bot2 = -1;
169 top2 = -1;
170 }
171
172 rT->rt_bloatBot[i] = MAX(MAX(bot1,bot2),bot);
173 rT->rt_bloatTop[i] = MAX(MAX(top1,top2),top);
174 }
175 }
176
177 /*
178 * compute context radius = how much to bloat blockage area
179 * to be built to obtain search area for mask data.
180 */
181 {
182 int i;
183
184 mzContextRadius = 0;
185 for(rT=mzActiveRTs; rT!=NULL; rT=rT->rt_nextActive)
186 for(i=0;i<=TT_MAXTYPES;i++)
187 mzContextRadius = MAX(mzContextRadius,rT->rt_bloatBot[i]);
188 }
189
190 /* If max walk length is -1, set to twice the context radius */
191 if(mzMaxWalkLength==-1)
192 {
193 mzMaxWalkLength = mzContextRadius * 2;
194 }
195
196 /* If bounds increment is -1, set to 30 times min active pitch */
197 if(mzBoundsIncrement==-1)
198 {
199 int minPitch = INFINITY;
200
201 for(rL=mzActiveRLs; rL!=NULL; rL=rL->rl_nextActive)
202 {
203 RouteType *rT = &(rL->rl_routeType);
204 int pitch = rT->rt_width + rT->rt_spacing[rT->rt_tileType];
205
206 minPitch = MIN(minPitch, pitch);
207 }
208
209 if(minPitch==INFINITY)
210 /* Don't coredump just because no active rL's */
211 {
212 mzBoundsIncrement = 100;
213 }
214 else
215 {
216 mzBoundsIncrement = 30*minPitch;
217 }
218 }
219
220 /* Set up (global) bounding rect for route */
221 if(mzBoundsHint)
222 /* Blockage gen will be confined to user supplied hint (+ 2 units)
223 * generate slightly larger bounds for other purposes (estimate generation
224 * and marking of tiles connected to dest nodes, for example) to avoid
225 * edge effects.
226 */
227 {
228 mzBoundingRect = *mzBoundsHint;
229
230 mzBoundingRect.r_xbot -= 2*mzContextRadius;
231 mzBoundingRect.r_ybot -= 2*mzContextRadius;
232 mzBoundingRect.r_xtop += 2*mzContextRadius;
233 mzBoundingRect.r_ytop += 2*mzContextRadius;
234 }
235 else
236 /* No user supplied bounds, shrink maximum paintable rect by a
237 * conservative amount (to avoid overflow during blockage
238 * plane generation etc.)
239 */
240 {
241 int maxWidth, maxSpacing, safeHalo;
242 RouteType *rT;
243
244 mzBoundingRect = TiPlaneRect;
245
246 maxWidth = 0;
247 maxSpacing = 0;
248 for (rT = mzRouteTypes; rT!=NULL; rT=rT->rt_next)
249 {
250 int i;
251
252 maxWidth = MAX(maxWidth,rT->rt_width);
253 for(i=0;i<TT_MAXTYPES+1;i++)
254 maxSpacing = MAX(maxSpacing,rT->rt_spacing[i]);
255 }
256 safeHalo = 3 * (maxSpacing + maxWidth + 2);
257
258 mzBoundingRect.r_xbot += safeHalo;
259 mzBoundingRect.r_xtop -= safeHalo;
260 mzBoundingRect.r_ybot += safeHalo;
261 mzBoundingRect.r_ytop -= safeHalo;
262
263 ASSERT(mzBoundingRect.r_xbot < mzBoundingRect.r_xtop,
264 "mzComputeDerivedParms");
265 ASSERT(mzBoundingRect.r_ybot < mzBoundingRect.r_ytop,
266 "mzComputeDerivedParms");
267 }
268 }
269
270 int mzMakeEndpoints; /* Set to MZ_EXPAND_START, MZ_EXPAND_DEST, or
271 * MZ_EXPAND_NONE.
272 */
273 /*
274 * ----------------------------------------------------------------------------
275 *
276 * mzMarkConnectedTiles --
277 *
278 * Marks tiles connected to given area on given layer in mask data.
279 * Used to mark tiles that are part of start or dest nodes.
280 *
281 * If mzExpandEndpoints is set, also adds dest areas for connected tiles.
282 *
283 * Results:
284 * none.
285 *
286 * Side effects:
287 * See above.
288 *
289 * ----------------------------------------------------------------------------
290 */
291
292 void
mzMarkConnectedTiles(rect,type,expandType)293 mzMarkConnectedTiles(rect, type, expandType)
294 Rect *rect;
295 TileType type;
296 int expandType;
297 {
298 List *expandList = NULL; /* areas remaining to be expanded from */
299
300 /* set global controlling the creation of dest areas for each connected
301 * tile found.
302 */
303 mzMakeEndpoints = expandType;
304
305 /* Create colored rect corresponding to passed args and initial
306 * expandList with it.
307 */
308 {
309 ColoredRect *e;
310 e = (ColoredRect *) mallocMagic((unsigned)(sizeof(ColoredRect)));
311 e->cr_type = type;
312 e->cr_rect = *rect;
313 LIST_ADD(e, expandList);
314 }
315
316 /* repeatedly expand from top area on expandList */
317 while(expandList)
318 {
319 ColoredRect *e = (ColoredRect *) LIST_FIRST(expandList);
320 SearchContext scx;
321 TileTypeBitMask typeMask;
322 int mzConnectedTileFunc();
323
324 /* Restrict marking to route bounds */
325 if(GEO_OVERLAP(&mzBoundingRect, &(e->cr_rect)))
326 {
327 /* Set search area to colored rect */
328 scx.scx_trans = GeoIdentityTransform;
329 scx.scx_use = mzRouteUse;
330 scx.scx_area = e->cr_rect;
331
332 /* Grow search area by one unit in each direction so that in
333 * addition to overlapping
334 * tiles we also get those that just touch it.
335 */
336 scx.scx_area.r_xbot -= 1;
337 scx.scx_area.r_ybot -= 1;
338 scx.scx_area.r_xtop += 1;
339 scx.scx_area.r_ytop += 1;
340
341 /* Build type mask with just the type of e set */
342 TTMaskSetOnlyType(&typeMask, e->cr_type);
343
344 /* search for connecting tiles, mark them, and add them to
345 * expandList (They are inserted
346 * AFTER the first (= current) element.)
347 */
348 (void)
349 DBTreeSrTiles(
350 &scx,
351 &(DBConnectTbl[e->cr_type]), /* enumerate all
352 * tiles of connecting
353 * types */
354 mzCellExpansionMask,
355 mzConnectedTileFunc,
356 (ClientData) expandList);
357 }
358
359 /* Done processing top element of expandList, toss it */
360 e = (ColoredRect *) ListPop(&expandList);
361 freeMagic((char *) e);
362 }
363
364
365 /* mark unexpanded subcells intersecting dest area */
366 {
367 if(mzCellExpansionMask != 0)
368 {
369 int mzConnectedSubcellFunc();
370 SearchContext scx;
371
372 scx.scx_trans = GeoIdentityTransform;
373 scx.scx_use = mzRouteUse;
374 scx.scx_area = *rect;
375
376 /* clip area to bounding box to avoid overflow during transforms */
377 GEOCLIP(&(scx.scx_area),&(mzRouteUse->cu_def->cd_bbox));
378
379 /* clip to route bounds for performance */
380 GEOCLIP(&(scx.scx_area),&mzBoundingRect);
381
382 DBTreeSrCells(
383 &scx,
384 mzCellExpansionMask,
385 mzConnectedSubcellFunc,
386 (ClientData) NULL);
387 }
388 }
389
390 return;
391 }
392
393
394 /*
395 * ---------------------------------------------------------------------
396 *
397 * mzConnectedTileFunc --
398 *
399 * Called by MZAddDest to mark mask data tile connected to a dest terminal.
400
401 *
402 * Results:
403 * Always returns 0 to continue search.
404 *
405 * Side effects:
406 * Mark clientdata fileds of connected tiles.
407 * Add freshly marked tiles to expandList (for recursive expansion).
408 * If mzExpandEndpoints is set, also adds dest areas for connected
409 * tiles.
410 *
411 * ---------------------------------------------------------------------
412 */
413
414 int
mzConnectedTileFunc(tile,cxp)415 mzConnectedTileFunc(tile, cxp)
416 Tile *tile;
417 TreeContext *cxp;
418 {
419 /* If tile not marked, mark it, add it to marked list, and add
420 * corresponding area to expand list. Mark start tiles MZ_EXPAND_START
421 * and destination tiles MZ_EXPAND_DEST so that we don't have to run
422 * the tile cleanup routing (in MZClean()) unnecessarily between
423 * MZAddStart() and MZAddDest().
424 */
425
426 if ((int)tile->ti_client != mzMakeEndpoints)
427 {
428 SearchContext *scx = cxp->tc_scx;
429 List *expandList = (List *) (cxp->tc_filter->tf_arg);
430 Rect rRaw, r;
431
432 /* Get bounding box of tile */
433 TITORECT(tile, &rRaw);
434 GEOTRANSRECT(&scx->scx_trans, &rRaw, &r);
435
436 /* mark tile with destination type */
437 tile->ti_client = (ClientData) mzMakeEndpoints;
438
439 /* Add tiles connected to Start to mzStartTerms */
440 /* (Added by Tim, August 2006) */
441
442 if (mzMakeEndpoints == MZ_EXPAND_START)
443 {
444 ColoredRect *newTerm;
445 extern List *mzStartTerms;
446
447 newTerm = (ColoredRect *) mallocMagic((unsigned)(sizeof(ColoredRect)));
448 newTerm->cr_rect = r;
449 newTerm->cr_type = TiGetType(tile);
450 LIST_ADD(newTerm, mzStartTerms);
451 }
452
453 /* Add dest area (if appropriate). Don't paint contact types, */
454 /* or the planes will get fractured up, possibly into areas too */
455 /* small to place a valid route. */
456
457 else if (mzMakeEndpoints == MZ_EXPAND_DEST)
458 {
459 RouteLayer *rL;
460 TileType ttype = TiGetType(tile);
461
462 for(rL=mzRouteLayers; rL!=NULL; rL=rL->rl_next)
463 {
464 if (rL->rl_routeType.rt_active &&
465 TTMaskHasType(&(DBConnectTbl[ttype]),
466 rL->rl_routeType.rt_tileType))
467 {
468 DBPaint(mzDestAreasUse->cu_def,
469 &r,
470 rL->rl_routeType.rt_tileType);
471 }
472 }
473 }
474
475 /* add entry to expandList */
476 {
477 ColoredRect *e;
478
479 /* build colored rect corresponding to tile */
480 e = (ColoredRect *) mallocMagic((unsigned)(sizeof(ColoredRect)));
481 e->cr_type = TiGetType(tile);
482 e->cr_rect = r;
483
484 /* add new entry to second position of expandList (just
485 * past current entry)
486 */
487 LIST_ADD(e, LIST_TAIL(expandList));
488 }
489 }
490
491 /* return 0 to continue search */
492 return 0;
493 }
494
495
496 /*
497 * ----------------------------------------------------------------------------
498 *
499 * mzConnectedSubcellFunc --
500 *
501 * Called by MZAddDest to mark subcells overlapping a dest terminal.
502 * (The blockage generation code treats marked subcells as same-node geometry,
503 * allowing walks and dest areas near them.)
504 *
505 * Results:
506 * Always returns 0 (to continue search)
507 *
508 * Side effects:
509 * Mark client field in subcell use, and add use to list of marked
510 * subcells.
511 *
512 * ----------------------------------------------------------------------------
513 */
514
515 int
mzConnectedSubcellFunc(scx,cdarg)516 mzConnectedSubcellFunc(scx, cdarg)
517 SearchContext *scx;
518 ClientData cdarg;
519 {
520 CellUse *cu = scx->scx_use;
521
522 /* If not already marked, mark celluse and add to marked list */
523 if (cu->cu_client == (ClientData)MZ_EXPAND_NONE)
524 {
525 cu->cu_client = (ClientData)MZ_EXPAND_DEST;
526 LIST_ADD(cu, mzMarkedCellsList);
527 }
528
529 /* continue search */
530 return (0);
531 }
532
533 /*
534 * ----------------------------------------------------------------------------
535 *
536 * mzGetContact --
537 *
538 * Get the RouteContact record that matches the contact type between
539 * planes path->rp_rLayer and prev->rp_rLayer,
540 *
541 * Results:
542 * A pointer to the appropriate RouteContact structure, or NULL if
543 * none exists (which shouldn't happen).
544 *
545 * Side effects:
546 * None.
547 *
548 * ----------------------------------------------------------------------------
549 */
550
551 RouteContact *
MZGetContact(path,prev)552 MZGetContact(path, prev)
553 RoutePath *path, *prev;
554 {
555 RouteContact *rC;
556 List *cL;
557
558 /* Find RouteContact connecting the route layers of path and prev. */
559
560 for (cL = path->rp_rLayer->rl_contactL; cL != NULL &&
561 ((RouteContact*)LIST_FIRST(cL))->rc_rLayer1 != prev->rp_rLayer &&
562 ((RouteContact*)LIST_FIRST(cL))->rc_rLayer2 != prev->rp_rLayer;
563 cL = LIST_TAIL(cL));
564
565 ASSERT(cL != NULL, "mzPaintContact");
566 rC = ((RouteContact*)LIST_FIRST(cL));
567
568 return rC;
569 }
570
571 /*
572 * ----------------------------------------------------------------------------
573 *
574 * mzPaintContact --
575 *
576 * Paint a single contact between planes path->rp_rLayer and prev->rp_rLayer,
577 *
578 * Results:
579 * None.
580 *
581 * Side effects:
582 * Updates both mask and blockage planes.
583 *
584 * ----------------------------------------------------------------------------
585 */
586
587 int
mzPaintContact(path,prev)588 mzPaintContact(path, prev)
589 RoutePath *path, *prev;
590 {
591 RouteContact *rC;
592 int pNum, pNumC, cWidth;
593 Rect r;
594 TileType cType;
595
596 rC = MZGetContact(path, prev);
597
598 /* compute the contact tileType */
599 cType = rC->rc_routeType.rt_tileType;
600 cWidth = rC->rc_routeType.rt_width;
601
602 /* compute bounds of contact tile */
603 r.r_ll = path->rp_entry;
604
605 if (path->rp_orient == 'X')
606 {
607 r.r_xtop = r.r_xbot + cWidth;
608 r.r_ytop = r.r_ybot + rC->rc_routeType.rt_length;
609 }
610 else if (path->rp_orient == 'O')
611 {
612 r.r_xtop = r.r_xbot + rC->rc_routeType.rt_length;
613 r.r_ytop = r.r_ybot + cWidth;
614 }
615 else /* Type "C", residues only */
616 {
617 r.r_xtop = r.r_xbot + cWidth;
618 r.r_ytop = r.r_ybot + cWidth;
619 }
620
621 /* Paint the contact on all connected mask planes */
622 /* (should just let DBPaint() do this. . . ) */
623
624 if (DBIsContact(cType))
625 {
626 if (path->rp_orient != 'C')
627 {
628 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
629 if (PlaneMaskHasPlane(DBConnPlanes[cType], pNum))
630 DBPaintPlane(mzResultDef->cd_planes[pNum],
631 &r, DBStdPaintTbl(cType, pNum),
632 (PaintUndoInfo *) NULL);
633 }
634 else
635 {
636 /* Paint residues, not the contact type, to avoid DRC errors */
637 RouteLayer *rL;
638
639 rL = rC->rc_rLayer1;
640 DBPaintPlane(mzResultDef->cd_planes[rL->rl_planeNum], &r,
641 DBStdPaintTbl(rL->rl_routeType.rt_tileType,
642 rL->rl_planeNum), (PaintUndoInfo *)NULL);
643 rL = rC->rc_rLayer2;
644 DBPaintPlane(mzResultDef->cd_planes[rL->rl_planeNum], &r,
645 DBStdPaintTbl(rL->rl_routeType.rt_tileType,
646 rL->rl_planeNum), (PaintUndoInfo *)NULL);
647 }
648 }
649 return cWidth;
650 }
651
652
653 /*
654 * ----------------------------------------------------------------------------
655 *
656 * mzCopyPath --
657 *
658 * Copy a RoutePath from the temporary arena into permanent storage
659 * allocated via mallocMagic.
660 *
661 * Results:
662 * Returns a pointer to a copy of the RoutePath passed to us
663 * as an argument.
664 *
665 * Side effects:
666 * Allocates memory.
667 *
668 * ----------------------------------------------------------------------------
669 */
670
671 RoutePath *
mzCopyPath(path)672 mzCopyPath(path)
673 RoutePath *path;
674 {
675 RoutePath *newHead, *newPrev, *new;
676
677 newPrev = newHead = (RoutePath *) NULL;
678 for (newPrev = NULL; path; newPrev = new, path = path->rp_back)
679 {
680 new = (RoutePath *) mallocMagic((unsigned)(sizeof (RoutePath)));
681 *new = *path;
682 if (newPrev) newPrev->rp_back = new;
683 if (newHead == NULL) newHead = new;
684 }
685
686 return (newHead);
687 }
688
689 /*--------------- Static variables only referenced by RPath allocation
690 and deallocation routines below ----------------------- */
691
692 /* First, last, and current RoutePages on list for allocating RoutePaths */
693 RoutePage *mzFirstPage = NULL;
694 RoutePage *mzLastPage = NULL;
695 RoutePage *mzCurPage = NULL;
696
697
698 /*
699 * ----------------------------------------------------------------------------
700 *
701 * mzAllocRPath --
702 *
703 * Allocate a new RoutePath from our temporary RoutePath arena.
704 *
705 * Results:
706 * Returns a pointer to a newly allocated RoutePath.
707 * This RoutePath is NOT allocated directly via
708 * mallocMagic/freeMagic,
709 * but rather via our own temporary mechanism. It goes away
710 * once mzFreeAllTemp() gets called, so callers that wish to
711 * retain the "best" RoutePath must call mzCopyPath() to
712 * preserve it.
713 *
714 * Side effects:
715 * May allocate memory.
716 *
717 * ----------------------------------------------------------------------------
718 */
719
720 RoutePath *
mzAllocRPath()721 mzAllocRPath()
722 {
723 /* Skip to next page if this one is full */
724 if (mzCurPage && mzCurPage->rpp_free >= PATHSPERSEG)
725 mzCurPage = mzCurPage->rpp_next;
726
727 /* If out of pages, allocate a new one */
728 if (mzCurPage == NULL)
729 {
730 mzCurPage = (RoutePage *) mallocMagic((unsigned)(sizeof (RoutePage)));
731 mzCurPage->rpp_next = (RoutePage *) NULL;
732 mzCurPage->rpp_free = 0;
733 if (mzLastPage == NULL)
734 mzFirstPage = mzLastPage = mzCurPage;
735 else
736 mzLastPage->rpp_next = mzCurPage, mzLastPage = mzCurPage;
737 }
738
739 return (&mzCurPage->rpp_array[mzCurPage->rpp_free++]);
740 }
741
742 /*
743 * ----------------------------------------------------------------------------
744 *
745 * mzFreeAllRPaths --
746 *
747 * Reset the temporary arena used for allocating RoutePaths.
748 *
749 * Results:
750 * None.
751 *
752 * Side effects:
753 * Any RoutePaths in the arena become available again for
754 * allocation. Callers wishing to preserve paths must
755 * do so by calling mzCopyPath().
756 *
757 * ----------------------------------------------------------------------------
758 */
759
760 void
mzFreeAllRPaths()761 mzFreeAllRPaths()
762 {
763 RoutePage *rpage;
764
765 for (rpage = mzFirstPage; rpage; rpage = rpage->rpp_next)
766 {
767 /* Mark page of RoutePaths as being free */
768 rpage->rpp_free = 0;
769
770 /* Can stop after processing the last page used in this cycle */
771 if (rpage == mzCurPage)
772 break;
773 }
774
775 /* Start allocating again from the first page on the list */
776 mzCurPage = mzFirstPage;
777 }
778
779 /*
780 * ----------------------------------------------------------------------------
781 *
782 * mzPresent --
783 *
784 * Predicate, checkes if type corresponding to rL is set in touchingTypes
785 * mask.
786 *
787 * Results:
788 * TRUE if RL in touchingTypes, else FALSE
789 *
790 * Side effects:
791 * None.
792 *
793 * ----------------------------------------------------------------------------
794 */
795
796 bool
mzPresent(rL,touchingTypes)797 mzPresent(rL,touchingTypes)
798 RouteLayer *rL;
799 TileTypeBitMask *touchingTypes;
800 {
801 List *l;
802
803 /* return true if rL present */
804 if(TTMaskHasType(touchingTypes, rL->rl_routeType.rt_tileType))
805 return TRUE;
806
807 /* return true if rL present as part of contact */
808 for(l=rL->rl_contactL; l!=NULL; l=LIST_TAIL(l))
809 {
810 RouteContact *rC = (RouteContact *)LIST_FIRST(l);
811 if(TTMaskHasType(touchingTypes, rC->rc_routeType.rt_tileType) &&
812 (rC->rc_rLayer1==rL || rC->rc_rLayer2==rL))
813 return TRUE;
814 }
815
816 return FALSE;
817 }
818