A number of things in one commit:

1) Added a "*showmem" "wizard" command to get a dump of all memory
   being used by tiles in the database.
2) Made a slight correction to the way magic detects exact overlap
   of instances of the same cell.  This probably does not make any
   actual difference in practice.
3) Corrected an uninitialized variable in dbReComputeBboxFunc().
4) Changes DBSrCellPlaneArea() to use a static BPEnum variable, so
   that it does not waste time allocating and freeing memory for
   the same thing over and over again.
5) Corrected a memory leak in the tech file "extract" section that
   loses memory every time the extraction style is changed.
6) Corrected the tile join routines to fix a bad memory leak in the
   tile allocation and recovery---a fix which was mentioned in issue
   #414 but which had not yet been implemented.  This has now been
   tested and confirmed to work.
This commit is contained in:
R. Timothy Edwards 2025-11-07 11:00:22 -05:00
parent 969137d1e2
commit 957d7edd64
11 changed files with 275 additions and 8 deletions

View File

@ -1 +1 @@
8.3.573 8.3.574

View File

@ -367,6 +367,9 @@ extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a
* def. * def.
*/ */
extern Plane *CIFTotalPlanes[]; /* Exported for diagnostics */
extern Plane *CIFComponentPlanes[]; /* Exported for diagnostics */
/* Valid values of CIFWarningLevel (see cif.h) */ /* Valid values of CIFWarningLevel (see cif.h) */
typedef enum {CIF_WARN_DEFAULT, CIF_WARN_NONE, CIF_WARN_ALIGN, typedef enum {CIF_WARN_DEFAULT, CIF_WARN_NONE, CIF_WARN_ALIGN,

View File

@ -47,6 +47,10 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "utils/utils.h" #include "utils/utils.h"
#include "textio/txcommands.h" #include "textio/txcommands.h"
/* For diagnostics */
#include "cif/CIFint.h"
#include "database/databaseInt.h"
/* C99 compat */ /* C99 compat */
#include "extract/extract.h" #include "extract/extract.h"
@ -189,6 +193,233 @@ CmdExtractTest(
} }
#endif #endif
/*
* ----------------------------------------------------------------------------
*
* tileCountProc --
*
* Routine to count tiles.
*
* Return:
* 0 to keep the search going
*
* Side effects:
* Keeps count in clientData
*
* ----------------------------------------------------------------------------
*/
int
tileCountProc(
Tile *tile,
int *tcount)
{
(*tcount)++;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* showMem --
* CmdShowmem --
*
* Usage:
*
* showmem [outfile]
*
* Display all the (principle) internal memory usage for tiles, including
* all cell defs, and all CIF generated planes.
*
* Results:
* None.
*
* Side effects:
* May write to a disk file.
*
* ----------------------------------------------------------------------------
*/
void
showMem(
FILE *outf, /* File to which information is to be output */
bool verbose) /* If TRUE, output detailed erase table */
{
int ttotal, ttotal1, ttotal2;
int i;
Plane *plane;
CellDef *def;
int pNum;
HashSearch hs;
HashEntry *entry;
fprintf(outf, "Tile memory usage summary\n");
fprintf(outf, "Technology %s\n", DBTechName);
/* Search every cell def (including internal ones), count tiles,
* and add up the tile memory usage on every plane.
*/
/* Search the CIFPlanes and count tiles. */
/* CIFPlanes, CIFTotalPlanes, CIFComponentPlanes */
ttotal2 = 0;
if (CIFCurStyle != NULL)
{
fprintf(outf, "\nCIFPlanes:\n");
ttotal1 = 0;
for (i = 0; i < MAXCIFLAYERS; i++)
{
plane = CIFPlanes[i];
if (plane != NULL)
{
ttotal = 0;
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllTypeBits, tileCountProc, &ttotal);
ttotal1 += ttotal;
if (CIFCurStyle->cs_layers[i])
fprintf(outf, " layer %s: %ld\n",
CIFCurStyle->cs_layers[i]->cl_name,
(long)ttotal * (long)sizeof(Tile));
else
fprintf(outf, " layer %d: %d\n", i,
(long)ttotal * (long)sizeof(Tile));
}
}
fprintf(outf, " Subtotal: %ld bytes\n",
(long)ttotal1 * (long)sizeof(Tile));
ttotal2 += ttotal1;
fprintf(outf, "\nCIFTotalPlanes\n");
ttotal1 = 0;
for (i = 0; i < MAXCIFLAYERS; i++)
{
plane = CIFTotalPlanes[i];
if (plane != NULL)
{
ttotal = 0;
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllTypeBits, tileCountProc, &ttotal);
ttotal1 += ttotal;
if (CIFCurStyle->cs_layers[i])
fprintf(outf, " layer %s: %ld\n",
CIFCurStyle->cs_layers[i]->cl_name,
(long)ttotal * (long)sizeof(Tile));
else
fprintf(outf, " layer %d: %d\n", i,
(long)ttotal * (long)sizeof(Tile));
}
}
fprintf(outf, " Subtotal: %ld bytes\n",
(long)ttotal1 * (long)sizeof(Tile));
ttotal2 += ttotal1;
fprintf(outf, "\nCIFComponentPlanes\n");
ttotal1 = 0;
for (i = 0; i < MAXCIFLAYERS; i++)
{
plane = CIFComponentPlanes[i];
if (plane != NULL)
{
ttotal = 0;
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllTypeBits, tileCountProc, &ttotal);
ttotal1 += ttotal;
if (CIFCurStyle->cs_layers[i])
fprintf(outf, " layer %s: %ld bytes\n",
CIFCurStyle->cs_layers[i]->cl_name,
(long)ttotal * (long)sizeof(Tile));
else
fprintf(outf, " layer %d: %ld bytes\n", i,
(long)ttotal * (long)sizeof(Tile));
}
}
fprintf(outf, " Subtotal: %ld bytes\n",
(long)ttotal1 * (long)sizeof(Tile));
ttotal2 += ttotal1;
}
else
{
fprintf(outf, "CIF planes: No memory usage\n");
}
HashStartSearch(&hs);
while ((entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
def = (CellDef *)HashGetValue(entry);
if (def != (CellDef *)NULL)
{
fprintf(outf, "\nCell def %s\n", def->cd_name);
ttotal1 = 0;
for (pNum = 0; pNum < DBNumPlanes; pNum++)
{
plane = def->cd_planes[pNum];
if (plane != NULL)
{
ttotal = 0;
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllTypeBits, tileCountProc, &ttotal);
fprintf(outf, " plane %s: %ld bytes\n",
DBPlaneLongNameTbl[pNum],
(long)ttotal * (long)sizeof(Tile));
ttotal1 += ttotal;
}
}
fprintf(outf, " Subtotal: %ld bytes\n",
(long)ttotal1 * (long)sizeof(Tile));
ttotal2 += ttotal1;
}
}
fprintf(outf, " Grand total: %ld bytes\n",
(long)ttotal2 * (long)sizeof(Tile));
}
void
CmdShowmem(
MagWindow *w,
TxCommand *cmd)
{
FILE *outf;
bool verbose;
char **av;
int ac;
if (cmd->tx_argc > 3)
{
TxError("Usage: showmem [-v] [file]\n");
return;
}
verbose = FALSE;
av = &cmd->tx_argv[1];
ac = cmd->tx_argc - 1;
outf = stdout;
if (ac > 0 && strcmp(av[0], "-v") == 0)
{
verbose = TRUE;
av++, ac--;
}
if (ac > 0)
{
outf = fopen(av[0], "w");
if (outf == (FILE *) NULL)
{
perror(av[0]);
TxError("Nothing written\n");
return;
}
}
showMem(outf, verbose);
if (outf != stdout)
(void) fclose(outf);
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------

View File

@ -109,14 +109,23 @@ DBCellFindDup(use, parent)
while ((dupUse = BPEnumNext(&bpe))) while ((dupUse = BPEnumNext(&bpe)))
if (dupUse->cu_def == use->cu_def) if (dupUse->cu_def == use->cu_def)
/* Transforms must be equal---Aligned bounding boxes are /* Transforms must be equal---Aligned bounding boxes are
* an insufficient measure of exact overlap. * an insufficient measure of exact overlap. Also, array
* counts and separation must match for arrayed devices
*/ */
if ((dupUse->cu_transform.t_a == use->cu_transform.t_a) && 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_b == use->cu_transform.t_b) &&
(dupUse->cu_transform.t_c == use->cu_transform.t_c) && (dupUse->cu_transform.t_c == use->cu_transform.t_c) &&
(dupUse->cu_transform.t_d == use->cu_transform.t_d) && (dupUse->cu_transform.t_d == use->cu_transform.t_d) &&
(dupUse->cu_transform.t_e == use->cu_transform.t_e) && (dupUse->cu_transform.t_e == use->cu_transform.t_e) &&
(dupUse->cu_transform.t_f == use->cu_transform.t_f)) (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)))
break; break;
BPEnumTerm(&bpe); BPEnumTerm(&bpe);

