/* * 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[] = "$Header: /ufs/repository/magic/mzrouter/mzTech.c,v 1.2 2001/01/12 22:13:03 jsolomon Exp $"; #endif #include #include "misc/magic.h" #include "utils/geometry.h" #include "utils/hash.h" #include "utils/doubleint.h" #include "utils/heap.h" #include "tiles/tile.h" #include "database/database.h" #include "signals/signals.h" #include "textio/textio.h" #include "wiring/wiring.h" #include "utils/utils.h" #include "tech/tech.h" #include "utils/malloc.h" #include "utils/list.h" #include "windows/windows.h" #include "main/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). */ /* * ---------------------------------------------------------------------------- * * 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() { /* 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. * * Results: * None. * * ---------------------------------------------------------------------------- */ Void mzAfterTech() { MazeStyle *style; RouteType *rT; int i, maxSpacing; /* Now that DRC tech readin is complete, 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); } return; } /* * ---------------------------------------------------------------------------- * * 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. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ 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; MALLOC(MazeStyle*, new, 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 */ DOUBLE_CREATE(parms->mp_wRate, DEF_WINDOW_RATE); DOUBLE_CREATE(parms->mp_wWidth, DEF_WINDOW_WIDTH); DOUBLE_CREATE(parms->mp_bloomDeltaCost, 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; /* dest expansion flag, if set dest areas are expanded to include * all electrically connected areas. */ parms->mp_expandDests = DEF_EXPAND_DESTS; /* 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 * * 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!=6) { TechError("Malformed \"layer\" line, should be: \"layer name hCost vCost jogCost hintCost\"\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 */ CALLOC(RouteLayer *, new, 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; } /* set jogCost */ 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 (!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; } /* 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[]; { register 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 */ MALLOC(TechSpacing*, new, 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 controling 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 { DOUBLE_CREATE(mzStyles->ms_parms.mp_wRate,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 { DOUBLE_CREATE(mzStyles->ms_parms.mp_wWidth,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) { 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; 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[]; { register 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 */ CALLOC(RouteContact *, new, 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; } /* * ---------------------------------------------------------------------------- * * MZDRCInit -- * * Initialization before processing the "drc" section for the * interactive router. * * Made client of tech module in main/main.c. * Called prior to technology file read in. * * Results: * None. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ Void MZDRCInit() { return; } /* * ---------------------------------------------------------------------------- * * MZDRCLine -- * * Process a single line of the "drc" section, to garner spacing info. * for the route layers. * * This routine is made a client of the tech module in main/main.c, and * is called once for each line in the drc section of the technogy file. * * Results: * TRUE always. * * Side effects: * Add spacing info to the RouteLayers. * * Organization: * We select a procedure based on the first keyword (argv[0]) * and call it to do the work of implementing the rule. Each * such procedure is of the following form: * * Void * proc(argc, argv) * int argc; * char *argv[]; * { * } * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ bool MZDRCLine(sectionName, argc, argv) char *sectionName; /* Unused */ int argc; char *argv[]; { Void mzWidthRule(); Void mzSpacingRule(); Void mzEdgeRule(); int which; static struct { char *rk_keyword; /* Initial keyword */ int rk_minargs; /* Min # arguments */ int rk_maxargs; /* Max # arguments */ int (*rk_proc)(); /* Procedure implementing this keyword */ } ruleKeys[] = { "edge", 8, 9, mzEdgeRule, "edge4way", 8, 9, mzEdgeRule, "spacing", 6, 6, mzSpacingRule, "width", 4, 4, mzWidthRule, 0 }, *rp; /* * Leave the job of printing error messages to the DRC tech file reader. */ which = LookupStruct(argv[0], (LookupTable *) ruleKeys, sizeof ruleKeys[0]); if (which >= 0) { rp = &ruleKeys[which]; if (argc >= rp->rk_minargs && argc <= rp->rk_maxargs) (*rp->rk_proc)(argc, argv); } return (TRUE); } /* * ---------------------------------------------------------------------------- * * mzWidthRule -- * * Process a width rule. * This is of the form: * * width types width error * e.g, width diff,dmc,dfet 2 "diffusion width must be at least 2" * * Results: * None. * * Side effects: * Add width info to appropriate RouteType strucs. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ mzWidthRule(argc, argv) int argc; char *argv[]; { int width = atoi(argv[2]); TileTypeBitMask typeSet; register TileType t; /* convert type list to mask */ DBTechNoisyNameMask(argv[1], &typeSet); /* for types on list on width rule that pertain to routeTypes */ for (t = TT_SELECTBASE; t < DBNumTypes; t++) { if (TTMaskHasType(&typeSet, t) && TTMaskHasType(&mzRTypesMask, t)) { MazeStyle *style; /* for routetypes that t is an image of */ for(style=mzStyles; style!=NULL; style=style->ms_next) { RouteType *rT; for (rT=style->ms_parms.mp_rTypes; rT!=NULL; rT = rT->rt_next) { if(TTMaskHasType(&(DBLayerTypeMaskTbl[rT->rt_tileType]),t)) { /* update width in RouteType */ rT->rt_width = MAX(rT->rt_width,width); } } } } } return; } /* * ---------------------------------------------------------------------------- * * mzSpacingRule -- * * Process a spacing rule. * This is of the form: * * spacing layers1 layers2 distance adjacency why * e.g, spacing metal,pmc/m,dmc/m metal,pmc/m,dmc/m 4 touching_ok \ * "metal spacing must be at least 4" * * Adjacency may be either "touching_ok" or "touching_illegal", * but this doesn't matter here. * * Results: * None. * * Side effects: * Add spacing info to appropriate RouteType strucs. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ mzSpacingRule(argc, argv) int argc; char *argv[]; { int distance = atoi(argv[3]); TileTypeBitMask set1, set2; register int t, t1, t2; /* convert layer lists to masks */ DBTechNoisyNameMask(argv[1], &set1); DBTechNoisyNameMask(argv[2], &set2); /* for types in set1 that pertain to routeTypes */ for (t = TT_SELECTBASE; t < DBNumTypes; t++) { if (TTMaskHasType(&set1, t) && TTMaskHasType(&mzRTypesMask, t)) { MazeStyle *style; /* for routetypes that t is an image of */ for(style=mzStyles; style!=NULL; style=style->ms_next) { RouteType *rT; /* for routetypes that t is an image of */ for (rT=style->ms_parms.mp_rTypes; rT!=NULL; rT = rT->rt_next) { if(TTMaskHasType(&(DBLayerTypeMaskTbl[rT->rt_tileType]),t)) { /* for tiletypes in set2 */ for (t2 = TT_SELECTBASE; t2 < DBNumTypes; t2++) { if (TTMaskHasType(&set2, t2)) { /* interpolate spacing between route type in * set1 and arbitarary tiletype in set2 into * routeLayer data structure */ mzUpdateSpacing(rT,t2,distance); } } } } } } } /* for types in set2 that pertain to routeTypes */ for (t = TT_SELECTBASE; t < DBNumTypes; t++) { if (TTMaskHasType(&set2, t) && TTMaskHasType(&mzRTypesMask, t)) { MazeStyle *style; /* for routetypes that t is an image of */ for(style=mzStyles; style!=NULL; style=style->ms_next) { RouteType *rT; /* for routetypes that t is an image of */ for (rT=style->ms_parms.mp_rTypes; rT!=NULL; rT = rT->rt_next) { if(TTMaskHasType(&(DBLayerTypeMaskTbl[rT->rt_tileType]),t)) { /* for tiletypes in set1 */ for (t1 = TT_SELECTBASE; t1 < DBNumTypes; t1++) { if (TTMaskHasType(&set1, t1)) { /* interpolate spacing between route layer * in set2 and arbitarary tiletype in set1 * into routeLayer data structure */ mzUpdateSpacing(rT,t1,distance); } } } } } } } return; } /* * ---------------------------------------------------------------------------- * * mzEdgeRule -- * ******************* NOTE CURRENTLY THIS FUNC IS A NO OP. *************** * Process a primitive edge rule. * * This is of the form: * * edge types1 types2 dist okTypes cornerTypes cornerDist errorMsg [plane] * or * edge4way layers1 layers2 dist okTypes cornerTypes cornerDist errorMsg * [plane] * e.g, * edge poly,pmc s 1 diff poly,pmc "poly-diff separation must be 2" * * An "edge" rule is applied only down and to the left. * An "edge4way" rule is applied in all four directions. * * Results: * None. * * Side effects: * Updates Spacing info associated with RouteTypes. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ mzEdgeRule(argc, argv) int argc; char *argv[]; { #ifdef notdef TileTypeBitMask types1Set, types2Set, okTypesSet, cornerTypesSet; TileTypeBitMask tmp1; register TileType t1,tCheck; RouteType *rT; int pNum, checkPlane; int distance; /* give names to args */ bool isFourWay = (strcmp(argv[0], "edge4way") == 0); char * types1 = argv[1]; char * types2 = argv[2]; int dist = atoi(argv[3]); char * okTypes = argv[4]; char * cornerTypes = argv[5]; int cornerDist = atoi(argv[6]); char * errorMsg = argv[7]; char * plane = ((argc==9) ? argv[8] : NULL); /* convert type lists to masks */ DBTechNoisyNameMask(types1, &types1Set); DBTechNoisyNameMask(types2, &types2Set); DBTechNoisyNameMask(okTypes, &okTypesSet); DBTechNoisyNameMask(cornerTypes, &cornerTypesSet); /*---- Find plane common to types1 and types2 *---- (the types of these sets should be on a common plane, *---- if not, we just return) *---- */ /* first find plane common to types1Set */ for (pNum = PL_SELECTBASE; pNum < DBNumPlanes; pNum++) if (DBTechSubsetLayers(types1Set, DBPlaneTypes[pNum], &tmp1)) break; /* if none, return */ if (pNum >= DBNumPlanes) return; /* if types2Set not on same plane, return */ if (!DBTechSubsetLayers(types2Set, DBPlaneTypes[pNum], &tmp1)) return; /* Get images of types1 and types2 on common plane * (i.e. exclude contact images on other planes) */ ASSERT(DBTechSubsetLayers(types1Set, DBPlaneTypes[pNum], &types1Set), "mzEdgeRule"); ASSERT(DBTechSubsetLayers(types2Set, DBPlaneTypes[pNum], &types2Set), "mzEdgeRule"); /* If an explicit check plane was specified, use it, else use * plane of set1 and set2 (computed above). */ if(plane!=NULL) { checkPlane = DBTechNamePlane(plane); if (checkPlane<0) return; } else { checkPlane = pNum; } /* Get the images of everything in okTypes on the check plane */ if (!DBTechSubsetLayers(okTypesSet, DBPlaneTypes[checkPlane], &okTypesSet)) return; /* * PROCESS CASE1: types2 includes space. * => * Spacings are recorded between the types1 and routeTypes on * checkPlane that are not in okTypes. * * In case1 no distinction is made between edge and edge4way * rules and the max of dist and cornerDist is used as the spacing * distance, e.g. the rules are interpeted conservatively as * simple spacing rules. */ if (TTMaskHasType(&types2Set, TT_SPACE)) { /* spacing distance is max of dist and cornerDist */ distance = MAX(dist,cornerDist); /* for each type in types1 */ for (t1 = TT_SELECTBASE; t1 < DBNumTypes; t1++) if (TTMaskHasType(&types1Set, t1)) { /* for each routeType on the checkPlane but not in setOK */ for (tCheck = TT_SELECTBASE; tCheck < DBNumTypes; tCheck++) if(!TTMaskHasType(&okTypesSet,tCheck) && TTMaskHasType(&mzRTypesMask,tCheck) && DBPlane(tCheck)==checkPlane) { /* add spacing to routeType struc */ rT=mzFindRouteType(tCheck); ASSERT(rT!=NULL,"mzEdgeRule"); mzUpdateSpacing(rT,t1,distance); } } } return; #endif } /* * ---------------------------------------------------------------------------- * * mzInitRouteType -- * * Initialize RouteType struc. * * Results: * None. * * Side effects: * Element added to mzRouteTypes list. * Types ORed into mzRTypesMask. * * ---------------------------------------------------------------------------- */ 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. * * ---------------------------------------------------------------------------- */ 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 return; }