274 lines
6.8 KiB
C
274 lines
6.8 KiB
C
/*
|
||
* lefCmd.c --
|
||
*
|
||
* Commands for the LEF module only.
|
||
*
|
||
*/
|
||
|
||
#ifndef lint
|
||
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/lefCmd.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
||
#endif /* not lint */
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
#include "tcltk/tclmagic.h"
|
||
#include "utils/magic.h"
|
||
#include "utils/geometry.h"
|
||
#include "tiles/tile.h"
|
||
#include "utils/hash.h"
|
||
#include "database/database.h"
|
||
#include "windows/windows.h"
|
||
#include "dbwind/dbwind.h"
|
||
#include "utils/main.h"
|
||
#include "textio/txcommands.h"
|
||
#include "commands/commands.h"
|
||
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* CmdLef --
|
||
*
|
||
* Implement the "lef" and "def" commands: generate LEF-format output
|
||
* for a layout, or read LEF- or DEF-format files.
|
||
*
|
||
* Usage:
|
||
* lef [options]
|
||
* def [options]
|
||
*
|
||
* Results:
|
||
* Always return 0.
|
||
*
|
||
* Side effects:
|
||
* Generates LEF-format output on disk somewhere, or reads
|
||
* LEF- or DEF-format files, generating cell definitions and
|
||
* uses in the process.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
/* These definitions must correspond to the ordering in cmdLefOption[] below */
|
||
|
||
#define LEF_READ 0
|
||
#define LEF_WRITE 1
|
||
#define LEF_WRITEALL 2
|
||
#define LEF_HELP 3
|
||
|
||
void
|
||
CmdLef(w, cmd)
|
||
MagWindow *w;
|
||
TxCommand *cmd;
|
||
{
|
||
int option, i, cargs, units = 1000; /* Default nanometers */
|
||
char **msg, *namep;
|
||
CellUse *selectedUse;
|
||
CellDef *selectedDef;
|
||
bool is_lef;
|
||
bool lefImport = FALSE; /* Indicates whether or not we
|
||
* read cells from .mag files
|
||
* when the FOREIGN statement
|
||
* is encountered in a macro.
|
||
*/
|
||
bool lefTopCell = TRUE; /* Indicates whether or not we
|
||
* write the top-level cell to
|
||
* LEF, or just the subcells.
|
||
*/
|
||
bool allSpecial = FALSE; /* Indicates whether we should
|
||
* treat all geometry as "special"
|
||
* nets in DEF format output.
|
||
*/
|
||
bool lefTech = FALSE; /* Indicates that technology info
|
||
* will be output along with the
|
||
* lef macro.
|
||
*/
|
||
bool lefHide = FALSE; /* If TRUE, hide all details of
|
||
* the macro other than pin area
|
||
* immediately surrounding labels.
|
||
*/
|
||
|
||
static char *cmdLefOption[] =
|
||
{
|
||
"read [filename] read a LEF file filename[.lef]\n"
|
||
" read [filename] -import read a LEF file; import cells from .mag files",
|
||
"write [filename] [-tech] write LEF for current cell\n"
|
||
" write [filename] -hide hide all details other than ports",
|
||
"writeall write all cells including the top-level cell\n"
|
||
" writeall -notop write all subcells of the top-level cell",
|
||
"help print this help information",
|
||
NULL
|
||
};
|
||
|
||
static char *cmdDefOption[] =
|
||
{
|
||
"read [filename] read a DEF file filename[.def]",
|
||
"write [cell] [-allspecial] write DEF for current or indicated cell",
|
||
"writeall (use \"flatten -nosubckt\" + \"def"
|
||
" write\" instead)",
|
||
"help print this help information",
|
||
NULL
|
||
};
|
||
|
||
/* Determine whether this function has been called via the "lef" or
|
||
* the "def" command.
|
||
*/
|
||
is_lef = (cmd->tx_argv[0][0] == 'd') ? FALSE : TRUE;
|
||
|
||
if (cmd->tx_argc < 2)
|
||
option = LEF_HELP;
|
||
else
|
||
{
|
||
option = Lookup(cmd->tx_argv[1], cmdLefOption);
|
||
if (option < 0)
|
||
{
|
||
TxError("\"%s\" isn't a valid %s option.\n", cmd->tx_argv[1],
|
||
cmd->tx_argv[0]);
|
||
option = LEF_HELP;
|
||
}
|
||
}
|
||
|
||
if (option != LEF_HELP)
|
||
{
|
||
selectedUse = CmdGetSelectedCell((Transform *)NULL);
|
||
if (selectedUse == NULL)
|
||
{
|
||
windCheckOnlyWindow(&w, DBWclientID);
|
||
if (w == (MagWindow *) NULL)
|
||
{
|
||
if (ToolGetBox(&selectedDef,NULL) == FALSE)
|
||
{
|
||
TxError("Point to a window first\n");
|
||
return;
|
||
}
|
||
selectedUse = selectedDef->cd_parents;
|
||
}
|
||
else
|
||
selectedUse = (CellUse *)w->w_surfaceID;
|
||
}
|
||
}
|
||
|
||
switch (option)
|
||
{
|
||
case LEF_READ:
|
||
if (cmd->tx_argc != 3)
|
||
{
|
||
if (cmd->tx_argc == 4)
|
||
{
|
||
if (*(cmd->tx_argv[3]) == '-')
|
||
if (!strncmp(cmd->tx_argv[3], "-import", 7))
|
||
lefImport = TRUE;
|
||
}
|
||
else
|
||
goto wrongNumArgs;
|
||
}
|
||
namep = cmd->tx_argv[2];
|
||
if (is_lef)
|
||
LefRead(namep, lefImport);
|
||
else
|
||
DefRead(namep);
|
||
break;
|
||
case LEF_WRITEALL:
|
||
if (!is_lef)
|
||
{
|
||
TxError("Sorry, can't write hierarchical DEF at this time.\n");
|
||
TxError("Try \"def write\"\n");
|
||
}
|
||
else
|
||
{
|
||
for (i = 2; i < cmd->tx_argc; i++)
|
||
{
|
||
if (*(cmd->tx_argv[i]) == '-')
|
||
{
|
||
if (!strncmp(cmd->tx_argv[i], "-notop", 6))
|
||
lefTopCell = FALSE;
|
||
else if (!strncmp(cmd->tx_argv[i], "-tech", 5))
|
||
lefTech = TRUE;
|
||
else goto wrongNumArgs;
|
||
}
|
||
else goto wrongNumArgs;
|
||
}
|
||
LefWriteAll(selectedUse, lefTopCell, lefTech);
|
||
}
|
||
break;
|
||
case LEF_WRITE:
|
||
allSpecial = FALSE;
|
||
cargs = cmd->tx_argc;
|
||
for (i = 2; i < cmd->tx_argc; i++)
|
||
{
|
||
if (*(cmd->tx_argv[i]) == '-')
|
||
{
|
||
if (!strncmp(cmd->tx_argv[i], "-allspec", 8))
|
||
{
|
||
if (!is_lef)
|
||
allSpecial = TRUE;
|
||
else
|
||
TxPrintf("The \"-allspec\" option is only for def write\n");
|
||
}
|
||
else if (!strncmp(cmd->tx_argv[i], "-tech", 5))
|
||
{
|
||
if (is_lef)
|
||
lefTech = TRUE;
|
||
else
|
||
TxPrintf("The \"-tech\" option is only for lef write\n");
|
||
}
|
||
else if (!strncmp(cmd->tx_argv[i], "-hide", 5))
|
||
{
|
||
if (is_lef)
|
||
lefHide = TRUE;
|
||
else
|
||
TxPrintf("The \"-hide\" option is only for lef write\n");
|
||
}
|
||
else if (!strncmp(cmd->tx_argv[i], "-units", 5))
|
||
{
|
||
if (is_lef)
|
||
TxPrintf("The \"-units\" option is only for def write\n");
|
||
else
|
||
{
|
||
i++;
|
||
cargs--;
|
||
if ((cmd->tx_argc < i) || (!StrIsInt(cmd->tx_argv[i])))
|
||
{
|
||
TxPrintf("The \"-units\" option requires an argument.\n");
|
||
}
|
||
else
|
||
{
|
||
units = atoi(cmd->tx_argv[i]);
|
||
// To do: Check range of units
|
||
}
|
||
}
|
||
}
|
||
else goto wrongNumArgs;
|
||
cargs--;
|
||
}
|
||
else if (i != 2) /* Is argument a filename? */
|
||
goto wrongNumArgs;
|
||
}
|
||
if (cargs != 2 && cargs != 3) goto wrongNumArgs;
|
||
if (selectedUse == NULL)
|
||
{
|
||
TxError("No cell selected\n");
|
||
return;
|
||
}
|
||
if (cargs == 2)
|
||
namep = selectedUse->cu_def->cd_name;
|
||
else
|
||
namep = cmd->tx_argv[2];
|
||
if (!is_lef)
|
||
DefWriteCell(selectedUse->cu_def, namep, allSpecial, units);
|
||
else
|
||
LefWriteCell(selectedUse->cu_def, namep, selectedUse->cu_def
|
||
== EditRootDef, lefTech, lefHide);
|
||
break;
|
||
case LEF_HELP:
|
||
wrongNumArgs:
|
||
TxPrintf("The \"%s\" options are:\n", cmd->tx_argv[0]);
|
||
msg = (is_lef) ? &(cmdLefOption[0]) : &(cmdDefOption[0]);
|
||
for (; *msg != NULL; msg++)
|
||
{
|
||
TxPrintf(" %s %s\n", cmd->tx_argv[0], *msg);
|
||
}
|
||
break;
|
||
}
|
||
}
|