/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Claire Xenia 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 * 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 "kernel/yosys.h" #include "kernel/hashlib.h" #define CXXOPTS_VECTOR_DELIMITER '\0' #include "libs/cxxopts/include/cxxopts.hpp" #include #include #ifdef YOSYS_ENABLE_READLINE # include # include #endif #ifdef YOSYS_ENABLE_EDITLINE # include #endif #ifdef YOSYS_ENABLE_TCL # include #endif #ifdef YOSYS_ENABLE_PYTHON # include # include namespace py = pybind11; #endif #include #include #include #include #include #ifndef __STDC_FORMAT_MACROS # define __STDC_FORMAT_MACROS #endif #include #if defined (__linux__) || defined(__FreeBSD__) # include # include # include #endif #ifdef __FreeBSD__ # include # include #endif #if !defined(_WIN32) || defined(__MINGW32__) # include #endif #include #include USING_YOSYS_NAMESPACE #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 } #if defined(__OpenBSD__) namespace Yosys { extern char *yosys_argv0; extern char yosys_path[PATH_MAX]; }; #endif #ifdef YOSYS_ENABLE_TCL namespace Yosys { extern int yosys_tcl_interp_init(Tcl_Interp *interp); extern void yosys_tcl_activate_repl(); }; #endif namespace Yosys { extern bool log_stderr_sink_forced; }; class ColorConsoleLogSink : public LogSink { public: explicit ColorConsoleLogSink(bool err, bool quiet) : error_output(err), quiet_warnings(quiet) {} void log(const LogMessage &msg) override; bool should_log(const LogMessage &msg) const override; void flush() override; FILE *file_handle() override { return error_output ? nullptr : stdout; } private: bool error_output; bool quiet_warnings; }; bool no_color = false; bool is_colored(FILE *file) { if (no_color) return false; #if defined(_WIN32) HANDLE handle = reinterpret_cast(_get_osfhandle(_fileno(file))); DWORD mode; return handle != INVALID_HANDLE_VALUE && GetConsoleMode(handle, &mode); #else return isatty(fileno(file)); #endif } void ColorConsoleLogSink::flush() { fflush(stdout); fflush(stderr); } bool next_print_log = true; void ColorConsoleLogSink::log(const LogMessage &msg) { FILE *f = (error_output || msg.severity == LogSeverity::Error) ? stderr : stdout; if (logger().get_log_time() && next_print_log) { auto elapsed = msg.timestamp - logger().get_initial_time(); auto us = std::chrono::duration_cast(elapsed); std::string time_str = stringf("[%05d.%06d] ", int(us.count() / 1'000'000),int(us.count() % 1'000'000)); fmt::print(f, fg(fmt::terminal_color::blue), "{}", time_str); next_print_log = false; } if (!msg.src.filename.empty()) fmt::print(f, fg(fmt::terminal_color::bright_cyan), "{}:{}: ", msg.src.filename, msg.src.start_line); switch (msg.severity) { case LogSeverity::Warning: fmt::print(f, fg(fmt::terminal_color::bright_yellow), "{}", msg.prefix); fmt::print(f, fg(fmt::terminal_color::blue) | fmt::emphasis::bold, "{}", msg.message); break; case LogSeverity::Error: case LogSeverity::NonFatalError: fmt::print(f, fg(fmt::terminal_color::bright_red), "{}", msg.prefix); fmt::print(f, fg(fmt::terminal_color::blue) | fmt::emphasis::bold, "{}", msg.message); break; case LogSeverity::Header: fmt::print(f, fg(fmt::terminal_color::cyan) | fmt::emphasis::bold, "{}", msg.prefix); fmt::print(f, fg(fmt::terminal_color::white) | fmt::emphasis::bold, "{}", msg.message); break; case LogSeverity::Highlight: fmt::print(f, fg(fmt::terminal_color::cyan) | fmt::emphasis::bold, "{}{}", msg.prefix, msg.message); break; case LogSeverity::Comment: case LogSeverity::Debug: fmt::print(f, fg(fmt::terminal_color::bright_black), "{}{}", msg.prefix, msg.message); break; case LogSeverity::Info: default: if (!msg.prefix.empty()) fmt::print(f, fg(fmt::terminal_color::bright_black), "{}", msg.prefix); fmt::print(f, "{}", msg.message); break; } if (!msg.message.empty()) next_print_log = msg.message.back() == '\n'; } bool ColorConsoleLogSink::should_log(const LogMessage &msg) const { return (!error_output) || (msg.severity == LogSeverity::Error || msg.severity == LogSeverity::NonFatalError || (msg.severity == LogSeverity::Warning && !quiet_warnings) || log_stderr_sink_forced); } #ifdef _WIN32 int wmain(int argc, wchar_t **wargv) { // Configure ASCII functions like fopen() to use UTF-8 filenames. // See https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=msvc-170#utf-8-support #ifdef _UCRT setlocale(LC_ALL, ".UTF-8"); #endif // Configure the Win32 console to use UTF-8. SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); std::vector uargs; for (int i = 0; i < argc; i++) { int usize = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, NULL); char *uarg = (char *)malloc(usize); WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, uarg, usize, NULL, NULL); uargs.push_back(uarg); } uargs.push_back(NULL); char **argv = uargs.data(); #else int main(int argc, char **argv) { #endif auto wall_clock_start = std::chrono::steady_clock::now(); std::string frontend_command = "auto"; std::string backend_command = "auto"; std::vector vlog_defines; std::vector passes_commands; std::vector frontend_files; std::vector plugin_filenames; std::vector special_args; std::string output_filename = ""; std::string scriptfile = ""; std::string depsfile = ""; std::string topmodule = ""; std::string perffile = ""; bool scriptfile_tcl = false; bool scriptfile_python = false; bool print_banner = true; bool print_stats = true; bool call_abort = false; bool timing_details = false; bool run_shell = true; bool run_tcl_shell = false; bool mode_v = false; bool mode_q = false; bool quiet_warnings = false; bool log_stderr = false; no_color = std::getenv("NO_COLOR") != nullptr; cxxopts::Options options(argv[0], "Yosys Open SYnthesis Suite"); options.set_width(SIZE_MAX); options.add_options("operation") ("b,backend", "use for the output file specified on the command line", cxxopts::value(), "") ("f,frontend", "use for the input files on the command line", cxxopts::value(), "") ("s,scriptfile", "execute the commands in ", cxxopts::value(), "") #ifdef YOSYS_ENABLE_TCL ("c,tcl-scriptfile", "execute the commands in the TCL (see 'help tcl' for details)", cxxopts::value(),"") ("C,tcl-interactive", "enters TCL interactive shell mode") #endif // YOSYS_ENABLE_TCL #ifdef YOSYS_ENABLE_PYTHON ("y,py-scriptfile", "execute the Python