Corrected the use of the global substrate node name; this has been
restricted to its original intent, which is to replace the long name formed from the plane short name and the "minfinity" coordinate. This avoids issues with conflicting substrate names derived from a real layer such as pwell. Also, the global substrate node name now returns the variable name without the "$" in front if the variable has not been set to anything. This avoids potential syntax errors in the netlist.
This commit is contained in:
parent
2bbe1be790
commit
67d0d8c3f0
|
|
@ -1618,8 +1618,8 @@ CmdFindNetProc(nodename, use, rect, warn_not_found)
|
|||
/* go to that point (transformed to the top level of the design */
|
||||
/* hierarchy). */
|
||||
|
||||
/* see extract/extractInt.h for the format of the node, found in */
|
||||
/* extMakeNodeNumPrint(), which is a macro, not a subroutine. */
|
||||
/* see extract/extBasic.c for the format of the node, found */
|
||||
/* in extMakeNodeNumPrint(). */
|
||||
|
||||
locvalid = FALSE;
|
||||
if ((xstr = strchr(s, '_')) != NULL)
|
||||
|
|
|
|||
|
|
@ -740,6 +740,139 @@ extOutputNodes(nodeList, outFile)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* extSubsName --
|
||||
*
|
||||
* Return the name of the substrate node, if the node belongs to
|
||||
* the substrate region and a global substrate node name has been
|
||||
* specified by the tech file. If the substrate node name is a
|
||||
* Tcl variable name, then perform the variable substitution.
|
||||
*
|
||||
* Results:
|
||||
* Pointer to a character string.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
extSubsName(node)
|
||||
LabRegion *node;
|
||||
{
|
||||
char *subsName;
|
||||
|
||||
/* If the techfile specifies a global name for the substrate, use */
|
||||
/* that in preference to the default "p_x_y#" name. Use this name */
|
||||
/* only to substitute for nodes with tiles at -(infinity). */
|
||||
|
||||
if (ExtCurStyle->exts_globSubstrateName != NULL)
|
||||
{
|
||||
if (node->lreg_ll.p_x <= (MINFINITY + 3))
|
||||
{
|
||||
if (ExtCurStyle->exts_globSubstrateName[0] == '$' &&
|
||||
ExtCurStyle->exts_globSubstrateName[1] != '$')
|
||||
{
|
||||
// If subsName is a Tcl variable (begins with "$"), make the
|
||||
// variable substitution, if one exists. Ignore double-$.
|
||||
// If the variable is undefined in the interpreter, then
|
||||
// strip the "$" from the front as this is not legal in most
|
||||
// netlist formats.
|
||||
|
||||
char *varsub = (char *)Tcl_GetVar(magicinterp,
|
||||
&ExtCurStyle->exts_globSubstrateName[1],
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (varsub != NULL) ? varsub : ExtCurStyle->exts_globSubstrateName
|
||||
+ 1;
|
||||
}
|
||||
else
|
||||
return ExtCurStyle->exts_globSubstrateName;
|
||||
}
|
||||
else return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* extMakeNodeNumPrint --
|
||||
*
|
||||
* Construct a node name from the plane number "plane" and lower left Point
|
||||
* "coord", and place it in the string "buf" (which must be large enough).
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Fills in string "buf".
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
extMakeNodeNumPrint(buf, lreg)
|
||||
char *buf;
|
||||
LabRegion *lreg;
|
||||
{
|
||||
int plane = lreg->lreg_pnum;
|
||||
Point *p = &lreg->lreg_ll;
|
||||
char *subsName;
|
||||
|
||||
subsName = extSubsName(lreg);
|
||||
if (subsName != NULL)
|
||||
strcpy(buf, subsName);
|
||||
else
|
||||
sprintf(buf, "%s_%s%d_%s%d#",
|
||||
DBPlaneShortName(plane),
|
||||
(p->p_x < 0) ? "n": "", abs(p->p_x),
|
||||
(p->p_y < 0) ? "n": "", abs(p->p_y));
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* extNodeName --
|
||||
*
|
||||
* Given a pointer to a LabRegion, return a pointer to a string
|
||||
* that can be printed as the name of the node. If the LabRegion
|
||||
* has a list of attached labels, use one of the labels; otherwise,
|
||||
* use its node number.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to a string. If the node had a label, this
|
||||
* is a pointer to the lab_text field of the first label on the
|
||||
* label list for the node; otherwise, it is a pointer to a static
|
||||
* buffer into which we have printed the node number.
|
||||
*
|
||||
* Side effects:
|
||||
* May overwrite the static buffer used to hold the printable
|
||||
* version of a node number.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
extNodeName(node)
|
||||
LabRegion *node;
|
||||
{
|
||||
static char namebuf[256]; /* Big enough to hold a generated nodename */
|
||||
LabelList *ll;
|
||||
|
||||
if (node == (LabRegion *) NULL || SigInterruptPending)
|
||||
return ("(none)");
|
||||
|
||||
for (ll = node->lreg_labels; ll; ll = ll->ll_next)
|
||||
if (extLabType(ll->ll_label->lab_text, LABTYPE_NAME))
|
||||
return (ll->ll_label->lab_text);
|
||||
|
||||
extMakeNodeNumPrint(namebuf, node);
|
||||
return (namebuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -807,8 +940,7 @@ extFindDuplicateLabels(def, nreg)
|
|||
{
|
||||
r.r_ll = r.r_ur = ll2->ll_label->lab_rect.r_ll;
|
||||
r.r_xbot--, r.r_ybot--, r.r_xtop++, r.r_ytop++;
|
||||
extMakeNodeNumPrint(name,
|
||||
np2->nreg_pnum, np2->nreg_ll);
|
||||
extMakeNodeNumPrint(name, np2);
|
||||
(void) sprintf(message, badmesg, text, name);
|
||||
DBWFeedbackAdd(&r, message, def,
|
||||
1, STYLE_PALEHIGHLIGHTS);
|
||||
|
|
@ -827,69 +959,6 @@ extFindDuplicateLabels(def, nreg)
|
|||
HashKill(&labelHash);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* extNodeName --
|
||||
*
|
||||
* Given a pointer to a LabRegion, return a pointer to a string
|
||||
* that can be printed as the name of the node. If the LabRegion
|
||||
* has a list of attached labels, use one of the labels; otherwise,
|
||||
* use its node number.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to a string. If the node had a label, this
|
||||
* is a pointer to the lab_text field of the first label on the
|
||||
* label list for the node; otherwise, it is a pointer to a static
|
||||
* buffer into which we have printed the node number.
|
||||
*
|
||||
* Side effects:
|
||||
* May overwrite the static buffer used to hold the printable
|
||||
* version of a node number.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
extNodeName(node)
|
||||
LabRegion *node;
|
||||
{
|
||||
static char namebuf[256]; /* Big enough to hold a generated nodename */
|
||||
LabelList *ll;
|
||||
|
||||
if (node == (LabRegion *) NULL || SigInterruptPending)
|
||||
return ("(none)");
|
||||
|
||||
for (ll = node->lreg_labels; ll; ll = ll->ll_next)
|
||||
if (extLabType(ll->ll_label->lab_text, LABTYPE_NAME))
|
||||
return (ll->ll_label->lab_text);
|
||||
|
||||
/* If the techfile specifies a global name for the substrate, use */
|
||||
/* that in preference to the default "p_x_y#" name. */
|
||||
|
||||
if (((NodeRegion *)node == glob_subsnode) || ((NodeRegion *)node == temp_subsnode))
|
||||
{
|
||||
if (ExtCurStyle->exts_globSubstrateName != NULL)
|
||||
{
|
||||
if (ExtCurStyle->exts_globSubstrateName[0] == '$' &&
|
||||
ExtCurStyle->exts_globSubstrateName[1] != '$')
|
||||
{
|
||||
// If subsName is a Tcl variable (begins with "$"), make the
|
||||
// variable substitution, if one exists. Ignore double-$.
|
||||
|
||||
char *varsub = (char *)Tcl_GetVar(magicinterp,
|
||||
&ExtCurStyle->exts_globSubstrateName[1],
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (varsub != NULL) ? varsub : ExtCurStyle->exts_globSubstrateName;
|
||||
}
|
||||
else
|
||||
return ExtCurStyle->exts_globSubstrateName;
|
||||
}
|
||||
}
|
||||
extMakeNodeNumPrint(namebuf, node->lreg_pnum, node->lreg_ll);
|
||||
return (namebuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
|||
|
|
@ -406,22 +406,7 @@ extHardGenerateLabel(scx, reg, arg)
|
|||
Rect r;
|
||||
Point p;
|
||||
|
||||
// Modification 9/9/2014 by Tim:
|
||||
// Convert the treg_ll value up to top-level coordinates.
|
||||
// Otherwise you end up with a node that is apparently in
|
||||
// "canonical coordinates", but if you try to find the
|
||||
// location of the node using the name, you'll end up in
|
||||
// a random place. It also allows the low-probability
|
||||
// but possible conflict between this node and another with
|
||||
// the same name in the parent cell.
|
||||
//
|
||||
// Reverted 10/30/2014: Apparently this causes worse
|
||||
// problems.
|
||||
//
|
||||
// GeoTransPoint(&scx->scx_trans, ®->treg_ll, &r.r_ll);
|
||||
// extMakeNodeNumPrint(gen, reg->treg_pnum, r.r_ll);
|
||||
|
||||
extMakeNodeNumPrint(gen, reg->treg_pnum, reg->treg_ll);
|
||||
extMakeNodeNumPrint(gen, (LabRegion *)reg);
|
||||
|
||||
prefixlen = tpath->tp_next - tpath->tp_first;
|
||||
len = strlen(gen) + prefixlen;
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ extMakeUnique(def, ll, lreg, lregList, labelHash, option)
|
|||
nwarn++;
|
||||
r.r_ll = r.r_ur = ll2->ll_label->lab_rect.r_ll;
|
||||
GEO_EXPAND(&r, 1, &r);
|
||||
extMakeNodeNumPrint(name, lp2->lreg_pnum, lp2->lreg_ll);
|
||||
extMakeNodeNumPrint(name, lp2);
|
||||
(void) sprintf(message, badmesg, text, name);
|
||||
DBWFeedbackAdd(&r, message, def, 1, STYLE_MEDIUMHIGHLIGHTS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,28 +239,6 @@ typedef struct {
|
|||
CapValue subcap_adjust;
|
||||
} SubCapAdjust;
|
||||
|
||||
/*
|
||||
* The following constructs a node name from the plane number 'n'
|
||||
* and lower left Point l, and places it in the string 's' (which must
|
||||
* be large enough).
|
||||
*/
|
||||
#define extMakeNodeNumPrint(buf, plane, coord) \
|
||||
(void) sprintf((buf), "%s_%s%d_%s%d#", DBPlaneShortName(plane), \
|
||||
((coord).p_x < 0) ? "n": "", abs((coord).p_x), \
|
||||
((coord).p_y < 0) ? "n": "", abs((coord).p_y))
|
||||
|
||||
/* Old way: cryptic numbers, but a bit shorter
|
||||
*
|
||||
* #define extMakeNodeNumPrint(s, n, l) \
|
||||
* (void) sprintf((s), "%d_%d_%d#", (n), extCoord((l).p_x), extCoord((l).p_y))
|
||||
*
|
||||
* The following is used to map the full coordinate space into
|
||||
* the positive integers, for constructing internally generated
|
||||
* node names.
|
||||
*
|
||||
* #define extCoord(x) (((x) < 0) ? (1 - ((x) << 1)) : ((x) << 1))
|
||||
*/
|
||||
|
||||
/*
|
||||
* Argument passed to filter functions for finding regions.
|
||||
*/
|
||||
|
|
@ -1076,6 +1054,7 @@ extern NodeRegion *extFindNodes();
|
|||
extern ExtTree *extHierNewOne();
|
||||
extern int extNbrPushFunc();
|
||||
extern TileType extGetDevType();
|
||||
extern void extMakeNodeNumPrint();
|
||||
|
||||
/* --------------------- Miscellaneous globals ------------------------ */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue