/* * ExtTimes.c -- * * Circuit extraction timing. * * ********************************************************************* * * 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. * * ********************************************************************* */ #ifndef lint static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtTimes.c,v 1.2 2009/05/13 15:03:16 tim Exp $"; #endif /* not lint */ #include #include #include #include #include #ifdef SYSV #include #include #endif #include /* for sqrt() function */ #include "utils/magic.h" #include "utils/utils.h" #include "utils/geometry.h" #include "utils/geofast.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "utils/malloc.h" #include "textio/textio.h" #include "extract/extract.h" #include "extract/extractInt.h" /* * One of the following structures gets allocated for each cell. * It holds the statistics we accumulate while extracting that cell. */ struct cellStats { CellDef *cs_def; /* Which cell */ struct timeval cs_tpaint; /* Paint-only extraction time */ struct timeval cs_tcell; /* Extract just this cell */ struct timeval cs_thier; /* Extract complete tree */ struct timeval cs_tincr; /* Incremental extraction time */ int cs_fets; /* Transistor count in this cell */ int cs_rects; /* Non-space tile count in this cell */ int cs_hfets; /* Hierarchical transistor count */ int cs_hrects; /* Hierarchical tile count */ int cs_ffets; /* Total flat transistor count */ int cs_frects; /* Total flat tile count */ long cs_area; /* Total area of cell */ long cs_interarea; /* Interaction areas sum */ long cs_cliparea; /* Interaction area, counting each * overlap of interaction areas only * once instead of once for each * interaction area. */ }; /* Hash table of all the above structs, keyed by CellDef */ HashTable cellStatsTable; /* * Cumulative statistics */ struct cumStats { double cums_min; /* Smallest value */ double cums_max; /* Largest value */ double cums_sum; /* Sum of values */ double cums_sos; /* Sum of squares */ int cums_n; /* Number values */ }; struct cumStats cumFetsPerSecPaint; struct cumStats cumRectsPerSecPaint; struct cumStats cumFetsPerSecFlat; struct cumStats cumRectsPerSecFlat; struct cumStats cumFetsPerSecHier; struct cumStats cumRectsPerSecHier; struct cumStats cumIncrTime; struct cumStats cumPercentClipped; struct cumStats cumPercentInteraction; struct cumStats cumTotalArea, cumInteractArea, cumClippedArea; FILE *extDevNull = NULL; /* Forward declarations */ struct cellStats *extGetStats(); void extTimesCellFunc(); void extTimesIncrFunc(); void extTimesSummaryFunc(); void extTimesParentFunc(); void extTimeProc(); void extCumInit(); void extCumOutput(); void extCumAdd(); void extPaintOnly(CellDef *); void extHierCell(CellDef *); int extCountTiles(); extern int extDefInitFunc(); /* * ---------------------------------------------------------------------------- * * ExtTimes -- * * Time the extractor. * All cells in the tree rooted at 'rootUse' are extracted. * We report the following times for each cell (seconds of CPU * time, accurate to 10 milliseconds). * * Time to extract just its paint. * Time to extract it completely. * Time to perform incremental re-extraction if just this cell changed. * * In addition, we report: * * Fets/second paint extraction speed * Fets/second cell extraction speed * Fets/second hierarchical extraction speed * Rects/second paint extraction speed * Rects/second cell extraction speed * Rects/second hierarchical extraction speed * * Also for each cell, we report the number of transistors, number * of rectangles, and rectangles per transistor. * * In addition, we report the following cumulative information, as * means, standard deviation, min, and max: * * Fets/second flat extraction speed * Fets/second complete extraction speed * Rects/second flat extraction speed * Rects/second complete extraction speed * Incremental extraction time after changing one cell. * * Results: * None. * * Side effects: * Writes to the file 'f'. * * ---------------------------------------------------------------------------- */ void ExtTimes(rootUse, f) CellUse *rootUse; FILE *f; { double clip, inter; HashSearch hs; HashEntry *he; /* Make sure this cell is read in */ if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE)) { TxError("Failure to read entire subtree of cell.\n"); return; } /* Initialize cumulative statistics */ extCumInit(&cumFetsPerSecPaint); extCumInit(&cumRectsPerSecPaint); extCumInit(&cumFetsPerSecFlat); extCumInit(&cumRectsPerSecFlat); extCumInit(&cumFetsPerSecHier); extCumInit(&cumRectsPerSecHier); extCumInit(&cumIncrTime); extCumInit(&cumPercentClipped); extCumInit(&cumPercentInteraction); extCumInit(&cumTotalArea); extCumInit(&cumInteractArea); extCumInit(&cumClippedArea); /* Open to /dev/null */ extDevNull = fopen("/dev/null", "w"); if (extDevNull == NULL) { perror("/dev/null"); return; } /* Mark all defs as unvisited */ (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); /* Recursively visit all defs in the tree and store in hash table */ HashInit(&cellStatsTable, 128, 1); (void) extTimesInitFunc(rootUse); /* * Now visit every cell in the hash table and compute * its individual statistics. */ TxPrintf("Computing individual cell statistics:\n"); TxFlush(); HashStartSearch(&hs); while (he = HashNext(&cellStatsTable, &hs)) extTimesCellFunc((struct cellStats *) HashGetValue(he)); /* * Now visit every cell in the hash table and compute * its incremental time (ancestors) and hierarchical * time (children). */ TxPrintf("Computing hierarchical and incremental statistics:\n"); TxFlush(); HashStartSearch(&hs); while (he = HashNext(&cellStatsTable, &hs)) extTimesIncrFunc((struct cellStats *) HashGetValue(he)); /* * Compute the summary statistics and output everything. * Free each entry in the table as we go. */ TxPrintf("Computing summary statistics:\n"); TxFlush(); HashStartSearch(&hs); while (he = HashNext(&cellStatsTable, &hs)) { extTimesSummaryFunc((struct cellStats *) HashGetValue(he), f); freeMagic((char *) HashGetValue(he)); } /* Output the summary statistics */ fprintf(f, "\n\nSummary statistics:\n\n"); fprintf(f, "%s %8s %8s %8s %8s\n", " ", "min", "max", "mean", "std.dev"); extCumOutput("fets/sec paint ", &cumFetsPerSecPaint, f); extCumOutput("fets/sec hier ", &cumFetsPerSecHier, f); extCumOutput("fets/sec flat ", &cumFetsPerSecFlat, f); extCumOutput("rects/sec paint", &cumRectsPerSecPaint, f); extCumOutput("rects/sec hier ", &cumRectsPerSecHier, f); extCumOutput("rects/sec flat ", &cumRectsPerSecFlat, f); extCumOutput("tot incr time ", &cumIncrTime, f); extCumOutput("% cell clipped ", &cumPercentClipped, f); extCumOutput("% cell interact", &cumPercentInteraction, f); /* Fix up average value to be weighted */ clip = inter = 0.0; if (cumTotalArea.cums_sum > 0) { clip = 100.0 * cumClippedArea.cums_sum / cumTotalArea.cums_sum; inter = 100.0 * cumInteractArea.cums_sum / cumTotalArea.cums_sum; } fprintf(f, "Mean %% clipped area = %.2f\n", clip); fprintf(f, "Mean %% interaction area = %.2f\n", inter); /* Free the hash table */ HashKill(&cellStatsTable); (void) fclose(extDevNull); } /* * ---------------------------------------------------------------------------- * * extTimesInitFunc -- * * Called to add the cellStats struct for use->cu_def to the hash table * cellStatsTable if it is not already present, and to initialize this * structure. * * Results: * Returns 0 always. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ int extTimesInitFunc(use) CellUse *use; { CellDef *def = use->cu_def; struct cellStats *cs; HashEntry *he; he = HashFind(&cellStatsTable, (char *) def); if (HashGetValue(he)) return (0); /* Not yet visited: add it to the hash table */ cs = (struct cellStats *) mallocMagic(sizeof (struct cellStats)); cs->cs_def = def; cs->cs_tpaint.tv_sec = cs->cs_tpaint.tv_usec = 0; cs->cs_tcell.tv_sec = cs->cs_tcell.tv_usec = 0; cs->cs_thier.tv_sec = cs->cs_thier.tv_usec = 0; cs->cs_tincr.tv_sec = cs->cs_tincr.tv_usec = 0; cs->cs_fets = cs->cs_rects = 0; cs->cs_ffets = cs->cs_frects = 0; cs->cs_hfets = cs->cs_hrects = 0; cs->cs_area = cs->cs_interarea = cs->cs_cliparea = 0; HashSetValue(he, (ClientData) cs); /* Visit our children */ (void) DBCellEnum(def, extTimesInitFunc, (ClientData) 0); return (0); } /* * ---------------------------------------------------------------------------- * * extTimesCellFunc -- * * Called for each cellStats structure in the hash table, we extract * the paint of cs->cs_def and then both the paint and subcells, timing * both. Also count the number of fets in this cell and the total number * of tiles. Store this information in: * * cs->cs_tpaint Time to extract paint only * cs->cs_tcell Time to extract paint and subcells * cs->cs_fets Number of fets * cs->cs_rects Number of non-space tiles * * Results: * None. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ void extTimesCellFunc(cs) struct cellStats *cs; { extern long extSubtreeTotalArea; extern long extSubtreeInteractionArea; extern long extSubtreeClippedArea; TransRegion *transList, *tl; CellDef *def = cs->cs_def; int pNum; TxPrintf("Processing %s\n", def->cd_name); TxFlush(); /* Count the number of transistors */ transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect, &ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn, extUnInit, extTransFirst, extTransEach, FALSE); ExtResetTiles(def, extUnInit); for (tl = transList; tl; tl = tl->treg_next) cs->cs_fets++; ExtFreeLabRegions((LabRegion *) transList); /* Count the number of tiles */ for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &TiPlaneRect, &DBAllButSpaceBits, extCountTiles, (ClientData) cs); /* Measure the flat extraction time */ extTimeProc(extPaintOnly, def, &cs->cs_tpaint); /* Measure the total extraction time */ extSubtreeTotalArea = 0; extSubtreeInteractionArea = 0; extSubtreeClippedArea = 0; extTimeProc(extHierCell, def, &cs->cs_tcell); cs->cs_area = extSubtreeTotalArea; cs->cs_interarea = extSubtreeInteractionArea; cs->cs_cliparea = extSubtreeClippedArea; } /* * extCountTiles -- * * Count the number of tiles in a cell. * Called via DBSrPaintArea by extTimesCellFunc() above. * * Results: * Returns 0 always. * * Side effects: * Increments cs->cs_rects. */ int extCountTiles(tile, cs) Tile *tile; /* UNUSED */ struct cellStats *cs; { cs->cs_rects++; return (0); } /* * ---------------------------------------------------------------------------- * * extTimesIncrFunc -- * * All cells have been visited by extTimesCellFunc above. This procedure * accumulates the hierarchical information from both above and below * in the tree. The cs_tcell times for all ancestors, plus this cell, * are summed into cs->cs_tincr. The cs_tcell times for all children, * counting each child once, are summed into cs->cs_thier. The cs_fets * and cs_rects for all children, also counting each child once, are * summed into cs_hfets and cs_hrects. Finally, the cs_fets and cs_rects * for all children, counting each child as many times as it appears, * are summed into cs_ffets and cs_frects. * * Results: * None. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ void extTimesIncrFunc(cs) struct cellStats *cs; { /* * Visit all of our parents recursively. * This sums the incremental times. */ extTimesParentFunc(cs->cs_def, cs); /* Reset all defs */ (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); /* * Visit all of our children recursively, visiting * each child only once. This sums the number of fets * and rectangles for cs_hfets and cs_hrects. */ (void) extTimesHierFunc(cs->cs_def, cs); /* Reset all defs */ (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); /* * Visit all of our children recursively, visiting each * child as many times as it appears. This sums the * number of fets and rectangles as cs_ffets and cs_frects. */ (void) extTimesFlatFunc(cs->cs_def, cs); } /* * ---------------------------------------------------------------------------- * * extTimesSummaryFunc -- * * Write the statistics contained in the cellStats structure 'cs' * out to the FILE 'f'. Add them to the summary structures being * maintained (cumFetsPerSecPaint, etc). * * Results: * None. * * Side effects: * Writes to the FILE f. * * ---------------------------------------------------------------------------- */ void extTimesSummaryFunc(cs, f) struct cellStats *cs; FILE *f; { double tpaint, tcell, thier, tincr; double fetspaint, rectspaint; double fetshier, rectshier; double fetsflat, rectsflat; double pctinter, pctclip; pctinter = pctclip = 0.0; if (cs->cs_area > 0) { pctinter = ((double)cs->cs_interarea) / ((double)cs->cs_area) * 100.0; pctclip = ((double)cs->cs_cliparea) / ((double)cs->cs_area) * 100.0; } tpaint = cs->cs_tpaint.tv_usec; tpaint = (tpaint / 1000000.) + cs->cs_tpaint.tv_sec; tcell = cs->cs_tcell.tv_usec; tcell = (tcell / 1000000.) + cs->cs_tcell.tv_sec; thier = cs->cs_thier.tv_usec; thier = (thier / 1000000.) + cs->cs_thier.tv_sec; tincr = cs->cs_tincr.tv_usec; tincr = (tincr / 1000000.) + cs->cs_tincr.tv_sec; fetspaint = fetsflat = fetshier = 0.0; rectspaint = rectsflat = rectshier = 0.0; if (tpaint > 0.01) { fetspaint = cs->cs_fets / tpaint; rectspaint = cs->cs_rects / tpaint; } if (thier > 0.01) { fetshier = cs->cs_hfets / thier; rectshier = cs->cs_hrects / thier; fetsflat = cs->cs_ffets / thier; rectsflat = cs->cs_frects / thier; } /* Cell name */ fprintf(f, "\n%8s %8s %s\n", "", "", cs->cs_def->cd_name); /* Sizes */ fprintf(f, "%8d %8d (paint) fets rects\n", cs->cs_fets, cs->cs_rects); fprintf(f, "%8d %8d (hier) fets rects\n", cs->cs_hfets, cs->cs_hrects); fprintf(f, "%8d %8d (flat) fets rects\n", cs->cs_ffets, cs->cs_frects); /* Times */ fprintf(f, "%8.2f %8.2f Tpaint, Tcell\n", tpaint, tcell); fprintf(f, "%8.2f %8.2f Thier, Tincr\n", thier, tincr); /* Speeds */ fprintf(f, "%8.2f %8.2f (paint) fets/sec rects/sec\n", fetspaint, rectspaint); fprintf(f, "%8.2f %8.2f (hier) fets/sec rects/sec\n", fetshier, rectshier); fprintf(f, "%8.2f %8.2f (flat) fets/sec rects/sec\n", fetsflat, rectsflat); /* Fraction of area in subtree processing */ fprintf(f, "%8.2f %8.2f clip %% inter %%\n", pctclip, pctinter); /* Accumulate statistics */ if (cs->cs_fets > 0) extCumAdd(&cumFetsPerSecPaint, fetspaint); if (cs->cs_rects > 0) extCumAdd(&cumRectsPerSecPaint, rectspaint); if (cs->cs_hfets > 0) extCumAdd(&cumFetsPerSecHier, fetshier); if (cs->cs_hrects > 0) extCumAdd(&cumRectsPerSecHier, rectshier); if (cs->cs_ffets > 0) extCumAdd(&cumFetsPerSecFlat, fetsflat); if (cs->cs_frects > 0) extCumAdd(&cumRectsPerSecFlat, rectsflat); if (pctclip > 0.0) extCumAdd(&cumPercentClipped, pctclip); if (pctinter > 0.0) extCumAdd(&cumPercentInteraction, pctinter); extCumAdd(&cumTotalArea, (double) cs->cs_area); extCumAdd(&cumInteractArea, (double) cs->cs_interarea); extCumAdd(&cumClippedArea, (double) cs->cs_cliparea); extCumAdd(&cumIncrTime, tincr); } /* * ---------------------------------------------------------------------------- * * extTimesParentFunc -- * * Function to visit all the parents of 'def' and add their * times to that of 'cs'. We only add the times if the def * being visited is unmarked, ie, its cd_client field is 0. * After adding the times for a def, we mark it by setting * its cd_client field to 1. * * Results: * None. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ void extTimesParentFunc(def, cs) CellDef *def; struct cellStats *cs; { struct cellStats *csForDef; CellUse *parent; if (def->cd_client) return; /* Mark this def as visited */ def->cd_client = (ClientData) 1; /* Find its statistics in the table */ if ((csForDef = extGetStats(def)) == NULL) return; /* Add the time */ cs->cs_tincr.tv_sec += csForDef->cs_tcell.tv_sec; cs->cs_tincr.tv_usec += csForDef->cs_tcell.tv_usec; if (cs->cs_tincr.tv_usec > 1000000) { cs->cs_tincr.tv_usec -= 1000000; cs->cs_tincr.tv_sec += 1; } /* Visit all our parents */ for (parent = def->cd_parents; parent; parent = parent->cu_nextuse) if (parent->cu_parent) extTimesParentFunc(parent->cu_parent, cs); } /* * ---------------------------------------------------------------------------- * * extTimesHierFunc -- * * Function to visit all the children of 'def' and add their * times to that of 'cs'. We only add the times if the def * being visited is unmarked, ie, its cd_client field is 0. * After adding the times for a def, we mark it by setting * its cd_client field to 1. * * Results: * Returns 0 always. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ int extTimesHierFunc(def, cs) CellDef *def; struct cellStats *cs; { int extTimesHierUse(); struct cellStats *csForDef; if (def->cd_client) return (0); /* Mark this def as visited */ def->cd_client = (ClientData) 1; /* Find its statistics in the table */ if ((csForDef = extGetStats(def)) == NULL) return (0); /* Add the time */ cs->cs_thier.tv_sec += csForDef->cs_tcell.tv_sec; cs->cs_thier.tv_usec += csForDef->cs_tcell.tv_usec; if (cs->cs_thier.tv_usec > 1000000) { cs->cs_thier.tv_usec -= 1000000; cs->cs_thier.tv_sec += 1; } /* Add the fets and rectangles */ cs->cs_hfets += csForDef->cs_fets; cs->cs_hrects += csForDef->cs_rects; /* Visit our children */ (void) DBCellEnum(def, extTimesHierUse, (ClientData) cs); return (0); } int extTimesHierUse(use, cs) CellUse *use; struct cellStats *cs; { return (extTimesHierFunc(use->cu_def, cs)); } /* * ---------------------------------------------------------------------------- * * extTimesFlatFunc -- * * Function to visit all the children of 'def' and add their * fet and rect counts to those of 'cs'. This is a fully * instantiated count, rather than a drawn count, so we count * each cell as many times as it appears in an array or as * a subcell. * * Results: * Returns 0 always. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ int extTimesFlatFunc(def, cs) CellDef *def; struct cellStats *cs; { struct cellStats *csForDef; int extTimesFlatUse(); /* Find this cell's statistics in the table */ if ((csForDef = extGetStats(def)) == NULL) return (0); /* Add the fets and rectangles */ cs->cs_ffets += csForDef->cs_fets; cs->cs_frects += csForDef->cs_rects; /* Visit our children */ (void) DBCellEnum(def, extTimesFlatUse, (ClientData) cs); return (0); } int extTimesFlatUse(use, cs) CellUse *use; struct cellStats *cs; { struct cellStats dummyCS; int nx, ny, nel; /* Compute statistics for this cell and its children */ bzero((char *) &dummyCS, sizeof dummyCS); (void) extTimesFlatFunc(use->cu_def, &dummyCS); /* Scale by number of elements in this array */ if (use->cu_xlo < use->cu_xhi) nx = use->cu_xhi - use->cu_xlo + 1; else nx = use->cu_xlo - use->cu_xhi + 1; if (use->cu_ylo < use->cu_yhi) ny = use->cu_yhi - use->cu_ylo + 1; else ny = use->cu_ylo - use->cu_yhi + 1; nel = nx * ny; /* Fets and rects */ cs->cs_ffets += dummyCS.cs_ffets * nel; cs->cs_frects += dummyCS.cs_frects * nel; return (0); } /* * ---------------------------------------------------------------------------- * * extTimeProc -- * * Time a procedure applied to the CellDef 'def', storing the time * in the timeval pointed to by 'tv'. The procedure should be of * the form: * * (*proc)(def) * CellDef *def; * { * } * * Results: * None. * * Side effects: * See above. * * Algorithm: * If (*proc)() takes less than a second to run, we run it ten * times to get a better time estimate, then divide by ten. * * ---------------------------------------------------------------------------- */ void extTimeProc(proc, def, tv) int (*proc)(); CellDef *def; struct timeval *tv; { int secs, usecs, i; #ifdef SYSV tv->tv_sec = 0; tv->tv_usec = 0; #else extern int getrusage(); struct rusage r1, r2; (void) getrusage(RUSAGE_SELF, &r1); (*proc)(def); (void) getrusage(RUSAGE_SELF, &r2); tv->tv_sec = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec; tv->tv_usec = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec; if (tv->tv_usec < 0) { tv->tv_usec += 1000000; tv->tv_sec -= 1; } if (tv->tv_sec < 1) { (void) getrusage(RUSAGE_SELF, &r1); for (i = 0; i < 10; i++) (*proc)(def); (void) getrusage(RUSAGE_SELF, &r2); secs = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec; usecs = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec; usecs = (usecs + (secs * 1000000)) / 10; tv->tv_sec = usecs / 1000000; tv->tv_usec = usecs % 1000000; } #endif } /* * ---------------------------------------------------------------------------- * * extPaintOnly -- * * Called via extTimeProc() above. Extract just the paint in a cell. * * Results: * None. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ void extPaintOnly(def) CellDef *def; { NodeRegion *reg; reg = extBasic(def, extDevNull); if (reg) ExtFreeLabRegions((LabRegion *) reg); ExtResetTiles(def, extUnInit); } /* * ---------------------------------------------------------------------------- * * extHierCell -- * * Called via extTimeProc() above. Extract a cell normally, but * send the extracted output to /dev/null. * * Results: * None. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ void extHierCell(def) CellDef *def; { extCellFile(def, extDevNull, FALSE); } /* * ---------------------------------------------------------------------------- * * extCumInit -- * * Initialize a cumulative statistics structure. * * Results: * None. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ void extCumInit(cum) struct cumStats *cum; { cum->cums_min = (double) INFINITY; cum->cums_max = (double) MINFINITY; cum->cums_sum = 0.0; cum->cums_sos = 0.0; cum->cums_n = 0; } /* * ---------------------------------------------------------------------------- * * extCumOutput -- * * Output a cumulative statistics structure. * * Results: * None. * * Side effects: * Writes to the FILE 'f'. * * ---------------------------------------------------------------------------- */ void extCumOutput(str, cum, f) char *str; /* Prefix string */ struct cumStats *cum; FILE *f; { double mean, var; mean = var = 0.0; if (cum->cums_n != 0) { mean = cum->cums_sum / (double) cum->cums_n; var = (cum->cums_sos / (double) cum->cums_n) - (mean * mean); } fprintf(f, "%s", str); if (cum->cums_min < INFINITY) fprintf(f, " %8.2f", cum->cums_min); else fprintf(f, " "); if (cum->cums_max > MINFINITY) fprintf(f, " %8.2f", cum->cums_max); else fprintf(f, " "); fprintf(f, " %8.2f %8.2f\n", mean, sqrt(var)); } /* * ---------------------------------------------------------------------------- * * extCumAdd -- * * Add the value v to the cumulative statistics structure, * updating the statistics. * * Results: * None. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ void extCumAdd(cum, v) struct cumStats *cum; double v; { if (v < cum->cums_min) cum->cums_min = v; if (v > cum->cums_max) cum->cums_max = v; cum->cums_sum += v; cum->cums_sos += v*v; cum->cums_n++; } /* * ---------------------------------------------------------------------------- * * extGetStats -- * * Return the cellStats record for the CellDef 'def'. * * Results: * See above. * * Side effects: * None. * * ---------------------------------------------------------------------------- */ struct cellStats * extGetStats(def) CellDef *def; { HashEntry *he; he = HashLookOnly(&cellStatsTable, (char *) def); if (he == (HashEntry *) NULL) return ((struct cellStats *) NULL); return ((struct cellStats *) HashGetValue(he)); } /* * ---------------------------------------------------------------------------- * * ExtInterCount -- * * Find all interaction areas in an entire design, and count * the fraction of the total area that is really an interaction * area. Report this for each cell in the design, and as a * fraction of the total area. * * Results: * None. * * Side effects: * Writes to the FILE 'f'. * * ---------------------------------------------------------------------------- */ int extInterCountHalo; CellDef *extInterCountDef; void ExtInterCount(rootUse, halo, f) CellUse *rootUse; int halo; FILE *f; { double inter; /* Make sure this cell is read in */ if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE)) { TxError("Failure to read entire subtree of cell.\n"); return; } /* Initialize cumulative statistics */ extCumInit(&cumPercentInteraction); extCumInit(&cumTotalArea); extCumInit(&cumInteractArea); /* Mark all defs as unvisited */ (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); /* * Recursively visit all defs in the tree and compute * their interaction area. */ extInterCountHalo = halo; (void) extInterAreaFunc(rootUse, f); /* Mark all defs as unvisited */ (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); /* Output the summary statistics */ fprintf(f, "\n\nSummary statistics:\n\n"); fprintf(f, "%s %8s %8s %8s %8s\n", " ", "min", "max", "mean", "std.dev"); extCumOutput("% cell interact", &cumPercentInteraction, f); /* Fix up average value to be weighted */ inter = 0.0; if (cumTotalArea.cums_sum > 0) inter = 100.0 * cumInteractArea.cums_sum / cumTotalArea.cums_sum; fprintf(f, "Mean %% interaction area = %.2f\n", inter); } int extInterAreaFunc(use, f) CellUse *use; FILE *f; { static Plane *interPlane = (Plane *) NULL; CellDef *def = use->cu_def; int extInterCountFunc(); int area, interarea; double pctinter; if (interPlane == NULL) interPlane = DBNewPlane((ClientData) TT_SPACE); /* Skip if already visited */ if (def->cd_client) return (0); /* Mark as visited */ def->cd_client = (ClientData) 1; /* Compute interaction area */ extInterCountDef = def; ExtFindInteractions(def, extInterCountHalo, 0, interPlane); interarea = 0; (void) DBSrPaintArea((Tile *) NULL, interPlane, &TiPlaneRect, &DBAllButSpaceBits, extInterCountFunc, (ClientData) &interarea); DBClearPaintPlane(interPlane); area = (def->cd_bbox.r_xtop - def->cd_bbox.r_xbot) * (def->cd_bbox.r_ytop - def->cd_bbox.r_ybot); pctinter = 0.0; if (area > 0) pctinter = ((double) interarea) / ((double) area) * 100.0; if (pctinter > 0.0) extCumAdd(&cumPercentInteraction, pctinter); extCumAdd(&cumTotalArea, (double) area); extCumAdd(&cumInteractArea, (double) interarea); fprintf(f, "%7.2f%% %s\n", pctinter, def->cd_name); /* Visit our children */ (void) DBCellEnum(def, extInterAreaFunc, (ClientData) f); return (0); } int extInterCountFunc(tile, pArea) Tile *tile; int *pArea; { Rect r; TITORECT(tile, &r); GEOCLIP(&r, &extInterCountDef->cd_bbox); *pArea += (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot); return (0); }