X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=kernel%2Fdriver.cc;h=1786411019708fe8d78b0bb91140766bc1b37f07;hb=0d9c850a0713e3ff59a9ff2ab89e9fd47fd8aa08;hp=5e69cced3a9eb66c3d3a32a76389ef21402e7906;hpb=b3a6f8f53019d1984d4e319db459b11da0663aa3;p=yosys.git diff --git a/kernel/driver.cc b/kernel/driver.cc index 5e69cced3..178641101 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -2,11 +2,11 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * + * * 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 @@ -25,11 +25,26 @@ # include #endif +#ifdef YOSYS_ENABLE_EDITLINE +# include +#endif + #include #include #include #include +#if defined (__linux__) || defined(__FreeBSD__) +# include +# include +# include +#endif + +#ifdef __FreeBSD__ +# include +# include +#endif + #if !defined(_WIN32) || defined(__MINGW32__) # include #else @@ -67,6 +82,99 @@ int getopt(int argc, char **argv, const char *optstring) USING_YOSYS_NAMESPACE +#ifdef EMSCRIPTEN +# include +# include +# include + +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 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) +{ + int selSize = GetSize(yosys_get_design()->selection_stack); + try { + log_last_error = "Internal error (see JavaScript console for details)"; + run_pass(command); + log_last_error = ""; + } catch (...) { + while (GetSize(yosys_get_design()->selection_stack) > selSize) + yosys_get_design()->selection_stack.pop_back(); + throw; + } +} + +const char *errmsg() +{ + return log_last_error.c_str(); +} + +const char *prompt() +{ + const char *p = create_prompt(yosys_get_design(), 0); + while (*p == '\n') p++; + return p; +} + +#else /* EMSCRIPTEN */ + +#if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE) +int yosys_history_offset = 0; +std::string yosys_history_file; +#endif + +void yosys_atexit() +{ +#if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE) + if (!yosys_history_file.empty()) { +#if defined(YOSYS_ENABLE_READLINE) + if (yosys_history_offset > 0) { + history_truncate_file(yosys_history_file.c_str(), 100); + append_history(where_history() - yosys_history_offset, yosys_history_file.c_str()); + } else + write_history(yosys_history_file.c_str()); +#else + write_history(yosys_history_file.c_str()); +#endif + } + + clear_history(); +#if defined(YOSYS_ENABLE_READLINE) + HIST_ENTRY **hist_list = history_list(); + if (hist_list != NULL) + free(hist_list); +#endif +#endif +} + int main(int argc, char **argv) { std::string frontend_command = "auto"; @@ -75,27 +183,140 @@ int main(int argc, char **argv) std::vector plugin_filenames; std::string output_filename = ""; std::string scriptfile = ""; + std::string depsfile = ""; bool scriptfile_tcl = false; bool got_output_filename = false; bool print_banner = true; bool print_stats = true; bool call_abort = false; + bool timing_details = false; + bool mode_v = false; + bool mode_q = false; -#ifdef YOSYS_ENABLE_READLINE - int history_offset = 0; - std::string history_file; +#if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE) if (getenv("HOME") != NULL) { - history_file = stringf("%s/.yosys_history", getenv("HOME")); - read_history(history_file.c_str()); - history_offset = where_history(); + yosys_history_file = stringf("%s/.yosys_history", getenv("HOME")); + read_history(yosys_history_file.c_str()); + yosys_history_offset = where_history(); } #endif + if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-help") || !strcmp(argv[1], "--help"))) + { + printf("\n"); + printf("Usage: %s [options] [ [..]]\n", argv[0]); + printf("\n"); + printf(" -Q\n"); + printf(" suppress printing of banner (copyright, disclaimer, version)\n"); + printf("\n"); + printf(" -T\n"); + printf(" suppress printing of footer (log hash, version, timing statistics)\n"); + printf("\n"); + printf(" -q\n"); + printf(" quiet operation. only write warnings and error messages to console\n"); + printf(" use this option twice to also quiet warning messages\n"); + printf("\n"); + printf(" -v \n"); + printf(" print log headers up to level to the console. (this\n"); + printf(" implies -q for everything except the 'End of script.' message.)\n"); + printf("\n"); + printf(" -t\n"); + printf(" annotate all log messages with a time stamp\n"); + printf("\n"); + printf(" -d\n"); + printf(" print more detailed timing stats at exit\n"); + printf("\n"); + printf(" -l logfile\n"); + printf(" write log messages to the specified file\n"); + printf("\n"); + printf(" -L logfile\n"); + printf(" like -l but open log file in line buffered mode\n"); + printf("\n"); + printf(" -o outfile\n"); + printf(" write the design to the specified file on exit\n"); + printf("\n"); + printf(" -b backend\n"); + printf(" use this backend for the output file specified on the command line\n"); + printf("\n"); + printf(" -f frontend\n"); + printf(" use the specified frontend for the input files on the command line\n"); + printf("\n"); + printf(" -H\n"); + printf(" print the command list\n"); + printf("\n"); + printf(" -h command\n"); + printf(" print the help message for the specified command\n"); + printf("\n"); + printf(" -s scriptfile\n"); + printf(" execute the commands in the script file\n"); + printf("\n"); + printf(" -c tcl_scriptfile\n"); + printf(" execute the commands in the tcl script file (see 'help tcl' for details)\n"); + printf("\n"); + printf(" -p command\n"); + printf(" execute the commands\n"); + printf("\n"); + printf(" -m module_file\n"); + printf(" load the specified module (aka plugin)\n"); + printf("\n"); + printf(" -X\n"); + printf(" enable tracing of core data structure changes. for debugging\n"); + printf("\n"); + printf(" -M\n"); + printf(" will slightly randomize allocated pointer addresses. for debugging\n"); + printf("\n"); + printf(" -A\n"); + printf(" will call abort() at the end of the script. for debugging\n"); + printf("\n"); + printf(" -D [:]\n"); + printf(" dump the design when printing the specified log header to a file.\n"); + printf(" yosys_dump_.il is used as filename if none is specified.\n"); + printf(" Use 'ALL' as to dump at every header.\n"); + printf("\n"); + printf(" -W regex\n"); + 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 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 \n"); + printf(" write a Makefile dependencies file with in- and output file names\n"); + printf("\n"); + printf(" -V\n"); + printf(" print version information and exit\n"); + printf("\n"); + printf("The option -S is an shortcut for calling the \"synth\" command, a default\n"); + printf("script for transforming the Verilog input to a gate-level netlist. For example:\n"); + printf("\n"); + printf(" yosys -o output.blif -S input.v\n"); + printf("\n"); + printf("For more complex synthesis jobs it is recommended to use the read_* and write_*\n"); + printf("commands in a script file instead of specifying input and output files on the\n"); + printf("command line.\n"); + printf("\n"); + printf("When no commands, script files or input files are specified on the command\n"); + printf("line, yosys automatically enters the interactive command mode. Use the 'help'\n"); + printf("command to get information on the individual commands.\n"); + printf("\n"); + exit(0); + } + int opt; - while ((opt = getopt(argc, argv, "AQTVSm:f:Hh:b:o:p:l:qv:ts:c:")) != -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) { + case 'M': + memhasher_on(); + break; + case 'X': + yosys_xtrace++; + break; case 'A': call_abort = true; break; @@ -134,22 +355,32 @@ int main(int argc, char **argv) got_output_filename = true; break; case 'l': + case 'L': log_files.push_back(fopen(optarg, "wt")); if (log_files.back() == NULL) { fprintf(stderr, "Can't open log file `%s' for writing!\n", optarg); exit(1); } + if (opt == 'L') + setvbuf(log_files.back(), NULL, _IOLBF, 0); break; case 'q': + mode_q = true; + if (log_errfile == stderr) + log_quiet_warnings = true; log_errfile = stderr; break; case 'v': + mode_v = true; log_errfile = stderr; log_verbose_level = atoi(optarg); break; case 't': log_time = true; break; + case 'd': + timing_details = true; + break; case 's': scriptfile = optarg; scriptfile_tcl = false; @@ -158,112 +389,80 @@ int main(int argc, char **argv) scriptfile = optarg; scriptfile_tcl = true; break; + case 'W': + log_warn_regexes.push_back(std::regex(optarg, + std::regex_constants::nosubs | + std::regex_constants::optimize | + std::regex_constants::egrep)); + break; + case 'w': + log_nowarn_regexes.push_back(std::regex(optarg, + std::regex_constants::nosubs | + 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, ":"); + if (!args.empty() && args[0] == "ALL") { + if (GetSize(args) != 1) { + fprintf(stderr, "Invalid number of tokens in -D ALL.\n"); + exit(1); + } + log_hdump_all = true; + } else { + if (!args.empty() && !args[0].empty() && args[0].back() == '.') + args[0].pop_back(); + if (GetSize(args) == 1) + args.push_back("yosys_dump_" + args[0] + ".il"); + if (GetSize(args) != 2) { + fprintf(stderr, "Invalid number of tokens in -D.\n"); + exit(1); + } + log_hdump[args[0]].insert(args[1]); + } + } + break; + case 'E': + depsfile = optarg; + break; default: - fprintf(stderr, "\n"); - fprintf(stderr, "Usage: %s [-V -S -Q -T -q] [-v [-t] [-l ] [-o ] [-f ] [-h cmd] \\\n", argv[0]); - fprintf(stderr, " %*s[{-s|-c} ] [-p [-p ..]] [-b ] [-m ] [ [..]]\n", int(strlen(argv[0])+1), ""); - fprintf(stderr, "\n"); - fprintf(stderr, " -Q\n"); - fprintf(stderr, " suppress printing of banner (copyright, disclaimer, version)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -T\n"); - fprintf(stderr, " suppress printing of footer (log hash, version, timing statistics)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -q\n"); - fprintf(stderr, " quiet operation. only write error messages to console\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -v \n"); - fprintf(stderr, " print log headers up to level to the console. (implies -q)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -t\n"); - fprintf(stderr, " annotate all log messages with a time stamp\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -l logfile\n"); - fprintf(stderr, " write log messages to the specified file\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -o outfile\n"); - fprintf(stderr, " write the design to the specified file on exit\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -b backend\n"); - fprintf(stderr, " use this backend for the output file specified on the command line\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -f backend\n"); - fprintf(stderr, " use the specified front for the input files on the command line\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -H\n"); - fprintf(stderr, " print the command list\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -h command\n"); - fprintf(stderr, " print the help message for the specified command\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -s scriptfile\n"); - fprintf(stderr, " execute the commands in the script file\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -c tcl_scriptfile\n"); - fprintf(stderr, " execute the commands in the tcl script file (see 'help tcl' for details)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -p command\n"); - fprintf(stderr, " execute the commands\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -m module_file\n"); - fprintf(stderr, " load the specified module (aka plugin)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -A\n"); - fprintf(stderr, " will call abort() at the end of the script. useful for debugging\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -V\n"); - fprintf(stderr, " print version information and exit\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "The option -S is an shortcut for calling the \"synth\" command, a default\n"); - fprintf(stderr, "script for transforming the verilog input to a gate-level netlist. For example:\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " yosys -o output.blif -S input.v\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "For more complex synthesis jobs it is recommended to use the read_* and write_*\n"); - fprintf(stderr, "commands in a script file instead of specifying input and output files on the\n"); - fprintf(stderr, "command line.\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "When no commands, script files or input files are specified on the command\n"); - fprintf(stderr, "line, yosys automatically enters the interactive command mode. Use the 'help'\n"); - fprintf(stderr, "command to get information on the individual commands.\n"); - fprintf(stderr, "\n"); + fprintf(stderr, "Run '%s -h' for help.\n", argv[0]); exit(1); } } - if (log_errfile == NULL) - log_files.push_back(stderr); - - if (print_banner) { - log("\n"); - log(" /----------------------------------------------------------------------------\\\n"); - log(" | |\n"); - log(" | yosys -- Yosys Open SYnthesis Suite |\n"); - log(" | |\n"); - log(" | Copyright (C) 2012 Clifford Wolf |\n"); - log(" | |\n"); - log(" | Permission to use, copy, modify, and/or distribute this software for any |\n"); - log(" | purpose with or without fee is hereby granted, provided that the above |\n"); - log(" | copyright notice and this permission notice appear in all copies. |\n"); - log(" | |\n"); - log(" | THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |\n"); - log(" | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |\n"); - log(" | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |\n"); - log(" | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |\n"); - log(" | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |\n"); - log(" | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |\n"); - log(" | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |\n"); - log(" | |\n"); - log(" \\----------------------------------------------------------------------------/\n"); - log("\n"); - log(" %s\n", yosys_version_str); - log("\n"); + if (log_errfile == NULL) { + log_files.push_back(stdout); + log_error_stderr = true; } + if (print_banner) + yosys_banner(); + 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; for (auto &fn : plugin_filenames) load_plugin(fn, {}); @@ -275,7 +474,7 @@ int main(int argc, char **argv) } while (optind < argc) - run_frontend(argv[optind++], frontend_command, yosys_design, output_filename == "-" ? &backend_command : NULL, NULL); + run_frontend(argv[optind++], frontend_command, output_filename == "-" ? &backend_command : NULL); if (!scriptfile.empty()) { if (scriptfile_tcl) { @@ -286,14 +485,32 @@ int main(int argc, char **argv) log_error("Can't exectue TCL script: this version of yosys is not built with TCL support enabled.\n"); #endif } else - run_frontend(scriptfile, "script", yosys_design, output_filename == "-" ? &backend_command : NULL, NULL); + run_frontend(scriptfile, "script", output_filename == "-" ? &backend_command : NULL); } for (auto it = passes_commands.begin(); it != passes_commands.end(); it++) - run_pass(*it, yosys_design); + run_pass(*it); if (!backend_command.empty()) - run_backend(output_filename, backend_command, yosys_design); + run_backend(output_filename, backend_command); + + if (!depsfile.empty()) + { + FILE *f = fopen(depsfile.c_str(), "wt"); + if (f == nullptr) + log_error("Can't open dependencies file for writing: %s\n", strerror(errno)); + bool first = true; + for (auto fn : yosys_output_files) { + fprintf(f, "%s%s", first ? "" : " ", fn.c_str()); + first = false; + } + fprintf(f, ":"); + for (auto fn : yosys_input_files) { + if (yosys_output_files.count(fn) == 0) + fprintf(f, " %s", fn.c_str()); + } + fprintf(f, "\n"); + } if (print_stats) { @@ -301,20 +518,56 @@ int main(int argc, char **argv) delete log_hasher; log_hasher = nullptr; + log_time = false; + yosys_xtrace = 0; log_spacer(); + + if (mode_v && !mode_q) + log_files.push_back(stderr); + + if (log_warnings_count) + log("Warnings: %d unique messages, %d total\n", GetSize(log_warnings), log_warnings_count); #ifdef _WIN32 log("End of script. Logfile hash: %s\n", hash.c_str()); #else + std::string meminfo; + std::string stats_divider = ", "; +# if defined(__linux__) + std::ifstream statm; + statm.open(stringf("/proc/%lld/statm", (long long)getpid())); + if (statm.is_open()) { + int sz_total, sz_resident; + statm >> sz_total >> sz_resident; + meminfo = stringf(", MEM: %.2f MB total, %.2f MB resident", + sz_total * (getpagesize() / 1024.0 / 1024.0), + 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; getrusage(RUSAGE_SELF, &ru_buffer); - log("End of script. Logfile hash: %s, CPU: user %.2fs system %.2fs\n", hash.c_str(), - ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec, - ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec); + log("End of script. Logfile hash: %s%sCPU: user %.2fs system %.2fs%s\n", hash.c_str(), + stats_divider.c_str(), ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec, + ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec, meminfo.c_str()); #endif log("%s\n", yosys_version_str); int64_t total_ns = 0; - std::set> timedat; + std::set> timedat; for (auto &it : pass_register) if (it.second->call_counter) { @@ -322,37 +575,49 @@ int main(int argc, char **argv) timedat.insert(make_tuple(it.second->runtime_ns + 1, it.second->call_counter, it.first)); } - int out_count = 0; - log("Time spent:"); - for (auto it = timedat.rbegin(); it != timedat.rend() && out_count < 4; it++, out_count++) { - if (out_count >= 2 && (std::get<0>(*it) < 1000000000 || int(100*std::get<0>(*it) / total_ns) < 20)) { - log(", ..."); - break; + if (timing_details) + { + log("Time spent:\n"); + for (auto it = timedat.rbegin(); it != timedat.rend(); it++) { + log("%5d%% %5d calls %8.3f sec %s\n", int(100*std::get<0>(*it) / total_ns), + std::get<1>(*it), std::get<0>(*it) / 1000000000.0, std::get<2>(*it).c_str()); + } + } + else + { + int out_count = 0; + log("Time spent:"); + for (auto it = timedat.rbegin(); it != timedat.rend() && out_count < 4; it++, out_count++) { + if (out_count >= 2 && (std::get<0>(*it) < 1000000000 || int(100*std::get<0>(*it) / total_ns) < 20)) { + log(", ..."); + break; + } + log("%s %d%% %dx %s (%d sec)", out_count ? "," : "", int(100*std::get<0>(*it) / total_ns), + std::get<1>(*it), std::get<2>(*it).c_str(), int(std::get<0>(*it) / 1000000000)); } - log("%s %d%% %dx %s (%d sec)", out_count ? "," : "", int(100*std::get<0>(*it) / total_ns), - std::get<1>(*it), std::get<2>(*it).c_str(), int(std::get<0>(*it) / 1000000000)); + log("%s\n", out_count ? "" : " no commands executed"); } - log("%s\n", out_count ? "" : " no commands executed"); } -#ifdef COVER_ACTIVE +#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__)) if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE")) { - char filename_buffer[4096]; + string filename; FILE *f; if (getenv("YOSYS_COVER_DIR")) { - snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", getenv("YOSYS_COVER_DIR"), getpid()); - f = fdopen(mkstemps(filename_buffer, 4), "w"); + filename = stringf("%s/yosys_cover_%d_XXXXXX.txt", getenv("YOSYS_COVER_DIR"), getpid()); + filename = make_temp_file(filename); } else { - snprintf(filename_buffer, 4096, "%s", getenv("YOSYS_COVER_FILE")); - f = fopen(filename_buffer, "a+"); + filename = getenv("YOSYS_COVER_FILE"); } + f = fopen(filename.c_str(), "a+"); + if (f == NULL) - log_error("Can't create coverage file `%s'.\n", filename_buffer); + log_error("Can't create coverage file `%s'.\n", filename.c_str()); - log("\n", filename_buffer); + log("\n", filename.c_str()); for (auto &it : get_coverage_data()) fprintf(f, "%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str()); @@ -361,22 +626,17 @@ int main(int argc, char **argv) } #endif + yosys_atexit(); + + memhasher_off(); if (call_abort) abort(); -#ifdef YOSYS_ENABLE_READLINE - if (!history_file.empty()) { - if (history_offset > 0) { - history_truncate_file(history_file.c_str(), 100); - append_history(where_history() - history_offset, history_file.c_str()); - } else - write_history(history_file.c_str()); - } - - clear_history(); - HIST_ENTRY **hist_list = history_list(); - if (hist_list != NULL) - free(hist_list); + log_flush(); +#if defined(_MSC_VER) + _exit(0); +#elif defined(_WIN32) + _Exit(0); #endif yosys_shutdown(); @@ -384,3 +644,5 @@ int main(int argc, char **argv) return 0; } +#endif /* EMSCRIPTEN */ +