399 lines
9.5 KiB
C
399 lines
9.5 KiB
C
|
|
/* gcrInit.c -
|
|||
|
|
*
|
|||
|
|
* Initialization for the greedy router.
|
|||
|
|
*
|
|||
|
|
* *********************************************************************
|
|||
|
|
* * 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/gcr/gcrInit.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 "utils/hash.h"
|
|||
|
|
#include "utils/heap.h"
|
|||
|
|
#include "tiles/tile.h"
|
|||
|
|
#include "database/database.h"
|
|||
|
|
#include "router/router.h"
|
|||
|
|
#include "gcr/gcr.h"
|
|||
|
|
#include "utils/malloc.h"
|
|||
|
|
|
|||
|
|
int GCRSteadyNet =1; /*Values get imported from main*/
|
|||
|
|
int GCREndDist =1;
|
|||
|
|
int GCRMinJog =1;
|
|||
|
|
int GCRsplitAt =0;
|
|||
|
|
bool GcrShowResult =FALSE;
|
|||
|
|
bool GcrNoCheck =TRUE;
|
|||
|
|
bool GcrDebug =FALSE;
|
|||
|
|
#ifndef lint
|
|||
|
|
float GCRObstDist = 0.7;
|
|||
|
|
#else
|
|||
|
|
float GCRObstDist; /* Sun lint brain death */
|
|||
|
|
#endif /* lint */
|
|||
|
|
|
|||
|
|
/* Forward declarations */
|
|||
|
|
void gcrLinkPin();
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*
|
|||
|
|
* gcrSetEndDist --
|
|||
|
|
*
|
|||
|
|
* Set the global variable specifying how soon the router starts to get
|
|||
|
|
* nets into tracks for end connections.
|
|||
|
|
*
|
|||
|
|
* Get the number of end connections as a percentage of the width of
|
|||
|
|
* the channel. Add extra for multipin end connections.
|
|||
|
|
*
|
|||
|
|
* Results:
|
|||
|
|
* None.
|
|||
|
|
*
|
|||
|
|
* Side effects:
|
|||
|
|
* Changes GCREndDist.
|
|||
|
|
*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
void
|
|||
|
|
gcrSetEndDist(ch)
|
|||
|
|
GCRChannel *ch; /* The channel to be routed */
|
|||
|
|
{
|
|||
|
|
int rightTotal, multiTotal;
|
|||
|
|
GCRNet *net;
|
|||
|
|
GCRPin *pin;
|
|||
|
|
int count;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* Do this the easy way.
|
|||
|
|
* Enumerate each net and look at its pins, starting
|
|||
|
|
* from the rightmost.
|
|||
|
|
*/
|
|||
|
|
rightTotal = 0;
|
|||
|
|
multiTotal = 0;
|
|||
|
|
for (net = ch->gcr_nets; net; net = net->gcr_next)
|
|||
|
|
{
|
|||
|
|
count = 0;
|
|||
|
|
for (pin = net->gcr_rPin; pin; pin = pin->gcr_pPrev, count++)
|
|||
|
|
if (pin->gcr_x <= ch->gcr_length)
|
|||
|
|
break;
|
|||
|
|
rightTotal += count;
|
|||
|
|
if (count > 1)
|
|||
|
|
multiTotal++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
GCREndDist = (multiTotal/2 + rightTotal/4) * RtrEndConst;
|
|||
|
|
if (GCREndDist < 1) GCREndDist = 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*
|
|||
|
|
* gcrBuildNets --
|
|||
|
|
*
|
|||
|
|
* Scan the top, bot, left, and right pin arrays, setting pointers to
|
|||
|
|
* the left and right pins for each net. Sets pointers within the
|
|||
|
|
* pin arrays to point to next and previous pins.
|
|||
|
|
*
|
|||
|
|
* Results:
|
|||
|
|
* None.
|
|||
|
|
*
|
|||
|
|
* Side effects:
|
|||
|
|
* Allocates and initializes storage for nets.
|
|||
|
|
*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
void
|
|||
|
|
gcrBuildNets(ch)
|
|||
|
|
GCRChannel * ch;
|
|||
|
|
{
|
|||
|
|
HashTable ht;
|
|||
|
|
int i;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* Initialize the hash table that maps net ids to GCRNet structs.
|
|||
|
|
* The table is keyed by 2 words: seg/net.
|
|||
|
|
*/
|
|||
|
|
HashInit(&ht, 256, 2);
|
|||
|
|
|
|||
|
|
for (i = 1; i <= ch->gcr_width; i++)
|
|||
|
|
gcrLinkPin(&ch->gcr_lPins[i], &ht, ch);
|
|||
|
|
|
|||
|
|
for (i = 1; i <= ch->gcr_length; i++)
|
|||
|
|
{
|
|||
|
|
gcrLinkPin(&ch->gcr_bPins[i], &ht, ch);
|
|||
|
|
gcrLinkPin(&ch->gcr_tPins[i], &ht, ch);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (i = 1; i <= ch->gcr_width; i++)
|
|||
|
|
gcrLinkPin(&ch->gcr_rPins[i], &ht, ch);
|
|||
|
|
|
|||
|
|
HashKill(&ht);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*
|
|||
|
|
* gcrLinkPin --
|
|||
|
|
*
|
|||
|
|
* Establish the forward and backward links for a pin on the edge of
|
|||
|
|
* a channel.
|
|||
|
|
*
|
|||
|
|
* Results:
|
|||
|
|
* None.
|
|||
|
|
*
|
|||
|
|
* Side effects:
|
|||
|
|
* The pin is added to the end of the list for its net. A
|
|||
|
|
* new net structure is created if one doesn't already
|
|||
|
|
* exist.
|
|||
|
|
*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
void
|
|||
|
|
gcrLinkPin(pin, ht, ch)
|
|||
|
|
GCRPin *pin;
|
|||
|
|
HashTable *ht;
|
|||
|
|
GCRChannel *ch;
|
|||
|
|
{
|
|||
|
|
GCRNet *net;
|
|||
|
|
GCRNet *gcrNewNet();
|
|||
|
|
HashEntry *hEntry;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* GCR_BLOCKEDNETID means that the crossing was blocked.
|
|||
|
|
* Restore these crossings to "empty".
|
|||
|
|
*/
|
|||
|
|
if (pin->gcr_pId == GCR_BLOCKEDNETID) pin->gcr_pId = (GCRNet *) NULL;
|
|||
|
|
|
|||
|
|
/* Skip empty pins */
|
|||
|
|
if (pin->gcr_pId == (GCRNet *) NULL)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
/* Find the 2-word seg/net key */
|
|||
|
|
hEntry = HashFind(ht, (char *) &(pin->gcr_pSeg));
|
|||
|
|
net = (GCRNet *) HashGetValue(hEntry);
|
|||
|
|
if (net == (GCRNet *) NULL)
|
|||
|
|
{
|
|||
|
|
/* New net */
|
|||
|
|
net = (GCRNet *) mallocMagic((unsigned) (sizeof (GCRNet)));
|
|||
|
|
HashSetValue(hEntry, (char *) net);
|
|||
|
|
net->gcr_Id = (spointertype) pin->gcr_pId;
|
|||
|
|
|
|||
|
|
/* Link net onto channel net list */
|
|||
|
|
net->gcr_next = ch->gcr_nets;
|
|||
|
|
ch->gcr_nets = net;
|
|||
|
|
|
|||
|
|
/* Link pin onto net pin list */
|
|||
|
|
net->gcr_lPin = net->gcr_rPin= pin;
|
|||
|
|
pin->gcr_pPrev = (GCRPin *) NULL;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/* Old net. Add to end of net's list. */
|
|||
|
|
net->gcr_rPin->gcr_pNext = pin;
|
|||
|
|
pin->gcr_pPrev = net->gcr_rPin;
|
|||
|
|
net->gcr_rPin = pin;
|
|||
|
|
}
|
|||
|
|
pin->gcr_pId = net;
|
|||
|
|
pin->gcr_pNext = (GCRPin *) NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*
|
|||
|
|
* gcrUnlinkPin --
|
|||
|
|
*
|
|||
|
|
* Remove a pin from the pin list for a net. The pin had better
|
|||
|
|
* be the first pin of its net.
|
|||
|
|
*
|
|||
|
|
* Results:
|
|||
|
|
* None.
|
|||
|
|
*
|
|||
|
|
* Side effects:
|
|||
|
|
* The pin is removed from the list associated with its net.
|
|||
|
|
*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
void
|
|||
|
|
gcrUnlinkPin(pin)
|
|||
|
|
GCRPin *pin;
|
|||
|
|
{
|
|||
|
|
GCRNet *net;
|
|||
|
|
|
|||
|
|
if (net = pin->gcr_pId)
|
|||
|
|
{
|
|||
|
|
ASSERT(pin == net->gcr_lPin, "gcrUnlinkPin");
|
|||
|
|
net->gcr_lPin = pin->gcr_pNext;
|
|||
|
|
if (pin->gcr_pNext)
|
|||
|
|
pin->gcr_pNext->gcr_pPrev = pin->gcr_pPrev;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*
|
|||
|
|
* gcrDensity --
|
|||
|
|
*
|
|||
|
|
* Determine the channel density at every column. Starting at the left
|
|||
|
|
* end of the channel with density=0, the density of the next column is
|
|||
|
|
* the current density plus the number of nets with first pin in the
|
|||
|
|
* current column minus the number of nets with last pin in the previous
|
|||
|
|
* column.
|
|||
|
|
*
|
|||
|
|
* Must be called AFTER gcrBuildNets.
|
|||
|
|
*
|
|||
|
|
* Results:
|
|||
|
|
* Returns the maximum column density.
|
|||
|
|
*
|
|||
|
|
* Side effects:
|
|||
|
|
* Allocates storage for the density array GCRDensity and stores densities.
|
|||
|
|
*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
int
|
|||
|
|
gcrDensity(ch)
|
|||
|
|
GCRChannel *ch;
|
|||
|
|
{
|
|||
|
|
int density, i, last, maxVal;
|
|||
|
|
unsigned lenWds;
|
|||
|
|
|
|||
|
|
last = 0;
|
|||
|
|
density = 0;
|
|||
|
|
|
|||
|
|
for (i = 1; i <= ch->gcr_width; i++)
|
|||
|
|
if (ch->gcr_lPins[i].gcr_pId)
|
|||
|
|
{
|
|||
|
|
if (Is1stPin(&ch->gcr_lPins[i])) density++;
|
|||
|
|
if (IsLstPin(&ch->gcr_lPins[i])) last++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
lenWds = ch->gcr_length + 2;
|
|||
|
|
if (ch->gcr_density == (int *) NULL)
|
|||
|
|
{
|
|||
|
|
ch->gcr_density = (int *) mallocMagic((unsigned) (lenWds * sizeof (int)));
|
|||
|
|
}
|
|||
|
|
ch->gcr_density[0] = maxVal = density;
|
|||
|
|
|
|||
|
|
for (i = 1; i <= ch->gcr_length; i++)
|
|||
|
|
{
|
|||
|
|
density = density - last;
|
|||
|
|
last = 0;
|
|||
|
|
|
|||
|
|
if (ch->gcr_tPins[i].gcr_pId)
|
|||
|
|
{
|
|||
|
|
if (Is1stPin(&ch->gcr_tPins[i])) density++;
|
|||
|
|
else if (IsLstPin(&ch->gcr_tPins[i])) last++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (ch->gcr_bPins[i].gcr_pId)
|
|||
|
|
{
|
|||
|
|
if (Is1stPin(&ch->gcr_bPins[i])) density++;
|
|||
|
|
else if (IsLstPin(&ch->gcr_bPins[i]))
|
|||
|
|
{
|
|||
|
|
if (ch->gcr_tPins[i].gcr_pId == ch->gcr_bPins[i].gcr_pId)
|
|||
|
|
density--;
|
|||
|
|
else last++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ch->gcr_density[i] = density;
|
|||
|
|
if (density > maxVal)
|
|||
|
|
maxVal = density;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (maxVal);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*
|
|||
|
|
* gcrInitCol --
|
|||
|
|
*
|
|||
|
|
* Initialize the column structure to hold the configuration at
|
|||
|
|
* the left side of the channel.
|
|||
|
|
*
|
|||
|
|
* Results:
|
|||
|
|
* None.
|
|||
|
|
*
|
|||
|
|
* Side effects:
|
|||
|
|
* Pointers are updated in the column data structure.
|
|||
|
|
* Changes the track field of each net struct.
|
|||
|
|
*
|
|||
|
|
* ----------------------------------------------------------------------------
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
void
|
|||
|
|
gcrInitCol(ch, edgeArray)
|
|||
|
|
GCRChannel *ch;
|
|||
|
|
GCRPin *edgeArray; /* Nets at left edge of channel if non-NULL */
|
|||
|
|
{
|
|||
|
|
GCRNet *net;
|
|||
|
|
GCRColEl *col;
|
|||
|
|
int i, widWds;
|
|||
|
|
|
|||
|
|
col = ch->gcr_lCol;
|
|||
|
|
|
|||
|
|
/* Assign column tracks using an optionally provided pin array */
|
|||
|
|
if (edgeArray)
|
|||
|
|
{
|
|||
|
|
col[0].gcr_h = (GCRNet *) NULL;
|
|||
|
|
for (i = 1; i <= ch->gcr_width; i++)
|
|||
|
|
{
|
|||
|
|
col[i].gcr_h = edgeArray[i].gcr_pId;
|
|||
|
|
|
|||
|
|
/* Delete pin from net's pin list */
|
|||
|
|
gcrUnlinkPin(&edgeArray[i]);
|
|||
|
|
}
|
|||
|
|
col[ch->gcr_width+1].gcr_h = (GCRNet *) NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Initialize the hi and lo pointers for the column data structure */
|
|||
|
|
for (net = ch->gcr_nets; net; net = net->gcr_next)
|
|||
|
|
net->gcr_track = EMPTY;
|
|||
|
|
|
|||
|
|
widWds = ch->gcr_width + 1;
|
|||
|
|
for (i = 0; i <= widWds; i++)
|
|||
|
|
{
|
|||
|
|
col[i].gcr_v = (GCRNet *) NULL;
|
|||
|
|
col[i].gcr_hi = EMPTY;
|
|||
|
|
col[i].gcr_lo = EMPTY;
|
|||
|
|
col[i].gcr_hOk =FALSE;
|
|||
|
|
col[i].gcr_lOk =FALSE;
|
|||
|
|
col[i].gcr_wanted = (GCRNet *) NULL;
|
|||
|
|
col[i].gcr_flags = 0;
|
|||
|
|
net = col[i].gcr_h;
|
|||
|
|
if (net)
|
|||
|
|
{
|
|||
|
|
if (net->gcr_track == EMPTY) /* 1st track */
|
|||
|
|
col[i].gcr_h->gcr_track = i;
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
col[i].gcr_lo = net->gcr_track;
|
|||
|
|
col[net->gcr_track].gcr_hi = i;
|
|||
|
|
net->gcr_track = i;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Mark tracks needed to make some end connection */
|
|||
|
|
for (i = 1; i <= ch->gcr_width; i++)
|
|||
|
|
gcrWanted(ch, i, 0);
|
|||
|
|
}
|