/* rtrTech.c - * * This file processes the part of technology files that * provides information to the router. It sets up information * giving, for example, the layers to use for routing, their * widths, and so on. * * ********************************************************************* * * Copyright (C) 1985, 1990 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/router/rtrTech.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/utils.h" #include "utils/geometry.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "utils/tech.h" #include "textio/textio.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "router/router.h" /* The global routing variables are defined below. See router.h * for a description of what they mean. */ /* These are used by non-router modules (maybe they shouldn't be?) so */ /* they are defined in dbwind/DBWdisplay.c, one of the places where */ /* they are used. */ /* int RtrMetalWidth, RtrPolyWidth, RtrContactWidth; */ TileType RtrMetalType, RtrPolyType, RtrContactType; int RtrContactOffset; int RtrMetalSurround, RtrPolySurround; int RtrGridSpacing; int RtrSubcellSepUp, RtrSubcellSepDown; TileTypeBitMask RtrMetalObstacles, RtrPolyObstacles; int RtrPaintSepsUp[TT_MAXTYPES], RtrPaintSepsDown[TT_MAXTYPES]; /* The arrays below are used to hold the obstacle information separately * for the two routing layers. These are used temporarily while reading * the technology file, but also used directly by the maze router. Eventually * the info is combined and put into RtrPaintSepsUp and RtrPaintSepsDown. */ int RtrMetalSeps[TT_MAXTYPES], RtrPolySeps[TT_MAXTYPES]; /* * ---------------------------------------------------------------------------- * * RtrTechInit -- * * This routine is called once just before reading the router * section of the technology file. * * Results: * None. * * Side effects: * Initializes the data structures. The main idea is to make * things consistent so that if there is an empty router section, * the router won't crash if it's invoked (it probably won't * generate nice routing, but at least it won't core dump). * * ---------------------------------------------------------------------------- */ void RtrTechInit() { int i; RtrMetalType = RtrPolyType = RtrContactType = TT_SPACE; RtrMetalWidth = RtrPolyWidth = RtrContactWidth = 2; RtrContactOffset = 0; RtrMetalSurround = 0; RtrPolySurround = 0; RtrGridSpacing = 4; RtrSubcellSepUp = 4; RtrSubcellSepDown = 4; TTMaskZero(&RtrMetalObstacles); TTMaskZero(&RtrPolyObstacles); for (i=0; i= 0) RtrMetalType = type; width = atoi(argv[2]); if (width <= 0) TechError("Layer1 width must be positive; %d is illegal.\n", width); else RtrMetalWidth = width; TTMaskZero(&RtrMetalObstacles); argc -= 3; nextArg = &(argv[3]); while (argc >= 2) { DBTechNoisyNameMask(*nextArg, &mask); distance = atoi(nextArg[1]); if (distance < 0) { TechError("Layer1 obstacle separation must be positive; %d is illegal.\n", distance); } else for (i=0; i= 0) RtrPolyType = type; width = atoi(argv[2]); if (width <= 0) TechError("Layer2 width must be positive; %d is illegal.\n", width); else RtrPolyWidth = width; TTMaskZero(&RtrPolyObstacles); argc -= 3; nextArg = &(argv[3]); while (argc >= 2) { DBTechNoisyNameMask(*nextArg, &mask); distance = atoi(nextArg[1]); if (distance < 0) { TechError("Layer2 obstacle separation must be positive: %d is illegal.\n", distance); } else for (i=0; i= 0) RtrContactType = type; width = atoi(argv[2]); if (width <= 0) TechError("Contact width must be positive; %d is illegal.\n", width); else RtrContactWidth = width; RtrContactOffset = 0; if (argc == 5) { if (!StrIsInt(argv[3])) TechError("Metal contact surround \"%s\" isn't integral.\n", argv[3]); else { RtrMetalSurround = atoi(argv[3]); if (RtrMetalSurround < 0) { TechError("Metal contact surround \"%s\" mustn't be negative.\n", argv[3]); RtrMetalSurround = 0; } } if (!StrIsInt(argv[4])) TechError("Poly contact surround \"%s\" isn't integral.\n", argv[4]); else { RtrPolySurround = atoi(argv[4]); if (RtrPolySurround < 0) { TechError("Poly contact surround \"%s\" mustn't be negative.\n", argv[4]); RtrPolySurround = 0; } } } return TRUE; } /* Next, look for a gridspacing line. */ if (strcmp(argv[0], "gridspacing") == 0) { if (argc != 2) goto wrongNumArgs; i = atoi(argv[1]); if (i <= 0) TechError("Gridspacing must be positive; %d is illegal.\n", i); else RtrGridSpacing = i; return TRUE; } TechError("Unknown router statement \"%s\".\n", argv[0]); return TRUE; } /* * ---------------------------------------------------------------------------- * * RtrTechFinal -- * * Called once at the very end of the router section of the technology * file. * * Results: * None. * * Side effects: * Compute the actual subcell and paint separations, based on * the technology file information. * * ---------------------------------------------------------------------------- */ void RtrTechFinal() { int i, above, below; /* Pick a contact offset so that the contacts are more-or-less * centered on the routing material. Use the wider routing material * to make this decision; otherwise, the material might end up * sticking out past the edge of the contact. When rounding, round * down (since this works better if the two routing layers are different * widths). */ i = RtrMetalWidth; if (RtrPolyWidth > i) i = RtrPolyWidth; RtrContactOffset = - (RtrContactWidth + 1 - i)/2; /* The actual actual distance from a paint layer to a grid line * is a combination of how far the paint must be from routing * material, and where routing material goes relative to the * grid line. */ RtrSubcellSepUp = RtrSubcellSepDown = 0; /* Compute how far above and below grid lines the routing layers run, * and compensate the obstacle separations accordingly. This is * determined by the contact size and location. */ above = RtrContactWidth + RtrContactOffset; below = - RtrContactOffset; for (i=0; i < TT_MAXTYPES; i++) { int metal, poly; if (TTMaskHasType(&RtrMetalObstacles, i)) metal = RtrMetalSeps[i] + RtrMetalSurround; else metal = 0; if (TTMaskHasType(&RtrPolyObstacles, i)) poly = RtrPolySeps[i] + RtrPolySurround; else poly = 0; if (metal < poly) metal = poly; RtrPaintSepsDown[i] = metal + above; RtrPaintSepsUp[i] = metal + below; if (RtrPaintSepsDown[i] > RtrSubcellSepDown) RtrSubcellSepDown = RtrPaintSepsDown[i]; if (RtrPaintSepsUp[i] > RtrSubcellSepUp) RtrSubcellSepUp = RtrPaintSepsUp[i]; } #ifdef notdef TxPrintf("Routing information:\n"); TxPrintf(" Layer1 is %s, width %d.\n", DBTypeLongName(RtrMetalType), RtrMetalWidth); if (!TTMaskEqual(&RtrMetalObstacles, &DBZeroTypeBits)) { TxPrintf(" Layer1 obstacles are:"); for (i=0; i