281 lines
8.0 KiB
C
281 lines
8.0 KiB
C
/* rtrMain.c -
|
||
*
|
||
* Top level routing code, and glue that doesn't belong elsewhere.
|
||
*
|
||
* *********************************************************************
|
||
* * 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/rtrMain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
||
#endif /* not lint */
|
||
|
||
#include <stdio.h>
|
||
#include <sys/time.h>
|
||
#include <sys/types.h>
|
||
#include <sys/times.h>
|
||
#include <ctype.h>
|
||
|
||
#include "utils/magic.h"
|
||
#include "utils/geometry.h"
|
||
#include "utils/hash.h"
|
||
#include "utils/heap.h"
|
||
#include "tiles/tile.h"
|
||
#include "database/database.h"
|
||
#include "gcr/gcr.h"
|
||
#include "windows/windows.h"
|
||
#include "dbwind/dbwind.h"
|
||
#include "utils/main.h"
|
||
#include "utils/signals.h"
|
||
#include "router/rtrDcmpose.h"
|
||
#include "netmenu/netmenu.h"
|
||
#include "router/router.h"
|
||
#include "grouter/grouter.h"
|
||
#include "utils/netlist.h"
|
||
#include "textio/textio.h"
|
||
#include "netmenu/netmenu.h"
|
||
#include "utils/runstats.h"
|
||
|
||
/* Forward declarations */
|
||
|
||
extern int rtrMakeChannel();
|
||
void RtrMilestoneStart(char *);
|
||
void RtrMilestoneDone();
|
||
|
||
|
||
/*
|
||
* The origin point for the routing grid.
|
||
* Set by the "route origin" command.
|
||
*/
|
||
Point RtrOrigin = { 0, 0 };
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* Route --
|
||
*
|
||
* Top level procedure for the routing code.
|
||
*
|
||
* Route all channels in the cell routeUse->cu_def, based on net lists
|
||
* in the net list hash table. There currently is no check that the net
|
||
* list belongs to the edit cell.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Memory for channels is allocated and set. The channel structure is
|
||
* kept around to allow flags to be examined and displayed on the screen.
|
||
* Leaves paint in routeUse->cu_def.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
Route(routeUse, routeArea)
|
||
CellUse *routeUse;
|
||
Rect *routeArea;
|
||
{
|
||
CellDef *channelDef;
|
||
int errs, numNets;
|
||
NLNetList netList;
|
||
char *netListName;
|
||
|
||
/* Read the netlist into an internal NLNetList structure */
|
||
if (!NMHasList())
|
||
{
|
||
netListName = routeUse->cu_def->cd_name;
|
||
TxPrintf("No netlist selected yet; using \"%s\".\n", netListName);
|
||
NMNewNetlist(netListName);
|
||
}
|
||
else netListName = NMNetlistName();
|
||
RtrMilestoneStart("Building netlist");
|
||
numNets = NLBuild(routeUse, &netList);
|
||
RtrMilestoneDone();
|
||
if (numNets == 0)
|
||
{
|
||
TxError("No nets to route.\n");
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* Create a plane whose space tiles correspond to channels.
|
||
* See the comments in RtrDecompose() for details.
|
||
*/
|
||
RtrMilestoneStart("Channel decomposition");
|
||
channelDef = RtrDecompose(routeUse, routeArea, &netList);
|
||
RtrMilestoneDone();
|
||
if (channelDef == NULL)
|
||
{
|
||
TxError("Routing area (box) is too small to be of any use.\n");
|
||
goto done;
|
||
}
|
||
RtrChannelPlane = channelDef->cd_planes[PL_DRC_ERROR];
|
||
|
||
/*
|
||
* Enumerate all space tiles in the channel plane, generating a
|
||
* channel for each one. Initialize each channel's dimensions,
|
||
* but don't do anything else.
|
||
*/
|
||
RtrChannelList = (GCRChannel *) NULL;
|
||
(void) DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &RouteArea,
|
||
&DBAllTypeBits, rtrMakeChannel, (ClientData) &RouteArea);
|
||
if (!SigInterruptPending)
|
||
{
|
||
errs = GARoute(RtrChannelList, routeUse, &netList);
|
||
if (errs == 0)
|
||
TxPrintf("No routing errors.\n");
|
||
else if (errs == 1)
|
||
TxPrintf("There was one routing error: see feedback.\n");
|
||
else TxPrintf("There were %d routing errors: see feedback.\n", errs);
|
||
}
|
||
|
||
done:
|
||
/* Clean up global routing information */
|
||
NLFree(&netList);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* rtrMakeChannel --
|
||
*
|
||
* Function passed to DBSrPaintArea to enumerate space tiles and convert them
|
||
* to channels. Clip all tiles against the box 'clipBox'. Don't set
|
||
* hazards for this channel; that has to happen after stem assignment.
|
||
*
|
||
* Results:
|
||
* Return 0 to keep the search going, 1 to abort.
|
||
*
|
||
* Side effects:
|
||
* Hashes space tile pointers from the channel cell's drc error plane
|
||
* to get a pointer to a malloc'ed channel structure.
|
||
*
|
||
* Prepends this channel to the list being built in RtrChannelList.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
rtrMakeChannel(tile, clipBox)
|
||
Tile *tile; /* Potential channel tile; we create a channel whose
|
||
* area is equal to that of this tile if the type of
|
||
* this tile is TT_SPACE.
|
||
*/
|
||
Rect *clipBox; /* If non-NULL, clip the channel area to this box */
|
||
{
|
||
int length, width;
|
||
HashEntry *entry;
|
||
GCRChannel *ch;
|
||
Point origin;
|
||
Rect bbox;
|
||
|
||
if (SigInterruptPending) return (1);
|
||
if (TiGetBody(tile) != (ClientData) NULL) return (0);
|
||
|
||
entry = HashFind(&RtrTileToChannel, (char *) tile);
|
||
ASSERT(HashGetValue(entry) == (char *) 0, "rtrMakeChannel");
|
||
TITORECT(tile, &bbox);
|
||
GeoClip(&bbox, clipBox);
|
||
|
||
/*
|
||
* Figure out how many columns and rows will fit in the area,
|
||
* then create and initialize a channel.
|
||
*/
|
||
RtrChannelBounds(&bbox, &length, &width, &origin);
|
||
ch = GCRNewChannel(length, width);
|
||
ch->gcr_area = bbox;
|
||
ch->gcr_origin = origin;
|
||
ch->gcr_type = CHAN_NORMAL;
|
||
|
||
/* Remember that we've processed it */
|
||
HashSetValue(entry, (char *) ch);
|
||
|
||
/* Prepend to RtrChannelList */
|
||
ch->gcr_next = RtrChannelList;
|
||
RtrChannelList = ch;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* RtrRunStats --
|
||
* RtrMilestoneStart --
|
||
* RtrMilestoneDone --
|
||
* RtrMilestonePrint --
|
||
*
|
||
* Miscellaneous procedures for debugging/timing.
|
||
* Calling RtrRunStats() prints out the time since the last call
|
||
* and the total amount of memory used in the heap. The procedures
|
||
* RtrMilestoneStart() and RtrMilestoneDone() should be used to bracket
|
||
* calls to the various pieces of the router: the former announces
|
||
* that the router is about to enter a given section, and the latter
|
||
* says it is done and tells how long it took. During a given section,
|
||
* RtrMilestonePrint() will print '#' if no errors have occurred since
|
||
* the last call; otherwise, it will print a '!'.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Output to terminal.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
/* The following are both set by RtrMilestoneStart() */
|
||
static char *rtrMilestoneName; /* Name of the current section */
|
||
static struct tms rtrStartTime; /* Starting time of the current section */
|
||
static int rtrFeedCount; /* Most recent # of feedback areas */
|
||
|
||
void
|
||
RtrRunStats()
|
||
{
|
||
char *RunStats();
|
||
static struct tms last, delta;
|
||
|
||
TxPrintf("%s\n", RunStats(RS_TINCR|RS_MEM, &last, &delta));
|
||
TxFlush();
|
||
}
|
||
|
||
void
|
||
RtrMilestoneStart(event)
|
||
char *event;
|
||
{
|
||
rtrMilestoneName = event;
|
||
TxPrintf("%s: ", event);
|
||
TxFlush();
|
||
(void) times(&rtrStartTime);
|
||
rtrFeedCount = DBWFeedbackCount;
|
||
}
|
||
|
||
void
|
||
RtrMilestoneDone()
|
||
{
|
||
struct tms tend;
|
||
|
||
times(&tend);
|
||
TxPrintf("\n%s time: %.1fu %.1fs\n", rtrMilestoneName,
|
||
(tend.tms_utime - rtrStartTime.tms_utime) / 60.0,
|
||
(tend.tms_stime - rtrStartTime.tms_stime) / 60.0);
|
||
}
|
||
|
||
void
|
||
RtrMilestonePrint()
|
||
{
|
||
TxPrintf("%c", (DBWFeedbackCount > rtrFeedCount) ? '!' : '#');
|
||
TxFlush();
|
||
rtrFeedCount = DBWFeedbackCount;
|
||
}
|