Added a "lef datestamp" command option which is the equivalent of

"gds datestamp" for LEF reads.  When set to non-default, all cell
definitions created from LEF macros will be given the specified
timestamp, which allows the stamps of abstract views to match the
stamps of full views, preventing issues of updated timestamps
whenever a layout is switched between views.
This commit is contained in:
Tim Edwards 2022-01-22 13:02:47 -05:00
parent 416b604eff
commit 81ecdbf209
4 changed files with 80 additions and 8 deletions

View File

@ -70,6 +70,13 @@ LEF-format input and output
itself would be written to a DEF file. <BR>
Options <B>-hide</B>, <B>-tech</B>, and <B>-toplayer</B> are
the same as for the <B>lef write</B> command.
<DT> <B>datestamp</B> [<I>value</I>|<B>default</B>]
<DD> Force all cell definitions generated from LEF macros to have
the datestamp (timestamp) of <I>value</I>. This can be used to
ensure that the timestamps of abstract views match the timestamps
of the equivalent full views, so that switching between abstract
and full views does not cause timestamp mismatch handling. The
string <B>default</B> cancels any fixed timestamps.
<DT> <B>help</B>
<DD> Print help information
</DL>

View File

@ -1597,6 +1597,7 @@ DefReadComponents(f, rootDef, sname, oscale, total)
defMacro = DBCellNewDef(token);
defMacro->cd_flags &= ~CDNOTFOUND;
dereference = (defMacro->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(defMacro, (char *)NULL, TRUE, dereference, NULL))
{
LefError(DEF_ERROR, "Cell %s is not defined. Maybe you "

View File

@ -12,6 +12,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
@ -26,7 +27,13 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "textio/txcommands.h"
#include "commands/commands.h"
int *lefDateStamp = NULL; /* If non-NULL, defines the timestamp
* to use when creating new cell defs
* from LEF or DEF. Useful when generating
* libraries to make sure that full and
* abstract views of the same cell have
* matching timestamps.
*/
/*
* ----------------------------------------------------------------------------
*
@ -55,7 +62,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#define LEF_READ 0
#define LEF_WRITE 1
#define LEF_WRITEALL 2
#define LEF_HELP 3
#define LEF_DATESTAMP 3
#define LEF_HELP 4
void
CmdLef(w, cmd)
@ -113,7 +121,6 @@ CmdLef(w, cmd)
* center of the first rectangle
* found on that net.
*/
static char *cmdLefOption[] =
{
"read [filename] read a LEF file filename[.lef]\n"
@ -127,6 +134,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",
"datestamp [value] force the timestamp of cells read from LEF",
"help print this help information",
NULL
};
@ -208,9 +216,9 @@ CmdLef(w, cmd)
namep = cmd->tx_argv[2];
if (is_lef)
LefRead(namep, lefImport, lefAnnotate);
LefRead(namep, lefImport, lefAnnotate, lefDateStamp);
else
DefRead(namep, defLabelNets);
DefRead(namep, defLabelNets, lefDateStamp);
break;
case LEF_WRITEALL:
if (!is_lef)
@ -375,6 +383,53 @@ CmdLef(w, cmd)
== EditRootDef, lefTech, lefHide, lefPinOnly,
lefTopLayer, lefDoMaster);
break;
case LEF_DATESTAMP:
if (!is_lef)
{
TxPrintf("The \"datestamp\" option is only for LEF reads.\n");
break;
}
if (cmd->tx_argc == 2)
{
#ifdef MAGIC_WRAPPER
if (lefDateStamp != NULL)
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(*lefDateStamp));
else
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj("default", -1));
#else
if (lefDateStamp != NULL)
TxPrintf("Macros will contain a header creation date "
"stamp of %d.\n", *lefDateStamp);
else
TxPrintf("Macros will contain a default header creation date "
"stamp.\n");
#endif
return;
}
else if (cmd->tx_argc != 3)
goto wrongNumArgs;
if (!strcmp(cmd->tx_argv[2], "default"))
{
if (lefDateStamp != NULL)
{
freeMagic((char *)lefDateStamp);
lefDateStamp = NULL;
}
}
else if (StrIsInt(cmd->tx_argv[2]))
{
if (lefDateStamp == NULL)
lefDateStamp = (int *)mallocMagic(sizeof(int));
*lefDateStamp = atoi(cmd->tx_argv[2]);
}
else
{
TxError("Unrecognizable date stamp \"%s\".\n", cmd->tx_argv[2]);
goto wrongNumArgs;
}
break;
case LEF_HELP:
wrongNumArgs:
TxPrintf("The \"%s\" options are:\n", cmd->tx_argv[0]);

View File

@ -1719,7 +1719,7 @@ enum lef_macro_keys {LEF_CLASS = 0, LEF_SIZE, LEF_ORIGIN,
LEF_TIMING, LEF_FOREIGN, LEF_PROPERTY, LEF_MACRO_END};
void
LefReadMacro(f, mname, oscale, importForeign, doAnnotate)
LefReadMacro(f, mname, oscale, importForeign, doAnnotate, lefTimestamp)
FILE *f; /* LEF file being read */
char *mname; /* name of the macro */
float oscale; /* scale factor um->magic units */
@ -1729,6 +1729,9 @@ LefReadMacro(f, mname, oscale, importForeign, doAnnotate)
bool doAnnotate; /* If true, ignore all macros that are
* not already CellDefs.
*/
int *lefTimestamp; /* If non-NULL, use the value pointed to
* as the CellDef's timestamp.
*/
{
CellDef *lefMacro;
HashEntry *he;
@ -1802,6 +1805,11 @@ LefReadMacro(f, mname, oscale, importForeign, doAnnotate)
else
is_imported = TRUE;
}
if (lefTimestamp != NULL)
{
lefMacro->cd_timestamp = *lefTimestamp;
lefMacro->cd_flags = CDFIXEDSTAMP;
}
/* Initial values */
pinNum = 1;
@ -2523,10 +2531,11 @@ enum lef_sections {LEF_VERSION = 0,
LEF_END};
void
LefRead(inName, importForeign, doAnnotate)
LefRead(inName, importForeign, doAnnotate, lefTimestamp)
char *inName;
bool importForeign;
bool doAnnotate;
int *lefTimestamp;
{
FILE *f;
char *filename;
@ -2751,7 +2760,7 @@ LefRead(inName, importForeign, doAnnotate)
TxPrintf("LEF file: Defines new cell %s\n", token);
*/
sprintf(tsave, "%.127s", token);
LefReadMacro(f, tsave, oscale, importForeign, doAnnotate);
LefReadMacro(f, tsave, oscale, importForeign, doAnnotate, lefTimestamp);
break;
case LEF_END:
if (LefParseEndStatement(f, "LIBRARY") == 0)