diff --git a/VERSION b/VERSION index f6e30960..5eb3bdf8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.344 +8.3.345 diff --git a/database/database.h.in b/database/database.h.in index 1e677fed..d0f7e230 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -418,6 +418,8 @@ typedef struct celldef * the same timestamp value. * CDNOEXTRACT is used by incremental extraction to flag cells that * 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 @@ -438,6 +440,7 @@ typedef struct celldef #define CDDEREFERENCE 0x08000 #define CDFIXEDSTAMP 0x10000 #define CDNOEXTRACT 0x20000 +#define CDDONTUSE 0x40000 /* * Description of an array. diff --git a/extract/ExtCell.c b/extract/ExtCell.c index 1f0ba250..89257185 100644 --- a/extract/ExtCell.c +++ b/extract/ExtCell.c @@ -543,6 +543,8 @@ extOutputUsesFunc(cu, outf) { 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); if (cu->cu_xlo != cu->cu_xhi || cu->cu_ylo != cu->cu_yhi) { diff --git a/extract/ExtHier.c b/extract/ExtHier.c index 4b36a648..509cc5c5 100644 --- a/extract/ExtHier.c +++ b/extract/ExtHier.c @@ -115,6 +115,9 @@ extHierSubstrate(ha, use, x, y) /* then there is no need to do it again. */ 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; /* Register the name of the parent's substrate */ diff --git a/extract/ExtMain.c b/extract/ExtMain.c index 46b36847..a87fcd82 100644 --- a/extract/ExtMain.c +++ b/extract/ExtMain.c @@ -171,6 +171,48 @@ ExtInit() 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; LinkedDef *newLD; - /* Ignore all internal cells and cells that have been visited */ - if (def->cd_flags & CDINTERNAL) return 0; + /* Ignore all internal cells and cells that are marked "don't use" */ + if (def->cd_flags & (CDINTERNAL | CDDONTUSE)) return 0; /* Recurse to the bottom first */ (void) DBCellEnum(def, extDefListFunc, (ClientData)defList); @@ -194,6 +236,31 @@ extDefListFunc(use, defList) /* Don't add cells that have already been visited */ 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 */ newLD = (LinkedDef *)mallocMagic(sizeof(LinkedDef)); @@ -201,9 +268,6 @@ extDefListFunc(use, defList) newLD->ld_next = *defList; *defList = newLD; - /* Mark self as visited */ - def->cd_client = (ClientData) 1; - return 0; } @@ -221,8 +285,8 @@ extDefListFuncIncremental(use, defList) CellDef *def = use->cu_def; LinkedDef *newLD; - /* Ignore all internal cells */ - if (def->cd_flags & CDINTERNAL) return 0; + /* Ignore all internal cells and cells marked "don't use" */ + if (def->cd_flags & (CDINTERNAL | CDDONTUSE)) return 0; /* Mark cells that don't need updating */ if (!extTimestampMisMatch(def)) @@ -234,6 +298,31 @@ extDefListFuncIncremental(use, defList) /* Don't add cells that have already been visited */ 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 */ newLD = (LinkedDef *)mallocMagic(sizeof(LinkedDef)); @@ -241,9 +330,6 @@ extDefListFuncIncremental(use, defList) newLD->ld_next = *defList; *defList = newLD; - /* Mark self as visited */ - def->cd_client = (ClientData) 1; - return 0; }