magic/gcr/gcrDebug.c

1029 lines
25 KiB
C
Raw Normal View History

/* gcrDebug.c -
*
* The greedy router, debug routines.
*
* *********************************************************************
* * 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/gcrDebug.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/times.h>
#include "utils/magic.h"
#include "utils/geometry.h"
#include "textio/textio.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "gcr/gcr.h"
#include "utils/heap.h"
#include "router/router.h"
#include "utils/malloc.h"
int gcrViaCount;
bool GcrShowEnd = FALSE;
bool GcrShowMap = FALSE;
int gcrStandalone=FALSE; /*Flag to control standalone/integrated operation*/
/* Forward declarations */
void gcrDumpResult();
void gcrStats();
void gcrShowMap();
bool gcrMakeChannel();
void gcrPrintCol(GCRChannel *, int, int);
/*
* ----------------------------------------------------------------------------
*
* GCRRouteFromFile --
*
* Reads a routing problem from the named file and performs the routing.
*
* Results:
* Returns a pointer to the routed channel.
*
* Side effects:
* Allocates memory.
*
* ----------------------------------------------------------------------------
*/
GCRChannel *
GCRRouteFromFile(fname)
char *fname;
{
static Point initOrigin = { 0, 0 };
struct tms tbuf1, tbuf2;
GCRChannel *ch;
Transform trans;
FILE *fp;
Rect box;
fp = fopen(fname, "r");
if (fp == NULL)
{
perror(fname);
return ((GCRChannel *) NULL);
}
ch = (GCRChannel *) mallocMagic((unsigned) (sizeof (GCRChannel)));
ch->gcr_type = CHAN_NORMAL;
/* ch->gcr_area = box; */
ch->gcr_transform = GeoIdentityTransform;
ch->gcr_lCol = (GCRColEl *) NULL;
ch->gcr_nets = (GCRNet *) NULL;
ch->gcr_result = (short **) NULL;
ch->gcr_origin = initOrigin;
if (!gcrMakeChannel(ch, fp))
{
TxError("Couldn't initialize channel routing problem\n");
(void) fclose(fp);
freeMagic((char *) ch);
return ((GCRChannel *) NULL);
}
(void) fclose(fp);
ch->gcr_lCol = (GCRColEl *) mallocMagic((unsigned) ((ch->gcr_width+2) * sizeof (GCRColEl)));
times(&tbuf1);
(void) GCRroute(ch);
times(&tbuf2);
TxPrintf("Time : %5.2fu %5.2fs\n", (tbuf2.tms_utime -
tbuf1.tms_utime)/60.0, (double)(tbuf2.tms_stime-tbuf1.tms_stime)*60);
gcrDumpResult(ch, GcrShowEnd);
gcrShowMap(ch);
return (ch);
}
/*
* ----------------------------------------------------------------------------
*
* gcrMakeChannel --
*
* Read a channel in the new file format.
*
* Results:
* TRUE if successful, FALSE if not.
*
* Side effects:
* Sets values in *channel.
*
* ----------------------------------------------------------------------------
*/
bool
gcrMakeChannel(ch, fp)
GCRChannel *ch;
FILE *fp;
{
GCRPin *gcrMakePinLR();
unsigned lenWds, widWds;
int i, j, c, pid;
char s[25];
c = getc(fp);
if (c != '*')
{
TxError("Old-style channel format no longer supported.\n");
return (FALSE);
}
if (fscanf(fp, "%d %d", &ch->gcr_width, &ch->gcr_length) != 2)
{
TxError("Format error in input file width or length.\n");
return (FALSE);
}
lenWds = ch->gcr_length + 2;
widWds = ch->gcr_width + 2;
ch->gcr_density = (int *) mallocMagic((unsigned) (lenWds * sizeof (int)));
ch->gcr_lPins = gcrMakePinLR(fp, 0, ch->gcr_width);
ch->gcr_tPins = (GCRPin *) mallocMagic((unsigned) (lenWds * sizeof (GCRPin)));
ch->gcr_bPins = (GCRPin *) mallocMagic((unsigned) (lenWds * sizeof (GCRPin)));
ch->gcr_result = (short **) mallocMagic((unsigned) (lenWds * sizeof (short *)));
/* Initialize end columns */
ch->gcr_result[0] = (short *) mallocMagic((unsigned) (widWds * sizeof (short)));
ch->gcr_result[ch->gcr_length+1] = (short *) mallocMagic((unsigned) (widWds * sizeof (short)));
for (i = 0; i < widWds; i++)
{
ch->gcr_result[0][i] = 0;
ch->gcr_result[ch->gcr_length + 1][i] = 0;
}
/* Initialize internal columns */
for (i = 1; i <= ch->gcr_length; i++)
{
/* Allocate the column */
ch->gcr_result[i] = (short *) mallocMagic((unsigned) (widWds * sizeof (short)));
/* Initialize the bottom pin */
if (fscanf(fp, "%d", &pid) != 1)
{
TxError("Format error in pin-id in channel file\n");
return (FALSE);
}
ch->gcr_bPins[i].gcr_pId = (GCRNet *)(spointertype) pid;
ch->gcr_bPins[i].gcr_x = i;
ch->gcr_bPins[i].gcr_y = 0;
ch->gcr_result[i][0] = 0;
ch->gcr_result[i][ch->gcr_width+1] = 0;
for (j = 1; j <= ch->gcr_width; j++)
{
/*
* Read a column of obstacles. m and M mean metal is blocked,
* p and P mean poly is blocked. Upper case means vacate the
* column, lower case means vacate the track.
*/
if (fscanf(fp, "%24s", s) != 1)
{
TxError("Format error in router input file\n");
return (FALSE);
}
switch (s[0])
{
case 'M': case 'm':
ch->gcr_result[i][j] = GCRBLKM;
break;
case 'P': case 'p':
ch->gcr_result[i][j] = GCRBLKP;
break;
case '.':
ch->gcr_result[i][j] = 0;
break;
default:
ch->gcr_result[i][j] = GCRBLKP | GCRBLKM;
break;
}
}
/* Read bottom pin id */
if (fscanf(fp, "%d", &pid) != 1)
{
TxError("Format error in router input file\n");
return (FALSE);
}
ch->gcr_tPins[i].gcr_pId = (GCRNet *)(spointertype) pid;
ch->gcr_tPins[i].gcr_x = i;
ch->gcr_tPins[i].gcr_y = ch->gcr_width + 1;
}
ch->gcr_rPins = gcrMakePinLR(fp, ch->gcr_length + 1, ch->gcr_width);
ch->gcr_area.r_xbot = 0;
ch->gcr_area.r_ybot = 0;
ch->gcr_area.r_xtop = (ch->gcr_length + 1) * RtrGridSpacing;
ch->gcr_area.r_ytop = (ch->gcr_width + 1) * RtrGridSpacing;
return (TRUE);
}
GCRPin *
gcrMakePinLR(fp, x, size)
FILE *fp;
int x, size;
{
GCRPin *result;
int i;
result = (GCRPin *) mallocMagic((unsigned) ((size+2) * sizeof (GCRPin)));
result[0].gcr_x = result[0].gcr_y = 0;
result[0].gcr_pId = (GCRNet *) NULL;
result[size + 1].gcr_x = result[size + 1].gcr_y = 0;
result[size + 1].gcr_pId = (GCRNet *) NULL;
for (i = 1; i <= size; i++)
{
/* FIXME: Reading a pointer from file is almost guaranteed to break. */
dlong pointer_bits;
(void) fscanf(fp, "%"DLONG_PREFIX"d", &pointer_bits);
result[i].gcr_pId = (struct gcrnet *) pointer_bits;
result[i].gcr_x = x;
result[i].gcr_y = i;
}
return (result);
}
/*
* ----------------------------------------------------------------------------
*
* gcrSaveChannel --
*
* Write a channel file for subsequent use in debugging.
*
* Results:
* None.
*
* Side effects:
* Creates a disk file named by the channel address,
* e.g, chan.1efb0
*
* ----------------------------------------------------------------------------
*/
void
gcrSaveChannel(ch)
GCRChannel *ch;
{
FILE *fp;
char name[128];
int flags, i, j;
(void) sprintf(name, "chan.%p", ch);
fp = fopen(name, "w");
if (fp == NULL)
{
TxPrintf("Can't dump channel to file; "); TxFlush();
perror(name);
return;
}
/* Output the prologue */
fprintf(fp, "* %d %d\n", ch->gcr_width, ch->gcr_length);
#define NETID(pin) ((pin).gcr_pId ? (pin).gcr_pId->gcr_Id : 0)
/* Output the left pin array */
for (j = 1; j <= ch->gcr_width; j++)
fprintf(fp, "%d ", NETID(ch->gcr_lPins[j]));
fprintf(fp, "\n");
/* Process main body of channel */
for (i = 1; i <= ch->gcr_length; i++)
{
/* Bottom pin */
fprintf(fp, "%d ", NETID(ch->gcr_bPins[i]));
/*
* Interior points (for obstacle map).
* Codes are as follows:
*
* m metal blocked vacate track
* M metal blocked vacate column
* p poly blocked vacate track
* P poly blocked vacate column
*/
for (j = 1; j <= ch->gcr_width; j++)
{
flags = ch->gcr_result[i][j];
switch (flags & (GCRBLKM|GCRBLKP))
{
case 0: fprintf(fp, ". "); break;
case GCRBLKM: fprintf(fp, "m "); break;
case GCRBLKP: fprintf(fp, "p "); break;
case GCRBLKM|GCRBLKP: fprintf(fp, "x "); break;
}
}
/* Top pin */
fprintf(fp, "%d\n", NETID(ch->gcr_tPins[i]));
}
/* Output the right pin array */
for (j = 1; j <= ch->gcr_width; j++)
fprintf(fp, "%d ", NETID(ch->gcr_rPins[j]));
fprintf(fp, "\n");
(void) fclose(fp);
}
/*
* ----------------------------------------------------------------------------
*
* gcrPrDensity --
*
* Create a file of the form "dens.xbot.ybot.xtop.ytop", where
* xbot, ybot are the lower-left coordinates of ch->gcr_area
* and xtop, ytop are the upper right coordinates. This file
* contains a comparison of the density computed by the global
* router with that computed by the channel router; it is used
* for debugging only.
*
* Results:
* None.
*
* Side effects:
* Creates a file named as described above.
*
* ----------------------------------------------------------------------------
*/
void
gcrPrDensity(ch, chanDensity)
GCRChannel *ch;
int chanDensity;
{
int i, diff;
char name[256];
FILE *fp, *fp_always_close;
(void) sprintf(name, "dens.%d.%d.%d.%d",
ch->gcr_area.r_xbot, ch->gcr_area.r_ybot,
ch->gcr_area.r_xtop, ch->gcr_area.r_ytop);
fp_always_close = fopen(name, "w");
fp = fp_always_close ? fp_always_close : stdout;
fprintf(fp, "Chan width: %d\n", ch->gcr_width);
fprintf(fp, "Chan length: %d\n", ch->gcr_length);
fprintf(fp, "Chan area: ll=(%d,%d) ur=(%d,%d)\n",
ch->gcr_area.r_xbot, ch->gcr_area.r_ybot,
ch->gcr_area.r_xtop, ch->gcr_area.r_ytop);
fprintf(fp, "Max column density (global): %d\n", ch->gcr_dMaxByCol);
fprintf(fp, "Max column density (channel): %d\n", chanDensity);
fprintf(fp, "Column density by column:\n");
fprintf(fp, "%3s %5s", "COL", "GLOB");
#ifdef IDENSITY
fprintf(fp, " %5s %5s", "INIT", "DIFF");
#endif /* IDENSITY */
fprintf(fp, " %5s\n", "CHAN");
for (i = 1; i <= ch->gcr_length; i++)
{
fprintf(fp, "%3d %5d", i, ch->gcr_dRowsByCol[i]);
diff = ch->gcr_dRowsByCol[i];
#ifdef IDENSITY
diff -= ch->gcr_iRowsByCol[i];
fprintf(fp, " %5d %5d", ch->gcr_iRowsByCol[i], diff);
#endif /* IDENSITY */
fprintf(fp, "%5d%s\n", ch->gcr_density[i],
(diff != ch->gcr_density[i]) ? " *****" : "");
}
fprintf(fp, "------\n");
fprintf(fp, "Row density by column (global only):\n");
fprintf(fp, "%3s %5s", "ROW", "GLOB");
#ifdef IDENSITY
fprintf(fp, " %5s %5s", "INIT", "DIFF");
#endif /* IDENSITY */
fprintf(fp, "\n");
for (i = 1; i <= ch->gcr_width; i++)
{
fprintf(fp, "%3d %5d", i, ch->gcr_dColsByRow[i]);
#ifdef IDENSITY
fprintf(fp, " %5d %5d", ch->gcr_iColsByRow[i],
ch->gcr_dColsByRow[i] - ch->gcr_iColsByRow[i]);
#endif /* IDENSITY */
fprintf(fp, "\n");
}
(void) fflush(fp);
if (fp_always_close != NULL)
(void) fclose(fp_always_close);
}
/*
* ----------------------------------------------------------------------------
*
* gcrDumpPins --
*
* Prints a pin array.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrDumpPins(ch)
GCRChannel *ch;
{
int i;
GCRPin * pinArray;
pinArray=ch->gcr_lPins;
TxPrintf("LEFT PINS\n");
for(i=0; i<=ch->gcr_width; i++)
{
TxPrintf("Location [%d]=%ld: x=%d, y=%d, pNext=%ld, pPrev=%ld, id=%ld\n",
i, (intmax_t) &pinArray[i], pinArray[i].gcr_x, pinArray[i].gcr_y,
(intmax_t) pinArray[i].gcr_pNext, (intmax_t) pinArray[i].gcr_pPrev, (intmax_t) pinArray[i].gcr_pId);
}
pinArray=ch->gcr_rPins;
TxPrintf("RIGHT PINS\n");
for(i=0; i<=ch->gcr_width; i++)
{
TxPrintf("Location [%d]=%ld: x=%d, y=%d, pNext=%ld, pPrev=%ld, id=%ld\n",
i, (intmax_t) &pinArray[i], pinArray[i].gcr_x, pinArray[i].gcr_y,
(intmax_t) pinArray[i].gcr_pNext, (intmax_t) pinArray[i].gcr_pPrev, (intmax_t) pinArray[i].gcr_pId);
}
pinArray=ch->gcr_bPins;
TxPrintf("BOTTOM PINS\n");
for(i=0; i<=ch->gcr_length; i++)
{
TxPrintf("Location [%d]=%ld: x=%d, y=%d, pNext=%ld, pPrev=%ld, id=%ld\n",
i, (intmax_t) &pinArray[i], pinArray[i].gcr_x, pinArray[i].gcr_y,
(intmax_t) pinArray[i].gcr_pNext, (intmax_t) pinArray[i].gcr_pPrev, (intmax_t) pinArray[i].gcr_pId);
}
pinArray=ch->gcr_tPins;
TxPrintf("TOP PINS\n");
for(i=0; i<=ch->gcr_length; i++)
{
TxPrintf("Location [%d]=%ld: x=%d, y=%d, pNext=%ld, pPrev=%ld, id=%ld\n",
i, (intmax_t) &pinArray[i], pinArray[i].gcr_x, pinArray[i].gcr_y,
(intmax_t) pinArray[i].gcr_pNext, (intmax_t) pinArray[i].gcr_pPrev, (intmax_t) pinArray[i].gcr_pId);
}
}
/*
* ----------------------------------------------------------------------------
*
* gcrDumpPinList --
*
* Prints a list of pins for a net.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrDumpPinList(pin, dir)
GCRPin *pin;
bool dir;
{
if (pin)
{
TxPrintf("Location (%d, %d)=%lx: pNext=%ld, pPrev=%ld, id=%ld\n",
pin->gcr_x, pin->gcr_y, (intmax_t) pin,
(intmax_t) pin->gcr_pNext, (intmax_t) pin->gcr_pPrev, (intmax_t) pin->gcr_pId);
if (dir) gcrDumpPinList(pin->gcr_pNext, dir);
else gcrDumpPinList(pin->gcr_pPrev, dir);
}
}
/*
* ----------------------------------------------------------------------------
*
* gcrDumpCol --
*
* Print the left column contents.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrDumpCol(col, size)
GCRColEl *col;
int size;
{
int i;
if (!gcrStandalone)
return;
for (i = size; i >= 0; i--)
TxPrintf("[%2d] hi=%6d(%c) lo=%6d(%c) h=%6d v=%6d w=%6d f=%4d\n", i,
col[i].gcr_hi, col[i].gcr_hOk ? 'T' : 'F',
col[i].gcr_lo, col[i].gcr_lOk ? 'T' : 'F',
col[i].gcr_h, col[i].gcr_v,
col[i].gcr_wanted, col[i].gcr_flags);
}
/*
* ----------------------------------------------------------------------------
*
* gcrDumpResult --
*
* Print the results of the routing, up to the current column
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrDumpResult(ch, showResult)
GCRChannel *ch;
bool showResult;
{
int j;
if(!showResult)
return;
gcrStats(ch);
TxPrintf(" ");
for (j = 1; j <= ch->gcr_width; j++)
if (ch->gcr_lPins[j].gcr_pId)
TxPrintf("%2d", ch->gcr_lPins[j].gcr_pId->gcr_Id);
else
TxPrintf(" ");
TxPrintf("\n");
for (j = 0; j <= ch->gcr_length; j++)
gcrPrintCol(ch, j, showResult);
TxPrintf(" ");
for (j = 1; j <= ch->gcr_width; j++)
if (ch->gcr_rPins[j].gcr_pId)
TxPrintf("%2d", ch->gcr_rPins[j].gcr_pId->gcr_Id);
else
TxPrintf(" ");
TxPrintf("\n");
}
void gcrPrintCol(ch, i, showResult)
GCRChannel *ch;
int i, showResult;
{
short **res = ch->gcr_result;
int j;
if (!showResult)
return;
if (i>0)
{
if(ch->gcr_bPins[i].gcr_pId)
TxPrintf("[%3d] %2d:", i, (int) ch->gcr_bPins[i].gcr_pId->gcr_Id);
else TxPrintf("[%3d] :", i);
for (j = 0; j <= ch->gcr_width; j++)
{
if (j != 0)
{
if ((res[i][j] & GCRX) && (!(res[i][j] & (GCRBLKM|GCRBLKP))))
{
TxPrintf("X");
gcrViaCount++;
}
else if ((res[i][j] & GCRR) || (i > 0 && (res[i-1][j] & GCRR)))
{
if (res[i][j] & GCRBLKM) TxPrintf("|");
else if ((res[i][j] & GCRU)
|| (j != 0 && (res[i][j-1] & GCRU)))
{
if ((res[i][j]&GCRBLKM) && !(res[i][j]&GCRR))
TxPrintf("+");
else if (res[i][j]&GCRBLKP)
TxPrintf("#");
else
TxPrintf(")");
}
else TxPrintf("#");
}
else if ((res[i][j] & GCRU) || (j != 0 && (res[i][j-1] & GCRU)))
{
if((res[i][j]&GCRCC) && (!(res[i][j]&(GCRBLKM|GCRBLKP))))
{
gcrViaCount++;
TxPrintf("X");
}
else
if(res[i][j] & GCRBLKP)
TxPrintf("#");
else
if(res[i][j+1] & GCRBLKP)
TxPrintf("#");
else
if(res[i][j] & GCRVM)
TxPrintf("#");
else
TxPrintf("-");
}
else
if((res[i][j] & GCRBLKM) && (res[i][j] & GCRBLKP))
TxPrintf("~");
else
if(res[i][j] & GCRBLKM)
TxPrintf("'");
else
if(res[i][j] & GCRBLKP)
TxPrintf("`");
else
TxPrintf(" ");
}
if(res[i][j] & GCRU)
if(res[i][j] & GCRBLKP)
TxPrintf("#");
else
if(res[i][j+1] & GCRBLKP)
TxPrintf("#");
else
if(res[i][j] & GCRVM)
TxPrintf("#");
else
TxPrintf("-");
else
if((res[i][j] & GCRBLKM) && (res[i][j] & GCRBLKP))
TxPrintf("~");
else
if( ((res[i][j] & GCRBLKM) && (res[i][j+1] & GCRBLKP)) ||
((res[i][j] & GCRBLKP) && (res[i][j+1] & GCRBLKM)) )
TxPrintf("~");
else
if((res[i][j+1] & GCRBLKM) && (res[i][j+1] & GCRBLKP))
TxPrintf("~");
else
if((res[i][j] & GCRBLKM) || (res[i][j+1] & GCRBLKM))
TxPrintf("'");
else
if((res[i][j] & GCRBLKP) || (res[i][j+1] & GCRBLKP))
TxPrintf("`");
else
TxPrintf(" ");
}
if(ch->gcr_tPins[i].gcr_pId!=(GCRNet *) 0)
TxPrintf(":%2d {%2d}", (int) ch->gcr_tPins[i].gcr_pId->gcr_Id,
ch->gcr_density[i]);
else
TxPrintf(": {%2d}", ch->gcr_density[i]);
}
TxPrintf("\n :");
for(j=0; j<=ch->gcr_width; j++)
{
if(j!=0)
{
if(res[i][j] & GCRR)
if(res[i][j] & GCRBLKM)
TxPrintf("|");
else
if((i<=ch->gcr_length) && (res[i+1][j] & GCRBLKM))
TxPrintf("|");
else
TxPrintf("#");
else
if(((res[i][j] & GCRBLKM)&&(res[i][j] & GCRBLKP)) ||
((res[i+1][j] & GCRBLKM)&&(res[i+1][j] & GCRBLKP)))
TxPrintf("~");
else
if((res[i][j] & GCRBLKM) || (res[i+1][j] & GCRBLKM))
TxPrintf("'");
else
if((res[i][j] & GCRBLKP) || (res[i+1][j] & GCRBLKP))
TxPrintf("`");
else
TxPrintf(" ");
}
else
if((j!=0) && (i!=0))
{
if(res[i-1][j] & GCRR)
if(res[i-1][j] & GCRBLKM)
TxPrintf("|");
else
if((i<ch->gcr_length) && (res[i][j] & GCRBLKM))
TxPrintf("|");
else
TxPrintf("#");
else
if(((res[i-1][j] & GCRBLKM)&&(res[i-1][j] & GCRBLKP)) ||
((res[i ][j] & GCRBLKM)&&(res[i ][j] & GCRBLKP)))
TxPrintf("~");
else
if((res[i-1][j] & GCRBLKM) || (res[i][j] & GCRBLKM))
TxPrintf("'");
else
if((res[i-1][j] & GCRBLKP) || (res[i][j] & GCRBLKP))
TxPrintf("`");
else
TxPrintf(" ");
}
if((((res[i][j] & GCRBLKM) && (res[i][j] & GCRBLKP)) ||
((res[i][j+1] & GCRBLKM) && (res[i][j+1] & GCRBLKP))) ||
(((res[i+1][j] & GCRBLKM) && (res[i+1][j] & GCRBLKP)) ||
((res[i+1][j+1] & GCRBLKM) && (res[i+1][j+1] & GCRBLKP))))
TxPrintf("~");
else
if(((res[i][j] & GCRBLKM) || (res[i][j+1] & GCRBLKM))||
((res[i+1][j] & GCRBLKM) || (res[i+1][j+1] & GCRBLKM)))
TxPrintf("'");
else
if(((res[i][j] & GCRBLKP) || (res[i][j+1] & GCRBLKP))||
((res[i+1][j] & GCRBLKP) || (res[i+1][j+1] & GCRBLKP)))
TxPrintf("`");
else
TxPrintf(" ");
}
TxPrintf(":\n");
}
/*
* ----------------------------------------------------------------------------
*
* gcrStats --
*
* Print routing statistics.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrStats(ch)
GCRChannel * ch;
{
int wireLength=0, viaCount=0, row, col;
short **res, mask, code, code2;
int hWire=0, vWire=0;
viaCount=0;
res=ch->gcr_result;
for(col=0; col<=ch->gcr_length; col++)
for(row=0; row<=ch->gcr_width; row++)
{
code=res[col][row];
if(code & GCRR)
{
wireLength++;
hWire++;
}
if(code & GCRU)
{
wireLength++;
vWire++;
}
if(code & GCRX)
{
/* There is a connection at the crossing. Count a contact if metal
* and poly come together here.
*/
mask=0;
code2=ch->gcr_result[col][row+1];
if(code&GCRU)
{
if(code&GCRVM) mask|=GCRBLKM; /*What type is up*/
else mask|=GCRBLKP;
}
code2=ch->gcr_result[col+1][row];
if(code&GCRR)
{
if(code2&GCRBLKM) mask|=GCRBLKP; /*What type is right*/
else mask|=GCRBLKM;
}
code2=ch->gcr_result[col][row-1];
if(code2&GCRU)
{
if(code2&GCRVM) mask|=GCRBLKM; /*What type is down*/
else mask|=GCRBLKP;
}
code2=ch->gcr_result[col-1][row];
if(code2&GCRR)
{
if(code2&GCRBLKM) mask|=GCRBLKP; /*What type is left*/
else mask|=GCRBLKM;
}
if((mask!=GCRBLKM)&&(mask!=GCRBLKP))
viaCount++;
}
}
TxPrintf("Length : %d\n", wireLength);
TxPrintf("Vias : %d\n", viaCount);
TxPrintf("Hwire : %d\n", hWire);
TxPrintf("Vwire : %d\n", vWire);
}
/*
* ----------------------------------------------------------------------------
*
* gcrCheckCol --
*
* Check the accuracy of the column's hi and lo pointers. Abort if there
* is a mistake.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrCheckCol(ch, c, where)
GCRChannel *ch;
int c;
char *where;
{
int i, j;
GCRColEl * col;
if(GcrNoCheck)
return;
col=ch->gcr_lCol;
for(i=0; i<=ch->gcr_width; i++)
{
if( (col[i].gcr_hOk || col[i].gcr_lOk) && (col[i].gcr_h==(GCRNet *) 0))
{
if(gcrStandalone)
{
TxError("Botch at column %d, %s (bad hOk/lOk at %d)\n",
c, where, i);
gcrDumpCol(col, ch->gcr_width);
}
if(GcrDebug)
niceabort();
}
if(((col[i].gcr_hi==i)||(col[i].gcr_lo==i))&&(i!=0))
{
if(gcrStandalone)
{
TxError("Botch at column %d, %s(pointer loop at %d)\n",
c, where, i);
gcrDumpCol(col, ch->gcr_width);
}
if(GcrDebug)
niceabort();
}
if(col[i].gcr_h!=(GCRNet *) NULL)
/* Look upward from the track for the next higher track assigned to
* the net, if any. Just take the first one, breaking afterwards.
*/
for(j=i+1; j<=ch->gcr_width; j++)
{
if(col[j].gcr_h==col[i].gcr_h)
{
/* Check to see if the lower track at i points to the higher
* track at j, and vice versa. If an error, abort.
*/
if( ((col[j].gcr_lo!=i) && !col[j].gcr_lOk &&
!col[i].gcr_hOk) ||
((col[i].gcr_hi!=j) && !col[i].gcr_hOk &&
!col[j].gcr_lOk) )
{
if(gcrStandalone)
{
TxError("Botch at column %d, %s", c, where);
TxError(" (link error from %d to %d)\n", i, j);
gcrDumpCol(col, ch->gcr_width);
}
if(GcrDebug) niceabort();
}
else break;
}
}
if((col[i].gcr_hi>ch->gcr_width)||(col[i].gcr_hi< EMPTY)||
(col[i].gcr_lo>ch->gcr_width)||(col[i].gcr_lo< EMPTY))
{
if(gcrStandalone)
{
TxError("Botch at column %d, %s (bounds)\n", c, where);
gcrDumpCol(col, ch->gcr_width);
}
if(GcrDebug) niceabort();
}
}
}
/*
* ----------------------------------------------------------------------------
*
* gcrShowMap --
*
* Print the bit map in the result array for the selected field.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrShowMap(ch)
GCRChannel * ch;
{
int i, j, field;
short ** res;
char buff[512];
if (!GcrShowMap)
return;
while (1)
{
TxPrintf("Field selector (0 terminates): ");
if(scanf("%d", &field) != 1) /*typed something funny or EOF*/
{
if (feof(stdin)) {
TxPrintf("End of input detected. Terminating.\n");
return;
}
TxPrintf("Bad input. Legal responses are\n");
TxPrintf(" GCRBLKM 1\n");
TxPrintf(" GCRBLKP 2\n");
TxPrintf(" GCRU 4\n");
TxPrintf(" GCRR 8\n");
TxPrintf(" GCRX 16\n");
TxPrintf(" GCRVL 32\n");
TxPrintf(" GCRV2 64\n");
TxPrintf(" GCRTC 128\n");
TxPrintf(" GCRCC 256\n");
TxPrintf(" GCRTE 512\n");
TxPrintf(" GCRCE 1024\n");
TxPrintf(" GCRVM 2048\n");
TxPrintf(" GCRXX 4096\n");
TxPrintf(" GCRVR 8192\n");
TxPrintf(" GCRVU 16384\n");
TxPrintf(" GCRVD 32768\n");
(void) fgets(buff, 512, stdin);
}
TxPrintf("\n%d\n", field);
if(field==0)
return;
TxPrintf("\n ");
for(j=0; j<=ch->gcr_width+1; j++)
TxPrintf("%2d", j);
for(i=0; i<=ch->gcr_length+1; i++)
{
res=ch->gcr_result;
TxPrintf("\n[%3d] ", i);
for(j=0; j<=ch->gcr_width+1; j++)
{
if(res[i][j] & field)
TxPrintf("1 ");
else
TxPrintf(". ");
}
}
TxPrintf("\n");
}
}