/* * ExtHier.c -- * * Circuit extraction. * Lower-level procedures common both to ordinary subtree extraction, * and to array extraction. * The procedures in this file are not re-entrant. * * ********************************************************************* * * 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/ExtHier.c,v 1.3 2010/06/24 12:37:17 tim Exp $"; #endif /* not lint */ #include #include #include #include "utils/magic.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 "utils/styles.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "debug/debug.h" #include "extract/extract.h" #include "extract/extractInt.h" /* Local data */ /* Passed to search functions by extHierConnections */ ExtTree *extHierCumFlat; /* Cum buffer */ ExtTree *extHierOneFlat; /* Subtree being compared with extHierCumFlat */ /* List of free cells around for use in yanking subtrees */ ExtTree *extHierFreeOneList = (ExtTree *) NULL; /* Appended to the name of each new CellDef created by extHierNewOne() */ int extHierOneNameSuffix = 0; /* Forward declarations */ int extHierConnectFunc1(); int extHierConnectFunc2(); int extHierConnectFunc3(); Node *extHierNewNode(); /* * ---------------------------------------------------------------------------- * * extHierConnections -- * * Process connections between the two ExtTrees 'oneFlat' and 'cumFlat'. * This consists of detecting overlaps or abutments between connecting * tiles (maybe on different planes), and recording the connection in the hash * table ha->ha_connHash. * * Results: * None. * * Side effects: * Adds connections to ha->ha_connHash. * Doesn't change resistance or capacitance of the connected * nodes; that is the job of extHierAdjustments(). * * ---------------------------------------------------------------------------- */ void extHierConnections(ha, cumFlat, oneFlat) HierExtractArg *ha; ExtTree *cumFlat, *oneFlat; { int pNum; CellDef *sourceDef = oneFlat->et_use->cu_def; Label *lab; extHierCumFlat = cumFlat; extHierOneFlat = oneFlat; for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { ha->hierPNum = pNum; (void) DBSrPaintArea((Tile *) NULL, sourceDef->cd_planes[pNum], &ha->ha_subArea, &DBAllButSpaceBits, extHierConnectFunc1, (ClientData) ha); } /* Look for sticky labels in the child cell that are not */ /* connected to any geometry. */ for (lab = sourceDef->cd_labels; lab; lab = lab->lab_next) { CellDef *cumDef = cumFlat->et_use->cu_def; Rect r = lab->lab_rect; TileTypeBitMask *connected = &DBConnectTbl[lab->lab_type]; int i = DBPlane(lab->lab_type); ha->hierOneTile = (Tile *)lab; /* Blatant hack recasting */ ha->hierType = lab->lab_type; ha->hierPNumBelow = i; GEOCLIP(&r, &ha->ha_subArea); if (lab->lab_flags & LABEL_STICKY) DBSrPaintArea((Tile *) NULL, cumFlat->et_use->cu_def->cd_planes[i], &r, connected, extHierConnectFunc3, (ClientData) ha); } } /* * ---------------------------------------------------------------------------- * extHierConnectFunc1 -- * * Called for each tile 'oneTile' in the ExtTree 'oneFlat' above * that lies in the area ha->ha_subArea. * * Results: * Returns 0 always. * * Side effects: * None here, but see extHierConnectFunc2(). * ---------------------------------------------------------------------------- */ int extHierConnectFunc1(oneTile, ha) Tile *oneTile; /* Comes from 'oneFlat' in extHierConnections */ HierExtractArg *ha; /* Extraction context */ { CellDef *cumDef = extHierCumFlat->et_use->cu_def; Rect r; TileTypeBitMask mask, *connected; TileType rtype; Label *lab, *newlab; int i; unsigned n; int extHierSubsFunc(); int extHierSubConnectFunc(); /* * Find all tiles that connect to 'srcTile', but in the * yank buffer cumDef. Adjust connectivity for each tile found. * Widen the rectangle to detect connectivity by abutment. */ ha->hierOneTile = oneTile; ha->hierType = TiGetTypeExact(oneTile); if (IsSplit(oneTile)) { rtype = ha->hierType; ha->hierType = (rtype & TT_SIDE) ? SplitRightType(oneTile) : SplitLeftType(oneTile); } connected = &(ExtCurStyle->exts_nodeConn[ha->hierType]); TITORECT(oneTile, &r); GEOCLIP(&r, &ha->ha_subArea); r.r_xbot--, r.r_ybot--, r.r_xtop++, r.r_ytop++; for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) { ha->hierPNumBelow = i; TTMaskAndMask3(&mask, connected, &DBPlaneTypes[i]); if (!TTMaskIsZero(&mask)) { if (IsSplit(oneTile)) DBSrPaintNMArea((Tile *) NULL, cumDef->cd_planes[i], rtype, &r, ((i == ha->hierPNum) ? &ExtCurStyle->exts_activeTypes : connected), extHierConnectFunc2, (ClientData) ha); else DBSrPaintArea((Tile *) NULL, cumDef->cd_planes[i], &r, ((i == ha->hierPNum) ? &ExtCurStyle->exts_activeTypes : connected), extHierConnectFunc2, (ClientData) ha); } } /* Where the type connects to substrate, and the substrate region */ /* under the tile is the default (global) substrate, then the tile */ /* will connect to anything in cumDef that is also connected to the */ /* default substrate. This is where a "substrate halo" could be */ /* applied to restrict the distance at which a substrate region is */ /* considered to be connected (but would have to ignore identifier */ /* types like "pwell" that are part of the substrate itself). */ if ((ExtSubsPlane != NULL) && TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, ha->hierType)) { Region *region, *saveRegion; TileTypeBitMask subMaskNonSpace; TTMaskZero(&subMaskNonSpace); TTMaskSetMask(&subMaskNonSpace, &ExtCurStyle->exts_globSubstrateTypes); TTMaskClearType(&subMaskNonSpace, TT_SPACE); if (DBSrPaintArea((Tile *)NULL, ExtSubsPlane, &r, &subMaskNonSpace, extHierSubsFunc, (ClientData)®ion) == 0) region = ExtSubsRegionList[0]; /* This tile connects to a substrate region, so search */ /* cumDef for any tile also connected to the same region. */ saveRegion = ha->ha_parentReg; ha->ha_parentReg = region; for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) { ha->hierPNumBelow = i; TTMaskAndMask3(&mask, connected, &DBPlaneTypes[i]); if (!TTMaskIsZero(&mask)) DBSrPaintArea((Tile *) NULL, cumDef->cd_planes[i], &TiPlaneRect, &subMaskNonSpace, extHierSubConnectFunc, (ClientData)ha); } ha->ha_parentReg = saveRegion; } /* Where labels have been saved from the parent cell, look for any */ /* that are inside the cell boundary and would connect to the tile. */ /* This allows the extractor to catch "sticky" labels that are not */ /* attached to a physical layer in the parent cell. */ // NOTE by Tim, 9/10/2014: This generates phantom nodes when the // labels are created by the "hard" node search; I think this code // should be restricted to sticky labels only. But not certain. // Definitely this causes problems in arrays, because the array node // name may refer to a range of array elements, and the generated // node only describes a single point. for (lab = cumDef->cd_labels; lab; lab = lab->lab_next) { // All sticky labels are at the front of the list in cumDef, so // stop when we see the first non-sticky label. if (!(lab->lab_flags & LABEL_STICKY)) break; if (GEO_TOUCH(&r, &lab->lab_rect)) if (TTMaskHasType(connected, lab->lab_type)) { HashTable *table = &ha->ha_connHash; HashEntry *he; NodeName *nn; Node *node1, *node2; char *name; /* Register the name, like is done in extHierConnectFunc2 */ he = HashFind(table, lab->lab_text); nn = (NodeName *) HashGetValue(he); node1 = nn ? nn->nn_node : extHierNewNode(he); name = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat, ha, TRUE); he = HashFind(table, name); nn = (NodeName *) HashGetValue(he); node2 = nn ? nn->nn_node : extHierNewNode(he); if (node1 != node2) { /* * Both sets of names will now point to node1. * We don't need to update node_cap since it * hasn't been computed yet. */ for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next) nn->nn_node = node1; nn->nn_node = node1; nn->nn_next = node1->node_names; node1->node_names = node2->node_names; freeMagic((char *) node2); } } } return (0); } /* * ---------------------------------------------------------------------------- * extHierSubsFunc -- * * Callback function to find a non-space tile in ExtSubsPlane. If found, * get the region associated with the tile by lookup in the list * ExtSubsRegionList. * * Results: * Return 1 to stop the search. * * Side effects: * Fills the Region * value pointed to by regionPtr * * ---------------------------------------------------------------------------- */ int extHierSubsFunc(tile, regionPtr) Tile *tile; Region **regionPtr; { int regIdx = (int)tile->ti_client; if (regIdx > ExtNumSubs) return 0; /* Invalid condition */ *regionPtr = ExtSubsRegionList[regIdx]; return 1; } /* * ---------------------------------------------------------------------------- * extHierConnectFunc2 -- * * Called once for each tile 'cum' in extHierCumFlat->et_use->cu_def * on the same plane as ha->hierOneTile that also overlaps or abuts * the intersection of ha->hierOneTile with ha->ha_subArea, and for tiles * in other planes that may connect. * * Results: * Returns 0 always. * * Side effects: * Makes a connection between the nodes of the two tiles * if the types of ha->hierOneTile and 'cum' connect. * Otherwise, if the tiles actually overlap (as opposed * to merely abut), mark it with feedback as an error. * ---------------------------------------------------------------------------- */ int extHierConnectFunc2(cum, ha) Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */ HierExtractArg *ha; /* Extraction context */ { HashTable *table = &ha->ha_connHash; Node *node1, *node2; TileType ttype; HashEntry *he; NodeName *nn; char *name1, *name2; Rect r; /* Compute the overlap area */ r.r_xbot = MAX(LEFT(ha->hierOneTile), LEFT(cum)); r.r_xtop = MIN(RIGHT(ha->hierOneTile), RIGHT(cum)); r.r_ybot = MAX(BOTTOM(ha->hierOneTile), BOTTOM(cum)); r.r_ytop = MIN(TOP(ha->hierOneTile), TOP(cum)); /* If the tiles don't even touch, they don't connect */ if (r.r_xtop < r.r_xbot || r.r_ytop < r.r_ybot || (r.r_xtop == r.r_xbot && r.r_ytop == r.r_ybot)) return (0); /* * Only make a connection if the types of 'ha->hierOneTile' and 'cum' * connect. If they overlap and don't connect, it is an error. * If they do connect, mark their nodes as connected. */ ttype = TiGetTypeExact(cum); if (IsSplit(cum)) ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum); if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn)) { name1 = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE); he = HashFind(table, name1); nn = (NodeName *) HashGetValue(he); node1 = nn ? nn->nn_node : extHierNewNode(he); name2 = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat, ha, TRUE); he = HashFind(table, name2); nn = (NodeName *) HashGetValue(he); node2 = nn ? nn->nn_node : extHierNewNode(he); if (node1 != node2) { /* * Both sets of names will now point to node1. * We don't need to update node_cap since it * hasn't been computed yet. */ for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next) nn->nn_node = node1; nn->nn_node = node1; nn->nn_next = node1->node_names; node1->node_names = node2->node_names; freeMagic((char *) node2); } } else if (r.r_xtop > r.r_xbot && r.r_ytop > r.r_ybot) { extNumFatal++; if (!DebugIsSet(extDebugID, extDebNoFeedback)) DBWFeedbackAdd(&r, "Illegal overlap (types do not connect)", ha->ha_parentUse->cu_def, 1, STYLE_MEDIUMHIGHLIGHTS); } return (0); } /* * ---------------------------------------------------------------------------- * * extHierConnectFunc3 -- * * Called once for each tile 'cum' in extHierCumFlat->et_use->cu_def * Similar to extHierConnectFunc2, but is called for a label in the * parent cell that does not necessarily have associated geometry. * Value passed in ha_oneTile is the label (recast for convenience; * need to use a union type in HierExtractArg). * * ---------------------------------------------------------------------------- */ int extHierConnectFunc3(cum, ha) Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */ HierExtractArg *ha; /* Extraction context */ { HashTable *table = &ha->ha_connHash; Node *node1, *node2; TileType ttype; HashEntry *he; NodeName *nn; char *name; Rect r; Label *lab = (Label *)(ha->hierOneTile); /* Lazy recasting */ /* Compute the overlap area */ r.r_xbot = MAX(lab->lab_rect.r_xbot, LEFT(cum)); r.r_xtop = MIN(lab->lab_rect.r_xtop, RIGHT(cum)); r.r_ybot = MAX(lab->lab_rect.r_ybot, BOTTOM(cum)); r.r_ytop = MIN(lab->lab_rect.r_ytop, TOP(cum)); /* If the tiles don't even touch, they don't connect */ if (r.r_xtop < r.r_xbot || r.r_ytop < r.r_ybot) return (0); /* * Only make a connection if the types of 'ha->hierOneTile' and 'cum' * connect. If they overlap and don't connect, it is an error. * If they do connect, mark their nodes as connected. */ ttype = TiGetTypeExact(cum); if (IsSplit(cum)) ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum); if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn)) { name = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE); he = HashFind(table, name); nn = (NodeName *) HashGetValue(he); node1 = nn ? nn->nn_node : extHierNewNode(he); name = lab->lab_text; he = HashFind(table, name); nn = (NodeName *) HashGetValue(he); node2 = nn ? nn->nn_node : extHierNewNode(he); if (node1 != node2) { /* * Both sets of names will now point to node1. * We don't need to update node_cap since it * hasn't been computed yet. */ for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next) nn->nn_node = node1; nn->nn_node = node1; nn->nn_next = node1->node_names; node1->node_names = node2->node_names; freeMagic((char *) node2); } } else if (r.r_xtop > r.r_xbot && r.r_ytop > r.r_ybot) { extNumFatal++; if (!DebugIsSet(extDebugID, extDebNoFeedback)) DBWFeedbackAdd(&r, "Illegal overlap (types do not connect)", ha->ha_parentUse->cu_def, 1, STYLE_MEDIUMHIGHLIGHTS); } return (0); } /* * ---------------------------------------------------------------------------- * * extHierSubConnectFunc -- * * Called for all tiles 'cum' in extHierCumFlat->et_use->cu_def * that connect to substrate types. Checks if the tile is marked * with the substrate region that has been saved in the * ha->ha_parentReg record. If so, then processes the connection. * Only one such connection needs to be processed, so return 1 to * stop the search. * * Results: * Returns 1 always to stop the search, as only one tile * with the substrate region needs to be processed. * * Side Effects: * Makes a connection between the nodes of the two tiles * if the types of ha->hierOneTile and 'cum' connect. * * ---------------------------------------------------------------------------- */ int extHierSubConnectFunc(cum, ha) Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */ HierExtractArg *ha; /* Extraction context */ { HashTable *table = &ha->ha_connHash; Node *node1, *node2; TileType ttype; HashEntry *he; NodeName *nn; char *name1, *name2; /* If Tile "cum" is not marked with the global substrate region, */ /* then ignore it (return 0 to keep the search going) */ if ((NodeRegion *)cum->ti_client != ha->ha_parentReg) return 0; ttype = TiGetTypeExact(cum); if (IsSplit(cum)) ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum); name1 = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE); he = HashFind(table, name1); nn = (NodeName *) HashGetValue(he); node1 = nn ? nn->nn_node : extHierNewNode(he); name2 = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat, ha, TRUE); he = HashFind(table, name2); nn = (NodeName *) HashGetValue(he); node2 = nn ? nn->nn_node : extHierNewNode(he); if (node1 != node2) { /* * Both sets of names will now point to node1. * We don't need to update node_cap since it * hasn't been computed yet. */ for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next) nn->nn_node = node1; nn->nn_node = node1; nn->nn_next = node1->node_names; node1->node_names = node2->node_names; freeMagic((char *) node2); } return 1; /* No need to process any other tiles */ } /* * ---------------------------------------------------------------------------- * * extHierAdjustments -- * * Process adjustments to substrate capacitance, coupling capacitance, * node perimeter, and node area between the subtree 'oneFlat' and the * cumulative yank buffer 'cumFlat'. The subtree 'lookFlat' is used * for looking up node names when handling capacitance/perimeter/area * adjustment. * * Results: * None. * * Side effects: * Updates capacitance in the table cumFlat->et_coupleHash. * Updates capacitance, perimeter, and area recorded in the * nodes of 'cumFlat'. * * Algorithm: * For each capacitor recorded in oneFlat->et_coupleHash, find * the corresponding nodes in 'cumFlat' and subtract the * capacitance from the entry indexed by these nodes in the * table cumFlat->et_coupleHash. * * For each node in oneFlat->et_nodes, find the corresponding * node in 'lookFlat'. Look for the Node with this name in * the table ha->ha_connHash, and subtract the oneFlat node's * capacitance, perimeter, and area from it. If no Node is * found in this table, don't do anything since the oneFlat * node must not participate in any connections. * * The node in 'cumFlat' corresponding to one in 'oneFlat' * is the one containing some point in 'oneFlat', since 'oneFlat' * is a strict subset of 'cumFlat'. * * ---------------------------------------------------------------------------- */ void extHierAdjustments(ha, cumFlat, oneFlat, lookFlat) HierExtractArg *ha; ExtTree *cumFlat, *oneFlat, *lookFlat; { HashEntry *he, *heCum; int n; CoupleKey *ckpOne, ckCum; NodeRegion *np; HashSearch hs; NodeName *nn; Tile *tp; char *name; /* Update all coupling capacitors */ if (ExtOptions & EXT_DOCOUPLING) { HashStartSearch(&hs); while (he = HashNext(&oneFlat->et_coupleHash, &hs)) { ckpOne = ((CoupleKey *) he->h_key.h_words); /* Find nodes in cumFlat->et_coupleHash */ NODETONODE(ckpOne->ck_1, cumFlat, ckCum.ck_1); NODETONODE(ckpOne->ck_2, cumFlat, ckCum.ck_2); if (ckCum.ck_1 == NULL || ckCum.ck_2 == NULL) continue; /* Skip if the same; reverse to make smaller node pointer first */ if (ckCum.ck_1 == ckCum.ck_2) continue; if (ckCum.ck_2 < ckCum.ck_1) np = ckCum.ck_1, ckCum.ck_1 = ckCum.ck_2, ckCum.ck_2 = np; /* Update the capacitor record in cumFlat->et_coupleHash */ heCum = HashFind(&cumFlat->et_coupleHash, (char *) &ckCum); extSetCapValue(heCum, extGetCapValue(heCum) - extGetCapValue(he)); } } /* * Update all node values. * Find the corresponding tile in the ExtTree lookFlat, then look * for its name. If this name appear in the connection hash table, * update the capacitance, perimeter, and area stored there; otherwise * ignore it. * * The FALSE argument to (*ha->ha_nodename)() means that we don't bother * looking for node names the hard way; if we didn't already have a valid * node name then it couldn't appear in the table ha->ha_connHash in the * first place. */ for (np = oneFlat->et_nodes; np; np = np->nreg_next) { /* Ignore orphaned nodes (non-Manhattan shards outside the clip box) */ if (np->nreg_pnum == DBNumPlanes) continue; tp = extNodeToTile(np, lookFlat); /* Ignore regions that do not participate in extraction */ if (!extHasRegion(tp, extUnInit)) continue; /* Ignore substrate nodes (failsafe: should not happen) */ if (TiGetTypeExact(tp) == TT_SPACE) continue; if (tp && (name = (*ha->ha_nodename)(tp, np->nreg_pnum, lookFlat, ha, FALSE)) && (he = HashLookOnly(&ha->ha_connHash, name)) && (nn = (NodeName *) HashGetValue(he))) { /* Adjust the capacitance and resistance */ nn->nn_node->node_cap -= np->nreg_cap; for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) { nn->nn_node->node_pa[n].pa_perim -= np->nreg_pa[n].pa_perim; nn->nn_node->node_pa[n].pa_area -= np->nreg_pa[n].pa_area; } } } } /* * ---------------------------------------------------------------------------- * * extOutputConns -- * * Dump the contents of the hash table 'table' of connectivity and * node R, C adjustments to the output file outf. * * Results: * None. * * Side effects: * Outputs a number of "merge" records to the file 'outf'. * * ---------------------------------------------------------------------------- */ void extOutputConns(table, outf) HashTable *table; FILE *outf; { CapValue c; /* cap value */ NodeName *nn, *nnext; Node *node; int n; NodeName *nfirst; HashSearch hs; HashEntry *he; HashStartSearch(&hs); while (he = HashNext(table, &hs)) { nfirst = (NodeName *) HashGetValue(he); /* * If nfirst->nn_node == NULL, the name for this hash entry * had been output previously as a member of the merge list * for a node appearing earlier in the table. If so, we need * only free the NodeName without any further processing. */ if (node = nfirst->nn_node) { /* * If there are N names for this node, output N-1 merge lines. * Only the first merge line will contain the C, perimeter, * and area updates. */ /* Note 3/1/2017: Cap value no longer used */ c = (node->node_cap) / ExtCurStyle->exts_capScale; nn = node->node_names; if (nnext = nn->nn_next) { /* First merge */ fprintf(outf, "merge \"%s\" \"%s\" %lg", nn->nn_name, nnext->nn_name, c); for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) fprintf(outf, " %d %d", node->node_pa[n].pa_area, node->node_pa[n].pa_perim); fprintf(outf, "\n"); nn->nn_node = (Node *) NULL; /* Processed */ /* Subsequent merges */ for (nn = nnext; nnext = nn->nn_next; nn = nnext) { fprintf(outf, "merge \"%s\" \"%s\"\n", nn->nn_name, nnext->nn_name); nn->nn_node = (Node *) NULL; /* Processed */ } } nn->nn_node = (Node *) NULL; freeMagic((char *) node); } freeMagic((char *) nfirst); } } /* * ---------------------------------------------------------------------------- * * extHierNewNode -- * * Create a new NodeName and Node to go with the HashEntry supplied. * The NodeName will point to the new Node, which will point back to the * NodeName. * * Results: * Returns a pointer to the newly created Node. * * Side effects: * Allocates memory. * Sets (via HashSetValue) the value of HashEntry 'he' to the * newly created NodeName. * * ---------------------------------------------------------------------------- */ Node * extHierNewNode(he) HashEntry *he; { int n, nclasses; NodeName *nn; Node *node; nclasses = ExtCurStyle->exts_numResistClasses; n = (nclasses - 1) * sizeof (PerimArea) + sizeof (Node); nn = (NodeName *) mallocMagic((unsigned) (sizeof (NodeName))); node = (Node *) mallocMagic((unsigned) n); nn->nn_node = node; nn->nn_next = (NodeName *) NULL; nn->nn_name = he->h_key.h_name; node->node_names = nn; node->node_cap = (CapValue) 0; for (n = 0; n < nclasses; n++) node->node_pa[n].pa_perim = node->node_pa[n].pa_area = 0; HashSetValue(he, (char *) nn); return (node); } /* * ---------------------------------------------------------------------------- * * extHierLabFirst -- * extHierLabEach -- * * Filter functions passed to ExtFindRegions when tracing out labelled * regions as part of a hierarchical circuit extraction. * * Results: * extHierLabFirst returns a pointer to a new LabRegion. * extHierLabEach returns 0 always. * * Side effects: * Memory is allocated by extHierLabFirst(); it conses the newly * allocated region onto the front of the existing region list. * The node-naming info (reg_ll, reg_pnum) is updated by * extHierLabEach(). * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ Region * extHierLabFirst(tile, arg) Tile *tile; FindRegion *arg; { LabRegion *new; new = (LabRegion *) mallocMagic((unsigned) (sizeof (LabRegion))); new->lreg_next = (LabRegion *) NULL; new->lreg_labels = (LabelList *) NULL; new->lreg_pnum = DBNumPlanes; new->lreg_type = 0; /* Prepend it to the region list */ new->lreg_next = (LabRegion *) arg->fra_region; arg->fra_region = (Region *) new; return ((Region *) new); } /*ARGSUSED*/ int extHierLabEach(tile, pNum, arg) Tile *tile; int pNum; FindRegion *arg; { LabRegion *reg; reg = (LabRegion *) arg->fra_region; extSetNodeNum(reg, pNum, tile); return (0); } /* * ---------------------------------------------------------------------------- * * extHierNewOne -- * * Allocate a new ExtTree for use in hierarchical extraction. * This ExtTree will be used to hold an entire flattened subtree. * We try to return one from our free list if one exists; if none * are left, we create a new CellDef and CellUse and allocate a * new ExtTree. The new CellDef has a name of the form __EXTTREEn__, * where 'n' is a small integer. * * The HashTable et_coupleHash will be initialized but empty. * The node list et_nodes, the next pointer et_next, and the CellDef * pointer et_lookNames will all be set to NULL. * * Results: * Returns a pointer to a new ExtTree. * * Side effects: * See above. * * ---------------------------------------------------------------------------- */ ExtTree * extHierNewOne() { char defname[128]; CellDef *dummy; ExtTree *et; if (extHierFreeOneList) { et = extHierFreeOneList; extHierFreeOneList = et->et_next; } else { et = (ExtTree *) mallocMagic((unsigned)(sizeof (ExtTree))); (void) sprintf(defname, "__EXTTREE%d__", extHierOneNameSuffix++); DBNewYank(defname, &et->et_use, &dummy); } et->et_next = (ExtTree *) NULL; et->et_lookNames = (CellDef *) NULL; et->et_nodes = (NodeRegion *) NULL; if (ExtOptions & EXT_DOCOUPLING) HashInit(&et->et_coupleHash, 32, HashSize(sizeof (CoupleKey))); return (et); } /* * ---------------------------------------------------------------------------- * * extHierFreeOne -- * * Return an ExtTree allocated via extHierNewOne() above to the * free list. Frees the HashTable et->et_coupleHash, any NodeRegions * on the list et->et_nodes, any labels on the label list and any * paint in the cell et->et_use->cu_def. * * Results: * None. * * Side effects: * See above. * The caller should NOT use et->et_next after this procedure * has returned. * * ---------------------------------------------------------------------------- */ void extHierFreeOne(et) ExtTree *et; { if (ExtOptions & EXT_DOCOUPLING) extCapHashKill(&et->et_coupleHash); if (et->et_nodes) ExtFreeLabRegions((LabRegion *) et->et_nodes); extHierFreeLabels(et->et_use->cu_def); DBCellClearDef(et->et_use->cu_def); et->et_next = extHierFreeOneList; extHierFreeOneList = et; }