2017-04-25 14:41:48 +02:00
|
|
|
/* rtrMain.c -
|
|
|
|
|
*
|
|
|
|
|
* Top level routing code, and glue that doesn't belong elsewhere.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
* * 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. *
|
2017-04-25 14:41:48 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#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>
|
2024-10-12 14:57:08 +02:00
|
|
|
#ifdef HAVE_SYS_TIME_H
|
2017-04-25 14:41:48 +02:00
|
|
|
#include <sys/time.h>
|
2024-10-12 14:57:08 +02:00
|
|
|
#endif
|
2017-04-25 14:41:48 +02:00
|
|
|
#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"
|
|
|
|
|
|
2022-10-10 11:50:15 +02:00
|
|
|
/* C99 compat */
|
|
|
|
|
#include "garouter/garouter.h"
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* 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 };
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* 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;
|
2019-03-23 00:58:47 +01:00
|
|
|
(void) DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &RouteArea,
|
|
|
|
|
&DBAllTypeBits, rtrMakeChannel, (ClientData) &RouteArea);
|
2017-04-25 14:41:48 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* rtrMakeChannel --
|
|
|
|
|
*
|
2019-03-23 00:58:47 +01:00
|
|
|
* Function passed to DBSrPaintArea to enumerate space tiles and convert them
|
2017-04-25 14:41:48 +02:00
|
|
|
* 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);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* 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();
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
void
|
2017-04-25 14:41:48 +02:00
|
|
|
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;
|
|
|
|
|
}
|