View File

@ -619,10 +619,9 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
/* /*
* Include area of subcells separately * Include area of subcells separately
*/ */
if ((foundAny = DBBoundCellPlane(cellDef, &extended, &rect)) > 0) if (!((foundAny = DBBoundCellPlane(cellDef, &extended, &rect)) > 0))
area = rect;
else
extended = GeoNullRect; extended = GeoNullRect;
area = rect;
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
if (pNum != PL_DRC_CHECK) if (pNum != PL_DRC_CHECK)

View File

@ -85,11 +85,13 @@ struct seeTypesArg
int int
DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg) DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg)
{ {
BPEnum sbpe;
BPEnum *bpe; BPEnum *bpe;
CellUse *use; CellUse *use;
int rval = 0; int rval = 0;
bpe = (BPEnum *)mallocMagic(sizeof(BPEnum)); /* bpe = (BPEnum *)mallocMagic(sizeof(BPEnum)); */
bpe = &sbpe;
BPEnumInit(bpe, plane, rect, BPE_OVERLAP, "DBSrCellPlaneArea"); BPEnumInit(bpe, plane, rect, BPE_OVERLAP, "DBSrCellPlaneArea");
while ((use = BPEnumNext(bpe))) while ((use = BPEnumNext(bpe)))
@ -102,7 +104,7 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
} }
BPEnumTerm(bpe); BPEnumTerm(bpe);
freeMagic(bpe); /* freeMagic(bpe); */
return rval; return rval;
} }

