From 942eaf8113383cd0798830787fcc8b5ff3f42a9e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 08:42:07 -0400 Subject: [PATCH 1/5] Revised the substrate extraction method: Instead of searching on all types specified in the "substrate" statement, split such types into those on the declared well plane, and everything else. Any types on the well plane are searched as before. Types not on the well plane (e.g., psd on active) are searched and added to the substrate node *only* if overlapping nothing on the well plane. This allows a type such as "psd" to be used on, e.g., both space (substrate) and deep pwell, but only be extracted as part of the substrate when found over space. Note that if there is NO implicit substrate, the substrate connections will always be found through the usual connection rules. --- database/DBprop.c | 13 ++++++++ extract/ExtBasic.c | 82 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 82 insertions(+), 13 deletions(-) diff --git a/database/DBprop.c b/database/DBprop.c index c2ded840..85574435 100644 --- a/database/DBprop.c +++ b/database/DBprop.c @@ -66,6 +66,15 @@ DBPropPut(cellDef, name, value) HashInit( (HashTable *) cellDef->cd_props, 8, 0); } htab = (HashTable *) cellDef->cd_props; + + /* Special handling of FIXED_BBOX, which uses CDFIXEDBBOX as a quick lookup */ + if (!strcmp(name, "FIXED_BBOX")) + { + if (value == (ClientData)NULL) + cellDef->cd_flags &= ~CDFIXEDBBOX; + else + cellDef->cd_flags |= CDFIXEDBBOX; + } entry = HashFind(htab, name); oldvalue = (char *)HashGetValue(entry); @@ -202,4 +211,8 @@ DBPropClearAll(cellDef) HashKill(htab); freeMagic((char *) htab); cellDef->cd_props = (ClientData) NULL; + + /* Since CDFIXEDBBOX requires a FIXED_BBOX property, clearing all */ + /* properties necessarily means this flag must be clear. */ + cellDef->cd_flags &= ~CDFIXEDBBOX; } diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 89e32cb7..57f12df1 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -123,18 +123,6 @@ LinkedBoundary **extSpecialBounds; /* Linked Boundary List */ NodeRegion *glob_subsnode = NULL; /* Global substrate node */ NodeRegion *temp_subsnode = NULL; /* Last subsnode found */ -/* Structure used for finding substrate connections on implicitly-defined - * substrates - */ - -typedef struct TSD1 -{ - bool found; /* Set to 1 if a substrate connection was found */ - Rect rtrans; /* Rectangle of device */ - Rect rhalo; /* Search halo around device */ - NodeRegion *nreg; /* Closest substrate region within halo */ -} TransSubsData; - #define EDGENULL(r) ((r)->r_xbot > (r)->r_xtop || (r)->r_ybot > (r)->r_ytop) /* Forward declarations */ @@ -3396,9 +3384,11 @@ extFindNodes(def, clipArea, subonly) { int extNodeAreaFunc(); int extSubsFunc(); + int extSubsFunc2(); FindRegion arg; int pNum, n; TileTypeBitMask subsTypesNonSpace; + bool space_is_substrate; /* Reset perimeter and area prior to node extraction */ for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) @@ -3418,19 +3408,52 @@ extFindNodes(def, clipArea, subonly) /* call extNodeAreaFunc() on the first of these to generate */ /* a single substrate node. */ + /* Refinement: Split search into two parts, one on the */ + /* globSubstratePlane and one on all other planes. ONLY */ + /* search other planes if TT_SPACE is in the list of */ + /* substrate types, and then only consider those types to */ + /* be part of the substrate node if they have only space */ + /* below them on the globSubstratePlane. This method lets */ + /* a single type like "psd" operate on, for example, both */ + /* the substrate and an isolated pwell, without implicitly */ + /* connecting the isolated pwell to the substrate. */ + temp_subsnode = (NodeRegion *)NULL; // Reset for new search + if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, TT_SPACE)) + space_is_substrate = True; + else + space_is_substrate = False; + TTMaskZero(&subsTypesNonSpace); TTMaskSetMask(&subsTypesNonSpace, &ExtCurStyle->exts_globSubstrateTypes); TTMaskClearType(&subsTypesNonSpace, TT_SPACE); + pNum = ExtCurStyle->exts_globSubstratePlane; + /* Does the type set of this plane intersect the substrate types? */ + if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace)) + { + arg.fra_pNum = pNum; + DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], + &TiPlaneRect, &subsTypesNonSpace, extUnInit, + extSubsFunc, (ClientData) &arg); + } + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { + if (pNum == ExtCurStyle->exts_globSubstratePlane) continue; + /* Does the type set of this plane intersect the substrate types? */ + if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace)) { arg.fra_pNum = pNum; - DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], + if (space_is_substrate) + DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], + &TiPlaneRect, &subsTypesNonSpace, extUnInit, + extSubsFunc2, (ClientData) &arg); + else + DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], &TiPlaneRect, &subsTypesNonSpace, extUnInit, extSubsFunc, (ClientData) &arg); } @@ -3503,6 +3526,39 @@ extSubsFunc(tile, arg) return (0); } +int +extSubsFunc2(tile, arg) + Tile *tile; + FindRegion *arg; +{ + int pNum; + Rect tileArea; + int extSubsFunc3(); + + TiToRect(tile, &tileArea); + + /* Run second search in the area of the tile on the substrate plane */ + /* to make sure that nothing but space is under these tiles. */ + + pNum = ExtCurStyle->exts_globSubstratePlane; + + if (DBSrPaintArea((Tile *) NULL, arg->fra_def->cd_planes[pNum], + &tileArea, &DBAllButSpaceBits, + extSubsFunc3, (ClientData)NULL) == 0) + { + /* Mark this tile as pending and push it */ + PUSHTILE(tile, arg->fra_pNum); + } + return (0); +} + +int +extSubsFunc3(tile) + Tile *tile; +{ + /* Stops the search because something that was not space was found */ + return 1; +} int extNodeAreaFunc(tile, arg) From aa4bb4b19ca8c00ac76bd24a00b7d5c895b6f796 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 10:37:12 -0400 Subject: [PATCH 2/5] Since allowing brackets to be part of cell names in a previous commit, found that DBTreeFindUse fails to find such uses because it strips the array delimiters off the name. Fixed the routine although the routine really should be checking if the use is a 1- or 2- dimensional array and stripping off only the components expected. The current code will probably fail for cell uses that have brackets in the name AND are arrayed. Fortunately this search routine does not appear to be used frequently or in any critical database functions like netlisting. --- database/DBlabel2.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/database/DBlabel2.c b/database/DBlabel2.c index 91c1908d..c060ac14 100644 --- a/database/DBlabel2.c +++ b/database/DBlabel2.c @@ -296,18 +296,25 @@ DBTreeFindUse(name, use, scx) if ((def->cd_flags & CDAVAILABLE) == 0) (void) DBCellRead(def, (char *) NULL, TRUE, NULL); - /* - * Pull off the next component of path up to but not including - * any array subscripts. - */ - for (cp = name; *cp && *cp != '[' && *cp != '/'; cp++) - /* Nothing */; - csave = *cp; - *cp = '\0'; he = HashLookOnly(&def->cd_idHash, name); - *cp = csave; if (he == NULL || HashGetValue(he) == NULL) - return; + { + /* + * Pull off the next component of path up to but not including + * any array subscripts. + * NOTE: This should check the array bounds and only remove + * array components that are expected, not array components + * embedded in the name. + */ + for (cp = name; *cp && *cp != '[' && *cp != '/'; cp++) + /* Nothing */; + csave = *cp; + *cp = '\0'; + he = HashLookOnly(&def->cd_idHash, name); + *cp = csave; + if (he == NULL || HashGetValue(he) == NULL) + return; + } use = (CellUse *) HashGetValue(he); def = use->cu_def; From c360fb9d5a91d4122aba2515f608c5a74d15bb75 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 14:44:20 -0400 Subject: [PATCH 3/5] Corrected check on cd_client in CalmaRdcl; if not set for holding GDS plane data, it is initialized to CLIENTDEFAULT, not NULL. --- calma/CalmaRdcl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index 28acae08..a42c624a 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -903,7 +903,8 @@ calmaElementSref(filename) for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) { - if (gdsplanes[pNum] != NULL) + if ((def->cd_client != (ClientData)CLIENTDEFAULT) && + (gdsplanes[pNum] != NULL)) { gdsCopyRec.plane = cifCurReadPlanes[pNum]; if (isArray) From d5b695fea07b2417899dc58fa82d9eb8e77f5eb1 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 15:05:30 -0400 Subject: [PATCH 4/5] Corrected one other instance of checking for NULL when it should have checked for CLIENTDEFAULT. --- calma/CalmaRdcl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index a42c624a..78de9986 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -415,7 +415,8 @@ calmaParseStructure(filename) for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) { - if (cifplanes[pNum] != NULL) + if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) && + (cifplanes[pNum] != NULL)) { DBFreePaintPlane(cifplanes[pNum]); TiFreePlane(cifplanes[pNum]); From a75aec4d7c20c86e7fb52f28f358ad09e0471608 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 15:10:45 -0400 Subject: [PATCH 5/5] Finally realized the problem came from a quick addition of a TO-DO item that was never properly validated. Corrected the root of the problem, which was an attempt to deallocate memory that had never been allocated in the first place. --- calma/CalmaRdcl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index 78de9986..e69bb386 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -405,18 +405,18 @@ calmaParseStructure(filename) */ if (CalmaFlattenUses && (!was_called) && (npaths < 10) && (nsrefs == 0)) { - /* To-do: If CDFLATGDS is already set, need to remove */ + /* If CDFLATGDS is already set, may need to remove */ /* existing planes and free memory. */ - if (cifReadCellDef->cd_flags & CDFLATGDS) + if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) && + (cifReadCellDef->cd_flags & CDFLATGDS)) { Plane **cifplanes = (Plane **)cifReadCellDef->cd_client; int pNum; for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) { - if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) && - (cifplanes[pNum] != NULL)) + if (cifplanes[pNum] != NULL) { DBFreePaintPlane(cifplanes[pNum]); TiFreePlane(cifplanes[pNum]);