/* * 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 #include #include #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;irt_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 * * 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; argIrt_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= 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 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 \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<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 * * 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 []\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= 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; }