icetime: Add support for searching for chipdb relative to binary

Like yosys and arachne-pnr, allow for searching for the desired chipdb
file relative to the executing binaries directory. This allows for
portable builds of icetime without needing to specify the exact path to
the needed chipdb file with the -C arg.

In order to support this icetime must be able to get the
"proc_self_dirname" path just like yosys and arachne-pnr. As such copy
the equivalent code to get this path information. To avoid cluttering
the icetime.cc file with this code, place it in a separate iceutil.cc
file.

Signed-off-by: Nathan Rossi <nathan@nathanrossi.com>
This commit is contained in:
Nathan Rossi 2018-09-03 22:50:03 +10:00
parent 3681ade2c7
commit c1c13f3b3e
3 changed files with 190 additions and 25 deletions

View File

@ -26,10 +26,11 @@ share/$(CHIPDB_SUBDIR)/chipdb-5k.txt: ../icebox/chipdb-5k.txt
override LDFLAGS += --embed-file share
endif
icetime$(EXE): icetime.o
icetime$(EXE): icetime.o iceutil.o
$(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS)
icetime.o: icetime.cc timings.inc
iceutil.o: iceutil.cc
timings.inc: timings.py ../icefuzz/timings_*.txt
python3 timings.py > timings.inc.new

View File

@ -38,6 +38,8 @@
#include <emscripten.h>
#endif
std::string find_chipdb(std::string config_device);
// add this number of ns as estimate for clock distribution mismatch
#define GLOBAL_CLK_DIST_JITTER 0.1
@ -322,35 +324,18 @@ void read_config()
void read_chipdb()
{
char buffer[1024];
std::string filepath = chipdbfile;
if (!chipdbfile.empty()) {
snprintf(buffer, 1024, "%s", chipdbfile.c_str());
} else
if (PREFIX[0] == '~' && PREFIX[1] == '/') {
std::string homedir;
#ifdef _WIN32
if (getenv("USERPROFILE") != nullptr) {
homedir += getenv("USERPROFILE");
}
else {
if (getenv("HOMEDRIVE") != nullptr &&
getenv("HOMEPATH") != nullptr) {
homedir += getenv("HOMEDRIVE");
homedir += getenv("HOMEPATH");
}
}
#else
homedir += getenv("HOME");
#endif
snprintf(buffer, 1024, "%s%s/share/" CHIPDB_SUBDIR "/chipdb-%s.txt", homedir.c_str(), PREFIX+1, config_device.c_str());
} else {
snprintf(buffer, 1024, PREFIX "/share/" CHIPDB_SUBDIR "/chipdb-%s.txt", config_device.c_str());
if (filepath.empty())
filepath = find_chipdb(config_device);
if (filepath.empty()) {
fprintf(stderr, "Can't find chipdb file for device %s\n", config_device.c_str());
exit(1);
}
FILE *fdb = fopen(buffer, "r");
FILE *fdb = fopen(filepath.c_str(), "r");
if (fdb == nullptr) {
perror("Can't open chipdb file");
fprintf(stderr, " %s\n", buffer);
exit(1);
}

179
icetime/iceutil.cc Normal file
View File

@ -0,0 +1,179 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include <errno.h>
#include <string>
#include <sstream>
#include <cstring>
#ifdef _WIN32
# include <windows.h>
# include <io.h>
#elif defined(__APPLE__)
# include <mach-o/dyld.h>
# include <unistd.h>
#else
# include <unistd.h>
#endif
#ifdef __FreeBSD__
# include <sys/sysctl.h>
#endif
#include <limits.h>
#if defined(__linux__) || defined(__CYGWIN__)
std::string proc_self_dirname()
{
char path[PATH_MAX];
ssize_t buflen = readlink("/proc/self/exe", path, sizeof(path));
if (buflen < 0) {
fprintf(stderr, "fatal error: readlink(\"/proc/self/exe\") failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
while (buflen > 0 && path[buflen-1] != '/')
buflen--;
return std::string(path, buflen);
}
#elif defined(__FreeBSD__)
std::string proc_self_dirname()
{
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
size_t buflen;
char *buffer;
std::string path;
if (sysctl(mib, 4, NULL, &buflen, NULL, 0) != 0) {
fprintf(stderr, "fatal error: sysctl failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
buffer = (char*)malloc(buflen);
if (buffer == NULL) {
fprintf(stderr, "fatal error: malloc failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (sysctl(mib, 4, buffer, &buflen, NULL, 0) != 0) {
fprintf(stderr, "fatal error: sysctl failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
while (buflen > 0 && buffer[buflen-1] != '/')
buflen--;
path.assign(buffer, buflen);
free(buffer);
return path;
}
#elif defined(__APPLE__)
std::string proc_self_dirname()
{
char *path = NULL;
uint32_t buflen = 0;
while (_NSGetExecutablePath(path, &buflen) != 0)
path = (char *) realloc((void *) path, buflen);
while (buflen > 0 && path[buflen-1] != '/')
buflen--;
return std::string(path, buflen);
}
#elif defined(_WIN32)
std::string proc_self_dirname()
{
int i = 0;
# ifdef __MINGW32__
char longpath[MAX_PATH + 1];
char shortpath[MAX_PATH + 1];
# else
WCHAR longpath[MAX_PATH + 1];
TCHAR shortpath[MAX_PATH + 1];
# endif
if (!GetModuleFileName(0, longpath, MAX_PATH+1)) {
fprintf(stderr, "fatal error: GetModuleFileName() failed.\n");
exit(EXIT_FAILURE);
}
if (!GetShortPathName(longpath, shortpath, MAX_PATH+1)) {
fprintf(stderr, "fatal error: GetShortPathName() failed.\n");
exit(EXIT_FAILURE);
}
while (shortpath[i] != 0)
i++;
while (i > 0 && shortpath[i-1] != '/' && shortpath[i-1] != '\\')
shortpath[--i] = 0;
std::string path;
for (i = 0; shortpath[i]; i++)
path += char(shortpath[i]);
return path;
}
#elif defined(EMSCRIPTEN)
std::string proc_self_dirname()
{
return "/";
}
#else
#error Dont know how to determine process executable base path!
#endif
bool file_test_open(std::string path)
{
FILE *fdb = fopen(path.c_str(), "r");
if (fdb == nullptr) {
return false;
}
fclose(fdb);
return true;
}
extern bool verbose;
std::string find_chipdb(std::string config_device)
{
if (PREFIX[0] == '~' && PREFIX[1] == '/') {
std::string homepath;
#ifdef _WIN32
if (getenv("USERPROFILE") != nullptr) {
homepath += getenv("USERPROFILE");
}
else {
if (getenv("HOMEDRIVE") != nullptr &&
getenv("HOMEPATH") != nullptr) {
homepath += getenv("HOMEDRIVE");
homepath += getenv("HOMEPATH");
}
}
#else
homepath += getenv("HOME");
#endif
homepath += std::string(PREFIX + 1) + "/" CHIPDB_SUBDIR "/chipdb-" + config_device + ".txt";
if (verbose)
fprintf(stderr, "Looking for chipdb '%s' at %s\n", config_device.c_str(), homepath.c_str());
if (file_test_open(homepath))
return homepath;
}
std::string prefixpath = PREFIX "/share/" CHIPDB_SUBDIR "/chipdb-" + config_device + ".txt";
if (verbose)
fprintf(stderr, "Looking for chipdb '%s' at %s\n", config_device.c_str(), prefixpath.c_str());
if (file_test_open(prefixpath))
return prefixpath;
std::string relbinarypath = proc_self_dirname() + "../share/" CHIPDB_SUBDIR "/chipdb-" + config_device + ".txt";
if (verbose)
fprintf(stderr, "Looking for chipdb '%s' at %s\n", config_device.c_str(), relbinarypath.c_str());
if (file_test_open(relbinarypath))
return relbinarypath;
return "";
}