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();