1401 lines
32 KiB
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"
|
|
|
|
/* C99 compat */
|
|
#include "drc/drc.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;
|
|
}
|
|
|