View File

@ -194,6 +194,8 @@ typedef struct
extern int dbNumSavedRules; extern int dbNumSavedRules;
extern Rule dbSavedRules[]; extern Rule dbSavedRules[];
extern HashTable dbCellDefTable; /* Exported for diagnostics */
/* -------------------- Internal procedure headers -------------------- */ /* -------------------- Internal procedure headers -------------------- */
extern void DBUndoPutLabel(); extern void DBUndoPutLabel();

View File

@ -75,6 +75,7 @@ extern void CmdExtResis();
extern void CmdPsearch(); extern void CmdPsearch();
extern void CmdPlowTest(); extern void CmdPlowTest();
extern void CmdShowtech(); extern void CmdShowtech();
extern void CmdShowmem();
extern void CmdTilestats(); extern void CmdTilestats();
extern void CmdTsearch(); extern void CmdTsearch();
extern void CmdWatch(); extern void CmdWatch();
@ -208,6 +209,9 @@ DBWInitCommands()
WindAddCommand(DBWclientID, WindAddCommand(DBWclientID,
"*psearch plane count invoke point search over box area", "*psearch plane count invoke point search over box area",
CmdPsearch, FALSE); CmdPsearch, FALSE);
WindAddCommand(DBWclientID,
"*showmem [file] print internal memory usage",
CmdShowmem, FALSE);
WindAddCommand(DBWclientID, WindAddCommand(DBWclientID,
"*showtech [file] print internal technology tables", "*showtech [file] print internal technology tables",
CmdShowtech, FALSE); CmdShowtech, FALSE);

View File

@ -1119,6 +1119,7 @@ ExtTechInit()
if (ExtCurStyle != NULL) if (ExtCurStyle != NULL)
{ {
extTechStyleInit(ExtCurStyle); extTechStyleInit(ExtCurStyle);
freeMagic(ExtCurStyle);
ExtCurStyle = NULL; ExtCurStyle = NULL;
} }

View File

@ -20,6 +20,10 @@
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/tiles/tile.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/tiles/tile.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */ #endif /* not lint */
/* Disable memory mapped tile allocation here and in tiles/tile.h
* #undef HAVE_SYS_MMAN_H
*/
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -816,6 +820,7 @@ TiJoinX1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane)
{ {
TiFreeIf(*delay1); TiFreeIf(*delay1);
TiJoinX(tile1, tile2, plane); TiJoinX(tile1, tile2, plane);
*delay1 = tile2;
} }
void void
@ -823,6 +828,7 @@ TiJoinY1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane)
{ {
TiFreeIf(*delay1); TiFreeIf(*delay1);
TiJoinY(tile1, tile2, plane); TiJoinY(tile1, tile2, plane);
*delay1 = tile2;
} }
#endif #endif

View File

@ -23,6 +23,14 @@
#ifndef _MAGIC__TILES__TILE_H #ifndef _MAGIC__TILES__TILE_H
#define _MAGIC__TILES__TILE_H #define _MAGIC__TILES__TILE_H
/* Disable memory mapped tile allocation here and in tiles/tile.h
* #undef HAVE_SYS_MMAN_H
*/
#ifndef HAVE_SYS_MMAN_H
#include "utils/malloc.h"
#endif
#ifndef _MAGIC__UTILS__MAGIC_H #ifndef _MAGIC__UTILS__MAGIC_H
#include "utils/magic.h" #include "utils/magic.h"
#endif #endif
@ -299,6 +307,7 @@ TiJoinX1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane)
{ {
TiFreeIf(*delay1); TiFreeIf(*delay1);
TiJoinX(tile1, tile2, plane); TiJoinX(tile1, tile2, plane);
*delay1 = tile2;
} }
inline void inline void
@ -306,6 +315,7 @@ TiJoinY1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane)
{ {
TiFreeIf(*delay1); TiFreeIf(*delay1);
TiJoinY(tile1, tile2, plane); TiJoinY(tile1, tile2, plane);
*delay1 = tile2;
} }
#else #else
/* To support older compilers (that don't auto emit based on -O level) */ /* To support older compilers (that don't auto emit based on -O level) */