Added two new features: (1) Default substrate name: Added an

optional name field to the "substrate" line in the extract section
of the techfile.  This is the default name of the substrate if not
connected to anything labeled.  It may use a Tcl variable (preferred).
(2) Added command option "instance orientation [-def]" that returns
the orientation of the named or selected instance.  The -def option
returns the orientation using DEF naming convention;  otherwise, the
naming used with "getcell" is generated.
This commit is contained in:
Tim Edwards 2020-06-01 16:49:59 -04:00
parent 336a7aa209
commit 15f1c82bc9
7 changed files with 294 additions and 13 deletions

View File

@ -1 +1 @@
8.3.19
8.3.20

View File

@ -579,6 +579,8 @@ outputCalma:
* cellname [list] filepath [path|"default"]
* or
* cellname property [name] [property_key [property_value]]
* or
* instance orientation [name] [-def]
*
* Results:
* None.
@ -597,7 +599,9 @@ CmdCellname(w, cmd)
MagWindow *w;
TxCommand *cmd;
{
bool is_cellname;
bool dolist = FALSE;
bool dodef = FALSE;
int option;
int locargc = cmd->tx_argc;
char *cellname = NULL;
@ -623,6 +627,7 @@ CmdCellname(w, cmd)
"lock lock the named cell (prevent changes to cell use)",
"unlock unlock the named cell (allow changes to cell use)",
"property list or set cell definition properties",
"orientation list or set instance orientation",
"rename rename the indicated cell",
"writeable make the cell definition read-only or read-write",
"modified true if modified, false if not",
@ -632,13 +637,15 @@ CmdCellname(w, cmd)
IDX_INSTANCE, IDX_CHILDINST, IDX_CELLDEF, IDX_ALLCELLS,
IDX_TOPCELLS, IDX_IN_WINDOW, IDX_CREATE,
IDX_DELETE, IDX_FILEPATH, IDX_FLAGS, IDX_LOCK, IDX_UNLOCK,
IDX_PROPERTY, IDX_RENAME, IDX_READWRITE,
IDX_MODIFIED } optionType;
IDX_PROPERTY, IDX_ORIENTATION, IDX_RENAME,
IDX_READWRITE, IDX_MODIFIED } optionType;
if (strstr(cmd->tx_argv[0], "in"))
func = DBUsePrint;
is_cellname = FALSE;
else
func = DBCellPrint;
is_cellname = TRUE;
func = (is_cellname) ? DBCellPrint : DBUsePrint;
if (locargc > 1)
{
@ -647,6 +654,21 @@ CmdCellname(w, cmd)
locargc--;
}
}
/* Check for option at end of option list */
if (*cmd->tx_argv[cmd->tx_argc - 1] == '-') {
char *option = cmd->tx_argv[cmd->tx_argc - 1] + 1;
if (!strcmp(option, "list")) {
dolist = TRUE;
locargc--;
}
else if (!strcmp(option, "def")) {
dodef = TRUE;
locargc--;
}
}
if (locargc > 5 || locargc < 2) goto badusage;
option = Lookup(cmd->tx_argv[1 + ((dolist) ? 1 : 0)], cmdCellOption);
@ -672,7 +694,7 @@ CmdCellname(w, cmd)
}
}
if (func != DBUsePrint)
if (is_cellname)
{
/* These functions only work with cell uses (instances) */
switch (option) {
@ -681,6 +703,10 @@ CmdCellname(w, cmd)
TxError("Cell definitions cannot be locked. Use \"instance\"?\n");
TxError(" or do you mean \"cellname writeable\"?\n");
return;
case IDX_ORIENTATION:
TxError("Cell definitions do not have orientations."
" Use \"instance\"?\n");
return;
}
}
else
@ -721,16 +747,16 @@ CmdCellname(w, cmd)
(*func)(cellname, SELF, dolist);
break;
case IDX_CELLDEF:
(*func)(cellname, ((func == DBUsePrint) ? OTHER : SELF), dolist);
(*func)(cellname, ((is_cellname == FALSE) ? OTHER : SELF), dolist);
break;
case IDX_INSTANCE:
(*func)(cellname, ((func == DBUsePrint) ? SELF : OTHER), dolist);
(*func)(cellname, ((is_cellname == FALSE) ? SELF : OTHER), dolist);
break;
case IDX_CHILDREN:
(*func)(cellname, CHILDREN, dolist);
break;
case IDX_CHILDINST:
(*func)(cellname, ((func == DBUsePrint) ? CHILDREN : CHILDINST), dolist);
(*func)(cellname, ((is_cellname == FALSE) ? CHILDREN : CHILDINST), dolist);
break;
case IDX_PARENTS:
(*func)(cellname, PARENTS, dolist);
@ -958,6 +984,9 @@ CmdCellname(w, cmd)
DBCellSetAvail(newDef);
}
break;
case IDX_ORIENTATION:
DBOrientUse(cellname, dodef);
break;
case IDX_LOCK:
DBLockUse(cellname, TRUE);
break;

