Add a few more filename rewrites
[yosys.git] / kernel / register.cc
index 9452eb3554ed0f1a0185724ea6bea54255cd0ee5..26da96b95b6d9e62a217f3577050a25d510c4d38 100644 (file)
@@ -2,11 +2,11 @@
  *  yosys -- Yosys Open SYnthesis Suite
  *
  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *  
+ *
  *  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
@@ -18,6 +18,8 @@
  */
 
 #include "kernel/yosys.h"
+#include "kernel/satgen.h"
+
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -78,11 +80,15 @@ Pass::pre_post_exec_state_t Pass::pre_execute()
        state.begin_ns = PerformanceTimer::query();
        state.parent_pass = current_pass;
        current_pass = this;
+       clear_flags();
        return state;
 }
 
 void Pass::post_execute(Pass::pre_post_exec_state_t state)
 {
+       IdString::checkpoint();
+       log_suppressed();
+
        int64_t time_ns = PerformanceTimer::query() - state.begin_ns;
        runtime_ns += time_ns;
        current_pass = state.parent_pass;
@@ -97,6 +103,10 @@ void Pass::help()
        log("\n");
 }
 
+void Pass::clear_flags()
+{
+}
+
 void Pass::cmd_log_args(const std::vector<std::string> &args)
 {
        if (args.size() <= 1)
@@ -148,9 +158,9 @@ void Pass::call(RTLIL::Design *design, std::string command)
        std::vector<std::string> args;
 
        std::string cmd_buf = command;
-       std::string tok = next_token(cmd_buf, " \t\r\n");
+       std::string tok = next_token(cmd_buf, " \t\r\n", true);
 
-       if (tok.empty() || tok[0] == '#')
+       if (tok.empty())
                return;
 
        if (tok[0] == '!') {
@@ -158,16 +168,21 @@ void Pass::call(RTLIL::Design *design, std::string command)
                while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' ||
                                cmd_buf.back() == '\r' || cmd_buf.back() == '\n'))
                        cmd_buf.resize(cmd_buf.size()-1);
-               log_header("Shell command: %s\n", cmd_buf.c_str());
-               int retCode = system(cmd_buf.c_str());
+               log_header(design, "Shell command: %s\n", cmd_buf.c_str());
+               int retCode = run_command(cmd_buf);
                if (retCode != 0)
                        log_cmd_error("Shell command returned error code %d.\n", retCode);
                return;
        }
 
        while (!tok.empty()) {
-               if (tok == "#")
-                       break;
+               if (tok[0] == '#') {
+                       int stop;
+                       for (stop = 0; stop < GetSize(cmd_buf); stop++)
+                               if (cmd_buf[stop] == '\r' || cmd_buf[stop] == '\n')
+                                       break;
+                       cmd_buf = cmd_buf.substr(stop);
+               } else
                if (tok.back() == ';') {
                        int num_semikolon = 0;
                        while (!tok.empty() && tok.back() == ';')
@@ -182,7 +197,19 @@ void Pass::call(RTLIL::Design *design, std::string command)
                                call(design, "clean -purge");
                } else
                        args.push_back(tok);
-               tok = next_token(cmd_buf, " \t\r\n");
+               bool found_nl = false;
+               for (auto c : cmd_buf) {
+                       if (c == ' ' || c == '\t')
+                               continue;
+                       if (c == '\r' || c == '\n')
+                               found_nl = true;
+                       break;
+               }
+               if (found_nl) {
+                       call(design, args);
+                       args.clear();
+               }
+               tok = next_token(cmd_buf, " \t\r\n", true);
        }
 
        call(design, args);
