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).
This commit is contained in:
Tim Edwards 2021-01-14 15:21:39 -05:00
parent fa5a49ac3d
commit 7dfe407787
12 changed files with 103 additions and 27 deletions

View File

@ -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();
/*

View File

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

View File

@ -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);
}
/*

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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

View File

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

View File

@ -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;

View File

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

View File

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

View File

@ -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 */

View File

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