mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-09-01 10:39:43 +02:00
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.
1031 lines
27 KiB
C
1031 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[];
|
|
{
|
|
ARG_UNUSED(sectionName);
|
|
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;
|
|
|
|
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 router) 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_ROUTER));
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBLayerPlanes --
|
|
*
|
|
* Like LayerPlaneMask(), except as a subroutine, not a macro. For export
|
|
* to other routines.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
PlaneMask
|
|
DBLayerPlanes(type)
|
|
TileType type;
|
|
{
|
|
return LayerPlaneMask(type);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* 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");
|
|
}
|
|
}
|
|
|