aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/register.cc
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/register.cc')
-rw-r--r--kernel/register.cc187
1 files changed, 106 insertions, 81 deletions
diff --git a/kernel/register.cc b/kernel/register.cc
index 226963fda..9ffb17c1a 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -108,7 +108,9 @@ Pass::Pass(std::string name, std::string short_help) : pass_name(name), short_he
void Pass::run_register()
{
- log_assert(pass_register.count(pass_name) == 0);
+ if (pass_register.count(pass_name))
+ log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str());
+
pass_register[pass_name] = this;
}
@@ -445,10 +447,13 @@ Frontend::Frontend(std::string name, std::string short_help) :
void Frontend::run_register()
{
- log_assert(pass_register.count(pass_name) == 0);
+ if (pass_register.count(pass_name))
+ log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str());
pass_register[pass_name] = this;
- log_assert(frontend_register.count(frontend_name) == 0);
+ if (frontend_register.count(frontend_name))
+ log_error("Unable to register frontend '%s', frontend already exists!\n", frontend_name.c_str());
+
frontend_register[frontend_name] = this;
}
@@ -526,10 +531,11 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
std::ifstream *ff = new std::ifstream;
ff->open(filename.c_str(), bin_input ? std::ifstream::binary : std::ifstream::in);
yosys_input_files.insert(filename);
- if (ff->fail())
+ if (ff->fail()) {
delete ff;
- else
- f = ff;
+ ff = nullptr;
+ }
+ f = ff;
if (f != NULL) {
// Check for gzip magic
unsigned char magic[3];
@@ -626,10 +632,12 @@ Backend::Backend(std::string name, std::string short_help) :
void Backend::run_register()
{
- log_assert(pass_register.count(pass_name) == 0);
+ if (pass_register.count(pass_name))
+ log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str());
pass_register[pass_name] = this;
- log_assert(backend_register.count(backend_name) == 0);
+ if (backend_register.count(backend_name))
+ log_error("Unable to register backend '%s', backend already exists!\n", backend_name.c_str());
backend_register[backend_name] = this;
}
@@ -765,61 +773,98 @@ struct HelpPass : public Pass {
log(" help <celltype>+ .... print verilog code for given cell type\n");
log("\n");
}
- void escape_tex(std::string &tex)
- {
- for (size_t pos = 0; (pos = tex.find('_', pos)) != std::string::npos; pos += 2)
- tex.replace(pos, 1, "\\_");
- 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)
+ void write_rst(std::string cmd, std::string title, std::string text)
{
- size_t begin = text.find_first_not_of("\n"), end = text.find_last_not_of("\n");
- if (begin != std::string::npos && end != std::string::npos && begin < end)
- text = text.substr(begin, end-begin+1);
- std::string cmd_unescaped = cmd;
- escape_tex(cmd);
- escape_tex(title);
- fprintf(f, "\\section{%s -- %s}\n", cmd.c_str(), title.c_str());
- fprintf(f, "\\label{cmd:%s}\n", cmd_unescaped.c_str());
- fprintf(f, "\\begin{lstlisting}[numbers=left,frame=single]\n");
- fprintf(f, "%s\n\\end{lstlisting}\n\n", text.c_str());
- }
- void escape_html(std::string &html)
- {
- size_t pos = 0;
- while ((pos = html.find_first_of("<>&", pos)) != std::string::npos)
- switch (html[pos]) {
- case '<':
- html.replace(pos, 1, "&lt;");
- pos += 4;
- break;
- case '>':
- html.replace(pos, 1, "&gt;");
- pos += 4;
- break;
- case '&':
- html.replace(pos, 1, "&amp;");
- pos += 5;
- break;
+ FILE *f = fopen(stringf("docs/source/cmd/%s.rst", cmd.c_str()).c_str(), "wt");
+ // make header
+ size_t char_len = cmd.length() + 3 + title.length();
+ std::string title_line = "\n";
+ title_line.insert(0, char_len, '=');
+ fprintf(f, "%s", title_line.c_str());
+ fprintf(f, "%s - %s\n", cmd.c_str(), title.c_str());
+ fprintf(f, "%s\n", title_line.c_str());
+ fprintf(f, ".. raw:: latex\n\n \\begin{comment}\n\n");
+
+ // render html
+ fprintf(f, ":code:`yosys> help %s`\n", cmd.c_str());
+ fprintf(f, "--------------------------------------------------------------------------------\n\n");
+ fprintf(f, ".. container:: cmdref\n");
+ std::stringstream ss;
+ std::string textcp = text;
+ ss << text;
+ bool IsUsage = true;
+ int blank_count = 0;
+ size_t def_strip_count = 0;
+ bool WasDefinition = false;
+ for (std::string line; std::getline(ss, line, '\n');) {
+ // find position of first non space character
+ std::size_t first_pos = line.find_first_not_of(" \t");
+ std::size_t last_pos = line.find_last_not_of(" \t");
+ if (first_pos == std::string::npos) {
+ // skip formatting empty lines
+ if (!WasDefinition)
+ fputc('\n', f);
+ blank_count += 1;
+ continue;
}
- }
- void write_html(FILE *idxf, std::string cmd, std::string title, std::string text)
- {
- FILE *f = fopen(stringf("cmd_%s.in", cmd.c_str()).c_str(), "wt");
- fprintf(idxf, "<li><a href=\"cmd_%s.html\"> ", cmd.c_str());
- escape_html(cmd);
- escape_html(title);
- escape_html(text);
-
- fprintf(idxf, "%s</a> <span>%s</span></a>\n", cmd.c_str(), title.c_str());
-
- fprintf(f, "@cmd_header %s@\n", cmd.c_str());
- fprintf(f, "<h1>%s - %s</h1>\n", cmd.c_str(), title.c_str());
- fprintf(f, "<pre>%s</pre>\n", text.c_str());
- fprintf(f, "@footer@\n");
+ // strip leading and trailing whitespace
+ std::string stripped_line = line.substr(first_pos, last_pos - first_pos +1);
+ bool IsDefinition = stripped_line[0] == '-';
+ IsDefinition &= stripped_line[1] != ' ' && stripped_line[1] != '>';
+ bool IsDedent = def_strip_count && first_pos <= def_strip_count;
+ bool IsIndent = first_pos == 2 || first_pos == 4;
+ if (cmd.compare(0, 7, "verific") == 0)
+ // verific.cc has strange and different formatting from the rest
+ IsIndent = false;
+
+ // another usage block
+ bool NewUsage = stripped_line.find(cmd) == 0;
+
+ if (IsUsage) {
+ if (stripped_line.compare(0, 4, "See ") == 0) {
+ // description refers to another function
+ fprintf(f, "\n %s\n", stripped_line.c_str());
+ } else {
+ // usage should be the first line of help output
+ fprintf(f, "\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str());
+ WasDefinition = true;
+ }
+ IsUsage = false;
+ } else if (IsIndent && NewUsage && (blank_count >= 2 || WasDefinition)) {
+ // another usage block
+ fprintf(f, "\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str());
+ WasDefinition = true;
+ def_strip_count = 0;
+ } else if (IsIndent && IsDefinition && (blank_count || WasDefinition)) {
+ // format definition term
+ fprintf(f, "\n\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str());
+ WasDefinition = true;
+ def_strip_count = first_pos;
+ } else {
+ if (IsDedent) {
+ fprintf(f, "\n\n ::\n");
+ def_strip_count = first_pos;
+ } else if (WasDefinition) {
+ fprintf(f, " ::\n");
+ WasDefinition = false;
+ }
+ fprintf(f, "\n %s", line.substr(def_strip_count, std::string::npos).c_str());
+ }
+ blank_count = 0;
+ }
+ fputc('\n', f);
+
+ // render latex
+ fprintf(f, ".. raw:: latex\n\n \\end{comment}\n\n");
+ fprintf(f, ".. only:: latex\n\n");
+ fprintf(f, " ::\n\n");
+ std::stringstream ss2;
+ ss2 << textcp;
+ for (std::string line; std::getline(ss2, line, '\n');) {
+ fprintf(f, " %s\n", line.c_str());
+ }
fclose(f);
}
void execute(std::vector<std::string> args, RTLIL::Design*) override
@@ -864,26 +909,7 @@ struct HelpPass : public Pass {
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");
- fprintf(f, "%% Generated using the yosys 'help -write-tex-command-reference-manual' command.\n\n");
- for (auto &it : pass_register) {
- 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());
- }
- fclose(f);
- }
- // this option is undocumented as it is for internal use only
- else if (args[1] == "-write-web-command-reference-manual") {
- FILE *f = fopen("templates/cmd_index.in", "wt");
+ else if (args[1] == "-write-rst-command-reference-manual") {
for (auto &it : pass_register) {
std::ostringstream buf;
log_streams.push_back(&buf);
@@ -894,9 +920,8 @@ struct HelpPass : public Pass {
log("\n");
}
log_streams.pop_back();
- write_html(f, it.first, it.second->short_help, buf.str());
+ write_rst(it.first, it.second->short_help, buf.str());
}
- fclose(f);
}
else if (pass_register.count(args[1])) {
pass_register.at(args[1])->help();