/* rtrVia.c.c - * * This file contains procedures that minimize vias and * maximize metal. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrVia.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; #endif /* not lint */ #include #include "utils/magic.h" #include "utils/geometry.h" #include "tiles/tile.h" #include "utils/hash.h" #include "utils/heap.h" #include "database/database.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "utils/main.h" #include "netmenu/netmenu.h" #include "textio/textio.h" #include "utils/styles.h" #include "utils/malloc.h" #include "gcr/gcr.h" #include "router/router.h" #include "router/routerInt.h" /* C99 compat */ #include "router/routerInt.h" /* * The following structures are used to hold information about * areas to be erased/modified/painted during via minimization. */ struct arealist { Rect ap_erase; /* Area to be erased. */ Rect ap_paint; /* Area to be painted. */ int ap_oldtype; /* Type to be erased */ int ap_newtype; /* Type to be painted */ struct arealist *ap_next; /* Next item in list, or NULL for end. */ }; struct vialist { Rect vp_area; /* Via area to be examined. */ struct vialist *vp_next; /* Next item in list, or NULL for end. */ }; struct paintlist { Rect pl_area; /* Extension segment to paint */ struct paintlist *pl_next;/* Next extension to paint */ }; struct srinfo { Rect *si_area; /* Expanded area surrounding via */ Rect *si_varea; /* Exact area of via */ Rect si_extend; /* Extended stub within si_varea */ Tile *si_tile; /* Reference tile */ Plane *si_plane; /* Plane being searched */ TileTypeBitMask si_mask; /* Tile type mask */ }; struct vialist *rtrViaList; /* List of vias to be processed */ struct arealist *rtrAreaList; /* List of areas to be processed */ struct paintlist *rtrPaintList; /* List of extension segments to paint */ int rtrVias; /* Count of vias eliminated */ int rtrExamineStack(); /* Examines the tile stack for replacement segments to be converted to the target material */ /* * ---------------------------------------------------------------------------- * * rtrFollowLocFunc -- * * This function is called once for each terminal location in * a netlist. It invokes a procedure to follow all electrically * connected paths from the terminal. * * Results: * Always returns 0 to keep the search from aborting. * * Side effects: * * ---------------------------------------------------------------------------- */ /* ARGSUSED */ int rtrFollowLocFunc(rect, name, label, area) Rect *rect; /* Area of the terminal, edit cell coords. */ char *name; /* Name of the terminal (ignored). */ Label *label; /* Pointer to the label, used to find out * what layer the label's attached to. */ Rect *area; /* We GeoInclude into this all the areas of * all the tiles we delete. */ { CellDef *def = EditCellUse->cu_def; Rect initialArea; GEO_EXPAND(rect, 1, &initialArea); (void) rtrSrTraverse(def, &initialArea, &DBConnectTbl[label->lab_type], DBConnectTbl, &TiPlaneRect, rtrExamineStack, 0); return 0; } /* * ---------------------------------------------------------------------------- * * rtrFollowName -- * * This function gets called during via minimization. It's invoked * once for each terminal name in the netlist. It calls * DBSrLabelLoc to invoke rtrFollowLocFunc for each terminal * location associated with the name. * * Results: * Always returns 0 to keep the search from aborting. * * Side effects: * Nothing here, but a list of segments of poly are generated. * * ---------------------------------------------------------------------------- */ /* ARGSUSED */ int rtrFollowName(name, firstInNet, area) char *name; /* Name of terminal. */ bool firstInNet; /* Ignored by this procedure. */ Rect *area; /* Passed through as ClientData to * rtrFollowLocFunc. */ { if ( firstInNet ) { RtrMilestonePrint("#"); (void) DBSrLabelLoc(EditCellUse, name, rtrFollowLocFunc, (ClientData) area); } return 0; } /* * ---------------------------------------------------------------------------- * * rtrCheckTypes -- * Abort area search if both poly and metal are adjacent to via. * * Results: * Returns 1 if poly and metal connect to via. * Returns zero otherwise. * * Side effects: * Type of connecting material returned in cdata parameter. * * ---------------------------------------------------------------------------- */ int rtrCheckTypes(tile, cdata) Tile *tile; ClientData cdata; { int type; int lastType = * (int *) cdata; type = TiGetType(tile); if ( (type == RtrMetalType) || (type == RtrPolyType) ) { if ( lastType ) { if ( lastType != type ) return 1; } else *(int *)cdata = type; } return 0; } /* * ---------------------------------------------------------------------------- * * rtrExtandStub -- * Generate an extension of a piece of routing material * by extending into the area of the via. * * Results: * None. * * Side effects: * Extension segment returned in *stub*. * * ---------------------------------------------------------------------------- */ void rtrExtend(tile,area,stub) Tile *tile; /* Tile adjacent to via */ Rect *area; /* Area occupied by via */ Rect *stub; /* Extension of routing material into area of via */ { if ( (TOP(tile) == area->r_ybot) || (BOTTOM(tile) == area->r_ytop) ) { stub->r_xbot = MAX(area->r_xbot, LEFT(tile)); stub->r_xtop = MIN(area->r_xtop, RIGHT(tile)); stub->r_ybot = area->r_ybot; stub->r_ytop = area->r_ytop; } else if ( (LEFT(tile) == area->r_xtop) || (RIGHT(tile) == area->r_xbot) ) { stub->r_xbot = area->r_xbot; stub->r_xtop = area->r_xtop; stub->r_ybot = MAX(area->r_ybot, BOTTOM(tile)); stub->r_ytop = MIN(area->r_ytop, TOP(tile)); } } /* * ---------------------------------------------------------------------------- * * rtrStubGen -- * Generate an extension segment for a piece of routing material. * * Results: * Return 0 to keep the search going. * * Side effects: * Extension segment entry added to rtrPaintList list for later painting. * * ---------------------------------------------------------------------------- */ int rtrStubGen(tile, si) Tile *tile; struct srinfo *si; { Rect area; struct paintlist *pl; if ( tile != si->si_tile ) { pl = (struct paintlist *) mallocMagic((unsigned) (sizeof(*pl))); pl->pl_next = rtrPaintList; rtrPaintList = pl; /* * Generate extension segment relative to reference segment. */ rtrExtend(tile, si->si_varea, &pl->pl_area); GeoClip(&pl->pl_area, &si->si_extend); TITORECT(tile, &area); GeoClip(&area, si->si_area); (void) GeoInclude(&area, &pl->pl_area); } return 0; } /* * ---------------------------------------------------------------------------- * * rtrReferenceTile -- * Store a reference tile and corresponding extension stub. * Recursively call DBSrPaintArea to generate extension * stubs intersecting the reference stub. Each tile * adjacent to the via will in turn be a reference tile. * * Results: * Always returns 0 to continue search. * * Side effects: * Tile pointer and extension stub stored in *srinfo* structure. * * ---------------------------------------------------------------------------- */ int rtrReferenceTile(tile, si) Tile *tile; struct srinfo *si; { si->si_tile = tile; rtrExtend(tile, si->si_varea, &si->si_extend); (void) DBSrPaintArea(tile, si->si_plane, si->si_area, &si->si_mask, rtrStubGen, (ClientData) si); return 0; } /* * ---------------------------------------------------------------------------- * * rtrViaCheck -- * Check to see if a via is necessary. * If only one routing layer connects to the via, * delete the via and replace with extended segments of routing material. * * Results: * None. * * Side effects: * Via erased. * * ---------------------------------------------------------------------------- */ void rtrViaCheck(area, def) Rect *area; CellDef *def; { Rect r; int type, plane; struct paintlist *pl; TileTypeBitMask mask; /* * Search around via for connecting pieces of metal or poly. */ GEO_EXPAND(area, 1, &r); type = 0; TTMaskZero(&mask); TTMaskSetType(&mask, RtrPolyType); TTMaskSetType(&mask, RtrMetalType); for ( plane = PL_PAINTBASE; plane < DBNumPlanes; plane++ ) if ( DBPaintOnPlane(RtrPolyType, plane) || DBPaintOnPlane(RtrMetalType, plane) ) if ( DBSrPaintArea((Tile *)NULL, def->cd_planes[plane], &r, &mask, rtrCheckTypes, (ClientData) &type) ) return; /* * No metal or poly connects to this via. * Enumerate all connecting routing material * and build a list if extension segments to replace the via. */ rtrPaintList = (struct paintlist *) NULL; for ( plane = PL_PAINTBASE; plane < DBNumPlanes; plane++ ) if ( DBPaintOnPlane(type, plane) ) { struct srinfo si; si.si_area = &r; si.si_varea = area; si.si_plane = def->cd_planes[plane]; TTMaskZero(&si.si_mask); TTMaskSetType(&si.si_mask, type); (void) DBSrPaintArea((Tile *)NULL, si.si_plane, &r, &mask, rtrReferenceTile, (ClientData) &si); } /* * Erase via and paint extensions. */ DBErase(def, area, RtrContactType); for ( pl = rtrPaintList; pl; pl = pl->pl_next) { DBPaint(def, &pl->pl_area, type); freeMagic( (char *)pl ); } rtrVias++; return; } /* * ---------------------------------------------------------------------------- * * rtrListArea -- * Append an entry into a linked list * of areas to be processed. * * Results: * None. * * Side effects: * rtrAreaList points to a new list entry * which is linked into the existing list. * * ---------------------------------------------------------------------------- */ void rtrListArea(tile, oldType, newType, deltax, deltay) Tile *tile; int oldType; int newType; int deltax; int deltay; { struct arealist *ap; ap = (struct arealist *) mallocMagic((unsigned) (sizeof(*ap))); TITORECT(tile, &ap->ap_erase); TITORECT(tile, &ap->ap_paint); /* * Adjust size of paint to correspond to new layer. */ ap->ap_paint.r_xtop += deltax; ap->ap_paint.r_ytop += deltay; ap->ap_oldtype = oldType; ap->ap_newtype = newType; ap->ap_next = rtrAreaList; rtrAreaList = ap; } /* * ---------------------------------------------------------------------------- * * rtrListVia -- * Append an entry into a linked list * of areas to be processed. * * Results: * Always return 0 to keep the search going. * * Side effects: * rtrViaList points to new list entry * which is linked in front of existing list. * Always returns 0 to continue search if called from * DBSrPaintArea. * * ---------------------------------------------------------------------------- */ int rtrListVia(tile) Tile *tile; { struct vialist *vp; vp = (struct vialist *) mallocMagic((unsigned)(sizeof(*vp))); TITORECT(tile, &vp->vp_area); vp->vp_next = rtrViaList; rtrViaList = vp; return 0; } /* * ---------------------------------------------------------------------------- * * RtrViaMinimize -- * Minimize vias and maximize metal. * * Results: * Return number of vias elminiated. * * Side effects: * On the first pass, segments of poly * are replaced with metal and connecting vias are erased. * On the second pass, segments of metal * are replaced with poly and connecting vias are erased. * * ---------------------------------------------------------------------------- */ int RtrViaMinimize(def) CellDef *def; { Rect area; struct vialist *vp; struct arealist *ap; /* * Pass 1 -- * Enumerate every terminal in the netlist * to follow all electrically connected paths. * Generate a list of segments of poly not overlapped by metal * and terminated at each end by vias. * These segments of poly are replaced with metal * and the connecting via's are removed. */ rtrVias = 0; rtrTarget = RtrMetalType; rtrReplace = RtrPolyType; rtrDelta = RtrMetalWidth - RtrPolyWidth; area = GeoNullRect; rtrViaList = (struct vialist *) NULL; rtrAreaList = (struct arealist *) NULL; (void) NMEnumNets(rtrFollowName, (ClientData) &area); /* * Replace poly with metal where appropriate. */ for ( ap = rtrAreaList; ap; ap = ap->ap_next) { DBErase(def, &ap->ap_erase, ap->ap_oldtype); DBPaint(def, &ap->ap_paint, ap->ap_newtype); freeMagic( (char *)ap); } /* * Eliminate unnecessary vias. */ for ( vp = rtrViaList; vp; vp = vp->vp_next) { rtrViaCheck(&vp->vp_area, def); freeMagic( (char *)vp); } /* * Pass 2 -- * Repeat the entire process replacing metal with poly. */ rtrTarget = RtrPolyType; rtrReplace = RtrMetalType; rtrDelta = RtrPolyWidth - RtrMetalWidth; area = GeoNullRect; rtrViaList = (struct vialist *) NULL; rtrAreaList = (struct arealist *) NULL; (void) NMEnumNets(rtrFollowName, (ClientData) &area); /* * Erase poly and replace with metal. */ for ( ap = rtrAreaList; ap; ap = ap->ap_next) { DBErase(def, &ap->ap_erase, ap->ap_oldtype); DBPaint(def, &ap->ap_paint, ap->ap_newtype); freeMagic( (char *)ap); } /* * Eliminate unnecessary vias. */ for ( vp = rtrViaList; vp; vp = vp->vp_next) { rtrViaCheck(&vp->vp_area, def); freeMagic( (char *)vp); } return rtrVias; }