View File

@ -1154,7 +1154,7 @@ DBLockUse(UseName, bval)
CellDef *celldef;
CellUse *celluse;
int dbUseLockFunc();
int dbLockUseFunc();
/*
*
@ -1199,6 +1199,169 @@ DBLockUse(UseName, bval)
}
}
/*
* ----------------------------------------------------------------------------
*
* DBOrientUse --
*
* This routine sets or reports a cell instance's orientation
* UseName is the name of a specific CellUse. If NULL, then the
* operation applies to all selected cell uses. "orient" is a
* string in the form used by "getcell" (e.g., "180", "270v",
* etc.), unless "dodef" is true, in which case the output is
* given in the form used by DEF ("N", "FN", etc.).
* reported.
*
* Results:
* None.
*
* Side effects:
* cu_transform changed for indicated cell use.
*
* ----------------------------------------------------------------------------
*/
void
DBOrientUse(UseName, dodef)
char *UseName;
bool dodef;
{
int found;
HashSearch hs;
HashEntry *entry;
CellDef *celldef;
CellUse *celluse;
int dbOrientUseFunc();
/*
*
* Check to see if a cell name was specified. If not, then search
* for selected cells.
*
*/
if (UseName == NULL)
{
if (EditCellUse == NULL)
TxError("Cannot set orientation of a non-edit cell!\n");
else
SelEnumCells(TRUE, (int *)NULL, (SearchContext *)NULL,
dbOrientUseFunc, (ClientData)&dodef);
}
else
{
SearchContext scx;
bzero(&scx, sizeof(SearchContext));
found = 0;
HashStartSearch(&hs);
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
celldef = (CellDef *) HashGetValue(entry);
if (celldef != (CellDef *) NULL)
{
celluse = celldef->cd_parents; /* only need one */
if (celluse != (CellUse *)NULL) {
DBTreeFindUse(UseName, celluse, &scx);
if (scx.scx_use != NULL) break;
}
}
}
if (scx.scx_use == NULL)
TxError("Cell %s is not currently loaded.\n", UseName);
else
dbOrientUseFunc(NULL, scx.scx_use, NULL, (ClientData)&dodef);
}
}
/*
* dbOrientUseFunc()
*/
/* For corresponding enumerations, see GeoTransOrient() */
enum def_orient {ORIENT_NORTH, ORIENT_SOUTH, ORIENT_EAST, ORIENT_WEST,
ORIENT_FLIPPED_NORTH, ORIENT_FLIPPED_SOUTH, ORIENT_FLIPPED_EAST,
ORIENT_FLIPPED_WEST};
int
dbOrientUseFunc(selUse, use, transform, data)
CellUse *selUse; /* Use from selection cell */
CellUse *use; /* Use from layout corresponding to selection */
Transform *transform;
ClientData data;
{
bool *dodef = (bool *)data;
if (EditCellUse && !DBIsChild(use, EditCellUse))
{
TxError("Cell %s (%s) isn't a child of the edit cell.\n",
use->cu_id, use->cu_def->cd_name);
return 0;
}
if (selUse != NULL)
{
switch (GeoTransOrient(&selUse->cu_transform)) {
#ifdef MAGIC_WRAPPER
case ORIENT_NORTH:
Tcl_AppendElement(magicinterp, (*dodef) ? "N" : "0");
break;
case ORIENT_EAST:
Tcl_AppendElement(magicinterp, (*dodef) ? "E" : "90");
break;
case ORIENT_SOUTH:
Tcl_AppendElement(magicinterp, (*dodef) ? "S" : "180");
break;
case ORIENT_WEST:
Tcl_AppendElement(magicinterp, (*dodef) ? "W" : "270");
break;
case ORIENT_FLIPPED_NORTH:
Tcl_AppendElement(magicinterp, (*dodef) ? "FN" : "0h");
break;
case ORIENT_FLIPPED_EAST:
Tcl_AppendElement(magicinterp, (*dodef) ? "FE" : "90h");
break;
case ORIENT_FLIPPED_SOUTH:
Tcl_AppendElement(magicinterp, (*dodef) ? "FS" : "180h");
break;
case ORIENT_FLIPPED_WEST:
Tcl_AppendElement(magicinterp, (*dodef) ? "FW" : "270h");
break;
#else
case ORIENT_NORTH:
TxPrintf((*dodef) ? "N" : "0");
break;
case ORIENT_EAST:
TxPrintf((*dodef) ? "E" : "90");
break;
case ORIENT_SOUTH:
TxPrintf((*dodef) ? "S" : "180");
break;
case ORIENT_WEST:
TxPrintf((*dodef) ? "W" : "270");
break;
case ORIENT_FLIPPED_NORTH:
TxPrintf((*dodef) ? "FN" : "0h");
break;
case ORIENT_FLIPPED_EAST:
TxPrintf((*dodef) ? "FE" : "90h");
break;
case ORIENT_FLIPPED_SOUTH:
TxPrintf((*dodef) ? "FS" : "180h");
break;
case ORIENT_FLIPPED_WEST:
TxPrintf((*dodef) ? "FW" : "270h");
break;
#endif
}
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -772,6 +772,9 @@ extern int DBCellSrDefs();
extern CellUse *DBCellNewUse();
extern bool DBCellDeleteUse();
extern CellUse *DBCellFindDup();
extern void DBLockUse();
extern void DBUnlockUse();
extern void DBOrientUse();
/* Cell selection */
extern CellUse *DBSelectCell();

View File

@ -321,7 +321,7 @@ extBasic(def, outFile)
/* Output each node, along with its resistance and capacitance to substrate */
if (!SigInterruptPending)
extOutputNodes(nodeList, outFile);
extOutputNodes(nodeList, outFile, glob_subsnode);
/* Output coupling capacitances */
if (!SigInterruptPending && (ExtOptions&EXT_DOCOUPLING) && (!propfound))
@ -862,6 +862,28 @@ extNodeName(node)
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)
{
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);
}

