Files
magic/garouter/gaTest.c
T
R. Timothy Edwards 516c9d7635 First cut of pulling the TT_SIDE bit out of the tile database
and forcing it to be passed as an argument to all the callback
functions for the search routines that require it.  Magic now
compiles and runs with the new code, but there are a number of
known issues that need to be fixed up.  Committing now so that
I can rebase on the last update to the master branch.
2026-01-09 12:05:03 -05:00

418 lines
11 KiB
C

/*
* gaTest.c --
*
* Testing code for the gate-array 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/garouter/gaTest.c,v 1.2 2009/05/01 18:59:44 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 "utils/signals.h"
#include "textio/textio.h"
#include "debug/debug.h"
#include "gcr/gcr.h"
#include "router/router.h"
#include "grouter/grouter.h"
#include "graphics/graphics.h"
#include "garouter/garouter.h"
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "textio/txcommands.h"
#include "utils/main.h"
#include "utils/utils.h"
#include "commands/commands.h"
#include "utils/styles.h"
bool gaInitialized = FALSE;
ClientData gaDebugID = 0;
int gaDebChanOnly = 0;
int gaDebChanStats = 0;
int gaDebMaze = 0;
int gaDebNoSimple = 0;
int gaDebPaintStems = 0;
int gaDebShowChans = 0;
int gaDebShowMaze = 0;
int gaDebStems = 0;
int gaDebVerbose = 0;
int gaDebNoClean = 0;
/* Used in the "*garoute split" command */
PlaneMask gaSplitPlaneMask;
int (*gaSplitPaintPlane)();
Rect gaSplitArea;
int gaSplitType;
/* Forward declarations */
void GAInit();
/*
* ----------------------------------------------------------------------------
*
* GATest --
*
* Command interface for testing the gate-array router.
*
* Results:
* None.
*
* Side effects:
* Depends on the command; see below.
*
* ----------------------------------------------------------------------------
*/
void
GATest(w, cmd)
MagWindow *w;
TxCommand *cmd;
{
int n;
typedef enum { CLRDEBUG, SETDEBUG, SHOWDEBUG} cmdType;
static const struct
{
char *cmd_name;
cmdType cmd_val;
} cmds[] = {
{"clrdebug", CLRDEBUG},
{"setdebug", SETDEBUG},
{"showdebug", SHOWDEBUG},
{0}
};
GAInit();
if (cmd->tx_argc == 1)
{
TxError("Must give subcommand\n");
goto badCmd;
}
n = LookupStruct(cmd->tx_argv[1], (const LookupTable *) cmds, sizeof cmds[0]);
if (n < 0)
{
TxError("Unrecognized subcommand: %s\n", cmd->tx_argv[1]);
badCmd:
TxError("Valid subcommands:");
for (n = 0; cmds[n].cmd_name; n++)
TxError(" %s", cmds[n].cmd_name);
TxError("\n");
return;
}
switch (cmds[n].cmd_val)
{
case SETDEBUG:
DebugSet(gaDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], TRUE);
break;
case CLRDEBUG:
DebugSet(gaDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], FALSE);
break;
case SHOWDEBUG:
DebugShow(gaDebugID);
break;
}
return;
}
/*
* ----------------------------------------------------------------------------
*
* GAGenChans --
*
* Generate gate-array channels over the area 'area'. These channels
* will be one of two types: CHAN_NORMAL, for channels over empty space,
* or chanType (either CHAN_HRIVER or CHAN_VRIVER) for channels over
* existing subcells. The output is a collection of "garoute channel"
* commands on the file 'f'.
*
* Results:
* None.
*
* Side effects:
* Writes to 'f'.
*
* ----------------------------------------------------------------------------
*/
void
GAGenChans(chanType, area, f)
int chanType;
Rect *area;
FILE *f;
{
extern int DBPaintPlane0(), DBPaintPlaneVert();
int gaSplitFunc(), gaSplitOut();
static CellDef *genDef = (CellDef *) NULL;
static CellUse *genUse = (CellUse *) NULL;
TileTypeBitMask obstacleMask;
int halfUp, halfDown;
SearchContext scx;
Plane *plane;
if (genDef == NULL)
DBNewYank("__GENCHANNEL__", &genUse, &genDef);
/*
* Round the appropriate side of area down to the nearest
* center-grid line.
*/
halfDown = RtrGridSpacing / 2;
halfUp = RtrGridSpacing - halfDown;
switch (chanType)
{
case CHAN_HRIVER:
gaSplitPaintPlane = DBPaintPlane0;
area->r_ytop = RTR_GRIDDOWN(area->r_ytop - halfUp, RtrOrigin.p_y)
+ halfUp;
area->r_ybot = RTR_GRIDUP(area->r_ybot + halfDown, RtrOrigin.p_y)
- halfDown;
break;
case CHAN_VRIVER:
gaSplitPaintPlane = DBPaintPlaneVert;
area->r_xtop = RTR_GRIDDOWN(area->r_xtop - halfUp, RtrOrigin.p_x)
+ halfUp;
area->r_xbot = RTR_GRIDUP(area->r_xbot + halfDown, RtrOrigin.p_x)
- halfDown;
break;
}
/* Make sure everything in 'area' is read */
(void) DBCellReadArea(EditCellUse, area, FALSE);
DBFixMismatch();
/* Start with a clean slate */
DBCellClearDef(genDef);
/*
* Basic algorithm:
* Find all cells in 'area'. Compute the bounding rectangle for
* each plane that can affect routing. Bloat by RtrSubcellSepUp or
* RtrSubcellSepDown (appropriate direction). Extend this to the top
* and bottom of 'area' for CHAN_HRIVER channels, or to the left and
* right of 'area' for CHAN_VRIVER ones, and paint into the DRC error
* plane of genDef.
*/
TTMaskSetMask3(&obstacleMask, &RtrPolyObstacles, &RtrMetalObstacles);
TTMaskSetType(&obstacleMask, RtrMetalType);
TTMaskSetType(&obstacleMask, RtrPolyType);
TTMaskSetType(&obstacleMask, RtrContactType);
gaSplitPlaneMask = DBTechTypesToPlanes(&obstacleMask);
gaSplitArea = *area;
gaSplitType = chanType;
scx.scx_use = EditCellUse;
scx.scx_area = gaSplitArea;
scx.scx_trans = GeoIdentityTransform;
plane = genDef->cd_planes[PL_DRC_ERROR];
(void) DBCellSrArea(&scx, gaSplitFunc, (ClientData) plane);
/* Output all the tiles that lie inside 'area' in 'plane */
(void) DBSrPaintArea((Tile *) NULL, plane, &gaSplitArea, &DBAllTypeBits,
gaSplitOut, (ClientData) f);
}
/*
* ----------------------------------------------------------------------------
*
* gaSplitOut --
*
* Called for each tile inside the area that was processed by GAGenChans()
* above. Outputs each tile as the appropriate type of channel (space
* tiles are CHAN_NORMAL, non-space are either CHAN_HRIVER or CHAN_VRIVER)
* after first clipping to the area gaSplitArea.
*
* Results:
* Always returns 0.
*
* Side effects:
* Writes to 'f'.
*
* ----------------------------------------------------------------------------
*/
int
gaSplitOut(tile, dinfo, f)
Tile *tile;
TileType dinfo; /* (unused) */
FILE *f;
{
Rect r;
TITORECT(tile, &r);
GeoClip(&r, &gaSplitArea);
if (GEO_RECTNULL(&r))
return (0);
fprintf(f, "garoute channel %d %d %d %d",
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
if (TiGetType(tile) != TT_SPACE)
fprintf(f, " %s", gaSplitType == CHAN_HRIVER ? "h" : "v");
fprintf(f, "\n");
return (0);
}
/*
* ----------------------------------------------------------------------------
*
* gaSplitFunc --
*
* Called for each cell in the area being processed by GAGenChans()
* above. Computes a "true" bounding box for the cell (only looking
* at the layers that are obstacles to routing), and then extends the
* box as follows:
*
* If producing CHAN_HRIVER channels, we extend the box to the
* top and bottom of gaSplitArea, and bloat it to the right and
* left to the next farthest-out line between two grid lines.
*
* If producing CHAN_VRIVER channels, we extend the box to the
* left and right of gaSplitArea, and bloat it to the top and
* bottom to the next farthest-out line between two grid lines.
*
* Results:
* Always returns 0.
*
* Side effects:
* Paints the bloated area into the DRC error plane of 'plane'
* with a TileType of 1.
*
* ----------------------------------------------------------------------------
*/
int
gaSplitFunc(scx, plane)
SearchContext *scx;
Plane *plane;
{
int halfUp, halfDown;
CellDef *def = scx->scx_use->cu_def;
Rect r, rAll, rTrans;
int pNum;
/* Compute the bounding rect for the interesting planes */
rAll = GeoNullRect;
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
if (PlaneMaskHasPlane(gaSplitPlaneMask, pNum))
{
if (DBBoundPlane(def->cd_planes[pNum], &r))
(void) GeoInclude(&r, &rAll);
}
GeoTransRect(&scx->scx_trans, &rAll, &rTrans);
GeoClip(&rTrans, &gaSplitArea);
/* Skip if no area */
if (GEO_RECTNULL(&rTrans))
return (0);
/* Extend in the appropriate direction and bloat in the other one */
halfDown = RtrGridSpacing / 2;
halfUp = RtrGridSpacing - halfDown;
switch (gaSplitType)
{
case CHAN_HRIVER:
rTrans.r_ytop = gaSplitArea.r_ytop;
rTrans.r_ybot = gaSplitArea.r_ybot;
rTrans.r_xtop += RtrSubcellSepUp;
rTrans.r_xbot -= RtrSubcellSepDown;
rTrans.r_xtop = RTR_GRIDUP(rTrans.r_xtop + halfDown, RtrOrigin.p_x)
- halfUp;
rTrans.r_xbot = RTR_GRIDDOWN(rTrans.r_xbot - halfUp, RtrOrigin.p_x)
+ halfDown;
break;
case CHAN_VRIVER:
rTrans.r_xtop = gaSplitArea.r_xtop;
rTrans.r_xbot = gaSplitArea.r_xbot;
rTrans.r_ytop += RtrSubcellSepUp;
rTrans.r_ybot -= RtrSubcellSepDown;
rTrans.r_ytop = RTR_GRIDUP(rTrans.r_ytop + halfDown, RtrOrigin.p_y)
- halfUp;
rTrans.r_ybot = RTR_GRIDDOWN(rTrans.r_ybot - halfUp, RtrOrigin.p_y)
+ halfDown;
break;
}
/* Paint into DRC error plane */
(*gaSplitPaintPlane)(plane, &rTrans, DBStdWriteTbl(1),
(PaintUndoInfo *) NULL, PAINT_NORMAL);
return (0);
}
/*
* ----------------------------------------------------------------------------
*
* GAInit --
*
* One-time-only initialization for the gate-array router.
* Called after technology initialization.
*
* Results:
* None.
*
* Side effects:
* Register ourself with the debug module and list all
* debugging flags. Also initialize channel information.
*
* ----------------------------------------------------------------------------
*/
void
GAInit()
{
int n;
static struct
{
char *di_name;
int *di_id;
} dflags[] = {
{"chanonly", &gaDebChanOnly},
{"chanstats", &gaDebChanStats},
{"maze", &gaDebMaze},
{"nosimple", &gaDebNoSimple},
{"paintstems", &gaDebPaintStems},
{"showchans", &gaDebShowChans},
{"showmaze", &gaDebShowMaze},
{"stems", &gaDebStems},
{"verbose", &gaDebVerbose},
{"noclean", &gaDebNoClean},
{0}
};
if (gaInitialized)
return;
gaInitialized = TRUE;
/* Register ourselves with the debugging module */
gaDebugID = DebugAddClient("garouter", sizeof dflags/sizeof dflags[0]);
for (n = 0; dflags[n].di_name; n++)
*(dflags[n].di_id) = DebugAddFlag(gaDebugID, dflags[n].di_name);
/* Initialize channel information */
GAChannelInitOnce();
}