/* * 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 #include #include #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; } }