aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/driver.cc70
-rw-r--r--kernel/log.cc92
-rw-r--r--kernel/log.h9
-rw-r--r--kernel/yosys.cc39
4 files changed, 153 insertions, 57 deletions
diff --git a/kernel/driver.cc b/kernel/driver.cc
index 97a78cd16..178641101 100644
--- a/kernel/driver.cc
+++ b/kernel/driver.cc
@@ -34,11 +34,17 @@
#include <limits.h>
#include <errno.h>
-#ifdef __linux__
+#if defined (__linux__) || defined(__FreeBSD__)
+# include <sys/resource.h>
# include <sys/types.h>
# include <unistd.h>
#endif
+#ifdef __FreeBSD__
+# include <sys/sysctl.h>
+# include <sys/user.h>
+#endif
+
#if !defined(_WIN32) || defined(__MINGW32__)
# include <unistd.h>
#else
@@ -79,20 +85,37 @@ USING_YOSYS_NAMESPACE
#ifdef EMSCRIPTEN
# include <sys/stat.h>
# include <sys/types.h>
+# include <emscripten.h>
extern "C" int main(int, char**);
extern "C" void run(const char*);
extern "C" const char *errmsg();
extern "C" const char *prompt();
-int main(int, char**)
+int main(int argc, char **argv)
{
+ EM_ASM(
+ if (ENVIRONMENT_IS_NODE)
+ {
+ FS.mkdir('/hostcwd');
+ FS.mount(NODEFS, { root: '.' }, '/hostcwd');
+ FS.mkdir('/hostfs');
+ FS.mount(NODEFS, { root: '/' }, '/hostfs');
+ }
+ );
+
mkdir("/work", 0777);
chdir("/work");
log_files.push_back(stdout);
log_error_stderr = true;
yosys_banner();
yosys_setup();
+
+ if (argc == 2)
+ {
+ // Run the first argument as a script file
+ run_frontend(argv[1], "script", 0, 0, 0);
+ }
}
void run(const char *command)
@@ -254,9 +277,13 @@ int main(int argc, char **argv)
printf(" print a warning for all log messages matching the regex.\n");
printf("\n");
printf(" -w regex\n");
- printf(" if a warning message matches the regex, it is printes as regular\n");
+ printf(" if a warning message matches the regex, it is printed as regular\n");
printf(" message instead.\n");
printf("\n");
+ printf(" -e regex\n");
+ printf(" if a warning message matches the regex, it is printed as error\n");
+ printf(" message instead and the tool terminates with a nonzero return code.\n");
+ printf("\n");
printf(" -E <depsfile>\n");
printf(" write a Makefile dependencies file with in- and output file names\n");
printf("\n");
@@ -280,7 +307,7 @@ int main(int argc, char **argv)
}
int opt;
- while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:D:E:")) != -1)
+ while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:E:")) != -1)
{
switch (opt)
{
@@ -374,6 +401,12 @@ int main(int argc, char **argv)
std::regex_constants::optimize |
std::regex_constants::egrep));
break;
+ case 'e':
+ log_werror_regexes.push_back(std::regex(optarg,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::egrep));
+ break;
case 'D':
{
auto args = split_tokens(optarg, ":");
@@ -416,6 +449,18 @@ int main(int argc, char **argv)
if (print_stats)
log_hasher = new SHA1;
+#if defined(__linux__)
+ // set stack size to >= 128 MB
+ {
+ struct rlimit rl;
+ const rlim_t stack_size = 128L * 1024L * 1024L;
+ if (getrlimit(RLIMIT_STACK, &rl) == 0 && rl.rlim_cur < stack_size) {
+ rl.rlim_cur = stack_size;
+ setrlimit(RLIMIT_STACK, &rl);
+ }
+ }
+#endif
+
yosys_setup();
log_error_atexit = yosys_atexit;
@@ -487,7 +532,7 @@ int main(int argc, char **argv)
#else
std::string meminfo;
std::string stats_divider = ", ";
-# ifdef __linux__
+# if defined(__linux__)
std::ifstream statm;
statm.open(stringf("/proc/%lld/statm", (long long)getpid()));
if (statm.is_open()) {
@@ -498,6 +543,19 @@ int main(int argc, char **argv)
sz_resident * (getpagesize() / 1024.0 / 1024.0));
stats_divider = "\n";
}
+# elif defined(__FreeBSD__)
+ pid_t pid = getpid();
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid};
+ struct kinfo_proc kip;
+ size_t kip_len = sizeof(kip);
+ if (sysctl(mib, 4, &kip, &kip_len, NULL, 0) == 0) {
+ vm_size_t sz_total = kip.ki_size;
+ segsz_t sz_resident = kip.ki_rssize;
+ meminfo = stringf(", MEM: %.2f MB total, %.2f MB resident",
+ (int)sz_total / 1024.0 / 1024.0,
+ (int)sz_resident * (getpagesize() / 1024.0 / 1024.0));
+ stats_divider = "\n";
+ }
# endif
struct rusage ru_buffer;
@@ -541,7 +599,7 @@ int main(int argc, char **argv)
}
}
-#if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
+#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE"))
{
string filename;
diff --git a/kernel/log.cc b/kernel/log.cc
index de564cb36..0ee2170a0 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -25,7 +25,7 @@
# include <sys/time.h>
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
# include <dlfcn.h>
#endif
@@ -41,7 +41,7 @@ YOSYS_NAMESPACE_BEGIN
std::vector<FILE*> log_files;
std::vector<std::ostream*> log_streams;
std::map<std::string, std::set<std::string>> log_hdump;
-std::vector<std::regex> log_warn_regexes, log_nowarn_regexes;
+std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
std::set<std::string> log_warnings;
int log_warnings_count = 0;
bool log_hdump_all = false;
@@ -203,7 +203,8 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap)
log_files.pop_back();
}
-void logv_warning(const char *format, va_list ap)
+static void logv_warning_with_prefix(const char *prefix,
+ const char *format, va_list ap)
{
std::string message = vstringf(format, ap);
bool suppressed = false;
@@ -214,13 +215,17 @@ void logv_warning(const char *format, va_list ap)
if (suppressed)
{
- log("Suppressed warning: %s", message.c_str());
+ log("Suppressed %s%s", prefix, message.c_str());
}
else
{
+ for (auto &re : log_werror_regexes)
+ if (std::regex_search(message, re))
+ log_error("%s", message.c_str());
+
if (log_warnings.count(message))
{
- log("Warning: %s", message.c_str());
+ log("%s%s", prefix, message.c_str());
log_flush();
}
else
@@ -228,7 +233,7 @@ void logv_warning(const char *format, va_list ap)
if (log_errfile != NULL && !log_quiet_warnings)
log_files.push_back(log_errfile);
- log("Warning: %s", message.c_str());
+ log("%s%s", prefix, message.c_str());
log_flush();
if (log_errfile != NULL && !log_quiet_warnings)
@@ -241,45 +246,30 @@ void logv_warning(const char *format, va_list ap)
}
}
-void logv_warning_noprefix(const char *format, va_list ap)
+void logv_warning(const char *format, va_list ap)
{
- std::string message = vstringf(format, ap);
- bool suppressed = false;
-
- for (auto &re : log_nowarn_regexes)
- if (std::regex_search(message, re))
- suppressed = true;
-
- if (suppressed)
- {
- log("%s", message.c_str());
- }
- else
- {
- if (log_warnings.count(message))
- {
- log("%s", message.c_str());
- log_flush();
- }
- else
- {
- if (log_errfile != NULL && !log_quiet_warnings)
- log_files.push_back(log_errfile);
-
- log("%s", message.c_str());
- log_flush();
-
- if (log_errfile != NULL && !log_quiet_warnings)
- log_files.pop_back();
+ logv_warning_with_prefix("Warning: ", format, ap);
+}
- log_warnings.insert(message);
- }
+void logv_warning_noprefix(const char *format, va_list ap)
+{
+ logv_warning_with_prefix("", format, ap);
+}
- log_warnings_count++;
- }
+void log_file_warning(const std::string &filename, int lineno,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ std::string prefix = stringf("%s:%d: Warning: ",
+ filename.c_str(), lineno);
+ logv_warning_with_prefix(prefix.c_str(), format, ap);
+ va_end(ap);
}
-void logv_error(const char *format, va_list ap)
+YS_ATTRIBUTE(noreturn)
+static void logv_error_with_prefix(const char *prefix,
+ const char *format, va_list ap)
{
#ifdef EMSCRIPTEN
auto backup_log_files = log_files;
@@ -294,7 +284,7 @@ void logv_error(const char *format, va_list ap)
f = stderr;
log_last_error = vstringf(format, ap);
- log("ERROR: %s", log_last_error.c_str());
+ log("%s%s", prefix, log_last_error.c_str());
log_flush();
if (log_error_atexit)
@@ -310,6 +300,21 @@ void logv_error(const char *format, va_list ap)
#endif
}
+void logv_error(const char *format, va_list ap)
+{
+ logv_error_with_prefix("ERROR: ", format, ap);
+}
+
+void log_file_error(const string &filename, int lineno,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ std::string prefix = stringf("%s:%d: ERROR: ",
+ filename.c_str(), lineno);
+ logv_error_with_prefix(prefix.c_str(), format, ap);
+}
+
void log(const char *format, ...)
{
va_list ap;
@@ -384,7 +389,7 @@ void log_pop()
log_flush();
}
-#if defined(__linux__) && defined(YOSYS_ENABLE_PLUGINS)
+#if (defined(__linux__) || defined(__FreeBSD__)) && defined(YOSYS_ENABLE_PLUGINS)
void log_backtrace(const char *prefix, int levels)
{
if (levels <= 0) return;
@@ -579,7 +584,7 @@ void log_wire(RTLIL::Wire *wire, std::string indent)
// ---------------------------------------------------
// This is the magic behind the code coverage counters
// ---------------------------------------------------
-#if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
+#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
dict<std::string, std::pair<std::string, int>> extra_coverage_data;
@@ -628,4 +633,3 @@ dict<std::string, std::pair<std::string, int>> get_coverage_data()
#endif
YOSYS_NAMESPACE_END
-
diff --git a/kernel/log.h b/kernel/log.h
index 90a12df36..0b4905c3a 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -49,7 +49,7 @@ struct log_cmd_error_exception { };
extern std::vector<FILE*> log_files;
extern std::vector<std::ostream*> log_streams;
extern std::map<std::string, std::set<std::string>> log_hdump;
-extern std::vector<std::regex> log_warn_regexes, log_nowarn_regexes;
+extern std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
extern std::set<std::string> log_warnings;
extern int log_warnings_count;
extern bool log_hdump_all;
@@ -73,8 +73,13 @@ YS_NORETURN void logv_error(const char *format, va_list ap) YS_ATTRIBUTE(noretur
void log(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
void log_header(RTLIL::Design *design, const char *format, ...) YS_ATTRIBUTE(format(printf, 2, 3));
void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
+
+// Log with filename to report a problem in a source file.
+void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4));
+
void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
+void log_file_error(const string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4), noreturn);
YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
void log_spacer();
@@ -114,7 +119,7 @@ static inline void log_assert_worker(bool cond, const char *expr, const char *fi
// This is the magic behind the code coverage counters
// ---------------------------------------------------
-#if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
+#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
#define cover(_id) do { \
static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1), used)) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index cade09048..dca277532 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -46,10 +46,15 @@
# include <unistd.h>
# include <dirent.h>
# include <sys/types.h>
+# include <sys/wait.h>
# include <sys/stat.h>
# include <glob.h>
#endif
+#ifdef __FreeBSD__
+# include <sys/sysctl.h>
+#endif
+
#include <limits.h>
#include <errno.h>
@@ -72,7 +77,7 @@ std::vector<void*> memhasher_store;
void memhasher_on()
{
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
memhasher_rng += time(NULL) << 16 ^ getpid();
#endif
memhasher_store.resize(0x10000);
@@ -598,6 +603,8 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a
std::string tcl_command_name = it.first;
if (tcl_command_name == "proc")
tcl_command_name = "procs";
+ else if (tcl_command_name == "rename")
+ tcl_command_name = "renames";
Tcl_CmdInfo info;
if (Tcl_GetCommandInfo(interp, tcl_command_name.c_str(), &info) != 0) {
log("[TCL: yosys -import] Command name collision: found pre-existing command `%s' -> skip.\n", it.first.c_str());
@@ -637,9 +644,9 @@ struct TclPass : public Pass {
log("Use 'yosys cmd' to run the yosys command 'cmd' from tcl.\n");
log("\n");
log("The tcl command 'yosys -import' can be used to import all yosys\n");
- log("commands directly as tcl commands to the tcl shell. The yosys\n");
- log("command 'proc' is wrapped using the tcl command 'procs' in order\n");
- log("to avoid a name collision with the tcl builtin command 'proc'.\n");
+ log("commands directly as tcl commands to the tcl shell. Yosys commands\n");
+ log("'proc' and 'rename' are wrapped to tcl commands 'procs' and 'renames'\n");
+ log("in order to avoid a name collision with the built in commands.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
@@ -665,6 +672,26 @@ std::string proc_self_dirname()
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)
+ log_error("sysctl failed: %s\n", strerror(errno));
+ buffer = (char*)malloc(buflen);
+ if (buffer == NULL)
+ log_error("malloc failed: %s\n", strerror(errno));
+ if (sysctl(mib, 4, buffer, &buflen, NULL, 0) != 0)
+ log_error("sysctl failed: %s\n", strerror(errno));
+ while (buflen > 0 && buffer[buflen-1] != '/')
+ buflen--;
+ path.assign(buffer, buflen);
+ free(buffer);
+ return path;
+}
#elif defined(__APPLE__)
std::string proc_self_dirname()
{
@@ -712,7 +739,7 @@ std::string proc_self_dirname()
#ifdef EMSCRIPTEN
std::string proc_share_dirname()
{
- return "/share";
+ return "/share/";
}
#else
std::string proc_share_dirname()
@@ -798,6 +825,8 @@ void run_frontend(std::string filename, std::string command, std::string *backen
command = "vhdl";
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".blif")
command = "blif";
+ else if (filename.size() > 5 && filename.substr(filename.size()-6) == ".eblif")
+ command = "blif";
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".json")
command = "json";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")