Implemented a method to handle empty subcells that exist because a
library has been read in with the "gds readonly true" option set because the cell contains information on where in the GDS the cell is located, but the cell is empty because it was flattened into the magic view and all of its contents were erased. This can cause issues with LVS if magic generates an empty cell into the netlist and the LVS tool tries to compare the cells by name. Also, this prevents unnecessary .ext files and unnecessary merges to the substrate of such cells (since all cells have an implied substrate).
This commit is contained in:
parent
0f05bb1356
commit
71dffb2fd2
|
|
@ -418,6 +418,8 @@ typedef struct celldef
|
||||||
* the same timestamp value.
|
* the same timestamp value.
|
||||||
* CDNOEXTRACT is used by incremental extraction to flag cells that
|
* CDNOEXTRACT is used by incremental extraction to flag cells that
|
||||||
* are up-to-date and do not need to be re-extracted.
|
* are up-to-date and do not need to be re-extracted.
|
||||||
|
* CDDONTUSE is used during extraction to flag cells that have no
|
||||||
|
* contents and should be ignored.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CDAVAILABLE 0x00001
|
#define CDAVAILABLE 0x00001
|
||||||
|
|
@ -438,6 +440,7 @@ typedef struct celldef
|
||||||
#define CDDEREFERENCE 0x08000
|
#define CDDEREFERENCE 0x08000
|
||||||
#define CDFIXEDSTAMP 0x10000
|
#define CDFIXEDSTAMP 0x10000
|
||||||
#define CDNOEXTRACT 0x20000
|
#define CDNOEXTRACT 0x20000
|
||||||
|
#define CDDONTUSE 0x40000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Description of an array.
|
* Description of an array.
|
||||||
|
|
|
||||||
|
|
@ -543,6 +543,8 @@ extOutputUsesFunc(cu, outf)
|
||||||
{
|
{
|
||||||
Transform *t = &cu->cu_transform;
|
Transform *t = &cu->cu_transform;
|
||||||
|
|
||||||
|
if (cu->cu_def->cd_flags & CDDONTUSE) return 0;
|
||||||
|
|
||||||
fprintf(outf, "use %s %s", cu->cu_def->cd_name, cu->cu_id);
|
fprintf(outf, "use %s %s", cu->cu_def->cd_name, cu->cu_id);
|
||||||
if (cu->cu_xlo != cu->cu_xhi || cu->cu_ylo != cu->cu_yhi)
|
if (cu->cu_xlo != cu->cu_xhi || cu->cu_ylo != cu->cu_yhi)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,9 @@ extHierSubstrate(ha, use, x, y)
|
||||||
/* then there is no need to do it again. */
|
/* then there is no need to do it again. */
|
||||||
if (use->cu_flags & CU_SUB_EXTRACTED) return;
|
if (use->cu_flags & CU_SUB_EXTRACTED) return;
|
||||||
|
|
||||||
|
/* Don't extract anything from cells marked "don't use". */
|
||||||
|
if (use->cu_def->cd_flags & CDDONTUSE) return;
|
||||||
|
|
||||||
def = (CellDef *)ha->ha_parentUse->cu_def;
|
def = (CellDef *)ha->ha_parentUse->cu_def;
|
||||||
|
|
||||||
/* Register the name of the parent's substrate */
|
/* Register the name of the parent's substrate */
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,48 @@ ExtInit()
|
||||||
extLengthInit();
|
extLengthInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Simple callback returns 1 if any cell is not marked with the CDDONTUSE
|
||||||
|
* flag. If DBCellEnum() returns 0 then all children of the CellDef are
|
||||||
|
* marked CDDONTUSE.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
extIsUsedFunc(use, clientData)
|
||||||
|
CellUse *use;
|
||||||
|
ClientData clientData; /* unused */
|
||||||
|
{
|
||||||
|
CellDef *def = use->cu_def;
|
||||||
|
|
||||||
|
/* If any cell is not marked CDDONTUSE then return 1 and stop the search. */
|
||||||
|
if (!(def->cd_flags & CDDONTUSE)) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Simple callback returns 1 if any non-space tile is found in a cell.
|
||||||
|
* Used to determine if a cell does not need extracting because it is
|
||||||
|
* an empty placeholder cell created when flattening part of a vendor
|
||||||
|
* GDS, and exists only to reference the GDS file location for writing
|
||||||
|
* GDS.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
extEnumFunc(tile, plane)
|
||||||
|
Tile *tile;
|
||||||
|
int *plane;
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -185,8 +227,8 @@ extDefListFunc(use, defList)
|
||||||
CellDef *def = use->cu_def;
|
CellDef *def = use->cu_def;
|
||||||
LinkedDef *newLD;
|
LinkedDef *newLD;
|
||||||
|
|
||||||
/* Ignore all internal cells and cells that have been visited */
|
/* Ignore all internal cells and cells that are marked "don't use" */
|
||||||
if (def->cd_flags & CDINTERNAL) return 0;
|
if (def->cd_flags & (CDINTERNAL | CDDONTUSE)) return 0;
|
||||||
|
|
||||||
/* Recurse to the bottom first */
|
/* Recurse to the bottom first */
|
||||||
(void) DBCellEnum(def, extDefListFunc, (ClientData)defList);
|
(void) DBCellEnum(def, extDefListFunc, (ClientData)defList);
|
||||||
|
|
@ -194,6 +236,31 @@ extDefListFunc(use, defList)
|
||||||
/* Don't add cells that have already been visited */
|
/* Don't add cells that have already been visited */
|
||||||
if (def->cd_client) return 0;
|
if (def->cd_client) return 0;
|
||||||
|
|
||||||
|
/* Mark self as visited */
|
||||||
|
def->cd_client = (ClientData) 1;
|
||||||
|
|
||||||
|
/* Check if all descendents are marked as "don't use" */
|
||||||
|
if (DBCellEnum(def, extIsUsedFunc, (ClientData)NULL) == 0)
|
||||||
|
{
|
||||||
|
int plane;
|
||||||
|
|
||||||
|
/* Nothing below this cell had anything to extract. */
|
||||||
|
/* Check this cell for paint. If it has none, then */
|
||||||
|
/* ignore it. */
|
||||||
|
|
||||||
|
for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
|
||||||
|
if (DBSrPaintArea((Tile *)NULL, def->cd_planes[plane], &TiPlaneRect,
|
||||||
|
&DBAllButSpaceAndDRCBits, extEnumFunc, (ClientData)NULL))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (plane == DBNumPlanes)
|
||||||
|
{
|
||||||
|
/* Cell has no material. Mark it and return. */
|
||||||
|
def->cd_flags |= CDDONTUSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* When done with descendents, add self to the linked list */
|
/* When done with descendents, add self to the linked list */
|
||||||
|
|
||||||
newLD = (LinkedDef *)mallocMagic(sizeof(LinkedDef));
|
newLD = (LinkedDef *)mallocMagic(sizeof(LinkedDef));
|
||||||
|
|
@ -201,9 +268,6 @@ extDefListFunc(use, defList)
|
||||||
newLD->ld_next = *defList;
|
newLD->ld_next = *defList;
|
||||||
*defList = newLD;
|
*defList = newLD;
|
||||||
|
|
||||||
/* Mark self as visited */
|
|
||||||
def->cd_client = (ClientData) 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,8 +285,8 @@ extDefListFuncIncremental(use, defList)
|
||||||
CellDef *def = use->cu_def;
|
CellDef *def = use->cu_def;
|
||||||
LinkedDef *newLD;
|
LinkedDef *newLD;
|
||||||
|
|
||||||
/* Ignore all internal cells */
|
/* Ignore all internal cells and cells marked "don't use" */
|
||||||
if (def->cd_flags & CDINTERNAL) return 0;
|
if (def->cd_flags & (CDINTERNAL | CDDONTUSE)) return 0;
|
||||||
|
|
||||||
/* Mark cells that don't need updating */
|
/* Mark cells that don't need updating */
|
||||||
if (!extTimestampMisMatch(def))
|
if (!extTimestampMisMatch(def))
|
||||||
|
|
@ -234,6 +298,31 @@ extDefListFuncIncremental(use, defList)
|
||||||
/* Don't add cells that have already been visited */
|
/* Don't add cells that have already been visited */
|
||||||
if (def->cd_client) return 0;
|
if (def->cd_client) return 0;
|
||||||
|
|
||||||
|
/* Mark self as visited */
|
||||||
|
def->cd_client = (ClientData) 1;
|
||||||
|
|
||||||
|
/* Check if all descendents are marked as "don't use" */
|
||||||
|
if (DBCellEnum(def, extIsUsedFunc, (ClientData)NULL) == 0)
|
||||||
|
{
|
||||||
|
int plane;
|
||||||
|
|
||||||
|
/* Nothing below this cell had anything to extract. */
|
||||||
|
/* Check this cell for paint. If it has none, then */
|
||||||
|
/* ignore it. */
|
||||||
|
|
||||||
|
for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
|
||||||
|
if (DBSrPaintArea((Tile *)NULL, def->cd_planes[plane], &TiPlaneRect,
|
||||||
|
&DBAllButSpaceAndDRCBits, extEnumFunc, (ClientData)NULL))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (plane == DBNumPlanes)
|
||||||
|
{
|
||||||
|
/* Cell has no material. Mark it and return. */
|
||||||
|
def->cd_flags |= CDDONTUSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* When done with descendents, add self to the linked list */
|
/* When done with descendents, add self to the linked list */
|
||||||
|
|
||||||
newLD = (LinkedDef *)mallocMagic(sizeof(LinkedDef));
|
newLD = (LinkedDef *)mallocMagic(sizeof(LinkedDef));
|
||||||
|
|
@ -241,9 +330,6 @@ extDefListFuncIncremental(use, defList)
|
||||||
newLD->ld_next = *defList;
|
newLD->ld_next = *defList;
|
||||||
*defList = newLD;
|
*defList = newLD;
|
||||||
|
|
||||||
/* Mark self as visited */
|
|
||||||
def->cd_client = (ClientData) 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue