Logo Search packages:      
Sourcecode: magic version File versions  Download package

mzTech.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-7.5/mzrouter/mzTech.c,v 1.7 2007/03/24 22:58:43 tim Exp $";
#endif  /* not lint */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/hash.h"
#include "utils/heap.h"
#include "tiles/tile.h"
#include "database/database.h"
#include "utils/signals.h"
#include "textio/textio.h"
#include "wiring/wiring.h"
#include "utils/utils.h"
#include "utils/tech.h"
#include "utils/malloc.h"
#include "utils/list.h"
#include "windows/windows.h"
#include "utils/main.h"
#include "mzrouter/mzrouter.h"
#include "mzrouter/mzInternal.h"

/* Procedures referenced before they are defined 
 * (these procedures are local to this file)
 */
RouteType *mzFindRouteType();
RouteLayer *mzFindRouteLayer();
RouteContact *mzFindRouteContact();

/* Techspacing structure -
 * 
 * This structure is used to build a temporary list of spacings from
 * spacing lines in the mzrouter section of the technology file.  Spacings are
 * copied to RouteTypes after technology readin completes.
 */
00061 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 controling 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;
}


Generated by  Doxygen 1.6.0   Back to index