@@ -190,7 +217,7 @@ void Pass::call(RTLIL::Design *design, std::string command)
 
 void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
 {
-       if (args.size() == 0 || args[0][0] == '#')
+       if (args.size() == 0 || args[0][0] == '#' || args[0][0] == ':')
                return;
 
        if (echo_mode) {
@@ -263,6 +290,60 @@ void Pass::call_on_module(RTLIL::Design *design, RTLIL::Module *module, std::vec
        design->selected_active_module = backup_selected_active_module;
 }
 
+bool ScriptPass::check_label(std::string label, std::string info)
+{
+       if (active_design == nullptr) {
+               log("\n");
+               if (info.empty())
+                       log("    %s:\n", label.c_str());
+               else
+                       log("    %s:    %s\n", label.c_str(), info.c_str());
+               return true;
+       } else {
+               if (!active_run_from.empty() && active_run_from == active_run_to) {
+                       block_active = (label == active_run_from);
+               } else {
+                       if (label == active_run_from)
+                               block_active = true;
+                       if (label == active_run_to)
+                               block_active = false;
+               }
+               return block_active;
+       }
+}
+
+void ScriptPass::run(std::string command, std::string info)
+{
+       if (active_design == nullptr) {
+               if (info.empty())
+                       log("        %s\n", command.c_str());
+               else
+                       log("        %s    %s\n", command.c_str(), info.c_str());
+       } else
+               Pass::call(active_design, command);
+}
+
+void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to)
+{
+       help_mode = false;
+       active_design = design;
+       block_active = run_from.empty();
+       active_run_from = run_from;
+       active_run_to = run_to;
+       script();
+}
+
+void ScriptPass::help_script()
+{
+       clear_flags();
+       help_mode = true;
+       active_design = nullptr;
+       block_active = true;
+       active_run_from.clear();
+       active_run_to.clear();
+       script();
+}
+
 Frontend::Frontend(std::string name, std::string short_help) :
                Pass(name.rfind("=", 0) == 0 ? name.substr(1) : "read_" + name, short_help),
                frontend_name(name.rfind("=", 0) == 0 ? name.substr(1) : name)
@@ -304,7 +385,8 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
        bool called_with_fp = f != NULL;
 
        next_args.clear();
-       for (; argidx < args.size(); argidx++)
+
+       if (argidx < args.size())
        {
                std::string arg = args[argidx];
 
@@ -333,17 +415,23 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
                                        if (buffer.size() > 0 && (buffer[buffer.size() - 1] == '\n' || buffer[buffer.size() - 1] == '\r'))
                                                break;
                                }
-                               int indent = buffer.find_first_not_of(" \t\r\n");
-                               if (buffer.substr(indent, eot_marker.size()) == eot_marker)
+                               size_t indent = buffer.find_first_not_of(" \t\r\n");
+                               if (indent != std::string::npos && buffer.substr(indent, eot_marker.size()) == eot_marker)
                                        break;
                                last_here_document += buffer;
                        }
                        f = new std::istringstream(last_here_document);
                } else {
-                       if (filename.substr(0, 2) == "+/")
-                               filename = proc_share_dirname() + filename.substr(1);
+                       rewrite_filename(filename);
+                       vector<string> filenames = glob_filename(filename);
+                       filename = filenames.front();
+                       if (GetSize(filenames) > 1) {
+                               next_args.insert(next_args.end(), args.begin(), args.begin()+argidx);
+                               next_args.insert(next_args.end(), filenames.begin()+1, filenames.end());
+                       }
                        std::ifstream *ff = new std::ifstream;
                        ff->open(filename.c_str());
+                       yosys_input_files.insert(filename);
                        if (ff->fail())
                                delete ff;
                        else
@@ -357,12 +445,13 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
                                cmd_error(args, i, "Found option, expected arguments.");
 
                if (argidx+1 < args.size()) {
-                       next_args.insert(next_args.begin(), args.begin(), args.begin()+argidx);
-                       next_args.insert(next_args.begin()+argidx, args.begin()+argidx+1, args.end());
+                       if (next_args.empty())
+                               next_args.insert(next_args.end(), args.begin(), args.begin()+argidx);
+                       next_args.insert(next_args.end(), args.begin()+argidx+1, args.end());
                        args.erase(args.begin()+argidx+1, args.end());
                }
-               break;
        }
+
        if (f == NULL)
                cmd_error(args, argidx, "No filename given.");
 
@@ -456,8 +545,10 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
                }
 
                filename = arg;
+               rewrite_filename(filename);
                std::ofstream *ff = new std::ofstream;
                ff->open(filename.c_str(), std::ofstream::trunc);
+               yosys_output_files.insert(filename);
                if (ff->fail()) {
                        delete ff;
                        log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
@@ -516,23 +607,36 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f
        design->check();
 }
 
