magic/mzrouter/mzTech.c

1401 lines
32 KiB
C

/*
* mzTech.c --
*
* Technology file read-in for the maze router.
* Processes mzrouter and drc sections of tech file to
* set up maze routing parameter sets.
*
* *********************************************************************
* * Copyright (C) 1988, 1990 Michael H. Arnold and the 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/mzrouter/mzTech.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.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 "wiring/wiring.h"
#include "utils/utils.h"
#include "utils/tech.h"
#include "utils/malloc.h"
#include "utils/list.h"
#include "windows/windows.h"
#include "utils/main.h"
#include "mzrouter/mzrouter.h"
#include "mzrouter/mzInternal.h"
/* Procedures referenced before they are defined
* (these procedures are local to this file)
*/
RouteType *mzFindRouteType();
RouteLayer *mzFindRouteLayer();
RouteContact *mzFindRouteContact();
/* Techspacing structure -
*
* This structure is used to build a temporary list of spacings from
* spacing lines in the mzrouter section of the technology file. Spacings are
* copied to RouteTypes after technology readin completes.
*/
typedef struct techspacing
{
RouteType *ts_routeType;
TileType ts_tileType;
int ts_spacing;
struct techspacing *ts_next;
} TechSpacing;
TechSpacing *mzTechSpacingList = NULL; /* Temporary list of explicit spacings.
* Generated by spacing lines in
* mzrouter
* section. Used in mzTechFinal to
* set spacings ispacings n RouteTypes
* after technology readin completes.
*/
/* mask of all routetypes - referenced in this file only */
TileTypeBitMask mzRTypesMask; /* And of bitmaps for tileTypes of
* all routeTypes of all styles
* (note image types for
* contacts included).
*/
/* Forward declarations */
extern void mzTechStyle();
extern void mzStyleEnd();
extern void mzSetParmDefaults();
extern void mzTechLayer();
extern void mzTechNotActive();
extern void mzTechSpacing();
extern void mzTechSearch();
extern void mzTechWidth();
extern void mzTechContact();
extern void mzInitRouteType();
extern void mzUpdateSpacing();
void mzWidthRule(int, char **);
void mzSpacingRule(int, char **);
void mzEdgeRule(int, char **);
/*
* ----------------------------------------------------------------------------
*
* MZFreeParameters ---
*
* Deallocate memory for a maze router style parameters structure.
*
* Results:
* None.
*
* Side effects:
* Memory free'd.
*
* ----------------------------------------------------------------------------
*/
void
MZFreeParameters(params)
MazeParameters *params;
{
RouteLayer *rL;
RouteContact *rC;
for (rL = params->mp_rLayers; rL; rL = rL->rl_next)
{
ListDealloc(rL->rl_contactL);
TiFreePlane(rL->rl_routeType.rt_hBlock);
TiFreePlane(rL->rl_routeType.rt_vBlock);
freeMagic(rL);
}
for (rC = params->mp_rContacts; rC; rC = rC->rc_next)
freeMagic(rC);
}
/*
* ----------------------------------------------------------------------------
*
* MZTechInit --
*
* Initialize the technology datastructures for the maze router.
* This routine is made a client of the tech module in main/main.c.
* It is called when the beginning of the "mzrouter" section is encountered.
*
* Results:
* None.
*
* ----------------------------------------------------------------------------
*/
void
MZTechInit()
{
MazeStyle *style;
/* Clear out any old information */
if (mzStyles != NULL)
{
for (style = mzStyles; style != NULL; style = style->ms_next)
{
MZFreeParameters(&(style->ms_parms));
freeMagic(style->ms_name);
freeMagic(style);
}
}
/* Initially no route types defined */
mzRTypesMask = DBZeroTypeBits;
/* Initially no maze styles are defined */
mzStyles = NULL;
return;
}
/*
* ----------------------------------------------------------------------------
*
* MZTechFinal --
*
* Close out final style.
* This routine is made a client of the tech module in main/main.c.
* It is called when the end of the "mzrouter" section is encountered.
*
* Results:
* None.
*
* ----------------------------------------------------------------------------
*/
void
MZTechFinal()
{
if(mzStyles)
{
mzStyleEnd();
}
return;
}
/*
* ----------------------------------------------------------------------------
*
* MZAfterTech --
*
* Finish up tech datastructures.
* This routine called by MZInit after tech file readin, or after grid
* rescaling, when the DRC rules are re-evaluated at the new scale. It
* derives all of the maze router width and spacing rules from the DRC
* rule set.
*
* Results:
* None.
*
* ----------------------------------------------------------------------------
*/
void
MZAfterTech()
{
MazeStyle *style;
RouteType *rT;
int i, maxSpacing;
/* Fill all width and spacing rules from DRC tables */
for(style=mzStyles; style!=NULL; style=style->ms_next)
{
for(rT=style->ms_parms.mp_rTypes; rT!=NULL; rT=rT->rt_next)
{
rT->rt_width = DRCGetDefaultLayerWidth(rT->rt_tileType);
for (i = 0; i < TT_MAXTYPES; i++)
rT->rt_spacing[i] = DRCGetDefaultLayerSpacing(rT->rt_tileType, i);
/* We assume square contacts and no area minimums unless */
/* specifically set by a wizard command (for now, at least) */
rT->rt_length = rT->rt_width;
}
}
/* Adjust spacings for all styles */
for(style=mzStyles; style!=NULL; style=style->ms_next)
{
List *l;
/* add (non SUBCELL) spacings in spacingL to spacing
* arrays in RouteTypes */
for(l=style->ms_spacingL; l!=NULL; l=LIST_TAIL(l))
{
TechSpacing *tS = (TechSpacing *) LIST_FIRST(l);
if(tS->ts_tileType != TT_SUBCELL)
{
tS->ts_routeType->rt_spacing[tS->ts_tileType] = tS->ts_spacing;
}
}
/* Compute spacing to unexpanded subcells for each routeType
* = maximum of all spacings for that route type
*/
for(rT=style->ms_parms.mp_rTypes; rT!=NULL; rT=rT->rt_next)
{
maxSpacing = 0;
for(i=0;i<TT_MAXTYPES;i++)
maxSpacing = MAX(maxSpacing,rT->rt_spacing[i]);
rT->rt_spacing[TT_SUBCELL] = maxSpacing;
}
/* add SUBCELL spacings in spacingL to spacing
* arrays in RouteTypes */
for(l=style->ms_spacingL; l!=NULL; l=LIST_TAIL(l))
{
TechSpacing *tS = (TechSpacing *) LIST_FIRST(l);
if(tS->ts_tileType == TT_SUBCELL)
{
tS->ts_routeType->rt_spacing[tS->ts_tileType] = tS->ts_spacing;
}
}
/* free up spacing list */
ListDeallocC(style->ms_spacingL);
style->ms_spacingL = NULL;
}
}
/*
* ----------------------------------------------------------------------------
*
* MZTechLine --
*
* This routine is made a client of the tech module in main/main.c.
* It is invoked during technology file readin, once for each line
* in the mzrouter section of the technology file.
*
* On each invocation one line of the "mzrouter" section is processed.
*
* Results:
* TRUE always.
*
* Side effects:
* An element is built and added to the RouteLayers or RouteContacts
* list. Or in the case of spacing request, the spacing is added to
* the deferred spacing list for processing in mzTechFinal after
* technology readin is completed.
*
* Note:
* The mzrouter section of the technology file must preceed the drc
* section. Thus the route layers and contacts are known prior
* to design rule processsing.
*
* ----------------------------------------------------------------------------
*/
bool
MZTechLine(sectionName, argc, argv)
char *sectionName; /* Unused */
int argc;
char *argv[];
{
if(strcmp(argv[0], "style") == 0)
{
mzTechStyle(argc, argv);
}
else if(mzStyles == NULL)
{
TechError("Missing style line.\n");
}
else if (strcmp(argv[0], "layer") == 0)
{
mzTechLayer(argc, argv);
}
else if (strcmp(argv[0], "contact") == 0)
{
mzTechContact(argc, argv);
}
else if (strcmp(argv[0], "notactive") == 0)
{
mzTechNotActive(argc, argv);
}
else if (strcmp(argv[0], "spacing") == 0)
{
mzTechSpacing(argc, argv);
}
else if (strcmp(argv[0], "search") == 0)
{
mzTechSearch(argc, argv);
}
else if (strcmp(argv[0], "width") == 0)
{
mzTechWidth(argc, argv);
}
else
{
TechError("Unrecognized keyword: \"%s\"\n", argv[0]);
}
return (TRUE);
}
/*
* ----------------------------------------------------------------------------
*
* mzTechStyle --
*
* Process a "style" line from the "mzrouter" section of the tech file.
* Each set of lines in the "mzrouter" section of the tech file is headed
* by a style line that gives a name to the set of parameters.
* Style lines have the form:
*
* style <name>
*
* Results:
* None.
*
* Side effects:
* Complete previous style and initial this one.
*
* ----------------------------------------------------------------------------
*/
void
mzTechStyle(argc, argv)
int argc;
char *argv[];
{
/* if there is a previous style, complete processing on it */
if(mzStyles)
{
mzStyleEnd();
}
/* alloc new style */
{
MazeStyle *new;
new = (MazeStyle*) mallocMagic((unsigned)(sizeof (MazeStyle)));
new->ms_name = StrDup(NULL, argv[1]);
new->ms_spacingL = NULL;
new->ms_next = mzStyles;
mzStyles = new;
}
/* set default parameters */
mzSetParmDefaults(&(mzStyles->ms_parms));
/* reset temporary lists */
mzRouteLayers = NULL;
mzRouteContacts = NULL;
mzRouteTypes = NULL;
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzStyleEnd --
*
* Close out style. (Saves temporary lists in parms for style.)
*
* Results:
* None.
*
* Side effects:
* See above.
*
* ----------------------------------------------------------------------------
*/
void
mzStyleEnd()
{
/* Reverse mzRouteLayer, mzRouteContacts and mzRouteTypes lists
* so they are displayed in order they appear in tech file.
*/
{
RouteLayer *newRLList;
RouteContact *newRCList;
RouteType *newRTList;
newRLList = NULL;
while(mzRouteLayers!=NULL)
{
RouteLayer *rL = mzRouteLayers;
mzRouteLayers = rL->rl_next;
rL->rl_next = newRLList;
newRLList = rL;
}
mzRouteLayers = newRLList;
newRCList = NULL;
while(mzRouteContacts!=NULL)
{
RouteContact *rC = mzRouteContacts;
mzRouteContacts = rC->rc_next;
rC->rc_next = newRCList;
newRCList = rC;
}
mzRouteContacts = newRCList;
newRTList = NULL;
while(mzRouteTypes!=NULL)
{
RouteType *rT = mzRouteTypes;
mzRouteTypes = rT->rt_next;
rT->rt_next = newRTList;
newRTList = rT;
}
mzRouteTypes = newRTList;
}
/* Copy lists to parm structure for this style */
mzStyles->ms_parms.mp_rLayers = mzRouteLayers;
mzStyles->ms_parms.mp_rContacts = mzRouteContacts;
mzStyles->ms_parms.mp_rTypes = mzRouteTypes;
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzSetParmDefaults --
*
* Results:
* None.
*
* Side effects:
* Sets default parameter values.
*
* ----------------------------------------------------------------------------
*/
void
mzSetParmDefaults(parms)
MazeParameters *parms;
{
/* initialize penalty factor for excess cost togo */
parms->mp_penalty.rf_mantissa = DEF_PENALTY_MANTISSA;
parms->mp_penalty.rf_nExponent = DEF_PENALTY_NEXPONENT;
/* Initialize other Search Control Parameters */
parms->mp_wRate = (dlong) DEF_WINDOW_RATE;
parms->mp_wWidth = (dlong) DEF_WINDOW_WIDTH;
parms->mp_bloomDeltaCost = (dlong) DEF_BLOOM_DELTA_COST;
/* initialize blockage generation increment */
parms->mp_boundsIncrement = DEF_BOUNDS_INCREMENT;
/* Estimation flags (if set nontrivial estimation used) */
parms->mp_estimate = DEF_ESTIMATE;
/* endpoint expansion flag, if set start and dest areas are
* expanded to include all electrically connected areas.
*/
parms->mp_expandEndpoints = DEF_EXPAND_ENDPOINTS;
/* If set, only hints in toplevel cell are recognized */
parms->mp_topHintsOnly = DEF_TOP_HINTS_ONLY;
/* Maximum penetration into node (or subcell) blockage to reach
* destination.
*/
parms->mp_maxWalkLength = DEF_MAX_WALK_LENGTH;
/* If nonnull, limits search area for performance
* NOTE: IF NONNULL, IT IS THE USERS RESPONSIBILITY TO CONFINE THE
* ROUTE TO WITHIN THIS AREA BY FENCES.
*/
parms->mp_boundsHint = NULL;
/* Amount of messages printed */
parms->mp_verbosity = DEF_VERBOSITY;
/* If positive, limit on number of blooms during search */
parms->mp_bloomLimit = DEF_BLOOM_LIMIT;
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzTechLayer --
*
* Process a "layer" line from the "mzrouter" section of the tech file.
* A layer line defines a route layer. It has the following form:
*
* layer layername hcost vcost jogcost hintcost overcost
*
* Results:
* None.
*
* Side effects:
* Builds and adds an element to the RouteLayers list.
* RouteType also added to RouteTypes list.
*
* ----------------------------------------------------------------------------
*/
void
mzTechLayer(argc, argv)
int argc;
char *argv[];
{
RouteLayer *new;
TileType tileType;
/* Check the argument count */
if (argc < 4 || argc > 7)
{
TechError("Malformed \"layer\" line, should be: \"layer name hCost vCost [jogCost [hintCost [overCost]]]\"\n");
return;
}
/* get the tiletype */
tileType = DBTechNoisyNameType(argv[1]);
if (tileType < 0) return;
/* make sure we don't already have a routeLayer on same plane */
{
RouteLayer *rL;
for(rL=mzRouteLayers; rL!=NULL; rL=rL->rl_next)
{
if(DBTypePlaneTbl[rL->rl_routeType.rt_tileType] ==
DBTypePlaneTbl[tileType])
{
TechError("Attempt to define two route layers on same plane: %s and %s\n",
DBTypeLongNameTbl[tileType],
DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
return;
}
}
}
/* Allocate new route layer */
new = (RouteLayer *) callocMagic((unsigned) (sizeof (RouteLayer)));
/* Initialize RouteType section */
mzInitRouteType(&(new->rl_routeType),tileType);
/* Initialize list of contacts connecting this layer to NULL */
new->rl_contactL = NULL;
/* set the plane */
new->rl_planeNum = DBPlane(new->rl_routeType.rt_tileType);
if (new->rl_planeNum < 0)
{
TechError("Type \"%s\" appears on more than one plane\n", argv[1]);
return;
}
/* set hCost */
if (!StrIsInt(argv[2]))
{
TechError("Cost arguments to \"layer\" line must be numeric\n");
return;
}
new->rl_hCost = atoi(argv[2]);
if (new->rl_hCost <= 0)
{
TechError("hCost must be > 0\n");
return;
}
/* set vCost */
if (!StrIsInt(argv[3]))
{
TechError("Cost arguments to \"layer\" line must be numeric\n");
return;
}
new->rl_vCost = atoi(argv[3]);
if (new->rl_vCost <= 0)
{
TechError("vCost must be > 0\n");
return;
}
/* Other costs are optional, and default to 1 */
new->rl_jogCost = 1;
new->rl_hintCost = 1;
new->rl_overCost = 1;
/* set jogCost */
if (argc > 4)
{
if (!StrIsInt(argv[4]))
{
TechError("Cost arguments to \"layer\" line must be numeric\n");
return;
}
new->rl_jogCost = atoi(argv[4]);
if (new->rl_jogCost <= 0)
{
TechError("jogCost must be > 0\n");
return;
}
}
/* set hintCost */
if (argc > 5)
{
if (!StrIsInt(argv[5]))
{
TechError("Cost arguments to \"layer\" line must be numeric\n");
return;
}
new->rl_hintCost = atoi(argv[5]);
if (new->rl_hintCost <= 0)
{
TechError("hintCost must be > 0\n");
return;
}
}
/* set overCost */
if (argc > 6)
{
if (!StrIsInt(argv[6]))
{
TechError("Cost arguments to \"layer\" line must be numeric\n");
return;
}
new->rl_overCost = atoi(argv[6]);
if (new->rl_overCost <= 0)
{
TechError("overCost must be > 0\n");
return;
}
}
/* Add new route layer to list */
new->rl_next = mzRouteLayers;
mzRouteLayers = new;
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzTechNotActive --
*
* Process a "notactive" line from the "mzrouter" section of the tech file.
* A notactive line specifies routetype(s) that are to be initially unavail.
* to the router.
*
* spacing routeType1 ... [routeTypen]
*
* Valid spacings are nonnegative integers, or "nil: if no spacing applies.
*
* Results:
* None.
*
* Side effects:
* Build and add an element to spacing list
*
* ----------------------------------------------------------------------------
*/
void
mzTechNotActive(argc, argv)
int argc;
char *argv[];
{
int argI;
TileType tileType;
RouteType *rT;
/* check number of arguments */
if(argc < 2)
{
TechError("Bad form on mzroute notactive.\n");
TechError("Usage: notactive routeType1 ... [routeTypen]\n");
return;
}
/* process args */
for(argI = 1; argI<argc; argI += 1)
{
/* convert arg to routeType */
{
tileType = DBTechNoisyNameType(argv[argI]);
if(tileType < 0) continue;
rT = mzFindRouteType(tileType);
if(rT==NULL)
{
TechError("Unrecognized route type: \"%.20s\"\n",
argv[argI]);
continue;
}
}
/* set to not active */
rT->rt_active = FALSE;
}
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzTechSpacing --
*
* Process a "spacing" line from the "mzrouter" section of the tech file.
* A spacing line defines spacings from a routetype (layer or contact) to
* other type(s). These spacings are stored on a list on technology readin
* and then actually set in the routeType structure after technology readin
* is complete. This is so they will overide default values based on the
* DRC section.
*
* spacing routeType type1 spacing1 ... [typen] [spacingn]
*
* Valid spacings are nonnegative integers, or "nil: if no spacing applies.
*
* Results:
* None.
*
* Side effects:
* Build and add an element to spacing list
*
* ----------------------------------------------------------------------------
*/
void
mzTechSpacing(argc, argv)
int argc;
char *argv[];
{
TechSpacing *new;
TileType tileType;
RouteType *rT;
int argI, value, which;
char *s;
/* Subcell Table */
static struct
{
char *sT_name; /* name of value */
int sT_value; /* corresponding interger value */
} subcellTable[] = {
"subcell", TT_SUBCELL,
0
};
/* check number of arguments */
if(argc <4 || ODD(argc))
{
TechError("Bad form on mzroute spacing.\n");
TechError("Usage: spacing routeType type1 spacing1 ... [typen spacingn]\n");
return;
}
/* convert first arg to routeType */
tileType = DBTechNoisyNameType(argv[1]);
if(tileType < 0) return;
rT = mzFindRouteType(tileType);
if(rT==NULL)
{
TechError("Unrecognized route type: \"%.20s\"\n",
argv[1]);
return;
}
for(argI = 2; argI<argc; argI += 2)
{
/* convert argI to type */
tileType = DBTechNameType(argv[argI]);
if(tileType<0)
{
/* if not a real type, check to see if "SUBCELL" */
which = LookupStruct(
argv[argI],
(LookupTable *) subcellTable,
sizeof subcellTable[0]);
if ( which>= 0)
tileType = TT_SUBCELL;
}
if(tileType<0)
{
TechError("Unrecognized layer (type): \"%.20s\"\n",
argv[argI]);
continue;
}
/* convert argI+1 to value */
s = argv[argI+1];
value = -2;
if (StrIsInt(s))
{
value = atoi(s);
if (value < 0)
{
TechError("Bad spacing value: %d\n",value);
TechError("Valid values are nonnegative integers and \"NIL\".\n");
return;
}
}
else if (strcmp(s,"NIL")==0)
{
value = -1;
}
else
{
TechError("Bad spacing value: %s\n",s);
TechError("Valid values are nonnegative integers and \"NIL\".\n");
return;
}
/* add entry to spacing list */
new = (TechSpacing*) mallocMagic((unsigned)(sizeof (TechSpacing)));
new->ts_routeType = rT;
new->ts_tileType = tileType;
new->ts_spacing = value;
LIST_ADD(new, mzStyles->ms_spacingL);
}
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzTechSearch --
*
* Process a "search" line from the "mzrouter" section of the tech file.
* A search line sets several parameters controlling the search.
* It has the form:
*
* search <rate> <width> <penalty>
*
* Rate and width must be positive integers, penalty a non-negative decimal.
* Search lines are optional, if none is given for a style default values
* are assigned.
*
* Results:
* None.
*
* Side effects:
* Set rate width and penalty parms for this style.
*
* ----------------------------------------------------------------------------
*/
void
mzTechSearch(argc, argv)
int argc;
char *argv[];
{
/* check number of arguments */
if(argc != 4)
{
TechError("Bad form on search.\n");
TechError("Usage: search <rate> <width> <penalty>\n");
return;
}
/* set WINDOW RATE */
if (!StrIsInt(argv[1]))
{
TechError("Bad rate: %s\n",argv[1]);
TechError("Rate must be a positive integer.\n");
}
else
{
int value = atoi(argv[1]);
if (value <= 0)
{
TechError("Bad rate: %d\n",value);
TechError("Rate must be a positive integer.\n");
}
else
{
mzStyles->ms_parms.mp_wRate = (dlong) value;
}
}
/* set WINDOW WIDTH */
if (!StrIsInt(argv[2]))
{
TechError("Bad width: %s\n",argv[2]);
TechError("Width must be a positive integer.\n");
}
else
{
int value = atoi(argv[2]);
if (value <= 0)
{
TechError("Bad width: %d\n",value);
TechError("Width must be a positive integer.\n");
}
else
{
mzStyles->ms_parms.mp_wWidth = (dlong) value;
}
}
/* set PENALTY */
{
float value;
if(sscanf(argv[3],"%f",&value)!=1)
{
TxError("Bad penalty value: %s\n",argv[3]);
TxError("Penalty must be non-negative decimal.\n");
}
else
{
if(value<0)
{
TxError("Bad penalty value: %f\n", value);
TxError("Penalty must be non-negative decimal.\n");
}
else
{
mzStyles->ms_parms.mp_penalty.rf_mantissa
= (int) (value *
(1<<mzStyles->ms_parms.mp_penalty.rf_nExponent));
}
}
}
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzTechWidth --
*
* Process "width" line from the "mzrouter" section of the tech file.
* A width line defines a routing width for a given route type. It
* has the form.
*
* width <routeType> <width>
*
* Valid widths are positive integers.
*
* Results:
* None.
*
* Side effects:
* Set width for given routetype in current style.
*
* ----------------------------------------------------------------------------
*/
void
mzTechWidth(argc, argv)
int argc;
char *argv[];
{
TileType tileType;
RouteType *rT;
int value;
/* check number of arguments */
if (argc !=3 && argc != 4)
{
TechError("Bad form on mzroute width.\n");
TechError("Usage: width <routeType> <width> [<length>]\n");
return;
}
/* convert first arg to routeType */
tileType = DBTechNoisyNameType(argv[1]);
if(tileType < 0) return;
rT = mzFindRouteType(tileType);
if(rT==NULL)
{
TechError("Unrecognized route type: \"%.20s\"\n",
argv[1]);
return;
}
/* convert 2nd arg to int */
{
if (!StrIsInt(argv[2]))
{
TechError("Bad width: %s\n",argv[2]);
TechError("Width must be a positive integer.\n");
return;
}
value = atoi(argv[2]);
if (value <= 0)
{
TechError("Bad width: %d\n",value);
TechError("Width must be a positive integer.\n");
return;
}
}
/* set width */
rT->rt_width = value;
/* convert 3rd arg, if any, to int */
if (argc == 4)
{
if (!StrIsInt(argv[3]))
{
TechError("Bad minimum length: %s\n",argv[3]);
TechError("Length must be a positive integer.\n");
return;
}
value = atoi(argv[3]);
if (value <= 0)
{
TechError("Bad minimum length: %d\n",value);
TechError("Length must be a positive integer.\n");
return;
}
rT->rt_length = value;
}
else
{
/* By default, set minimum length requirement to width */
rT->rt_length = rT->rt_width;
}
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzTechContact --
*
* Process a "contact" line from the "mzrouter" section of the tech file.
* A contact line defines a contact between route layers. It has the form:
*
* contact conlayer routelayer1 routelayer2 cost
*
* Results:
* None.
*
* Side effects:
* Build and add an element to RouteContacts list.
*
* ----------------------------------------------------------------------------
*/
void
mzTechContact(argc, argv)
int argc;
char *argv[];
{
RouteContact *new;
TileType type, tileType;
/* check arg count */
if (argc != 5)
{
TechError("Malformed \"contact\" line, should be: contact layer "
"layer1 layer2 cost\n");
return;
}
/* get tiletype */
tileType = DBTechNoisyNameType(argv[1]);
if(tileType < 0) return;
/* allocate new route contact */
new = (RouteContact *) callocMagic((unsigned) (sizeof (RouteContact)));
/* initialize RouteType section:
* sets route type, initializes spacing array, etc.
*/
mzInitRouteType(&(new->rc_routeType),tileType);
/* set first route layer */
type = DBTechNoisyNameType(argv[2]);
if(type<0) return;
new->rc_rLayer1 = mzFindRouteLayer(type);
if (new->rc_rLayer1==NULL)
{
TechError("route layer must be declared before used in contact.\n");
return;
}
/* add this contact to contacts list of first route layer */
LIST_ADD(new, new->rc_rLayer1->rl_contactL);
/* set second route layer */
type = DBTechNoisyNameType(argv[3]);
if(type<0) return;
new->rc_rLayer2 = mzFindRouteLayer(type);
if (new->rc_rLayer2==NULL)
{
TechError("route layer must be declared before used in contact.\n");
return;
}
/* add this contact to contacts list of second route layer */
LIST_ADD(new, new->rc_rLayer2->rl_contactL);
/* set cost */
if (!StrIsInt(argv[4]))
{
TechError("Cost argument to \"contact\" line must be numeric\n");
return;
}
new->rc_cost = atoi(argv[4]);
if (new->rc_cost <= 0)
{
TechError("Cost must be > 0\n");
return;
}
/* add route contact to list */
new->rc_next = mzRouteContacts;
mzRouteContacts = new;
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzInitRouteType --
*
* Initialize RouteType struc.
*
* Results:
* None.
*
* Side effects:
* Element added to mzRouteTypes list.
* Types ORed into mzRTypesMask.
*
* ----------------------------------------------------------------------------
*/
void
mzInitRouteType(rT,tileType)
RouteType *rT;
TileType tileType;
{
int t;
/* Get mask of all image types of routeType.
* RouteLayers will have one bit set in mask. RouteContacts will have
* two bits set, one for the contact "home" type, and one for the contact
* image type on the plane it connects to.
*/
TileTypeBitMask *imageTypeMask = &(DBLayerTypeMaskTbl[tileType]);
/* set tileType */
rT->rt_tileType = tileType;
/* initialize as active */
rT->rt_active = TRUE;
/* initialize spacing array (gives spacing between
* RouteType and all tiletypes)
*/
for (t=0;t<TT_MAXTYPES;t++)
{
/* If type "t" is on home plane of RouteType or
* plane of image of RouteContact */
if( DBTypePlaneTbl[t] >= 0 ) {
if(TTMaskIntersect(&(DBPlaneTypes[DBTypePlaneTbl[t]]),imageTypeMask)
&& t!=TT_SPACE)
{
/* initialize to zero spacing - i.e. no overlap allowed */
rT->rt_spacing[t] = 0;
}
else
{
/* otherwise no default spacing restriction applys */
rT->rt_spacing[t] = -1;
}
}
}
/* Initialize Blockage Planes */
rT->rt_hBlock = DBNewPlane((ClientData) TT_SPACE);
rT->rt_vBlock = DBNewPlane((ClientData) TT_SPACE);
/* Change tile policy for vertical plane */
rT->rt_vBlock->pl_policy = MAX_VERT_STRIPS;
/* Add to RouteType list */
rT->rt_next = mzRouteTypes;
mzRouteTypes = rT;
/* OR type and images into global route types mask */
TTMaskSetMask(&mzRTypesMask,imageTypeMask);
return;
}
/*
* ----------------------------------------------------------------------------
*
* mzFindRouteType --
*
* Search RouteLayer and RouteContact lists for routeType of given
* tile type.
*
* Results:
* pointer to routetype struc if found, else Null.
*
* ----------------------------------------------------------------------------
*/
RouteType *
mzFindRouteType(type)
TileType type;
{
RouteType *rT;
/* Search list of routetypes for one with appropriate type */
for (rT = mzRouteTypes;
rT && rT->rt_tileType!=type;
rT=rT->rt_next)
;
/* return result */
return(rT);
}
/*
* ----------------------------------------------------------------------------
*
* mzFindRouteLayer --
*
* Find routelayer struc for given tiletype.
*
* Results:
* pointer to routelayer struc if found, else Null.
*
* ----------------------------------------------------------------------------
*/
RouteLayer *
mzFindRouteLayer(type)
TileType type;
{
RouteLayer *rL;
/* Search list of routelayers for one with appropriate type */
for (rL = mzRouteLayers;
rL && rL->rl_routeType.rt_tileType!=type;
rL=rL->rl_next)
;
/* return result */
return(rL);
}
/*
* ----------------------------------------------------------------------------
*
* mzFindRouteContact --
*
* Find routecontact struc for given tiletype.
*
* Results:
* pointer to routecontact struc if found, else Null.
*
* ----------------------------------------------------------------------------
*/
RouteContact *
mzFindRouteContact(type)
TileType type;
{
RouteContact *rC;
/* Search list of routecontacts for one with appropriate type */
for (rC = mzRouteContacts;
rC && rC->rc_routeType.rt_tileType!=type;
rC=rC->rc_next)
;
/* return result */
return(rC);
}
/*
* ----------------------------------------------------------------------------
*
* mzUpdateSpacing --
*
* Add spacing requirement to RouteType.
* (RouteTypes are routing layers and contact layers used by the router.)
*
* Results:
* None.
*
* SideEffects:
* RouteType struc modifed.
*
* ----------------------------------------------------------------------------
*/
void
mzUpdateSpacing(rType,tType,distance)
RouteType *rType; /* Route Type to which spacing applies */
TileType tType; /* spacing from this tiletype */
int distance; /* min spacing betweeen rType and tType */
{
rType->rt_spacing[tType] =
MAX(rType->rt_spacing[tType],distance);
#ifdef debugmha
TxPrintf("UPDATESPACING:\n");
TxPrintf("\troute type = %s\n",DBTypeLongNameTbl[rType->rt_tileType]);
TxPrintf("\tother type = %s\n",DBTypeLongNameTbl[tType]);
TxPrintf("\tdistance = %d\n",distance);
#endif /* debugmha */
return;
}