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;
|
|
}
|