1398 lines
32 KiB
C
1398 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);
|
||
|
||
/* 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;
|
||
}
|
||
|