verilator/src/V3Os.cpp

225 lines
6.6 KiB
C++
Raw Normal View History

2015-02-27 01:40:45 +00:00
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Os-specific function wrapper
//
// Code available from: http://www.veripool.org/verilator
//
//*************************************************************************
//
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
2015-02-27 01:40:45 +00:00
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <cstdarg>
#include <sys/stat.h>
#include <sys/time.h>
2015-02-27 01:40:45 +00:00
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
2017-02-09 23:33:18 +00:00
#include <climits>
#include <cstdlib>
2015-02-27 01:40:45 +00:00
#include <cerrno>
#include <fcntl.h>
#include <iomanip>
#include <memory>
#if defined(WIN32) || defined(__MINGW32__)
# include <direct.h> // mkdir
#endif
#include "V3Global.h"
#include "V3String.h"
#include "V3Os.h"
//######################################################################
// Environment
string V3Os::getenvStr(const string& envvar, const string& defaultValue) {
if (const char* envvalue = getenv(envvar.c_str())) {
return envvalue;
} else {
return defaultValue;
}
}
void V3Os::setenvStr(const string& envvar, const string& value, const string& why) {
if (why != "") {
UINFO(1,"export "<<envvar<<"="<<value<<" # "<<why<<endl);
} else {
UINFO(1,"export "<<envvar<<"="<<value<<endl);
}
2015-06-08 11:24:04 +00:00
#if !defined(__MINGW32__) && (defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L))
2015-02-27 01:40:45 +00:00
setenv(envvar.c_str(),value.c_str(),true);
#else
//setenv() replaced by putenv() in MinGW/Solaris environment. Prototype is different
//putenv() requires NAME=VALUE format
string vareq = envvar + "=" + value;
putenv(const_cast<char*>(vareq.c_str()));
#endif
}
//######################################################################
2017-09-11 23:18:58 +00:00
// Generic filename utilities
2015-02-27 01:40:45 +00:00
string V3Os::filenameFromDirBase(const string& dir, const string& basename) {
2015-02-27 01:40:45 +00:00
// Don't return ./{filename} because if filename was absolute, that makes it relative
if (dir == ".") return basename;
else return dir+"/"+basename;
}
string V3Os::filenameDir(const string& filename) {
2015-02-27 01:40:45 +00:00
string::size_type pos;
if ((pos = filename.rfind("/")) != string::npos) {
return filename.substr(0,pos);
} else {
return ".";
}
}
string V3Os::filenameNonDir(const string& filename) {
2015-02-27 01:40:45 +00:00
string::size_type pos;
if ((pos = filename.rfind("/")) != string::npos) {
return filename.substr(pos+1);
} else {
return filename;
}
}
string V3Os::filenameNonExt(const string& filename) {
2015-02-27 01:40:45 +00:00
string base = filenameNonDir(filename);
string::size_type pos;
if ((pos = base.find(".")) != string::npos) {
base.erase(pos);
}
return base;
}
string V3Os::filenameSubstitute(const string& filename) {
2015-02-27 01:40:45 +00:00
string out;
enum { NONE, PAREN, CURLY } brackets = NONE;
for (string::size_type pos = 0; pos < filename.length(); ++pos) {
if ((filename[pos] == '$') && (pos+1 < filename.length())) {
switch (filename[pos+1]) {
case '{': brackets = CURLY; break;
case '(': brackets = PAREN; break;
default: brackets = NONE; break;
}
if (brackets != NONE) pos = pos+1;
string::size_type endpos = pos+1;
while (((endpos+1) < filename.length()) &&
(((brackets==NONE) && (isalnum(filename[endpos+1]) || filename[endpos+1]=='_')) ||
((brackets==CURLY) && (filename[endpos+1]!='}')) ||
((brackets==PAREN) && (filename[endpos+1]!=')'))))
++endpos;
// Catch bracket errors
if (((brackets==CURLY) && (filename[endpos+1]!='}')) ||
((brackets==PAREN) && (filename[endpos+1]!=')'))) {
v3fatal("Unmatched brackets in variable substitution in file: "+filename);
}
string envvar = filename.substr(pos+1,endpos-pos);
const char* envvalue = NULL;
if (envvar != "") envvalue = getenv(envvar.c_str());
if (envvalue) {
out += envvalue;
if (brackets==NONE) pos = endpos;
else pos = endpos+1;
} else {
out += filename[pos]; // *pos == '$'
}
} else {
out += filename[pos];
}
}
return out;
}
2017-02-09 23:33:18 +00:00
string V3Os::filenameRealPath(const string& filename) {
// Get rid of all the ../ behavior in the middle of the paths.
// If there is a ../ that goes down from the 'root' of this path it is preserved.
char retpath[PATH_MAX];
if (
#if defined( _MSC_VER ) || defined( __MINGW32__ )
::_fullpath(retpath,filename.c_str(),PATH_MAX)
#else
realpath(filename.c_str(), retpath)
#endif
) {
2017-02-13 23:11:22 +00:00
return string(retpath);
} else {
return filename;
}
2017-02-09 23:33:18 +00:00
}
2015-02-27 01:40:45 +00:00
bool V3Os::filenameIsRel(const string& filename) {
return (filename.length()>0 && filename[0] != '/');
}
//######################################################################
// Directory utilities
void V3Os::createDir(const string& dirname) {
#if defined(_WIN32) || defined(__MINGW32__)
mkdir(dirname.c_str());
#else
mkdir(dirname.c_str(), 0777);
#endif
}
void V3Os::unlinkRegexp(const string& dir, const string& regexp) {
if (DIR* dirp = opendir(dir.c_str())) {
while (struct dirent* direntp = readdir(dirp)) {
if (VString::wildmatch(direntp->d_name, regexp.c_str())) {
string fullname = dir + "/" + string(direntp->d_name);
unlink(fullname.c_str());
2015-02-27 01:40:45 +00:00
}
}
closedir(dirp);
}
}
//######################################################################
// METHODS (performance)
uint64_t V3Os::timeUsecs() {
#if defined(_WIN32) || defined(__MINGW32__)
return 0;
#else
timeval tv;
if (gettimeofday(&tv, NULL) < 0) return 0;
return static_cast<uint64_t>(tv.tv_sec)*1000000 + tv.tv_usec;
#endif
}
uint64_t V3Os::memUsageBytes() {
#if defined(_WIN32) || defined(__MINGW32__)
return 0;
#else
// Highly unportable. Sorry
const char* const statmFilename = "/proc/self/statm";
FILE* fp = fopen(statmFilename,"r");
if (!fp) {
return 0;
}
vluint64_t size, resident, share, text, lib, data, dt; // All in pages
if (7 != fscanf(fp, "%" VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64 "u %"
VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64 "u",
&size, &resident, &share, &text, &lib, &data, &dt)) {
2017-10-14 18:51:57 +00:00
fclose(fp);
return 0;
}
2017-10-14 18:51:57 +00:00
fclose(fp);
return (text + data) * getpagesize();
#endif
}