577 lines
14 KiB
C
577 lines
14 KiB
C
/* 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 <stdio.h>
|
||
|
||
#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"
|
||
|
||
/*
|
||
* 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;
|
||
}
|