* 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
*/
#include "kernel/yosys.h"
+#include "kernel/satgen.h"
+
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
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;
log("\n");
}
+void Pass::clear_flags()
+{
+}
+
void Pass::cmd_log_args(const std::vector<std::string> &args)
{
if (args.size() <= 1)
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] == '!') {
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() == ';')
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);
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) {
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)
bool called_with_fp = f != NULL;
next_args.clear();
- for (; argidx < args.size(); argidx++)
+
+ if (argidx < args.size())
{
std::string arg = args[argidx];
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
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.");
}
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));
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)
{
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");
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;
}
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");
}
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");
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.");
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