Add log_experimental() and experimental() API and "yosys -x"
[yosys.git] / kernel / register.cc
index e4237cac4aa451187335c391cb03b19b08b43be7..e59d59654b101c691039f8b8cb3c704eff856c09 100644 (file)
@@ -48,7 +48,7 @@ using zlib to write gzip-compressed data every time the stream is flushed.
 */
 class gzip_ostream : public std::ostream  {
 public:
-       gzip_ostream()
+       gzip_ostream() : std::ostream(nullptr)
        {
                rdbuf(&outbuf);
        }
@@ -71,7 +71,7 @@ private:
                        str("");
                        return 0;
                }
-               ~gzip_streambuf()
+               virtual ~gzip_streambuf()
                {
                        sync();
                        gzclose(gzf);
@@ -114,20 +114,35 @@ void Pass::run_register()
 
 void Pass::init_register()
 {
+       vector<Pass*> added_passes;
        while (first_queued_pass) {
+               added_passes.push_back(first_queued_pass);
                first_queued_pass->run_register();
                first_queued_pass = first_queued_pass->next_queued_pass;
        }
+       for (auto added_pass : added_passes)
+               added_pass->on_register();
 }
 
 void Pass::done_register()
 {
+       for (auto &it : pass_register)
+               it.second->on_shutdown();
+
        frontend_register.clear();
        pass_register.clear();
        backend_register.clear();
        log_assert(first_queued_pass == NULL);
 }
 
+void Pass::on_register()
+{
+}
+
+void Pass::on_shutdown()
+{
+}
+
 Pass::~Pass()
 {
 }
@@ -200,7 +215,7 @@ void Pass::extra_args(std::vector<std::string> args, size_t argidx, RTLIL::Desig
        {
                std::string arg = args[argidx];
 
-               if (arg.substr(0, 1) == "-")
+               if (arg.compare(0, 1, "-") == 0)
                        cmd_error(args, argidx, "Unknown option or option in arguments.");
 
                if (!select)
@@ -289,6 +304,9 @@ void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
        if (pass_register.count(args[0]) == 0)
                log_cmd_error("No such command: %s (type 'help' for a command overview)\n", args[0].c_str());
 
+       if (pass_register[args[0]]->experimental_flag)
+               log_experimental("%s", args[0].c_str());
+
        size_t orig_sel_stack_pos = design->selection_stack.size();
        auto state = pass_register[args[0]]->pre_execute();
        pass_register[args[0]]->execute(args, design);
@@ -439,7 +457,7 @@ void Frontend::execute(std::vector<std::string> args, RTLIL::Design *design)
 FILE *Frontend::current_script_file = NULL;
 std::string Frontend::last_here_document;
 
-void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<std::string> args, size_t argidx)
+void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<std::string> args, size_t argidx, bool bin_input)
 {
        bool called_with_fp = f != NULL;
 
@@ -449,7 +467,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
        {
                std::string arg = args[argidx];
 
-               if (arg.substr(0, 1) == "-")
+               if (arg.compare(0, 1, "-") == 0)
                        cmd_error(args, argidx, "Unknown option or option in arguments.");
                if (f != NULL)
                        cmd_error(args, argidx, "Extra filename argument in direct file mode.");
@@ -457,7 +475,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
                filename = arg;
                if (filename == "<<" && argidx+1 < args.size())
                        filename += args[++argidx];
-               if (filename.substr(0, 2) == "<<") {
+               if (filename.compare(0, 2, "<<") == 0) {
                        if (Frontend::current_script_file == NULL)
                                log_error("Unexpected here document '%s' outside of script!\n", filename.c_str());
                        if (filename.size() <= 2)
@@ -475,7 +493,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
                                                break;
                                }
                                size_t indent = buffer.find_first_not_of(" \t\r\n");
-                               if (indent != std::string::npos && buffer.substr(indent, eot_marker.size()) == eot_marker)
+                               if (indent != std::string::npos && buffer.compare(indent, eot_marker.size(), eot_marker) == 0)
                                        break;
                                last_here_document += buffer;
                        }
@@ -489,7 +507,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
                                next_args.insert(next_args.end(), filenames.begin()+1, filenames.end());
                        }
                        std::ifstream *ff = new std::ifstream;
-                       ff->open(filename.c_str());
+                       ff->open(filename.c_str(), bin_input ? std::ifstream::binary : std::ifstream::in);
                        yosys_input_files.insert(filename);
                        if (ff->fail())
                                delete ff;
@@ -498,7 +516,15 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
                        if (f != NULL) {
                                // Check for gzip magic
                                unsigned char magic[3];
-                               int n = readsome(*ff, reinterpret_cast<char*>(magic), 3);
+                               int n = 0;
+                               while (n < 3)
+                               {
+                                       int c = ff->get();
+                                       if (c != EOF) {
+                                               magic[n] = (unsigned char) c;
+                                       }
+                                       n++;
+                               }
                                if (n == 3 && magic[0] == 0x1f && magic[1] == 0x8b) {
        #ifdef YOSYS_ENABLE_ZLIB
                                        log("Found gzip magic in file `%s', decompressing using zlib.\n", filename.c_str());
@@ -522,7 +548,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
                        log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
 
                for (size_t i = argidx+1; i < args.size(); i++)
-                       if (args[i].substr(0, 1) == "-")
+                       if (args[i].compare(0, 1, "-") == 0)
                                cmd_error(args, i, "Found option, expected arguments.");
 
                if (argidx+1 < args.size()) {
@@ -604,7 +630,7 @@ void Backend::execute(std::vector<std::string> args, RTLIL::Design *design)
                delete f;
 }
 
-void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<std::string> args, size_t argidx)
+void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<std::string> args, size_t argidx, bool bin_output)
 {
        bool called_with_fp = f != NULL;
 
@@ -612,7 +638,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
        {
                std::string arg = args[argidx];
 
-               if (arg.substr(0, 1) == "-" && arg != "-")
+               if (arg.compare(0, 1, "-") == 0 && arg != "-")
                        cmd_error(args, argidx, "Unknown option or option in arguments.");
                if (f != NULL)
                        cmd_error(args, argidx, "Extra filename argument in direct file mode.");
@@ -625,7 +651,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
 
                filename = arg;
                rewrite_filename(filename);
-               if (filename.size() > 3 && filename.substr(filename.size()-3) == ".gz") {
+               if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".gz") == 0) {
 #ifdef YOSYS_ENABLE_ZLIB
                        gzip_ostream *gf = new gzip_ostream;
                        if (!gf->open(filename)) {
@@ -639,7 +665,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
 #endif
                } else {
                        std::ofstream *ff = new std::ofstream;
-                       ff->open(filename.c_str(), std::ofstream::trunc);
+                       ff->open(filename.c_str(), bin_output ? (std::ofstream::trunc | std::ofstream::binary) : std::ofstream::trunc);
                        yosys_output_files.insert(filename);
                        if (ff->fail()) {
                                delete ff;
@@ -801,6 +827,11 @@ struct HelpPass : public Pass {
                                                log("=");
                                        log("\n");
                                        it.second->help();
+                                       if (it.second->experimental_flag) {
+                                               log("\n");
+                                               log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", it.first.c_str());
+                                               log("\n");
+                                       }
                                }
                        }
                        else if (args[1] == "-cells") {
@@ -823,6 +854,11 @@ struct HelpPass : public Pass {
                                        std::ostringstream buf;
                                        log_streams.push_back(&buf);
                                        it.second->help();
+                                       if (it.second->experimental_flag) {
+                                               log("\n");
+                                               log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", it.first.c_str());
+                                               log("\n");
+                                       }
                                        log_streams.pop_back();
                                        write_tex(f, it.first, it.second->short_help, buf.str());
                                }
@@ -835,6 +871,11 @@ struct HelpPass : public Pass {
                                        std::ostringstream buf;
                                        log_streams.push_back(&buf);
                                        it.second->help();
+                                       if (it.second->experimental_flag) {
+                                               log("\n");
+                                               log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", it.first.c_str());
+                                               log("\n");
+                                       }
                                        log_streams.pop_back();
                                        write_html(f, it.first, it.second->short_help, buf.str());
                                }
@@ -842,6 +883,11 @@ struct HelpPass : public Pass {
                        }
                        else if (pass_register.count(args[1])) {
                                pass_register.at(args[1])->help();
+                               if (pass_register.at(args[1])->experimental_flag) {
+                                       log("\n");
+                                       log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", args[1].c_str());
+                                       log("\n");
+                               }
                        }
                        else if (cell_help_messages.cell_help.count(args[1])) {
                                log("%s", cell_help_messages.cell_help.at(args[1]).c_str());