2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* DBcell.c --
|
|
|
|
|
*
|
|
|
|
|
* Place and Delete subcells
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
|
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
|
|
|
* * software and its documentation for any purpose and without *
|
|
|
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
|
|
|
* * notice appear in all copies. The University of California *
|
|
|
|
|
* * makes no representations about the suitability of this *
|
|
|
|
|
* * software for any purpose. It is provided "as is" without *
|
|
|
|
|
* * express or implied warranty. Export of this software outside *
|
|
|
|
|
* * of the United States of America may require an export license. *
|
2017-04-25 14:41:48 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef lint
|
|
|
|
|
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBcell.c,v 1.2 2008/12/11 04:20:04 tim Exp $";
|
|
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
#include "utils/magic.h"
|
|
|
|
|
#include "utils/malloc.h"
|
|
|
|
|
#include "utils/geometry.h"
|
|
|
|
|
#include "tiles/tile.h"
|
|
|
|
|
#include "utils/hash.h"
|
|
|
|
|
#include "database/database.h"
|
|
|
|
|
#include "database/databaseInt.h"
|
|
|
|
|
#include "utils/undo.h"
|
|
|
|
|
#include "utils/signals.h"
|
|
|
|
|
|
|
|
|
|
int placeCellFunc();
|
|
|
|
|
int deleteCellFunc();
|
|
|
|
|
Tile * clipCellTile();
|
|
|
|
|
void dupTileBody();
|
2020-05-23 23:13:14 +02:00
|
|
|
void cellTileMerge();
|
2017-04-25 14:41:48 +02:00
|
|
|
bool ctbListMatch();
|
|
|
|
|
void freeCTBList();
|
|
|
|
|
|
|
|
|
|
struct searchArg
|
|
|
|
|
{
|
|
|
|
|
CellUse * celluse;
|
|
|
|
|
Rect * rect;
|
2019-03-23 00:58:47 +01:00
|
|
|
BPlane * bplane;
|
2017-04-25 14:41:48 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define TOPLEFT 10
|
|
|
|
|
#define TOPLEFTRIGHT 11
|
|
|
|
|
#define TOPBOTTOM 12
|
|
|
|
|
#define TOPBOTTOMLEFT 14
|
|
|
|
|
#define TOPBOTTOMLEFTRIGHT 15
|
|
|
|
|
|
|
|
|
|
int dbCellDebug = 0;
|
2019-03-23 00:58:47 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
dbInstanceUnplace(CellUse *use)
|
|
|
|
|
{
|
|
|
|
|
ASSERT(use != (CellUse *) NULL, "dbInstanceUnplace");
|
|
|
|
|
|
|
|
|
|
/* It's important that this code run with interrupts disabled,
|
|
|
|
|
* or else we could leave the subcell tile plane in a weird
|
|
|
|
|
* state.
|
|
|
|
|
*/
|
2020-05-16 02:49:51 +02:00
|
|
|
|
2019-03-23 00:58:47 +01:00
|
|
|
BPDelete(use->cu_parent->cd_cellPlane, use);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DBCellFindDup --
|
|
|
|
|
*
|
|
|
|
|
* This procedure indicates whether a particular cell is already
|
|
|
|
|
* present at a particular point in a particular parent. It is
|
|
|
|
|
* used to avoid placing duplicate copies of a cell on top of
|
|
|
|
|
* each other.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* The return value is NULL if there is not already a CellUse in parent
|
|
|
|
|
* that is identical to use (same bbox and def). If there is a duplicate
|
|
|
|
|
* already in parent, then the return value is a pointer to its CellUse.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CellUse *
|
|
|
|
|
DBCellFindDup(use, parent)
|
|
|
|
|
CellUse *use; /* Use that is about to be placed in parent.
|
|
|
|
|
* Is it a duplicate?
|
|
|
|
|
*/
|
|
|
|
|
CellDef *parent; /* Parent definiton: does it already have
|
|
|
|
|
* something identical to use?
|
|
|
|
|
*/
|
|
|
|
|
{
|
2019-03-23 00:58:47 +01:00
|
|
|
BPEnum bpe;
|
|
|
|
|
CellUse *dupUse;
|
|
|
|
|
|
|
|
|
|
BPEnumInit(&bpe, parent->cd_cellPlane, &use->cu_bbox, BPE_EQUAL,
|
|
|
|
|
"DBCellFindDup");
|
2024-10-04 18:19:27 +02:00
|
|
|
while ((dupUse = BPEnumNext(&bpe)))
|
2023-02-28 22:49:17 +01:00
|
|
|
if (dupUse->cu_def == use->cu_def)
|
|
|
|
|
/* Transforms must be equal---Aligned bounding boxes are
|
2025-11-07 17:00:22 +01:00
|
|
|
* an insufficient measure of exact overlap. Also, array
|
|
|
|
|
* counts and separation must match for arrayed devices
|
2023-02-28 22:49:17 +01:00
|
|
|
*/
|
|
|
|
|
if ((dupUse->cu_transform.t_a == use->cu_transform.t_a) &&
|
|
|
|
|
(dupUse->cu_transform.t_b == use->cu_transform.t_b) &&
|
|
|
|
|
(dupUse->cu_transform.t_c == use->cu_transform.t_c) &&
|
|
|
|
|
(dupUse->cu_transform.t_d == use->cu_transform.t_d) &&
|
|
|
|
|
(dupUse->cu_transform.t_e == use->cu_transform.t_e) &&
|
2025-11-07 17:00:22 +01:00
|
|
|
(dupUse->cu_transform.t_f == use->cu_transform.t_f) &&
|
|
|
|
|
((dupUse->cu_xhi > dupUse->cu_xlo) &&
|
|
|
|
|
((dupUse->cu_xhi - dupUse->cu_xlo) ==
|
|
|
|
|
(use->cu_xhi - use->cu_xlo)) &&
|
|
|
|
|
(dupUse->cu_xsep == use->cu_xsep)) &&
|
|
|
|
|
((dupUse->cu_yhi > dupUse->cu_ylo) &&
|
|
|
|
|
((dupUse->cu_yhi - dupUse->cu_ylo) ==
|
|
|
|
|
(use->cu_yhi - use->cu_ylo)) &&
|
|
|
|
|
(dupUse->cu_ysep == use->cu_ysep)))
|
2023-02-28 22:49:17 +01:00
|
|
|
break;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2019-03-23 00:58:47 +01:00
|
|
|
BPEnumTerm(&bpe);
|
|
|
|
|
return dupUse;
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
2019-03-23 00:58:47 +01:00
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DBPlaceCell --
|
2021-03-17 03:46:46 +01:00
|
|
|
* DBPlaceCellNoModify --
|
2017-04-25 14:41:48 +02:00
|
|
|
*
|
|
|
|
|
* Add a CellUse to the subcell tile plane of a CellDef.
|
|
|
|
|
* Assumes prior check that the new CellUse is not an exact duplicate
|
|
|
|
|
* of one already in place.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Modifies the subcell tile plane of the given CellDef.
|
|
|
|
|
* Resets the plowing delta of the CellUse to 0. Sets the
|
|
|
|
|
* CellDef's parent pointer to point to the parent def.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2019-03-23 00:58:47 +01:00
|
|
|
DBPlaceCell (use, def)
|
|
|
|
|
CellUse * use; /* new celluse to add to subcell tile plane */
|
|
|
|
|
CellDef * def; /* parent cell's definition */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2019-03-23 00:58:47 +01:00
|
|
|
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 */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2019-03-23 00:58:47 +01:00
|
|
|
use->cu_parent = def;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* Be careful not to permit interrupts during this, or the
|
|
|
|
|
* database could be left in a trashed state.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
SigDisableInterrupts();
|
2019-03-23 00:58:47 +01:00
|
|
|
BPAdd(def->cd_cellPlane, use);
|
|
|
|
|
def->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
2017-04-25 14:41:48 +02:00
|
|
|
if (UndoIsEnabled())
|
2019-03-23 00:58:47 +01:00
|
|
|
DBUndoCellUse(use, UNDO_CELL_PLACE);
|
2017-04-25 14:41:48 +02:00
|
|
|
SigEnableInterrupts();
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2021-03-17 03:46:46 +01:00
|
|
|
/* 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();
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
* DBDeleteCell --
|
|
|
|
|
*
|
|
|
|
|
* Remove a CellUse from the subcell tile plane of a CellDef.
|
2021-03-17 03:46:46 +01:00
|
|
|
* 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.
|
2017-04-25 14:41:48 +02:00
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Modifies the subcell tile plane of the CellDef, sets the
|
|
|
|
|
* parent pointer of the deleted CellUse to NULL.
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2019-03-23 00:58:47 +01:00
|
|
|
DBDeleteCell (use)
|
|
|
|
|
CellUse * use;
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2019-03-23 00:58:47 +01:00
|
|
|
ASSERT(use != (CellUse *) NULL, "DBDeleteCell");
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* It's important that this code run with interrupts disabled,
|
|
|
|
|
* or else we could leave the subcell tile plane in a weird
|
|
|
|
|
* state.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
SigDisableInterrupts();
|
2020-04-14 17:00:51 +02:00
|
|
|
dbInstanceUnplace(use);
|
2019-03-23 00:58:47 +01:00
|
|
|
use->cu_parent->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
2017-04-25 14:41:48 +02:00
|
|
|
if (UndoIsEnabled())
|
2019-03-23 00:58:47 +01:00
|
|
|
DBUndoCellUse(use, UNDO_CELL_DELETE);
|
|
|
|
|
use->cu_parent = (CellDef *) NULL;
|
2017-04-25 14:41:48 +02:00
|
|
|
SigEnableInterrupts();
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-17 03:46:46 +01:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
* 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();
|
|
|
|
|
}
|