From 5300f322de55305bc0d2bed9795638e82a8474ea Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 9 Jun 2023 15:31:58 -0400 Subject: [PATCH] Added code to calculate area and perimeter of layers that are not on the same plane as a device identifier layer. This (finally!) allows proper calculation of area and perimeter of diodes and bipolars, for example. --- VERSION | 2 +- extract/ExtBasic.c | 102 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 83 insertions(+), 21 deletions(-) diff --git a/VERSION b/VERSION index eda20a17..8a88198a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.401 +8.3.402 diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 7b4d1b45..1c09a2a2 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -1768,6 +1768,49 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec) } } +/* Structures used by extTermAPFunc() for storing area and perimeter data */ + +typedef struct _nodelist { + struct _nodelist *nl_next; + NodeRegion *nl_node; +} ExtNodeList; + +typedef struct _extareaperimdata { + int eapd_area; + int eapd_perim; + TileTypeBitMask eapd_mask; + TileTypeBitMask *eapd_gatemask; + NodeRegion *eapd_gatenode; + ExtNodeList *eapd_shared; +} ExtAreaPerimData; + +/* + * ---------------------------------------------------------------------------- + * + * extTransFindTermArea -- + * + * Callback function to find the area and perimeter of a terminal area in + * a plane other than the plane of the device identifier type. This routine + * searches around the first tile of the terminal for all connected terminal + * types and calculates area and perimeter. + * + * Return value: + * Always return 1 to stop the search, because we need only one tile + * under the identifier tile to start the search. + * + * ---------------------------------------------------------------------------- + */ +int +extTransFindTermArea(tile, eapd) + Tile *tile; + ExtAreaPerimData *eapd; +{ + int extTermAPFunc(); /* Forward declaration */ + + DBSrConnectOnePlane(tile, DBConnectTbl, extTermAPFunc, (ClientData)eapd); + return 1; +} + /* * ---------------------------------------------------------------------------- * @@ -1929,10 +1972,14 @@ extOutputDevices(def, transList, outFile) else if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum]) || (TTMaskHasType(tmask, TT_SPACE))) { + ExtAreaPerimData eapd; + TileType tt = TT_SPACE; + Rect r; + node = NULL; /* First try to find a region under the device */ - extTransFindSubs(reg->treg_tile, t, tmask, def, &node, NULL); + extTransFindSubs(reg->treg_tile, t, tmask, def, &node, &tt); if ((node == NULL) && (TTMaskHasType(tmask, TT_SPACE))) { /* Device node is the global substrate. */ @@ -1946,6 +1993,38 @@ extOutputDevices(def, transList, outFile) } extTransRec.tr_devmatch |= (MATCH_TERM << termcount); extTransRec.tr_termnode[termcount] = node; + + /* Terminals on other planes will not have area and perimeter + * computed, so do that here. + */ + TiToRect(reg->treg_tile, &r); + eapd.eapd_area = 0; + eapd.eapd_perim = 0; + eapd.eapd_shared = NULL; + /* NOTE: Currently there is no way to determine if a + * terminal on another plane belongs to multiple devices, + * so device sharing is not checked. Could be done by + * checking the terminal area for the gate mask (on its + * own plane) in extTermAPFunc(). + */ + eapd.eapd_gatemask = &DBZeroTypeBits; + TTMaskCom2(&eapd.eapd_mask, tmask); + if (tt == TT_SPACE) + { + /* Terminal may be the substrate, in which case */ + /* the device should not be recording area or */ + /* perimeter, so leave them as zero. */ + extTransRec.tr_termarea[termcount] = 0; + extTransRec.tr_termperim[termcount] = 0; + } + else + { + DBSrPaintArea((Tile *)NULL, def->cd_planes[DBPlane(tt)], + &r, &tmask, extTransFindTermArea, (ClientData)&eapd); + extTransRec.tr_termarea[termcount] = eapd.eapd_area; + extTransRec.tr_termperim[termcount] = eapd.eapd_perim; + } + extTransRec.tr_termshared[termcount] = 1; } else { /* Determine if there is another matching device record */ @@ -2749,7 +2828,7 @@ extTransTileFunc(tile, pNum, arg) { TileTypeBitMask mask, cmask, *smask; TileType loctype, idlayer, sublayer; - int perim, result; + int perim, result, i; bool allow_globsubsnode; ExtDevice *devptr, *deventry, *devtest; NodeRegion *region; @@ -2758,12 +2837,12 @@ extTransTileFunc(tile, pNum, arg) Label *lab; Rect r; + TITORECT(tile, &r); for (ll = extTransRec.tr_gatenode->nreg_labels; ll; ll = ll->ll_next) { /* Skip if already marked */ if (ll->ll_attr != LL_NOATTR) continue; lab = ll->ll_label; - TITORECT(tile, &r); if (GEO_TOUCH(&r, &lab->lab_rect) && extLabType(lab->lab_text, LABTYPE_GATEATTR)) { @@ -2944,26 +3023,9 @@ extTransTileFunc(tile, pNum, arg) extTransRec.tr_devmatch |= MATCH_ID; } extTransRec.tr_devrec = devptr; - return 0; } -/* Structures used by extTermAPFunc() for storing area and perimeter data */ - -typedef struct _nodelist { - struct _nodelist *nl_next; - NodeRegion *nl_node; -} ExtNodeList; - -typedef struct _extareaperimdata { - int eapd_area; - int eapd_perim; - TileTypeBitMask eapd_mask; - TileTypeBitMask *eapd_gatemask; - NodeRegion *eapd_gatenode; - ExtNodeList *eapd_shared; -} ExtAreaPerimData; - /* * ---------------------------------------------------------------------------- *