Found no fewer than three separate places that cause a pop-up prompt

for saving on a cell which is completely unmodified.  One of these
was due to the BPlane implementation, which forces an instance to be
deleted and re-placed on a bounding box recomputation, which should
not, in that case, be considered a modification.  Another always runs
DRC on a subcell upon reading rather than relying on any checkplane
entries in the file itself;  and the last one marking the timestamp
as modified stemming from an attempt to correct an O(N^2) check to
O(N).  All three cases have now been corrected.
This commit is contained in:
Tim Edwards 2021-03-16 22:46:46 -04:00
parent 010c0599bd
commit 59bfa6ce86
4 changed files with 83 additions and 5 deletions

View File

@ -118,6 +118,7 @@ DBCellFindDup(use, parent)
* ----------------------------------------------------------------------------
*
* DBPlaceCell --
* DBPlaceCellNoModify --
*
* Add a CellUse to the subcell tile plane of a CellDef.
* Assumes prior check that the new CellUse is not an exact duplicate
@ -162,11 +163,47 @@ DBPlaceCell (use, def)
SigEnableInterrupts();
}
/* Like DBPlaceCell(), but don't change the flags of the parent cell. */
/* This is needed by the bounding box recalculation routine, which may */
/* cause the cell to be deleted and replaced for the purpose of */
/* capturing the bounding box information in the BPlane structure, but */
/* this does not mean that anything in the parent cell has changed. */
void
DBPlaceCellNoModify (use, def)
CellUse * use; /* new celluse to add to subcell tile plane */
CellDef * def; /* parent cell's definition */
{
Rect rect; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
BPlane *bplane; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
struct searchArg arg; /* argument to placeCellFunc() */
ASSERT(use != (CellUse *) NULL, "DBPlaceCell");
ASSERT(def, "DBPlaceCell");
/* To do: Check non-duplicate placement, check non-duplicate ID */
use->cu_parent = def;
/* Be careful not to permit interrupts during this, or the
* database could be left in a trashed state.
*/
SigDisableInterrupts();
BPAdd(def->cd_cellPlane, use);
if (UndoIsEnabled())
DBUndoCellUse(use, UNDO_CELL_PLACE);
SigEnableInterrupts();
}
/*
* ----------------------------------------------------------------------------
* DBDeleteCell --
*
* Remove a CellUse from the subcell tile plane of a CellDef.
* If "nomodify" is TRUE, then don't set the parent cell's CDMODIFIED flag.
* This is needed when recomputing the bounding box, which should not by
* itself change the modified state.
*
* Results:
* None.
@ -197,3 +234,39 @@ DBDeleteCell (use)
SigEnableInterrupts();
}
/*
* ----------------------------------------------------------------------------
* DBDeleteCellNoModify --
*
* Remove a CellUse from the subcell tile plane of a CellDef, as above,
* but don't set the parent cell's CDMODIFIED flag. This is needed when
* recomputing the bounding box, which should not by itself change the
* modified state.
*
* Results:
* None.
*
* Side effects:
* Modifies the subcell tile plane of the CellDef, sets the
* parent pointer of the deleted CellUse to NULL.
* ----------------------------------------------------------------------------
*/
void
DBDeleteCellNoModify (use)
CellUse * use;
{
ASSERT(use != (CellUse *) NULL, "DBDeleteCell");
/* It's important that this code run with interrupts disabled,
* or else we could leave the subcell tile plane in a weird
* state.
*/
SigDisableInterrupts();
dbInstanceUnplace(use);
if (UndoIsEnabled())
DBUndoCellUse(use, UNDO_CELL_DELETE);
use->cu_parent = (CellDef *) NULL;
SigEnableInterrupts();
}

View File

@ -723,7 +723,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
*/
parent = use->cu_parent;
DBDeleteCell(use);
DBDeleteCellNoModify(use);
use->cu_parent = parent;
}
@ -751,7 +751,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
if ((parent = use->cu_parent) != (CellDef *) NULL)
{
parent->cd_flags |= CDBOXESCHANGED;
DBPlaceCell(use, parent);
DBPlaceCellNoModify(use, parent);
if (last != parent)
{
if (last != NULL) (*recurseProc)(last);

View File

@ -411,7 +411,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech, dereference)
int cellStamp = 0, rectCount = 0, rectReport = 10000;
char line[2048], tech[50], layername[50];
PaintResultType *ptable;
bool result = TRUE, scaleLimit = FALSE;
bool result = TRUE, scaleLimit = FALSE, has_mismatch;
Rect *rp;
int c;
TileType type, rtype, loctype;
@ -844,6 +844,7 @@ done:
* timestamp, then force the cell to be written out with a
* correct timestamp.
*/
has_mismatch = FALSE;
if ((cellDef->cd_timestamp != cellStamp) || (cellStamp == 0))
{
CellUse *cu;
@ -852,12 +853,13 @@ done:
if (cu->cu_parent != NULL)
{
DBStampMismatch(cellDef, &cellDef->cd_bbox);
has_mismatch = TRUE;
break;
}
}
}
/* Update timestamp flags */
DBFlagMismatches(cellDef);
if (has_mismatch) DBFlagMismatches(cellDef);
cellDef->cd_timestamp = cellStamp;
if (cellStamp == 0)
@ -869,7 +871,8 @@ done:
}
UndoEnable();
DRCCheckThis(cellDef, TT_CHECKPAINT, (Rect *) NULL);
/* Disabled 3/16/2021. Let <<checkpaint>> in file force a DRC check */
/* DRCCheckThis(cellDef, TT_CHECKPAINT, (Rect *) NULL); */
SigEnableInterrupts();
return (result);

View File

@ -790,7 +790,9 @@ extern CellUse *DBFindUse();
/* Insertion/deletion of cell uses into the cell tile plane of a parent */
extern void DBPlaceCell();
extern void DBPlaceCellNoModify();
extern void DBDeleteCell();
extern void DBDeleteCellNoModify();
extern void DBClearCellPlane();
/* Insertion/deletion of cell uses into the name space of a parent */