From 7dfe4077871bfe2af64f807a77941e85141c7d7e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 14 Jan 2021 15:21:39 -0500 Subject: [PATCH] Implemented a return value for the cell read-in checks with an option to stop the search whenever a cell is not found. Used this to implement a new option for GDS writes, "gds undefined allow|disallow" (default "disallow") controls whether or not GDS with undefined references will be allowed to be written. Similarly affects CIF and LEF writes, extraction, and DRC (when running "drc check" from the top). --- calma/CalmaWrite.c | 20 +++++++++++++------- calma/calma.h | 1 + cif/CIFwrite.c | 8 ++++++-- commands/CmdCD.c | 24 ++++++++++++++++++++++++ database/DBexpand.c | 26 +++++++++++++++++++------- database/DBio.c | 5 +++-- database/database.h.in | 2 +- drc/DRCmain.c | 6 +++++- extract/ExtMain.c | 18 +++++++++++++++--- extract/ExtTimes.c | 12 ++++++++++-- garouter/gaTest.c | 2 +- lef/lefWrite.c | 6 +++++- 12 files changed, 103 insertions(+), 27 deletions(-) diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index bb1134b4..920b9b02 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -53,12 +53,13 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c #include "utils/stack.h" /* Exports */ -bool CalmaDoLibrary = FALSE; /* If TRUE, do not output the top level */ -bool CalmaDoLabels = TRUE; /* If FALSE, don't output labels with GDS-II */ -bool CalmaDoLower = TRUE; /* If TRUE, allow lowercase labels. */ -bool CalmaFlattenArrays = FALSE; /* If TRUE, output arrays as individual uses */ -bool CalmaAddendum = FALSE; /* If TRUE, do not output readonly cell defs */ -bool CalmaNoDateStamp = FALSE; /* If TRUE, output zero for creation date stamp */ +bool CalmaDoLibrary = FALSE; /* If TRUE, do not output the top level */ +bool CalmaDoLabels = TRUE; /* If FALSE, don't output labels with GDS-II */ +bool CalmaDoLower = TRUE; /* If TRUE, allow lowercase labels. */ +bool CalmaFlattenArrays = FALSE; /* If TRUE, output arrays as individual uses */ +bool CalmaAddendum = FALSE; /* If TRUE, do not output readonly cell defs */ +bool CalmaNoDateStamp = FALSE; /* If TRUE, output zero for creation date stamp */ +bool CalmaAllowUndefined = FALSE; /* If TRUE, allow calls to undefined cells */ /* Experimental stuff---not thoroughly tested (as of Sept. 2007)! */ bool CalmaContactArrays = FALSE; /* If TRUE, output contacts as subcell arrays */ @@ -305,7 +306,12 @@ CalmaWrite(rootDef, f) */ dummy.cu_def = rootDef; - DBCellReadArea(&dummy, &rootDef->cd_bbox); + if (DBCellReadArea(&dummy, &rootDef->cd_bbox, !CalmaAllowUndefined)) + { + TxError("Failure to read entire subtree of the cell.\n"); + return FALSE; + } + DBFixMismatch(); /* diff --git a/calma/calma.h b/calma/calma.h index 0762f81a..d37d50f3 100644 --- a/calma/calma.h +++ b/calma/calma.h @@ -41,6 +41,7 @@ extern char **CalmaFlattenUsesByName; extern bool CalmaReadOnly; extern bool CalmaContactArrays; extern bool CalmaPostOrder; +extern bool CalmaAllowUndefined; /* Externally-visible procedures: */ extern bool CalmaWrite(); diff --git a/cif/CIFwrite.c b/cif/CIFwrite.c index 8f40c2b2..0dbfcc67 100644 --- a/cif/CIFwrite.c +++ b/cif/CIFwrite.c @@ -132,14 +132,18 @@ CIFWrite(rootDef, f) */ dummy.cu_def = rootDef; - DBCellReadArea(&dummy, &rootDef->cd_bbox); + if (DBCellReadArea(&dummy, &rootDef->cd_bbox, TRUE)) + { + TxError("Failure to read in entire subtree of the cell.\n"); + return (FALSE); + } DBFixMismatch(); if (CIFCurStyle->cs_reducer == 0) { TxError("The current CIF output style can only be used for writing\n"); TxError("Calma output. Try picking another output style.\n"); - return (TRUE); + return (FALSE); } /* diff --git a/commands/CmdCD.c b/commands/CmdCD.c index a4a2efb7..75326603 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -109,6 +109,7 @@ bool cmdDumpParseArgs(); #define CALMA_WRITE 18 #define CALMA_POLYS 19 #define CALMA_PATHS 20 +#define CALMA_UNDEFINED 21 #define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */ @@ -127,6 +128,7 @@ CmdCalma(w, cmd) static char *gdsExts[] = {".gds", ".gds2", ".strm", "", NULL}; static char *cmdCalmaYesNo[] = { "no", "false", "off", "0", "yes", "true", "on", "1", 0 }; + static char *cmdCalmaAllowDisallow[] = {"disallow", "0", "allow", "1", 0}; static char *cmdCalmaWarnOptions[] = { "default", "none", "align", "limit", "redirect", "help", 0 }; static char *cmdCalmaOption[] = @@ -156,6 +158,8 @@ CmdCalma(w, cmd) " put non-Manhattan polygons into subcells", "path subcells [yes|no]\n" " put wire paths into individual subcells", + "undefined [allow|disallow]\n" + " [dis]allow writing of GDS with calls to undefined cells", NULL }; @@ -279,6 +283,26 @@ CmdCalma(w, cmd) CalmaAddendum = (option < 4) ? FALSE : TRUE; return; + case CALMA_UNDEFINED: + if (cmd->tx_argc == 2) + { +#ifdef MAGIC_WRAPPER + Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaAllowUndefined)); +#else + TxPrintf("Writing of GDS file with undefined cells is %sallowed.\n", + (CalmaAllowUndefined) ? "" : "dis"); +#endif + return; + } + else if (cmd->tx_argc != 3) + goto wrongNumArgs; + + option = Lookup(cmd->tx_argv[2], cmdCalmaAllowDisallow); + if (option < 0) + goto wrongNumArgs; + CalmaAllowUndefined = (option < 2) ? FALSE : TRUE; + return; + case CALMA_CONTACTS: if (cmd->tx_argc == 2) { diff --git a/database/DBexpand.c b/database/DBexpand.c index 63d0f7d1..f93aaa67 100644 --- a/database/DBexpand.c +++ b/database/DBexpand.c @@ -275,7 +275,8 @@ dbUnexpandFunc(scx, arg) * the given rectangle. * * Results: - * None. + * If "halt_on_error" is TRUE, then return 1 if any subcell could not + * be read. Otherwise, return 0. * * Side effects: * May make new cells known to the database. Sets the CDAVAILABLE @@ -284,10 +285,11 @@ dbUnexpandFunc(scx, arg) * ---------------------------------------------------------------------------- */ -void -DBCellReadArea(rootUse, rootRect) +int +DBCellReadArea(rootUse, rootRect, halt_on_error) CellUse *rootUse; /* Root cell use from which search begins */ Rect *rootRect; /* Area to be read, in root coordinates */ + bool halt_on_error; /* If TRUE, failure to find a cell causes a halt */ { int dbReadAreaFunc(); SearchContext scontext; @@ -295,30 +297,39 @@ DBCellReadArea(rootUse, rootRect) scontext.scx_use = rootUse; scontext.scx_trans = GeoIdentityTransform; scontext.scx_area = *rootRect; - (void) dbReadAreaFunc(&scontext); + if (dbReadAreaFunc(&scontext, halt_on_error) == 1) + return 1; + + return 0; } int -dbReadAreaFunc(scx) +dbReadAreaFunc(scx, halt_on_error) SearchContext *scx; /* Pointer to context specifying * the cell use to be read in, and * an area to be recursively read in * coordinates of the cell use's def. */ + bool halt_on_error; /* If TURE, failure to find a cell causes a halt */ { CellDef *def = scx->scx_use->cu_def; if ((def->cd_flags & CDAVAILABLE) == 0) { bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; - (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL); + if (DBCellRead(def, (char *)NULL, TRUE, dereference, NULL) == FALSE) + if (halt_on_error) + return 1; + /* Note: we don't have to invoke DBReComputeBbox here because * if the bbox changed then there was a timestamp mismatch and * the timestamp code will take care of the bounding box later. */ } - (void) DBCellSrArea(scx, dbReadAreaFunc, (ClientData) NULL); + if (DBCellSrArea(scx, dbReadAreaFunc, (ClientData)halt_on_error)) + if (halt_on_error) + return 1; /* Be clever about handling arrays: if the search area covers this * whole definition, then there's no need to look at any other @@ -328,5 +339,6 @@ dbReadAreaFunc(scx) if (GEO_SURROUND(&scx->scx_area, &scx->scx_use->cu_def->cd_bbox)) return 2; + return 0; } diff --git a/database/DBio.c b/database/DBio.c index df5927f6..56874065 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -899,7 +899,7 @@ DBReadBackup(name) * * DBCellRead -- * - * This is the wrapper for DBCellReadDef. The routine has been divided into + * This is the wrapper for dbCellReadDef. The routine has been divided into * parts so that a single backup file can be made and recovered, and in * preparation for allowing certain cell definitions to be in-lined into the * output file (such as polygonXXXXX cells generated by the gds read-in). @@ -2947,7 +2947,8 @@ DBCellWrite(cellDef, fileName) { bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; /* Re-aquire the lock on the new file by opening it. */ - DBCellRead(cellDef, NULL, TRUE, dereference, NULL); + if (DBCellRead(cellDef, NULL, TRUE, dereference, NULL) == FALSE) + return FALSE; } #endif diff --git a/database/database.h.in b/database/database.h.in index 0815c75f..5b02ed8c 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -720,7 +720,7 @@ extern bool DBCellRead(); extern bool DBTestOpen(); extern char *DBGetTech(); extern bool DBCellWrite(); -extern void DBCellReadArea(); +extern int DBCellReadArea(); extern void DBFileRecovery(); extern bool DBWriteBackup(); extern bool DBReadBackup(); diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 59edd41b..6fa55e7c 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -664,7 +664,11 @@ DRCCheck(use, area) SearchContext scx; extern int drcCheckFunc(); /* Forward reference. */ - DBCellReadArea(use, area); + if (DBCellReadArea(use, area, TRUE)) + { + TxError("Failure to read in entire subtree of cell.\n"); + return; + } scx.scx_use = use; scx.scx_x = use->cu_xlo; diff --git a/extract/ExtMain.c b/extract/ExtMain.c index 8b8e75f6..d3b0c4f5 100644 --- a/extract/ExtMain.c +++ b/extract/ExtMain.c @@ -179,7 +179,11 @@ ExtAll(rootUse) CellUse *rootUse; { /* Make sure the entire subtree is read in */ - DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE)) + { + TxError("Failure to read entire subtree of cell.\n"); + return; + } /* Fix up bounding boxes if they've changed */ DBFixMismatch(); @@ -264,7 +268,11 @@ ExtUnique(rootUse, option) int nwarn; /* Make sure the entire subtree is read in */ - DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE)) + { + TxError("Failure to read entire subtree of cell.\n"); + return; + } /* Fix up bounding boxes if they've changed */ DBFixMismatch(); @@ -526,7 +534,11 @@ ExtIncremental(rootUse) CellUse *rootUse; { /* Make sure the entire subtree is read in */ - DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE)) + { + TxError("Failure to read entire subtree of cell.\n"); + return; + } /* Fix up bounding boxes if they've changed */ DBFixMismatch(); diff --git a/extract/ExtTimes.c b/extract/ExtTimes.c index 262b2bfe..c13c5f59 100644 --- a/extract/ExtTimes.c +++ b/extract/ExtTimes.c @@ -169,7 +169,11 @@ ExtTimes(rootUse, f) HashEntry *he; /* Make sure this cell is read in */ - DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE)) + { + TxError("Failure to read entire subtree of cell.\n"); + return; + } /* Initialize cumulative statistics */ extCumInit(&cumFetsPerSecPaint); @@ -1020,7 +1024,11 @@ ExtInterCount(rootUse, halo, f) double inter; /* Make sure this cell is read in */ - DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE)) + { + TxError("Failure to read entire subtree of cell.\n"); + return; + } /* Initialize cumulative statistics */ extCumInit(&cumPercentInteraction); diff --git a/garouter/gaTest.c b/garouter/gaTest.c index b48c78d5..a6f2fd70 100644 --- a/garouter/gaTest.c +++ b/garouter/gaTest.c @@ -201,7 +201,7 @@ GAGenChans(chanType, area, f) } /* Make sure everything in 'area' is read */ - (void) DBCellReadArea(EditCellUse, area); + (void) DBCellReadArea(EditCellUse, area, FALSE); DBFixMismatch(); /* Start with a clean slate */ diff --git a/lef/lefWrite.c b/lef/lefWrite.c index a8adc57e..17a3ac17 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -1982,7 +1982,11 @@ LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, lefTopLayer, lefDoMaster, r rootdef = rootUse->cu_def; /* Make sure the entire subtree is read in */ - DBCellReadArea(rootUse, &rootdef->cd_bbox); + if (DBCellReadArea(rootUse, &rootdef->cd_bbox, TRUE)) + { + TxError("Could not read entire subtree of the cell.\n"); + return; + } /* Fix up bounding boxes if they've changed */ DBFixMismatch();