1014 lines
27 KiB
C
1014 lines
27 KiB
C
/*
|
||
* DBtcontact.c --
|
||
*
|
||
* Management of contacts.
|
||
* This file makes a distinction between the following two terms:
|
||
*
|
||
* Layer -- Logical type as specified in "types" section of .tech
|
||
* file. A layer may consist of many TileTypes, as is the
|
||
* case when it is a contact.
|
||
* Type -- TileType stored in a tile
|
||
*
|
||
* *********************************************************************
|
||
* * 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/database/DBtcontact.c,v 1.3 2008/09/05 13:56:25 tim Exp $";
|
||
#endif /* not lint */
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <ctype.h>
|
||
|
||
#include "utils/magic.h"
|
||
#include "utils/geometry.h"
|
||
#include "utils/utils.h"
|
||
#include "utils/malloc.h"
|
||
#include "tiles/tile.h"
|
||
#include "utils/hash.h"
|
||
#include "database/database.h"
|
||
#include "database/databaseInt.h"
|
||
#include "utils/tech.h"
|
||
#include "textio/textio.h"
|
||
|
||
/* type-to-bitmask conversion (1 bit per entry) */
|
||
TileTypeBitMask DBLayerTypeMaskTbl[NT];
|
||
|
||
/* Filled in after contact types have been generated */
|
||
TileTypeBitMask DBPlaneTypes[PL_MAXTYPES];
|
||
TileTypeBitMask DBHomePlaneTypes[PL_MAXTYPES];
|
||
PlaneMask DBTypePlaneMaskTbl[NT];
|
||
|
||
/* --------------------- Data local to this file ---------------------- */
|
||
|
||
/* Table of the properties of all layers */
|
||
LayerInfo dbLayerInfo[NT];
|
||
|
||
/* Array of pointers to the entries in above table for contacts only */
|
||
LayerInfo *dbContactInfo[NT];
|
||
int dbNumContacts;
|
||
|
||
/* Forward declaration */
|
||
void dbTechMatchResidues();
|
||
void dbTechAddStackedContacts();
|
||
int dbTechAddOneStackedContact();
|
||
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBTechInitContact --
|
||
*
|
||
* Mark all types as being non-contacts initially.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Initializes dbLayerInfo.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
DBTechInitContact()
|
||
{
|
||
TileType t;
|
||
LayerInfo *lp;
|
||
|
||
for (t = 0; t < TT_MAXTYPES; t++)
|
||
{
|
||
lp = &dbLayerInfo[t];
|
||
lp->l_type = t;
|
||
lp->l_isContact = FALSE;
|
||
lp->l_pmask = 0;
|
||
TTMaskZero(&lp->l_residues);
|
||
TTMaskSetOnlyType(&DBLayerTypeMaskTbl[t], t);
|
||
}
|
||
|
||
dbNumContacts = 0;
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBTechAddContact --
|
||
*
|
||
* Add the definition of a new contact type.
|
||
* The syntax of each line in the "contact" section is:
|
||
*
|
||
* contactType res1 res2 [res3...]
|
||
*
|
||
* where res1, res2, res3, etc. are the residue types on the planes
|
||
* connected by the contact. The home plane of the contact (the
|
||
* plane specified in the "types" section for the type contactType)
|
||
* must be the lowest-numbered plane in the list of residues. Each
|
||
* listed residue must be on a different plane. There are no other
|
||
* restrictions on contacts.
|
||
*
|
||
* Magic-7.3 additional syntax:
|
||
*
|
||
* stackable type1 [type2 [alias12] [type3 [alias13] ...]]
|
||
*
|
||
* where type1 and type2 are contact types, allows type1 and type2
|
||
* to be drawn on top of one other by generating an extra contact
|
||
* type to represent the union of type1 and type2 on the shared
|
||
* plane. If more than two types are specified, then type1 will be
|
||
* set to be stackable with each of the indicated types. If only
|
||
* type1 is specified, then type1 will be made stackable with all
|
||
* other (existing) contact types. Wherever a layer name exists
|
||
* after a known type that is not a known layer name, it is
|
||
* considered to be an alias name for the stacked type. e.g.,
|
||
* "stackable pc via pm12contact" is valid if "pc" and "via" are
|
||
* defined types. Thie provides compatibility with layout files
|
||
* created with technology files that explicitly define stacked
|
||
* contact types, especially those from magic-7.2 and earlier
|
||
* versions.
|
||
*
|
||
* stackable
|
||
*
|
||
* allows all contact types to stack, where applicable. This
|
||
* statement overrides any other "stackable" statement.
|
||
*
|
||
* Notes:
|
||
* All indicated types must have been declared in the "contact"
|
||
* section prior to use of the "stackable" keyword. The 1- and
|
||
* 2-argument variants will create stacking types with all
|
||
* previously-declared contact types.
|
||
*
|
||
* Expanded syntax:
|
||
* Now allows the section "image" with statements "contact" and
|
||
* "device". Statements beginning with the layer name are
|
||
* backwardly-compatible with the original syntax. "contact"
|
||
* statements are equivalent to the original syntax after skipping
|
||
* the keyword "contact". "device" statements have the same
|
||
* syntax as the "contact" statement but describe a composite
|
||
* image such as a transistor or capacitor formed by layers on
|
||
* different planes.
|
||
*
|
||
* Results:
|
||
* FALSE on error, TRUE if successful.
|
||
*
|
||
* Side effects:
|
||
* Adds the definition of a new contact type.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
bool
|
||
DBTechAddContact(sectionName, argc, argv)
|
||
char *sectionName;
|
||
int argc;
|
||
char *argv[];
|
||
{
|
||
TileType contactType;
|
||
int nresidues;
|
||
|
||
if ((contactType = DBTechNameType(*argv)) < 0)
|
||
{
|
||
if (!strcmp(*argv, "contact") || !strcmp(*argv, "device"))
|
||
{
|
||
argc--;
|
||
argv++;
|
||
if ((contactType = DBTechNameType(*argv)) < 0)
|
||
{
|
||
DBTechNoisyNameType(*argv);
|
||
return FALSE;
|
||
}
|
||
}
|
||
else if (!strcmp(*argv, "stackable"))
|
||
{
|
||
TileType stackType, newType = -1;
|
||
LayerInfo *lim, *lin;
|
||
|
||
if (argc == 1)
|
||
dbTechAddStackedContacts();
|
||
else
|
||
{
|
||
contactType = DBTechNoisyNameType(*++argv);
|
||
if (contactType < 0)
|
||
return FALSE;
|
||
else if (argc == 2)
|
||
{
|
||
int n, result;
|
||
|
||
lim = &dbLayerInfo[contactType];
|
||
|
||
for (n = 0; n < dbNumContacts; n++)
|
||
{
|
||
lin = dbContactInfo[n];
|
||
if (lim == lin) continue;
|
||
result = dbTechAddOneStackedContact(lim->l_type, lin->l_type);
|
||
if (result == -3)
|
||
return FALSE; /* overran tiletype maximum number */
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TileType lastType = TT_SPACE;
|
||
char *primary;
|
||
|
||
while (--argc > 1)
|
||
{
|
||
stackType = DBTechNameType(*++argv);
|
||
if (stackType >= 0)
|
||
{
|
||
newType = dbTechAddOneStackedContact(contactType,
|
||
stackType);
|
||
if (newType == -1)
|
||
TechError("Contact types %s and %s do not stack\n",
|
||
DBTypeLongNameTbl[contactType],
|
||
DBTypeLongNameTbl[stackType]);
|
||
lastType = stackType;
|
||
}
|
||
else if (lastType >= TT_SPACE)
|
||
{
|
||
/* (*argv) becomes an alias name for layer newType */
|
||
if (newType < 0)
|
||
TechError("Contact type %s unknown or contact "
|
||
"missing in stackable statement\n", *argv);
|
||
else
|
||
DBTechAddNameToType(*argv, newType, FALSE);
|
||
lastType = TT_SPACE;
|
||
}
|
||
else
|
||
{
|
||
DBTechNoisyNameType(*argv);
|
||
lastType = TT_SPACE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
DBTechNoisyNameType(*argv);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
/* Read the contact residues and check them for validity */
|
||
nresidues = dbTechContactResidues(--argc, ++argv, contactType);
|
||
if (nresidues < 0)
|
||
return FALSE;
|
||
|
||
/* Remember this as a paintable contact */
|
||
dbContactInfo[dbNumContacts++] = &dbLayerInfo[contactType];
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
* dbTechAddStackedContacts --
|
||
*
|
||
* Generate new contact types where existing contact types share a
|
||
* residue. These contact types will exist only on the planes
|
||
* shared between the two contact types. This method allows contacts
|
||
* to be stacked without requiring a declaration of every combination
|
||
* in the techfile.
|
||
*
|
||
* When searching for contact types with shared planes, we want to
|
||
* make sure that no existing contact exactly matches the stacked
|
||
* type, in case stacked contacts are explicitly called out in the
|
||
* tech file (e.g., pm12contact).
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Adds to the tiletype database.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
dbTechAddStackedContacts()
|
||
{
|
||
int m, n;
|
||
LayerInfo *lim, *lin;
|
||
int dbNumUserContacts = dbNumContacts;
|
||
int result;
|
||
|
||
for (m = 0; m < dbNumUserContacts; m++)
|
||
{
|
||
lim = dbContactInfo[m];
|
||
for (n = m + 1; n < dbNumUserContacts; n++)
|
||
{
|
||
lin = dbContactInfo[n];
|
||
result = dbTechAddOneStackedContact(lim->l_type, lin->l_type);
|
||
if (result == -3)
|
||
return; /* overran tiletype maximum number */
|
||
}
|
||
}
|
||
|
||
/* Diagnostic */
|
||
/* fprintf(stderr, "DBNumUserLayers = %d, DBNumTypes = %d\n",
|
||
DBNumUserLayers, DBNumTypes);
|
||
fflush(stderr); */
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
* dbTechAddOneStackedContact --
|
||
*
|
||
* Generate one new stacked contact type representing the union of
|
||
* types "type1" and "type2" on their shared plane(s) (normally
|
||
* one, but not necessarily).
|
||
*
|
||
* Results:
|
||
* tile type of new stacked contact if successful, -1 if stacking
|
||
* not allowed, -2 if a contact type already exists which stacks
|
||
* type1 and type2, or -3 on overrun of the total number of layers.
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
dbTechAddOneStackedContact(type1, type2)
|
||
TileType type1, type2;
|
||
{
|
||
LayerInfo *lim, *lin, *lp;
|
||
TileTypeBitMask ttshared, ttall, mmask;
|
||
TileType stackedType, sres;
|
||
|
||
lim = &dbLayerInfo[type1];
|
||
lin = &dbLayerInfo[type2];
|
||
|
||
/* Both types must be contacts */
|
||
if (!lim->l_isContact || !lin->l_isContact) return -1;
|
||
|
||
/* Contacts do not stack if they share more than one plane */
|
||
/* if (lim->l_pmask == lin->l_pmask) return -1; */
|
||
if (((lim->l_pmask & lin->l_pmask) & ((lim->l_pmask & lin->l_pmask) - 1))
|
||
!= 0)
|
||
return -1;
|
||
|
||
TTMaskAndMask3(&ttshared, &lim->l_residues, &lin->l_residues);
|
||
|
||
if (!TTMaskEqual(&ttshared, &DBZeroTypeBits))
|
||
{
|
||
/* Find if there exists an image with the same residue */
|
||
/* mask as the combination of these two contact types. */
|
||
|
||
TTMaskZero(&ttall);
|
||
TTMaskSetMask3(&ttall, &lim->l_residues, &lin->l_residues);
|
||
|
||
dbTechMatchResidues(&ttall, &mmask, TRUE);
|
||
|
||
if (!TTMaskEqual(&mmask, &DBZeroTypeBits))
|
||
return -2; /* Contact type exists, so don't create one. */
|
||
|
||
/* Also check if there is a stacking type made of these contact */
|
||
/* images. If we already have one, don't re-make it. */
|
||
|
||
else if (DBTechFindStacking(type1, type2) != -1)
|
||
return -2; /* Stacking type exists, so don't create one. */
|
||
|
||
/* All clear to set the residue bitmask for this contact type */
|
||
|
||
/* Diagnostic */
|
||
/* fprintf(stderr, "Stackable %s and %s\n",
|
||
DBTypeLongName(lim->l_type),
|
||
DBTypeLongName(lin->l_type));
|
||
fflush(stderr); */
|
||
|
||
stackedType = dbTechNewStackedType(lim->l_type, lin->l_type);
|
||
|
||
/* Error condition (usually, reached max. no. tile types) */
|
||
if (stackedType < 0) return -3;
|
||
|
||
/* fill in layer info */
|
||
|
||
lp = &dbLayerInfo[stackedType];
|
||
lp->l_isContact = TRUE;
|
||
|
||
/* The residue of a stacked contact is the two contacts */
|
||
/* which make it up. Residues which are contact types */
|
||
/* are unique to stacking types. */
|
||
|
||
TTMaskZero(&lp->l_residues);
|
||
TTMaskSetType(&lp->l_residues, lim->l_type);
|
||
TTMaskSetType(&lp->l_residues, lin->l_type);
|
||
lp->l_pmask = lin->l_pmask | lim->l_pmask;
|
||
|
||
/* The home plane of the contact is the plane of the */
|
||
/* first shared residue found. */
|
||
|
||
for (sres = TT_TECHDEPBASE; sres < DBNumUserLayers; sres++)
|
||
if (TTMaskHasType(&ttshared, sres))
|
||
{
|
||
DBPlane(stackedType) = DBPlane(sres);
|
||
break;
|
||
}
|
||
|
||
/* Remember this as a paintable contact */
|
||
dbContactInfo[dbNumContacts++] = &dbLayerInfo[stackedType];
|
||
|
||
return (int)stackedType; /* success */
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBPlaneToResidue --
|
||
*
|
||
* For the given tile type and plane, return the residue of that type on the
|
||
* plane.
|
||
*
|
||
* Results:
|
||
* A tile type.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
TileType
|
||
DBPlaneToResidue(type, plane)
|
||
TileType type;
|
||
int plane;
|
||
{
|
||
TileType rt, rt2;
|
||
LayerInfo *lp = &dbLayerInfo[type], *lr;
|
||
|
||
for (rt = TT_TECHDEPBASE; rt < DBNumUserLayers; rt++)
|
||
if (TTMaskHasType(&lp->l_residues, rt))
|
||
{
|
||
if (type >= DBNumUserLayers) /* Stacked type */
|
||
{
|
||
lr = &dbLayerInfo[rt];
|
||
for (rt2 = TT_TECHDEPBASE; rt2 < DBNumUserLayers; rt2++)
|
||
if (TTMaskHasType(&lr->l_residues, rt2))
|
||
if (DBPlane(rt2) == plane)
|
||
return rt2;
|
||
}
|
||
else if (DBPlane(rt) == plane) /* Normal type */
|
||
return rt;
|
||
}
|
||
|
||
return TT_SPACE; /* no residue on plane */
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBMaskAddStacking ---
|
||
*
|
||
* A general-purpose routine to add stacked types containing types that are
|
||
* already in the mask.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
DBMaskAddStacking(mask)
|
||
TileTypeBitMask *mask;
|
||
{
|
||
TileType ttype;
|
||
TileTypeBitMask *rMask;
|
||
|
||
for (ttype = DBNumUserLayers; ttype < DBNumTypes; ttype++)
|
||
{
|
||
rMask = DBResidueMask(ttype);
|
||
if (TTMaskIntersect(rMask, mask))
|
||
TTMaskSetType(mask, ttype);
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* dbTechContactResidues --
|
||
*
|
||
* Process an argc/argv vector of contact residue type names, creating
|
||
* image types for each, and ensuring that:
|
||
* No residue is itself a contact
|
||
* One of the residues is on the home plane of contactType.
|
||
*
|
||
* Results:
|
||
* Returns the number of residues in the contact,
|
||
* or -1 in the event of an error.
|
||
*
|
||
* Side effects:
|
||
* Adds to database of layer types.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
dbTechContactResidues(argc, argv, contactType)
|
||
int argc;
|
||
char **argv;
|
||
TileType contactType;
|
||
{
|
||
int homePlane, residuePlane, nresidues;
|
||
PlaneMask pMask;
|
||
TileType residueType, imageType;
|
||
bool residueOnHome;
|
||
LayerInfo *lp;
|
||
TileTypeBitMask rmask, mmask;
|
||
|
||
nresidues = 0;
|
||
pMask = 0;
|
||
residueOnHome = FALSE;
|
||
|
||
TTMaskZero(&rmask);
|
||
homePlane = DBPlane(contactType);
|
||
for ( ; argc > 0; argc--, argv++)
|
||
{
|
||
if ((residueType = DBTechNoisyNameType(*argv)) < 0)
|
||
return -1;
|
||
|
||
if (IsContact(residueType))
|
||
{
|
||
TechError("Residue type %s is a contact itself\n",
|
||
DBTypeLongName(residueType));
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* Make sure the residue is on the same or an adjacent plane
|
||
* to the contact's home type.
|
||
*/
|
||
residuePlane = DBPlane(residueType);
|
||
if (residuePlane < 0)
|
||
{
|
||
TechError("Residue type %s doesn't have a home plane\n",
|
||
DBTypeLongName(residueType));
|
||
return -1;
|
||
}
|
||
|
||
/* Enforce a single residue per plane */
|
||
if (PlaneMaskHasPlane(pMask, residuePlane))
|
||
{
|
||
TechError("Contact residues (%s) must be on different planes\n",
|
||
DBTypeLongName(residueType));
|
||
return -1;
|
||
}
|
||
pMask |= PlaneNumToMaskBit(residuePlane);
|
||
if (homePlane == residuePlane)
|
||
residueOnHome = TRUE;
|
||
|
||
TTMaskSetType(&rmask, residueType);
|
||
}
|
||
|
||
if (!residueOnHome)
|
||
{
|
||
TechError("Contact type %s missing a residue on its home plane\n",
|
||
DBTypeLongName(contactType));
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* See if there are any other contact types with identical residues;
|
||
* if so, disallow contactType.
|
||
*
|
||
* Can this restriction be lifted? ---Tim 07/24/03
|
||
* This restriction is partially lifted, as one can create a non-stacked
|
||
* type such as "pad" having the same residues as one stacked type,
|
||
* such as "m123c". Due to the way magic handles stacked types, these
|
||
* will not be confused. ---Tim 05/11/04
|
||
*
|
||
* Restriction entirely lifted 6/18/04. Error message left as a warning
|
||
* until it is clear that there are no unwanted side effects of having
|
||
* two contact types with identical residues.
|
||
*/
|
||
|
||
/* Find if there exists an image with the same residue mask */
|
||
|
||
dbTechMatchResidues(&rmask, &mmask, TRUE);
|
||
|
||
/* Ignore self */
|
||
|
||
TTMaskClearType(&mmask, contactType);
|
||
|
||
if (!TTMaskEqual(&mmask, &DBZeroTypeBits))
|
||
{
|
||
TxPrintf("Contact residues for %s identical to those for ",
|
||
DBTypeLongName(contactType));
|
||
|
||
for (imageType = TT_TECHDEPBASE; imageType < DBNumTypes; imageType++)
|
||
if (TTMaskHasType(&mmask, imageType))
|
||
TxPrintf("%s ", DBTypeLongName(imageType));
|
||
|
||
TxPrintf("\n");
|
||
}
|
||
|
||
/* All clear to set the residue bitmask for this contact type */
|
||
|
||
lp = &dbLayerInfo[contactType];
|
||
|
||
lp->l_isContact = TRUE;
|
||
TTMaskSetMask(&lp->l_residues, &rmask);
|
||
lp->l_pmask = pMask;
|
||
|
||
return nresidues;
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* dbTechMatchResidues --
|
||
*
|
||
* Find the types whose residues match those of the supplied inMask.
|
||
*
|
||
* All this masking about is rather subtle, so pay attention: Each TYPE
|
||
* has a RESIDUAL, which for a contact is (generally) the type which surrounds
|
||
* each contact image on its plane (remember, there is one contact image per
|
||
* plane contacted). So when creating the paint/erase tables, we want to
|
||
* knock out planes from the residual mask of a contact and see if what's
|
||
* left is another kind of contact. So from the original contact TYPE, we
|
||
* make a mask of RESIDUALS, then this routine compares that to the mask
|
||
* of residuals for all other (contact) types, then create another mask of
|
||
* all the types which had matching residual masks, and return it. Grok
|
||
* that?
|
||
*
|
||
* Note that the stacked contact mechanism returns the stacked type where
|
||
* residues of two types match. This is required when composing paint
|
||
* rules for contacts on contacts.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Yet another TileType bitmask pointer, outMask, is filled in with
|
||
* the matching types.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
dbTechMatchResidues(inMask, outMask, contactsOnly)
|
||
TileTypeBitMask *inMask, *outMask;
|
||
bool contactsOnly;
|
||
{
|
||
TileType type;
|
||
LayerInfo *li;
|
||
|
||
TTMaskZero(outMask);
|
||
for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
|
||
{
|
||
li = &dbLayerInfo[type];
|
||
if (!li->l_isContact && contactsOnly)
|
||
continue;
|
||
|
||
if (TTMaskEqual(inMask, &li->l_residues))
|
||
TTMaskSetType(outMask, type);
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
* DBTechFindStacking --
|
||
*
|
||
* Find a stacking tile type which connects the two indicated types.
|
||
* Stacking types have the l_residues field of the LayerInfo entry filled
|
||
* with the mask of the two types which make up the stacked contact type.
|
||
*
|
||
* Results:
|
||
* The stacking tile type, if it exists, or -1 if there's no stacking
|
||
* type connecting type1 and type2.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
TileType
|
||
DBTechFindStacking(type1, type2)
|
||
TileType type1, type2;
|
||
{
|
||
TileType rtype, rtype1, rtype2, stackType;
|
||
LayerInfo *li;
|
||
|
||
for (stackType = DBNumUserLayers; stackType < DBNumTypes; stackType++)
|
||
{
|
||
rtype1 = rtype2 = -1;
|
||
li = &dbLayerInfo[stackType];
|
||
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
|
||
if (TTMaskHasType(&li->l_residues, rtype))
|
||
{
|
||
rtype1 = rtype;
|
||
break;
|
||
}
|
||
for (++rtype; rtype < DBNumUserLayers; rtype++)
|
||
if (TTMaskHasType(&li->l_residues, rtype))
|
||
{
|
||
rtype2 = rtype;
|
||
break;
|
||
}
|
||
|
||
if (((rtype1 == type1) && (rtype2 == type2)) ||
|
||
((rtype1 == type2) && (rtype2 == type1)))
|
||
return stackType;
|
||
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBTechFinalContact --
|
||
*
|
||
* Conclude reading the "contact" section of a technology file.
|
||
* At this point, all tile types are known so we can call dbTechInitPaint()
|
||
* to fill in the default paint/erase tables, and dbTechInitMasks() to fill
|
||
* in the various exported TileTypeBitMasks.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Fills in the dbLayerInfo table for non-contacts.
|
||
* Sets DBLayerTypeMaskTbl to its final value.
|
||
* Initializes DBTypePlaneMaskTbl[] and DBPlaneTypes[].
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
DBTechFinalContact()
|
||
{
|
||
TileType primaryType;
|
||
LayerInfo *lp;
|
||
int pNum;
|
||
|
||
/* Fill in plane and residue info for non-contact types */
|
||
|
||
for (primaryType = 0; primaryType < DBNumTypes; primaryType++)
|
||
{
|
||
lp = &dbLayerInfo[primaryType];
|
||
pNum = DBPlane(primaryType);
|
||
if (!lp->l_isContact && (pNum > 0))
|
||
{
|
||
lp->l_pmask = PlaneNumToMaskBit(pNum);
|
||
TTMaskSetOnlyType(&lp->l_residues, primaryType);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Initialize the masks of planes on which each type appears.
|
||
* It will contain all planes (except subcell) for space,
|
||
* the home plane for each type up to DBNumTypes, and no
|
||
* planes for undefined types. Also update the mask of
|
||
* types visible on each plane.
|
||
*/
|
||
|
||
DBTypePlaneMaskTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_CELL));
|
||
for (primaryType = 0; primaryType < DBNumTypes; primaryType++)
|
||
{
|
||
pNum = DBPlane(primaryType);
|
||
if (pNum > 0)
|
||
{
|
||
DBTypePlaneMaskTbl[primaryType] = PlaneNumToMaskBit(pNum);
|
||
if (!IsContact(primaryType))
|
||
TTMaskSetType(&DBPlaneTypes[pNum], primaryType);
|
||
else
|
||
{
|
||
lp = &dbLayerInfo[primaryType];
|
||
|
||
/* if (primaryType < DBNumUserLayers) */
|
||
DBTypePlaneMaskTbl[primaryType] |= lp->l_pmask;
|
||
|
||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||
if (PlaneMaskHasPlane(lp->l_pmask, pNum))
|
||
TTMaskSetType(&DBPlaneTypes[pNum], primaryType);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Create a mask for which each type only appears on one plane. */
|
||
/* This is useful for non-redundant searches. */
|
||
|
||
for (pNum = 0; pNum < PL_MAXTYPES; pNum++)
|
||
TTMaskZero(&DBHomePlaneTypes[pNum]);
|
||
|
||
for (primaryType = TT_SPACE + 1; primaryType < DBNumTypes; primaryType++)
|
||
TTMaskSetType(&DBHomePlaneTypes[DBPlane(primaryType)], primaryType);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
* DBTechTypesOnPlane --
|
||
*
|
||
* Given a tile type bitmask and a plane index, check if all types in the
|
||
* bitmask have an image on the indicated plane.
|
||
*
|
||
* Results:
|
||
* TRUE if all types in "src" have at least one image on plane.
|
||
* FALSE if any type in "src" does not contain any image in plane.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
bool
|
||
DBTechTypesOnPlane(src, plane)
|
||
TileTypeBitMask *src;
|
||
int plane;
|
||
{
|
||
int i;
|
||
PlaneMask pmask;
|
||
|
||
for (i = 0; i < DBNumTypes; i++)
|
||
if (TTMaskHasType(src, i))
|
||
if (!PlaneMaskHasPlane(DBTypePlaneMaskTbl[i], plane))
|
||
return FALSE;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBTechGetContact --
|
||
*
|
||
* Given two tile types, determine the corresponding contact type.
|
||
* (Or rather, for two types, get the first contact type connecting
|
||
* the two planes on which those types lie. . . not quite the same
|
||
* thing.)
|
||
*
|
||
* Results:
|
||
* Returns a contact type.
|
||
*
|
||
* Side effects:
|
||
* Prints stuff if it can't find a contact type.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
TileType
|
||
DBTechGetContact(type1, type2)
|
||
TileType type1, type2;
|
||
{
|
||
int pmask;
|
||
LayerInfo *lp;
|
||
TileType t;
|
||
|
||
pmask = DBTypePlaneMaskTbl[type1] | DBTypePlaneMaskTbl[type2];
|
||
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
||
{
|
||
lp = &dbLayerInfo[t];
|
||
if (lp->l_isContact)
|
||
if (lp->l_pmask == pmask)
|
||
return t;
|
||
}
|
||
|
||
TxPrintf("No contact type for %d %d\n", type1, type2);
|
||
return (TileType) -1;
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBIsContact --
|
||
*
|
||
* Like IsContact(), except as a subroutine, not a macro. For export
|
||
* to other routines.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
bool
|
||
DBIsContact(type)
|
||
TileType type;
|
||
{
|
||
if (IsContact(type)) return TRUE;
|
||
return FALSE;
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBResidueMask --
|
||
*
|
||
* Get the residue mask of the specified type. For export to other
|
||
* routines.
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
TileTypeBitMask *
|
||
DBResidueMask(type)
|
||
TileType type;
|
||
{
|
||
LayerInfo *li = &dbLayerInfo[type];
|
||
return (&li->l_residues);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* DBFullResidueMask --
|
||
*
|
||
* Get the residue mask of the specified type. For stacking contacts,
|
||
* decompose the contact residues into their component residue layers.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side Effects:
|
||
* "rmask" is a pointer to a TileTypeBitMask. The result is placed
|
||
* in this location.
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
DBFullResidueMask(type, rmask)
|
||
TileType type;
|
||
TileTypeBitMask *rmask;
|
||
{
|
||
TileType t;
|
||
TileTypeBitMask *lmask;
|
||
LayerInfo *li, *lr;
|
||
|
||
li = &dbLayerInfo[type];
|
||
lmask = &li->l_residues;
|
||
TTMaskZero(rmask);
|
||
|
||
if (type < DBNumUserLayers)
|
||
{
|
||
TTMaskSetMask(rmask, &li->l_residues);
|
||
}
|
||
else
|
||
{
|
||
for (t = TT_TECHDEPBASE; t < DBNumUserLayers; t++)
|
||
if (TTMaskHasType(lmask, t))
|
||
{
|
||
lr = &dbLayerInfo[t];
|
||
TTMaskSetMask(rmask, &lr->l_residues);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* dbTechPrintContacts --
|
||
*
|
||
* DEBUGGING.
|
||
* Print a list of the contact types to which each possible contact image
|
||
* belongs.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Prints stuff.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
dbTechPrintContacts()
|
||
{
|
||
LayerInfo *lpImage;
|
||
TileType t;
|
||
int m, pNum;
|
||
|
||
for (m = 0; m < dbNumContacts; m++)
|
||
{
|
||
lpImage = dbContactInfo[m];
|
||
TxPrintf("Contact %s (on %s) ",
|
||
DBTypeLongName(lpImage->l_type),
|
||
DBPlaneLongName(DBPlane(lpImage->l_type)));
|
||
|
||
TxPrintf(" connects:");
|
||
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
||
if ( TTMaskHasType(&DBConnectTbl[lpImage->l_type], t) )
|
||
TxPrintf(" %s", DBTypeLongName(t));
|
||
|
||
TxPrintf(" planes:");
|
||
for ( pNum = PL_TECHDEPBASE; pNum < PL_MAXTYPES; pNum++ )
|
||
if ( PlaneNumToMaskBit(pNum) & DBConnPlanes[lpImage->l_type] )
|
||
TxPrintf(" %s", DBPlaneLongName(pNum));
|
||
|
||
TxPrintf(" residues:");
|
||
for ( t = TT_TECHDEPBASE; t < DBNumTypes; t++ )
|
||
if (TTMaskHasType(&lpImage->l_residues, t))
|
||
TxPrintf(" %s on plane %s\n",
|
||
DBTypeLongName(t),
|
||
DBPlaneLongName(DBPlane(t)));
|
||
|
||
TxPrintf("\n");
|
||
}
|
||
}
|
||
|