2017-04-25 14:41:48 +02:00
|
|
|
|
/*
|
|
|
|
|
|
* 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.
|
2019-03-23 00:58:47 +01:00
|
|
|
|
* It will contain all planes (except router) for space,
|
2017-04-25 14:41:48 +02:00
|
|
|
|
* 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.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2019-03-23 00:58:47 +01:00
|
|
|
|
DBTypePlaneMaskTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER));
|
2017-04-25 14:41:48 +02:00
|
|
|
|
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");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|