Extended the "lef" command to include a new option "lef nocheck"

to create a list of net names to ignore for antenna gate and
diffusion area checks.  This allows the nets not to have to be
selected in their entirity but selected by chunk only.  This
reduces the time to write LEF on a large layout back to approximately
what it was before the change to include the hidden area from "-hide"
in the antenna area checks.  Plus, it greatly reduces the time to
generate LEF for large layouts when not using the "-hide" option.
This commit is contained in:
Tim Edwards 2023-06-13 11:28:46 -04:00
parent 5300f322de
commit 31b3c0d8b4
4 changed files with 109 additions and 18 deletions

View File

@ -1 +1 @@
8.3.402
8.3.403

View File

@ -24,6 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "dbwind/dbwind.h"
#include "utils/main.h"
#include "utils/utils.h"
#include "utils/malloc.h"
#include "textio/txcommands.h"
#include "commands/commands.h"
@ -37,6 +38,9 @@ int lefDateStamp = -1; /* If not -1, defines the timestamp to use when creating
* libraries to make sure that full and abstract views of
* the same cell have matching timestamps.
*/
linkedNetName *lefIgnoreNets = NULL; /* Nets names to ignore for antenna area */
/*
* ----------------------------------------------------------------------------
*
@ -65,8 +69,9 @@ int lefDateStamp = -1; /* If not -1, defines the timestamp to use when creating
#define LEF_READ 0
#define LEF_WRITE 1
#define LEF_WRITEALL 2
#define LEF_DATESTAMP 3
#define LEF_HELP 4
#define LEF_NOCHECK 3
#define LEF_DATESTAMP 4
#define LEF_HELP 5
void
CmdLef(w, cmd)
@ -155,6 +160,7 @@ CmdLef(w, cmd)
" writeall -all recurse on all subcells of the top-level cell\n"
" writeall -hide hide all details other than ports\n"
" writeall -hide [dist] hide details in area set back distance dist",
"nocheck [netname ...] ignore antenna area checks on named net(s)",
"datestamp [value] force the timestamp of cells read from LEF",
"help print this help information",
NULL
@ -463,6 +469,73 @@ CmdLef(w, cmd)
}
break;
case LEF_NOCHECK:
if (!is_lef)
{
TxPrintf("The \"nocheck\" option is only for LEF writes.\n");
break;
}
if (cmd->tx_argc == 2)
{
#ifdef MAGIC_WRAPPER
if (lefIgnoreNets == NULL)
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj("none", -1));
else
{
Tcl_Obj *lobj;
linkedNetName *lnn;
lobj = Tcl_NewListObj(0, NULL);
for (lnn = lefIgnoreNets; lnn; lnn = lnn->lnn_next)
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(lnn->lnn_name, -1));
Tcl_SetObjResult(magicinterp, lobj);
}
#else
if (lefIgnoreNets == NULL)
TxPrintf("There are no net names being ignored.\n");
else
{
linkedNetName *lnn;
for (lnn = lefIgnoreNets; lnn; lnn = lnn->lnn_next)
TxPrintf("%s ", lnn->lnn_name);
TxPrintf("\n");
}
#endif
}
else
{
int i;
char *inet;
linkedNetName *lnn;
/* This is inefficient, but there should never be more than
* a few items in this list.
*/
for (i = 2; i < cmd->tx_argc; i++)
{
inet = cmd->tx_argv[i];
if (!strcasecmp(inet, "none"))
{
/* Remove all net names from the list */
for (lnn = lefIgnoreNets; lnn; lnn = lnn->lnn_next)
freeMagic(lnn);
lefIgnoreNets = NULL;
}
else
{
lnn = (linkedNetName *)mallocMagic(sizeof(linkedNetName));
lnn->lnn_name = StrDup((char **)NULL, inet);
lnn->lnn_next = lefIgnoreNets;
lefIgnoreNets = lnn;
}
}
}
break;
case LEF_HELP:
wrongNumArgs:
TxPrintf("The \"%s\" options are:\n", cmd->tx_argv[0]);

View File

@ -127,10 +127,17 @@ typedef struct {
bool has_nets;
} NetCount;
/* Linked string structure used to maintain list of nets to ignore */
typedef struct _linkedNetName {
char *lnn_name;
struct _linkedNetName *lnn_next;
} linkedNetName;
/* External declaration of global variables */
extern int lefCurrentLine;
extern HashTable LefInfo;
extern HashTable LefNonDefaultRules;
extern linkedNetName *lefIgnoreNets;
/* Forward declarations */

View File

@ -1416,6 +1416,8 @@ lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster)
while (lab != NULL)
{
int antgatearea, antdiffarea;
linkedNetName *lnn;
bool ignored;
labr = lab->lab_rect;
@ -1440,7 +1442,14 @@ lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster)
scx.scx_area = labr;
SelectClear();
SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
// Check for net names to ignore for antenna checks.
ignored = FALSE;
for (lnn = lefIgnoreNets; lnn; lnn = lnn->lnn_next)
if (!strcmp(lnn->lnn_name, lab->lab_text))
ignored = TRUE;
if (!ignored || (setback != 0))
SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
// Search for gate and diff types and accumulate antenna
// areas. For gates, check for all gate types tied to
@ -1449,26 +1458,28 @@ lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster)
// statement in the extract section of the techfile.
antgatearea = 0;
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
if (!ignored)
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
&TiPlaneRect, &gatetypemask,
lefAccumulateArea, (ClientData) &antgatearea);
// Stop after first plane with geometry to avoid double-counting
// contacts.
if (antgatearea > 0) break;
}
// Stop after first plane with geometry to avoid double-counting
// contacts.
if (antgatearea > 0) break;
}
antdiffarea = 0;
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
if (!ignored)
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
&TiPlaneRect, &difftypemask,
lefAccumulateArea, (ClientData) &antdiffarea);
// Stop after first plane with geometry to avoid double-counting
// contacts.
if (antdiffarea > 0) break;
}
// Stop after first plane with geometry to avoid double-counting
// contacts.
if (antdiffarea > 0) break;
}
if (setback == 0)
{