Implemented more automation for attempting to find a tech file
based on the contents of a .mag file being read in, assuming compatibility with principles of open_pdks. The search paths are not meddled with unless a file is read for which the technology cannot be found (and a technology has not already been read, or at least no database file exists in memory using any technology that has already been read). If so, then variables PDK_PATH and PDK_ROOT are searched for in both the shell environment and the local Tcl environment. Also, if open_pdks has installed PDKs in the path /usr/share/pdk/, then that path will be searched. If a corresponding technology file is found, it will be loaded. If the path corresponds to an open_pdks-style path, then the library paths in libs.ref will also be added to the search paths for cells.
This commit is contained in:
parent
2bb3580f3e
commit
114b9a59f7
249
database/DBio.c
249
database/DBio.c
|
|
@ -135,6 +135,132 @@ file_is_not_writeable(name)
|
|||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBSearchForTech --
|
||||
*
|
||||
* Helper function for automatically discovering a technology used in a
|
||||
* .mag file when reading. This function will recursively search all
|
||||
* directories rooted at "pathroot" looking for a file "techname" which
|
||||
* must include the ".tech" extension. If found, the path name is returned.
|
||||
*
|
||||
* Results:
|
||||
* Pointer to a string containing the path name. This is allocated so as
|
||||
* not to be lost, and must be freed by the caller.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char *
|
||||
DBSearchForTech(techname, pathroot, level)
|
||||
char *techname;
|
||||
char *pathroot;
|
||||
int level;
|
||||
{
|
||||
char *newpath, *found;
|
||||
struct dirent *tdent;
|
||||
DIR *tdir;
|
||||
|
||||
/* Avoid potential infinite looping. Any tech file should not be very */
|
||||
/* far down the path. 10 levels is already excessive. */
|
||||
if (level > 10) return NULL;
|
||||
|
||||
tdir = opendir(pathroot);
|
||||
if (tdir) {
|
||||
|
||||
/* Read the directory contents of tdir */
|
||||
while ((tdent = readdir(tdir)) != NULL)
|
||||
{
|
||||
if (tdent->d_type != DT_DIR)
|
||||
{
|
||||
if (!strcmp(tdent->d_name, techname))
|
||||
return pathroot;
|
||||
}
|
||||
else if (strcmp(tdent->d_name, ".") && strcmp(tdent->d_name, ".."))
|
||||
{
|
||||
newpath = mallocMagic(strlen(pathroot) + strlen(tdent->d_name) + 3);
|
||||
sprintf(newpath, "%s/%s", pathroot, tdent->d_name);
|
||||
found = DBSearchForTech(techname, newpath, level + 1);
|
||||
if (found != newpath) freeMagic(newpath);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
closedir(tdir);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBAddStandardCellPaths --
|
||||
*
|
||||
* Search for .mag files in any directory below "pathptr", for any
|
||||
* directory found containing .mag files, add that path to the search
|
||||
* path for cells.
|
||||
*
|
||||
* Results:
|
||||
* Number of paths added to CellLibPath.
|
||||
*
|
||||
* Side effects:
|
||||
* May add paths to the CellLibPath.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
DBAddStandardCellPaths(pathptr, level)
|
||||
char *pathptr;
|
||||
int level;
|
||||
{
|
||||
int paths = 0;
|
||||
struct dirent *tdent;
|
||||
char *newpath;
|
||||
DIR *tdir;
|
||||
bool magfound = FALSE;
|
||||
|
||||
/* Avoid potential infinite looping. Any tech file should not be very */
|
||||
/* far down the path. 10 levels is already excessive. */
|
||||
if (level > 10) return 0;
|
||||
|
||||
tdir = opendir(pathptr);
|
||||
if (tdir) {
|
||||
|
||||
while ((tdent = readdir(tdir)) != NULL)
|
||||
{
|
||||
if ((tdent->d_type == DT_DIR) &&
|
||||
(strcmp(tdent->d_name, ".") && strcmp(tdent->d_name, "..")))
|
||||
{
|
||||
/* Scan the directory contents of tdir for more subdirectories */
|
||||
newpath = mallocMagic(strlen(pathptr) + strlen(tdent->d_name) + 3);
|
||||
sprintf(newpath, "%s/%s", pathptr, tdent->d_name);
|
||||
paths += DBAddStandardCellPaths(newpath, level + 1);
|
||||
freeMagic(newpath);
|
||||
}
|
||||
else if (tdent->d_type != DT_DIR)
|
||||
{
|
||||
/* Scan the directory contents of tdir for .mag files */
|
||||
if (!strcmp(tdent->d_name + strlen(tdent->d_name) - 4, ".mag"))
|
||||
{
|
||||
if (magfound == FALSE)
|
||||
{
|
||||
PaAppend(&CellLibPath, pathptr);
|
||||
paths++;
|
||||
magfound = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(tdir);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -335,13 +461,122 @@ dbCellReadDef(f, cellDef, name, ignoreTech, dereference)
|
|||
TxPrintf("Will attempt to read cell anyway.\n");
|
||||
else
|
||||
{
|
||||
TxError("Use command \"tech load\" if you want to switch"
|
||||
" technologies, or use\n");
|
||||
TxError("\"cellname delete %s\" and \"load %s -force\" to"
|
||||
" force the cell to load as technology %s\n",
|
||||
cellDef->cd_name, cellDef->cd_name, DBTechName);
|
||||
SigEnableInterrupts();
|
||||
return (FALSE);
|
||||
/* If no cells are currently in memory, then make an
|
||||
* attempt to find the technology associated with the
|
||||
* layout and load it.
|
||||
*/
|
||||
|
||||
if (!CmdCheckForPaintFunc())
|
||||
{
|
||||
/* Places to check for a technology: In the PDK_ROOT
|
||||
* (PDKROOT) directory, PDK_PATH (PDKPATH) from environment
|
||||
* variables, and CAD_ROOT from Tcl variables; the open_pdks
|
||||
* default install path /usr/share/pdk/, and magic's install
|
||||
* path. For CAD_ROOT the variable is expected to point to
|
||||
* a path containing the techfile. For PDK_PATH and PDK_ROOT,
|
||||
* search the directory tree for any subdirectory called
|
||||
* magic/ and look for a compatible techfile there.
|
||||
*/
|
||||
char *found = NULL;
|
||||
char *string, *techfullname;
|
||||
|
||||
techfullname = mallocMagic(strlen(tech) + 6);
|
||||
sprintf(techfullname, "%s.tech", tech);
|
||||
|
||||
string = getenv("PDK_PATH");
|
||||
if (string)
|
||||
found = DBSearchForTech(techfullname, string, 0);
|
||||
if (!found)
|
||||
{
|
||||
string = getenv("PDKPATH");
|
||||
if (string)
|
||||
found = DBSearchForTech(techfullname, string, 0);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
string = getenv("PDK_ROOT");
|
||||
if (string)
|
||||
found = DBSearchForTech(techfullname, string, 0);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
string = getenv("PDKROOT");
|
||||
if (string)
|
||||
found = DBSearchForTech(techfullname, string, 0);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
found = DBSearchForTech(techfullname, "/usr/share/pdk", 0);
|
||||
}
|
||||
#ifdef MAGIC_WRAPPER
|
||||
/* Additional checks for PDK_PATH, etc., as Tcl variables. */
|
||||
/* This is unlikely, as they would have to be set in a */
|
||||
/* startup file, and a startup file is likely to just load */
|
||||
/* the technology itself. */
|
||||
if (!found)
|
||||
{
|
||||
string = (char *)Tcl_GetVar(magicinterp, "PDK_ROOT",
|
||||
TCL_GLOBAL_ONLY);
|
||||
if (string)
|
||||
found = DBSearchForTech(techfullname, string, 0);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
string = (char *)Tcl_GetVar(magicinterp, "PDKROOT",
|
||||
TCL_GLOBAL_ONLY);
|
||||
if (string)
|
||||
found = DBSearchForTech(techfullname, string, 0);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
string = (char *)Tcl_GetVar(magicinterp, "PDK_PATH",
|
||||
TCL_GLOBAL_ONLY);
|
||||
if (string)
|
||||
found = DBSearchForTech(techfullname, string, 0);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
string = (char *)Tcl_GetVar(magicinterp, "PDKPATH",
|
||||
TCL_GLOBAL_ONLY);
|
||||
if (string)
|
||||
found = DBSearchForTech(techfullname, string, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
freeMagic(techfullname);
|
||||
if (found)
|
||||
{
|
||||
char *sptr;
|
||||
PaAppend(&SysLibPath, found);
|
||||
|
||||
TxError("Loading technology %s\n", tech);
|
||||
if (!TechLoad(tech, 0))
|
||||
TxError("Error in loading technology file\n");
|
||||
else if ((sptr = strstr(found, "libs.tech")) != NULL)
|
||||
{
|
||||
int paths = 0;
|
||||
/* Additional automatic handling of open_pdks- */
|
||||
/* style PDKs. Append the libs.ref libraries */
|
||||
/* to the cell search path. */
|
||||
|
||||
strcpy(sptr + 5, "ref");
|
||||
paths = DBAddStandardCellPaths(found, 0);
|
||||
if (paths > 0)
|
||||
TxPrintf("Cell path is now \"%s\"\n", CellLibPath);
|
||||
}
|
||||
freeMagic(found);
|
||||
}
|
||||
}
|
||||
if (strcmp(DBTechName, tech))
|
||||
{
|
||||
TxError("Use command \"tech load\" if you want to switch"
|
||||
" technologies, or use\n");
|
||||
TxError("\"cellname delete %s\" and \"load %s -force\" to"
|
||||
" force the cell to load as technology %s\n",
|
||||
cellDef->cd_name, cellDef->cd_name, DBTechName);
|
||||
SigEnableInterrupts();
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dbFgets(line, sizeof line, f) == NULL)
|
||||
|
|
|
|||
Loading…
Reference in New Issue