Files
magic/plow/PlowTech.c
T
Patrick Kurth ea03883829 Fixed unused-parameters/unused-variables warnings
Added a ARG_UNUSED macro in utils/magic.h, which
produces a simple cast to void to silence the warnings.
The reasons this is used as opposed to an attribute is
that most compilers should support this.
Besides this, the macro can be easily searched for in
the future to potentially remove (where possible) the
unused parameters.
2025-10-10 22:12:19 +02:00

1039 lines
27 KiB
C

/*
* PlowTech.c --
*
* Plowing.
* Read the "drc" section of the technology file and construct the
* design rules used by plowing.
*
* *********************************************************************
* * 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/plow/PlowTech.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "utils/utils.h"
#include "utils/malloc.h"
#include "plow/plowInt.h"
#include "drc/drc.h"
/* C99 compat */
#include "utils/tech.h"
#include "drc/drc.h"
/* Imports from DRC */
extern char *maskToPrint();
/* Rule tables */
PlowRule *plowSpacingRulesTbl[TT_MAXTYPES][TT_MAXTYPES];
PlowRule *plowWidthRulesTbl[TT_MAXTYPES][TT_MAXTYPES];
/* Special type masks */
TileTypeBitMask PlowContactTypes; /* All types that are contacts */
TileTypeBitMask PlowCoveredTypes; /* All types that can't be uncovered
* (i.e, have an edge slide past them)
*/
TileTypeBitMask PlowDragTypes; /* All types that drag along trailing
* minimum-width material when they
* move.
*/
TileTypeBitMask PlowFixedTypes; /* Fixed-width types (e.g, fets).
* Note that this is the one variable
* used outside the plow module (see
* select/selOps.c), for the "stretch"
* command.
*/
/*
* Entry [t] of the following table is the maximum distance associated
* with any design rules in a bucket with type 't' on the LHS.
*/
int plowMaxDist[TT_MAXTYPES];
/* Forward declarations */
extern int plowEdgeRule(), plowWidthRule(), plowSpacingRule();
PlowRule *plowTechOptimizeRule();
/*
* ----------------------------------------------------------------------------
*
* PlowInit() --
*
*
* One-time-only initialization (clearing) of plow tables on startup.
*
* ----------------------------------------------------------------------------
*/
void
PlowInit()
{
int i, j;
for (i = 0; i < TT_MAXTYPES; i++)
{
for (j = 0; j < TT_MAXTYPES; j++)
{
plowWidthRulesTbl[i][j] = (PlowRule *)NULL;
plowSpacingRulesTbl[i][j] = (PlowRule *)NULL;
}
}
}
/*
* ----------------------------------------------------------------------------
*
* PlowDRCInit --
*
* Initialization before processing the "drc" section for plowing.
*
* Results:
* None.
*
* Side effects:
* Clears the rules table.
*
* ----------------------------------------------------------------------------
*/
void
PlowDRCInit()
{
register int i, j;
register PlowRule *pr;
/* Remove all old rules from the plowing rules table */
for (i = 0; i < DBNumTypes; i++)
{
for (j = 0; j < DBNumTypes; j++)
{
for (pr = plowWidthRulesTbl[i][j]; pr; pr = pr->pr_next)
freeMagic((char *)pr);
for (pr = plowSpacingRulesTbl[i][j]; pr; pr = pr->pr_next)
freeMagic((char *)pr);
plowWidthRulesTbl[i][j] = NULL;
plowSpacingRulesTbl[i][j] = NULL;
}
}
}
/*
* ----------------------------------------------------------------------------
*
* PlowDRCLine --
*
* Process a single line from the "drc" section.
*
* Results:
* TRUE always.
*
* Side effects:
* Adds rules to our plowing rule tables.
*
* 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
PlowDRCLine(sectionName, argc, argv)
char *sectionName; /* Unused */
int argc;
char *argv[];
{
ARG_UNUSED(sectionName);
int which;
static const struct
{
const 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, plowEdgeRule},
{"edge4way", 8, 9, plowEdgeRule},
{"spacing", 6, 6, plowSpacingRule},
{"width", 4, 4, plowWidthRule},
{0}
}, *rp;
/*
* Leave the job of printing error messages to the DRC tech file reader.
* We only process a few of the various design-rule types here anyway.
*/
which = LookupStruct(argv[0], (const 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);
}
/*
* ----------------------------------------------------------------------------
*
* plowWidthRule --
*
* Process a width rule.
* This is of the form:
*
* width layers distance why
* e.g, width poly,pmc 2 "poly width must be at least 2"
*
* Results:
* None.
*
* Side effects:
* Updates the plowing width rule table.
*
* ----------------------------------------------------------------------------
*/
int
plowWidthRule(argc, argv)
int argc;
char *argv[];
{
ARG_UNUSED(argc);
char *layers = argv[1];
int distance = atoi(argv[2]);
TileTypeBitMask set, setC;
PlaneMask ptest, pmask;
register PlowRule *pr;
register TileType i, j;
int pNum;
/*
* All layers in a width rule must be on the same plane;
* CoincidentPlanes() below maps contacts to their proper images.
*/
ptest = DBTechNoisyNameMask(layers, &set);
pmask = CoincidentPlanes(&set, ptest);
if (pmask == 0)
return 0;
pNum = LowestMaskBit(pmask);
TTMaskCom2(&setC, &set);
TTMaskAndMask(&setC, &DBPlaneTypes[pNum]);
/*
* Must have types in 'set' for at least 'distance' to the right of
* any edge between a type in '~set' and a type in 'set'.
*/
for (i = 0; i < DBNumTypes; i++)
{
if (TTMaskHasType(&setC, i))
{
for (j = 0; j < DBNumTypes; j++)
{
if (DBTypesOnSamePlane(i, j) && TTMaskHasType(&set, j))
{
pr = (PlowRule *)mallocMagic(sizeof(PlowRule));
pr->pr_dist = distance;
pr->pr_mod = 0;
pr->pr_ltypes = setC;
pr->pr_oktypes = set;
pr->pr_pNum = pNum;
pr->pr_flags = PR_WIDTH;
pr->pr_next = plowWidthRulesTbl[i][j];
plowWidthRulesTbl[i][j] = pr;
}
}
}
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* plowSpacingRule --
*
* 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". In
* the former case, no violation occurs when types in layers1 are
* immediately adjacent to types in layers2. In the second case,
* such adjacency causes a violation.
*
* Results:
* None.
*
* Side effects:
* Updates the plowing spacing rules.
*
* ----------------------------------------------------------------------------
*/
int
plowSpacingRule(argc, argv)
int argc;
char *argv[];
{
ARG_UNUSED(argc);
char *layers1 = argv[1], *layers2 = argv[2];
int distance = atoi(argv[3]);
char *adjacency = argv[4];
TileTypeBitMask set1, set2, tmp1, tmp2, setR, setRreverse;
int pNum;
PlaneMask ptest, planes1, planes2;
register PlowRule *pr;
register TileType i, j;
ptest = DBTechNoisyNameMask(layers1, &set1);
planes1 = CoincidentPlanes(&set1, ptest);
ptest = DBTechNoisyNameMask(layers2, &set2);
planes2 = CoincidentPlanes(&set2, ptest);
if (planes1 == 0 || planes2 == 0)
return 0;
if (strcmp (adjacency, "touching_ok") == 0)
{
/* If touching is OK, everything must fall in the same plane. */
if (planes1 != planes2)
return 0;
pNum = LowestMaskBit(planes1);
/*
* Must not have 'set2' for 'distance' to the right of an edge between
* 'set1' and the types in neither 'set1' nor 'set2' (ie, 'setR').
*/
tmp1 = set1;
tmp2 = set2;
planes1 = planes2 = PlaneNumToMaskBit(pNum);
TTMaskCom(&tmp1);
TTMaskCom(&tmp2);
TTMaskAndMask(&tmp1, &tmp2);
TTMaskAndMask(&tmp2, &DBPlaneTypes[pNum]);
setRreverse = setR = tmp1;
}
else if (strcmp (adjacency, "touching_illegal") == 0)
{
/*
* Must not have 'set2' for 'distance' to the right of an edge between
* 'set1' and the types not in 'set1' (ie, 'setR').
*/
TTMaskCom2(&setR, &set1);
TTMaskCom2(&setRreverse, &set2);
}
else return 0;
for (i = 0; i < DBNumTypes; i++)
{
for (j = 0; j < DBNumTypes; j++)
{
if (i == j || !DBTypesOnSamePlane(i, j)) continue;
/* LHS is an element of set1 and RHS is an element of setR */
if (TTMaskHasType(&set1, i) && TTMaskHasType(&setR, j))
{
/* May have to insert several buckets on different planes */
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
if (!PlaneMaskHasPlane(planes2, pNum))
continue;
pr = (PlowRule *)mallocMagic(sizeof(PlowRule));
TTMaskClearMask3(&tmp1, &DBPlaneTypes[pNum], &set2);
TTMaskCom2(&tmp2, &setRreverse);
TTMaskAndMask3(&pr->pr_ltypes, &DBPlaneTypes[pNum], &tmp2);
pr->pr_oktypes = tmp1;
pr->pr_dist = distance;
pr->pr_mod = 0;
pr->pr_pNum = pNum;
pr->pr_flags = 0;
pr->pr_next = plowSpacingRulesTbl[i][j];
plowSpacingRulesTbl[i][j] = pr;
}
}
/* Also apply backwards, unless it would create duplicates */
if (TTMaskEqual(&set1, &set2)) continue;
/* LHS is an element of set2, RHS is an element of setRreverse */
if (TTMaskHasType(&set2, i) && TTMaskHasType(&setRreverse, j))
{
/* May have to insert several buckets on different planes */
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
if (!PlaneMaskHasPlane(planes1, pNum)) continue;
pr = (PlowRule *)mallocMagic(sizeof(PlowRule));
TTMaskClearMask3(&tmp1, &DBPlaneTypes[pNum], &set1);
TTMaskCom2(&tmp2, &setRreverse);
TTMaskAndMask3(&pr->pr_ltypes, &DBPlaneTypes[pNum], &tmp2);
pr->pr_oktypes = tmp1;
pr->pr_dist = distance;
pr->pr_mod = 0;
pr->pr_pNum = pNum;
pr->pr_flags = 0;
pr->pr_next = plowSpacingRulesTbl[i][j];
plowSpacingRulesTbl[i][j] = pr;
}
}
}
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* plowEdgeRule --
*
* Process a primitive edge rule.
* This is of the form:
*
* edge layers1 layers2 dist OKtypes cornerTypes cornerDist why [plane]
* or edge4way layers1 layers2 dist OKtypes cornerTypes cornerDist why [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.
*
* For plowing, we consider edge rules to be spacing rules.
* Ordinary "edge" rules can be handled exactly (taking the distance
* to be the maximum of dist and cornerDist above), because they are
* always applied in the proper direction. Each edge rule produces
* one normal spacing rule, and possibly an additional spacing rule
* that is only applied in the penumbra (if cornerTypes and layers2
* are different).
*
* An "edge4way" rule also requires a conservative approximation to
* handle the case when it is being applied in the opposite direction.
*
* Results:
* None.
*
* Side effects:
* Updates the plowing spacing rules.
*
* ----------------------------------------------------------------------------
*/
int
plowEdgeRule(argc, argv)
int argc;
char *argv[];
{
char *layers1 = argv[1], *layers2 = argv[2];
int distance = atoi(argv[3]);
char *okTypes = argv[4], *cornerTypes = argv[5];
int cdist = atoi(argv[6]);
TileTypeBitMask set1, set2, setC, setM;
TileTypeBitMask setOK, setLeft, setRight;
int pNum, checkPlane, flags;
PlaneMask ptest, planes1, planes2, pmask;
bool needPenumbraOnly;
bool isFourWay = (strcmp(argv[0], "edge4way") == 0);
register PlowRule *pr;
register TileType i, j;
ptest = DBTechNoisyNameMask(layers1, &set1);
planes1 = CoincidentPlanes(&set1, ptest);
ptest = DBTechNoisyNameMask(layers2, &set2);
planes2 = CoincidentPlanes(&set2, ptest);
distance = MAX(distance, cdist);
/* Make sure that all edges between the two sets exist on one plane */
if (planes1 == 0 || planes2 == 0)
return 0;
if (planes1 != planes2)
return 0;
ptest = DBTechNoisyNameMask(cornerTypes, &setC);
pmask = CoincidentPlanes(&setC, ptest);
if (pmask == 0)
return 0;
pNum = LowestMaskBit(pmask);
/* If an explicit check plane was specified, use it */
checkPlane = pNum;
if (argc == 9)
{
checkPlane = DBTechNamePlane(argv[8]);
if (checkPlane < 0)
return 0;
}
/* Get the images of everything in okTypes on the check plane */
ptest = DBTechNoisyNameMask(okTypes, &setM);
pmask = CoincidentPlanes(&setM, ptest);
if (pmask == 0)
return 0;
needPenumbraOnly = !TTMaskEqual(&set2, &setC);
TTMaskCom2(&setLeft, &setC);
TTMaskAndMask(&setLeft, &DBPlaneTypes[pNum]);
TTMaskCom2(&setRight, &set2);
TTMaskAndMask(&setRight, &DBPlaneTypes[pNum]);
flags = isFourWay ? PR_EDGE4WAY : PR_EDGE;
for (i = 0; i < DBNumTypes; i++)
{
if (TTMaskHasType(&set1, i))
{
for (j = 0; j < DBNumTypes; j++)
{
if (TTMaskHasType(&set2, j))
{
pr = (PlowRule *)mallocMagic(sizeof(PlowRule));
pr->pr_ltypes = setLeft;
pr->pr_oktypes = setM;
pr->pr_dist = distance;
pr->pr_mod = 0;
pr->pr_pNum = checkPlane;
pr->pr_next = plowSpacingRulesTbl[i][j];
pr->pr_flags = flags;
plowSpacingRulesTbl[i][j] = pr;
}
if (needPenumbraOnly && TTMaskHasType(&setC, j))
{
pr = (PlowRule *)mallocMagic(sizeof(PlowRule));
pr->pr_ltypes = setRight;
pr->pr_oktypes = setM;
pr->pr_dist = distance;
pr->pr_mod = 0;
pr->pr_pNum = checkPlane;
pr->pr_next = plowSpacingRulesTbl[i][j];
pr->pr_flags = flags|PR_PENUMBRAONLY;
plowSpacingRulesTbl[i][j] = pr;
}
}
}
}
if (!isFourWay)
return 0;
/*
* Four-way edge rules are applied by the design-rule checker
* both forwards and backwards. Since plowing can only look
* forward, we need to approximate the backward rules with
* a collection of forward rules.
*
* Suppose we have the following 4-way rule:
*
* CORNER
* --------+
* LEFT | RIGHT : OKTypes
*
* To check it in the following (backward) configuration, using
* only rightward-looking rules,
*
* OKTypes : RIGHT | LEFT
* +--------
* CORNER
*
* we generate the following forward rules (with the same distance):
*
* ~t
* --------+
* t | ~t : ~LEFT
*
* for each t in ~OKTypes. In plowing terms, each rule will have LTYPES of
* t and OKTYPES of ~LEFT. In effect, this is creating a forward spacing
* rule between each of the types ~OKTypes, and the materials in LEFT.
* The edge is found on checkPlane, and checked on plane pNum.
*
* Because the corner and right-hand types for these rules are the same,
* we don't need to generate any PR_PENUMBRAONLY rules.
*/
setRight = setM;
TTMaskCom2(&setLeft, &setM);
TTMaskAndMask(&setLeft, &DBPlaneTypes[checkPlane]);
TTMaskCom2(&setOK, &set1);
TTMaskAndMask(&setOK, &DBPlaneTypes[pNum]);
for (i = 0; i < DBNumTypes; i++)
{
if (TTMaskHasType(&setLeft, i))
{
for (j = 0; j < DBNumTypes; j++)
{
if (TTMaskHasType(&setRight, j))
{
pr = (PlowRule *)mallocMagic(sizeof(PlowRule));
TTMaskSetOnlyType(&pr->pr_ltypes, i);
pr->pr_oktypes = setOK;
pr->pr_dist = distance;
pr->pr_mod = 0;
pr->pr_pNum = pNum;
pr->pr_flags = flags|PR_EDGEBACK;
pr->pr_next = plowSpacingRulesTbl[i][j];
plowSpacingRulesTbl[i][j] = pr;
}
}
}
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* PlowDRCFinal --
*
* Called after all lines of the drc section in the technology file have been
* read. The preliminary plowing rules tables are pruned by removing rules
* covered by other (longer distance) rules.
*
* We also construct plowMaxDist[] to contain for entry 't' the maximum
* distance associated with any plowing rule in a bucket with 't' on its
* LHS.
*
* Results:
* None.
*
* Side effects:
* May remove PlowRules from the linked lists of the width and
* spacing rules tables. Sets the values in plowMaxDist[].
*
* ----------------------------------------------------------------------------
*/
void
PlowDRCFinal()
{
register PlowRule *pr;
register TileType i, j;
for (i = 0; i < DBNumTypes; i++)
{
plowMaxDist[i] = 0;
for (j = 0; j < DBNumTypes; j++)
{
if ((pr = plowWidthRulesTbl[i][j]))
{
pr = plowWidthRulesTbl[i][j] = plowTechOptimizeRule(pr);
for ( ; pr; pr = pr->pr_next)
if (pr->pr_dist > plowMaxDist[i])
plowMaxDist[i] = pr->pr_dist;
}
if ((pr = plowSpacingRulesTbl[i][j]))
{
pr = plowSpacingRulesTbl[i][j] = plowTechOptimizeRule(pr);
for ( ; pr; pr = pr->pr_next)
if (pr->pr_dist > plowMaxDist[i])
plowMaxDist[i] = pr->pr_dist;
}
}
}
}
/*
* ----------------------------------------------------------------------------
*
* plowTechOptimizeRule --
*
* Called to optimize the chain of rules in a single bin of either
* the spacing or width rules tables.
*
* In general, we want to remove any rule A "covered" by another
* rule B, i.e.,
*
* B's distance >= A's distance,
* B's OKTypes is a subset of A's OKTypes, and
* B's Ltypes == A's Ltypes
* B's check plane == A's check plane
*
* Results:
* Returns a pointer to the new chain of rules for this bin.
*
* Side effects:
* May deallocate memory.
*
* ----------------------------------------------------------------------------
*/
PlowRule *
plowTechOptimizeRule(ruleList)
PlowRule *ruleList;
{
PlowRule *pCand, *pCandLast, *pr;
TileTypeBitMask tmpMask;
/*
* The pointer 'pCand' in the following loop will iterate over
* candidates for deletion, and pCandLast will trail by one.
*/
pCand = ruleList;
pCandLast = (PlowRule *) NULL;
while (pCand)
{
for (pr = ruleList; pr; pr = pr->pr_next)
{
if (pr != pCand
&& pr->pr_dist >= pCand->pr_dist
&& pr->pr_flags == pCand->pr_flags
&& pr->pr_pNum == pCand->pr_pNum
&& TTMaskEqual(&pr->pr_ltypes, &pCand->pr_ltypes))
{
/*
* Is pr->pr_oktypes a subset of pCand->pr_oktypes,
* i.e, is it more restrictive?
*/
TTMaskAndMask3(&tmpMask, &pr->pr_oktypes, &pCand->pr_oktypes);
if (TTMaskEqual(&tmpMask, &pr->pr_oktypes))
{
/*
* Delete pCand, and resume outer loop with the
* new values of pCand and pCandLast set below.
*/
freeMagic((char *) pCand);
if (pCandLast)
pCandLast->pr_next = pCand->pr_next;
else
ruleList = pCand->pr_next;
pCand = pCand->pr_next;
goto next;
}
}
}
/* Normal continuation: advance to next rule in bin */
pCandLast = pCand, pCand = pCand->pr_next;
next: ;
}
return (ruleList);
}
/*
* ----------------------------------------------------------------------------
*
* PlowTechInit --
*
* Initialize the masks of types PlowFixedTypes, PlowCoveredTypes,
* and PlowDragTypes to be empty.
*
* Results:
* None.
*
* Side effects:
* Zeroes PlowFixedTypes, PlowCoveredTypes, and PlowDragTypes.
*
* ----------------------------------------------------------------------------
*/
void
PlowTechInit()
{
PlowFixedTypes = DBZeroTypeBits;
PlowCoveredTypes = DBZeroTypeBits;
PlowDragTypes = DBZeroTypeBits;
}
/*
* ----------------------------------------------------------------------------
*
* PlowTechLine --
*
* Process a line from the plowing section of a technology file.
* Such a line is currently of the following form:
*
* keyword types
*
* where 'types' is a comma-separated list of type names.
*
* Keywords:
*
* fixed each of 'types' is fixed-width; regions consisting
* of fixed-width types are not deformed by plowing.
* Contacts are automatically fixed size and so do not
* need to be included in this list. Space can never
* be fixed-size and so is automatically omitted from
* the list.
*
* covered each of 'types' cannot be uncovered as a result of
* plowing. This means that if material of type X
* covers a horizontal edge initially, it will continue
* to cover it after plowing.
*
* drag each of 'types' will drag along with it the LHS of
* any trailing minimum-width material when it moves.
* This is so transistors will drag their gates when
* the transistor moves, so we don't leave huge amounts
* of poly behind us.
*
* Results:
* Returns TRUE always.
*
* Side effects:
* Updates PlowFixedTypes, PlowCoveredTypes, and PlowDragTypes.
*
* ----------------------------------------------------------------------------
*/
bool
PlowTechLine(sectionName, argc, argv)
char *sectionName; /* Unused */
int argc;
char *argv[];
{
ARG_UNUSED(sectionName);
TileTypeBitMask types;
if (argc != 2)
{
TechError("Malformed line\n");
return (TRUE);
}
DBTechNoisyNameMask(argv[1], &types);
TTMaskAndMask(&types, &DBAllButSpaceBits);
if (strcmp(argv[0], "fixed") == 0)
{
TTMaskSetMask(&PlowFixedTypes, &types);
}
else if (strcmp(argv[0], "covered") == 0)
{
TTMaskSetMask(&PlowCoveredTypes, &types);
}
else if (strcmp(argv[0], "drag") == 0)
{
TTMaskSetMask(&PlowDragTypes, &types);
}
else
{
TechError("Illegal keyword \"%s\".\n", argv[0]);
}
return (TRUE);
}
/*
* ----------------------------------------------------------------------------
*
* PlowTechFinal --
*
* Final processing of the lines from the plowing section of a technology
* file. Add all contacts to the list of fixed types. Also sets the mask
* PlowContactTypes to have bits set for each image of each contact.
*
* Results:
* None.
*
* Side effects:
* Updates PlowFixedTypes and PlowContactTypes.
*
* ----------------------------------------------------------------------------
*/
void
PlowTechFinal()
{
TileType t;
TTMaskZero(&PlowContactTypes);
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
if (DBIsContact(t))
TTMaskSetType(&PlowContactTypes, t);
TTMaskSetMask(&PlowFixedTypes, &PlowContactTypes);
}
/*
* ----------------------------------------------------------------------------
*
* plowScaleUp ---
*
* Scale all plow distances according to the current DRC scale factor.
* ----------------------------------------------------------------------------
*/
void plowScaleUp(PlowRule *pr, int scalefactor)
{
int dist;
if (pr->pr_dist > 0)
{
dist = pr->pr_dist;
if (pr->pr_mod != 0)
pr->pr_dist--;
pr->pr_dist *= scalefactor;
pr->pr_dist += (short)pr->pr_mod;
pr->pr_mod = 0;
}
}
/*
* ----------------------------------------------------------------------------
*
* plowScaleDown ---
*
* Scale all plow distances according to the current DRC scale factor.
* ----------------------------------------------------------------------------
*/
void plowScaleDown(PlowRule *pr, int scalefactor)
{
int dist;
if (pr->pr_dist > 0)
{
dist = pr->pr_dist;
pr->pr_dist /= scalefactor;
if ((pr->pr_mod = (unsigned char)(dist % scalefactor)) != 0)
pr->pr_dist++;
}
}
/*
* ----------------------------------------------------------------------------
*
* DRCPlowScale ---
*
* Routine to run after the entire techfile has been processed (or reloaded),
* or when the DRC rules have been rescaled, after an internal grid rescaling.
* It derives all of the plow width and spacing rules from the DRC rules.
*
* ----------------------------------------------------------------------------
*/
void
DRCPlowScale(int scaled, int scalen, bool adjustmax)
{
PlowRule *pr;
TileType i, j;
for (i = 0; i < TT_MAXTYPES; i++)
{
for (j = 0; j < TT_MAXTYPES; j++)
{
for (pr = plowWidthRulesTbl[i][j]; pr; pr = pr->pr_next)
{
plowScaleUp(pr, scaled);
plowScaleDown(pr, scalen);
}
for (pr = plowSpacingRulesTbl[i][j]; pr; pr = pr->pr_next)
{
plowScaleUp(pr, scaled);
plowScaleDown(pr, scalen);
}
}
/* Scale plowMaxDist */
if (adjustmax)
{
plowMaxDist[i] *= scaled;
plowMaxDist[i] /= scalen;
}
}
}
/*
* ----------------------------------------------------------------------------
*
* plowTechPrintRule --
* plowTechShowTable --
* plowTechShow --
*
* For debugging purposes.
* Print the complete table of all plowing rules.
*
* Results:
* None.
*
* Side effects:
* Prints to the file 'f'.
*
* ----------------------------------------------------------------------------
*/
void
plowTechPrintRule(pr, f)
PlowRule *pr;
FILE *f;
{
fprintf(f, "\tDISTANCE=%d, PLANE=%s, FLAGS=",
pr->pr_dist, DBPlaneLongName(pr->pr_pNum));
if (pr->pr_flags & PR_WIDTH) fprintf(f, " Width");
if (pr->pr_flags & PR_PENUMBRAONLY) fprintf(f, " PenumbraOnly");
if (pr->pr_flags & PR_EDGE) fprintf(f, " Edge");
if (pr->pr_flags & PR_EDGE4WAY) fprintf(f, " Edge4way");
if (pr->pr_flags & PR_EDGEBACK) fprintf(f, " EdgeBack");
fprintf(f, "\n");
fprintf(f, "\tLTYPES = %s\n", maskToPrint(&pr->pr_ltypes));
fprintf(f, "\tOKTYPES = %s\n", maskToPrint(&pr->pr_oktypes));
fprintf(f, "\t-------------------------------\n");
}
void
plowTechShowTable(table, header, f)
PlowRule *table[TT_MAXTYPES][TT_MAXTYPES];
char *header;
FILE *f;
{
PlowRule *pr;
TileType i, j;
fprintf(f, "\n\n------------ %s ------------\n", header);
for (i = 0; i < DBNumTypes; i++)
for (j = 0; j < DBNumTypes; j++)
if ((pr = table[i][j]))
{
fprintf(f, "\n%s -- %s:\n",
DBTypeLongName(i), DBTypeLongName(j));
for ( ; pr; pr = pr->pr_next)
plowTechPrintRule(pr, f);
}
}
void
plowTechShow(f)
FILE *f;
{
plowTechShowTable(plowWidthRulesTbl, "Width Rules", f);
plowTechShowTable(plowSpacingRulesTbl, "Spacing Rules", f);
}