+static struct CellHelpMessages {
+       dict<string, string> cell_help, cell_code;
+       CellHelpMessages() {
+#include "techlibs/common/simlib_help.inc"
+#include "techlibs/common/simcells_help.inc"
+               cell_help.sort();
+               cell_code.sort();
+       }
+} cell_help_messages;
+
 struct HelpPass : public Pass {
        HelpPass() : Pass("help", "display help messages") { }
-       virtual void help()
+       void help() YS_OVERRIDE
        {
                log("\n");
-               log("    help  .............  list all commands\n");
-               log("    help <command>  ...  print help message for given command\n");
-               log("    help -all  ........  print complete command reference\n");
+               log("    help  ................  list all commands\n");
+               log("    help <command>  ......  print help message for given command\n");
+               log("    help -all  ...........  print complete command reference\n");
+               log("\n");
+               log("    help -cells ..........  list all cell types\n");
+               log("    help <celltype>  .....  print help message for given cell type\n");
+               log("    help <celltype>+  ....  print verilog code for given cell type\n");
                log("\n");
        }
        void escape_tex(std::string &tex)
        {
-               size_t pos = 0;
-               while ((pos = tex.find('_', pos)) != std::string::npos) {
+               for (size_t pos = 0; (pos = tex.find('_', pos)) != std::string::npos; pos += 2)
                        tex.replace(pos, 1, "\\_");
-                       pos += 2;
-               }
+               for (size_t pos = 0; (pos = tex.find('$', pos)) != std::string::npos; pos += 2)
+                       tex.replace(pos, 1, "\\$");
        }
        void write_tex(FILE *f, std::string cmd, std::string title, std::string text)
        {
@@ -584,7 +688,7 @@ struct HelpPass : public Pass {
 
                fclose(f);
        }
-       virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+       void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
        {
                if (args.size() == 1) {
                        log("\n");
@@ -592,6 +696,7 @@ struct HelpPass : public Pass {
                                log("    %-20s %s\n", it.first.c_str(), it.second->short_help.c_str());
                        log("\n");
                        log("Type 'help <command>' for more information on a command.\n");
+                       log("Type 'help -cells' for a list of all cell types.\n");
                        log("\n");
                        return;
                }
@@ -607,6 +712,18 @@ struct HelpPass : public Pass {
                                        it.second->help();
                                }
                        }
+                       else if (args[1] == "-cells") {
+                               log("\n");
+                               for (auto &it : cell_help_messages.cell_help) {
+                                       string line = split_tokens(it.second, "\n").at(0);
+                                       string cell_name = next_token(line);
+                                       log("    %-15s %s\n", cell_name.c_str(), line.c_str());
+                               }
+                               log("\n");
+                               log("Type 'help <cell_type>' for more information on a cell type.\n");
+                               log("\n");
+                               return;
+                       }
                        // this option is undocumented as it is for internal use only
                        else if (args[1] == "-write-tex-command-reference-manual") {
                                FILE *f = fopen("command-reference-manual.tex", "wt");
@@ -632,20 +749,30 @@ struct HelpPass : public Pass {
                                }
                                fclose(f);
                        }
-                       else if (pass_register.count(args[1]) == 0)
-                               log("No such command: %s\n", args[1].c_str());
-                       else
+                       else if (pass_register.count(args[1])) {
                                pass_register.at(args[1])->help();
+                       }
+                       else if (cell_help_messages.cell_help.count(args[1])) {
+                               log("%s", cell_help_messages.cell_help.at(args[1]).c_str());
+                               log("Run 'help %s+' to display the Verilog model for this cell type.\n", args[1].c_str());
+                               log("\n");
+                       }
+                       else if (cell_help_messages.cell_code.count(args[1])) {
+                               log("\n");
+                               log("%s", cell_help_messages.cell_code.at(args[1]).c_str());
+                       }
+                       else
+                               log("No such command or cell type: %s\n", args[1].c_str());
                        return;
                }
 
                help();
        }
 } HelpPass;
+
 struct EchoPass : public Pass {
        EchoPass() : Pass("echo", "turning echoing back of commands on and off") { }
-       virtual void help()
+       void help() YS_OVERRIDE
        {
                log("\n");
                log("    echo on\n");
@@ -658,7 +785,7 @@ struct EchoPass : public Pass {
                log("Do not print all commands to log before executing them. (default)\n");
                log("\n");
        }
-       virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+       void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
        {
                if (args.size() > 2)
                        cmd_error(args, 2, "Unexpected argument.");
@@ -675,6 +802,17 @@ struct EchoPass : public Pass {
                log("echo %s\n", echo_mode ? "on" : "off");
        }
 } EchoPass;
-YOSYS_NAMESPACE_END
 
+SatSolver *yosys_satsolver_list;
+SatSolver *yosys_satsolver;
+
+struct MinisatSatSolver : public SatSolver {
+       MinisatSatSolver() : SatSolver("minisat") {
+               yosys_satsolver = this;
+       }
+       ezSAT *create() YS_OVERRIDE {
+               return new ezMiniSAT();
+       }
+} MinisatSatSolver;
+
+YOSYS_NAMESPACE_END