View File

@ -166,8 +166,8 @@ static keydesc keyTable[] = {
"style", STYLE, 2, 4,
"stylename",
"substrate", SUBSTRATE, 3, 4,
"types plane",
"substrate", SUBSTRATE, 3, 5,
"types plane [subs-node]",
"units", UNITS, 2, 2,
"lambda|microns",
@ -786,6 +786,7 @@ extTechStyleInit(style)
style->exts_globSubstratePlane = -1;
TTMaskZero(&style->exts_globSubstrateTypes);
TTMaskZero(&style->exts_globSubstrateShieldTypes);
style->exts_globSubstrateName = (char *)NULL;
}
@ -2834,6 +2835,11 @@ ExtTechLine(sectionName, argc, argv)
TTMaskSetMask(&ExtCurStyle->exts_globSubstrateTypes, &types1);
ExtCurStyle->exts_globSubstrateShieldTypes = idTypes;
ExtCurStyle->exts_globSubstratePlane = DBTechNoisyNamePlane(argv[2]);
/* Handle optional substrate node name */
if (argc == 4)
ExtCurStyle->exts_globSubstrateName = StrDup((char **)NULL, argv[3]);
break;
case NOPLANEORDER: {
if ( ExtCurStyle->exts_planeOrderStatus == seenPlaneOrder )

View File

@ -530,6 +530,64 @@ GeoTransPos(t, pos)
return pos;
}
/*-------------------------------------------------------------------
* GeoTransOrient --
* This routine returns the orientation corresponding to a transform.
*
* Results:
* The return value is an orientation as defined by the enumeration
* below (which is also used by the LEF read routine). It has to
* agree with the enumeration used by dbOrientUseFunc.
*
* Side Effects: None.
*-------------------------------------------------------------------
*/
enum def_orient {ORIENT_NORTH, ORIENT_SOUTH, ORIENT_EAST, ORIENT_WEST,
ORIENT_FLIPPED_NORTH, ORIENT_FLIPPED_SOUTH, ORIENT_FLIPPED_EAST,
ORIENT_FLIPPED_WEST};
int
GeoTransOrient(t)
Transform *t; /* Transform to be applied. */
{
int pidx;
if ((t->t_b == 0) && (t->t_d == 0))
{
pidx = ((t->t_a) > 0) ? 1 : 0;
pidx += ((t->t_e) > 0) ? 2 : 0;
switch (pidx) {
case 0:
return ORIENT_SOUTH;
case 1:
return ORIENT_FLIPPED_SOUTH;
case 2:
return ORIENT_FLIPPED_NORTH;
case 3:
return ORIENT_NORTH;
}
}
else if ((t->t_a == 0) && (t->t_e == 0))
{
pidx = ((t->t_b) > 0) ? 1 : 0;
pidx += ((t->t_d) > 0) ? 2 : 0;
switch (pidx) {
case 0:
return ORIENT_FLIPPED_EAST;
case 1:
return ORIENT_EAST;
case 2:
return ORIENT_WEST;
case 3:
return ORIENT_FLIPPED_WEST;
}
}
}
/*-------------------------------------------------------------------
* GeoInvertTrans --