diff --git a/Makefile b/Makefile index 4d1a94bc2..1a5d8a093 100644 --- a/Makefile +++ b/Makefile @@ -890,6 +890,7 @@ MK_TEST_DIRS += tests/sim MK_TEST_DIRS += tests/svtypes MK_TEST_DIRS += tests/techmap MK_TEST_DIRS += tests/various +MK_TEST_DIRS += tests/rtlil ifeq ($(ENABLE_VERIFIC),1) ifneq ($(YOSYS_NOVERIFIC),1) MK_TEST_DIRS += tests/verific diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index cb17432b1..d607be837 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -24,12 +24,23 @@ #include "rtlil_backend.h" #include "kernel/yosys.h" +#include "kernel/utils.h" #include +#include USING_YOSYS_NAMESPACE using namespace RTLIL_BACKEND; YOSYS_NAMESPACE_BEGIN +void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj) +{ + for (const auto& [name, value] : reversed(obj->attributes)) { + f << stringf("%s" "attribute %s ", indent, name); + dump_const(f, value); + f << stringf("\n"); + } +} + void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint) { if (width < 0) @@ -110,8 +121,8 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo dump_sigchunk(f, sig.as_chunk(), autoint); } else { f << stringf("{ "); - for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) { - dump_sigchunk(f, *it, false); + for (const auto& chunk : reversed(sig.chunks())) { + dump_sigchunk(f, chunk, false); f << stringf(" "); } f << stringf("}"); @@ -120,14 +131,10 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire) { - for (auto &it : wire->attributes) { - f << stringf("%s" "attribute %s ", indent, it.first); - dump_const(f, it.second); - f << stringf("\n"); - } + dump_attributes(f, indent, wire); if (wire->driverCell_) { f << stringf("%s" "# driver %s %s\n", indent, - wire->driverCell()->name.c_str(), wire->driverPort().c_str()); + wire->driverCell()->name, wire->driverPort()); } f << stringf("%s" "wire ", indent); if (wire->width != 1) @@ -149,11 +156,7 @@ void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL:: void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory) { - for (auto &it : memory->attributes) { - f << stringf("%s" "attribute %s ", indent, it.first); - dump_const(f, it.second); - f << stringf("\n"); - } + dump_attributes(f, indent, memory); f << stringf("%s" "memory ", indent); if (memory->width != 1) f << stringf("width %d ", memory->width); @@ -166,23 +169,19 @@ void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell) { - for (auto &it : cell->attributes) { - f << stringf("%s" "attribute %s ", indent, it.first); - dump_const(f, it.second); - f << stringf("\n"); - } + dump_attributes(f, indent, cell); f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name); - for (auto &it : cell->parameters) { + for (const auto& [name, param] : reversed(cell->parameters)) { f << stringf("%s parameter%s%s %s ", indent, - (it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", - (it.second.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "", - it.first.c_str()); - dump_const(f, it.second); + (param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", + (param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "", + name); + dump_const(f, param); f << stringf("\n"); } - for (auto &it : cell->connections()) { - f << stringf("%s connect %s ", indent, it.first); - dump_sigspec(f, it.second); + for (const auto& [port, sig] : reversed(cell->connections_)) { + f << stringf("%s connect %s ", indent, port); + dump_sigspec(f, sig); f << stringf("\n"); } f << stringf("%s" "end\n", indent); @@ -190,47 +189,38 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs) { - for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) - { + for (const auto& [lhs, rhs] : cs->actions) { f << stringf("%s" "assign ", indent); - dump_sigspec(f, it->first); + dump_sigspec(f, lhs); f << stringf(" "); - dump_sigspec(f, it->second); + dump_sigspec(f, rhs); f << stringf("\n"); } - for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it) - dump_proc_switch(f, indent, *it); + for (const auto& sw : cs->switches) + dump_proc_switch(f, indent, sw); } void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw) { - for (auto it = sw->attributes.begin(); it != sw->attributes.end(); ++it) { - f << stringf("%s" "attribute %s ", indent, it->first); - dump_const(f, it->second); - f << stringf("\n"); - } + dump_attributes(f, indent, sw); f << stringf("%s" "switch ", indent); dump_sigspec(f, sw->signal); f << stringf("\n"); - for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) + for (const auto case_ : sw->cases) { - for (auto ait = (*it)->attributes.begin(); ait != (*it)->attributes.end(); ++ait) { - f << stringf("%s attribute %s ", indent, ait->first); - dump_const(f, ait->second); - f << stringf("\n"); - } + dump_attributes(f, indent, case_); f << stringf("%s case ", indent); - for (size_t i = 0; i < (*it)->compare.size(); i++) { + for (size_t i = 0; i < case_->compare.size(); i++) { if (i > 0) f << stringf(" , "); - dump_sigspec(f, (*it)->compare[i]); + dump_sigspec(f, case_->compare[i]); } f << stringf("\n"); - dump_proc_case_body(f, indent + " ", *it); + dump_proc_case_body(f, indent + " ", case_); } f << stringf("%s" "end\n", indent); @@ -253,20 +243,16 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT case RTLIL::STi: f << stringf("init\n"); break; } - for (auto &it: sy->actions) { + for (const auto& [lhs, rhs] : sy->actions) { f << stringf("%s update ", indent); - dump_sigspec(f, it.first); + dump_sigspec(f, lhs); f << stringf(" "); - dump_sigspec(f, it.second); + dump_sigspec(f, rhs); f << stringf("\n"); } for (auto &it: sy->mem_write_actions) { - for (auto it2 = it.attributes.begin(); it2 != it.attributes.end(); ++it2) { - f << stringf("%s attribute %s ", indent, it2->first); - dump_const(f, it2->second); - f << stringf("\n"); - } + dump_attributes(f, indent, &it); f << stringf("%s memwr %s ", indent, it.memid); dump_sigspec(f, it.address); f << stringf(" "); @@ -281,15 +267,11 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT void RTLIL_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc) { - for (auto it = proc->attributes.begin(); it != proc->attributes.end(); ++it) { - f << stringf("%s" "attribute %s ", indent, it->first); - dump_const(f, it->second); - f << stringf("\n"); - } + dump_attributes(f, indent, proc); f << stringf("%s" "process %s\n", indent, proc->name); dump_proc_case_body(f, indent + " ", &proc->root_case); - for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it) - dump_proc_sync(f, indent + " ", *it); + for (auto* sync : proc->syncs) + dump_proc_sync(f, indent + " ", sync); f << stringf("%s" "end\n", indent); } @@ -309,11 +291,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu if (print_header) { - for (auto it = module->attributes.begin(); it != module->attributes.end(); ++it) { - f << stringf("%s" "attribute %s ", indent, it->first); - dump_const(f, it->second); - f << stringf("\n"); - } + dump_attributes(f, indent, module); f << stringf("%s" "module %s\n", indent, module->name); @@ -335,40 +313,40 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu if (print_body) { - for (auto it : module->wires()) - if (!only_selected || design->selected(module, it)) { + for (const auto& [_, wire] : reversed(module->wires_)) + if (!only_selected || design->selected(module, wire)) { if (only_selected) f << stringf("\n"); - dump_wire(f, indent + " ", it); + dump_wire(f, indent + " ", wire); } - for (auto it : module->memories) - if (!only_selected || design->selected(module, it.second)) { + for (const auto& [_, mem] : reversed(module->memories)) + if (!only_selected || design->selected(module, mem)) { if (only_selected) f << stringf("\n"); - dump_memory(f, indent + " ", it.second); + dump_memory(f, indent + " ", mem); } - for (auto it : module->cells()) - if (!only_selected || design->selected(module, it)) { + for (const auto& [_, cell] : reversed(module->cells_)) + if (!only_selected || design->selected(module, cell)) { if (only_selected) f << stringf("\n"); - dump_cell(f, indent + " ", it); + dump_cell(f, indent + " ", cell); } - for (auto it : module->processes) - if (!only_selected || design->selected(module, it.second)) { + for (const auto& [_, process] : reversed(module->processes)) + if (!only_selected || design->selected(module, process)) { if (only_selected) f << stringf("\n"); - dump_proc(f, indent + " ", it.second); + dump_proc(f, indent + " ", process); } bool first_conn_line = true; - for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { + for (const auto& [lhs, rhs] : module->connections()) { bool show_conn = !only_selected || design->selected_whole_module(module->name); if (!show_conn) { - RTLIL::SigSpec sigs = it->first; - sigs.append(it->second); + RTLIL::SigSpec sigs = lhs; + sigs.append(rhs); for (auto &c : sigs.chunks()) { if (c.wire == NULL || !design->selected(module, c.wire)) continue; @@ -378,7 +356,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu if (show_conn) { if (only_selected && first_conn_line) f << stringf("\n"); - dump_conn(f, indent + " ", it->first, it->second); + dump_conn(f, indent + " ", lhs, rhs); first_conn_line = false; } } @@ -394,7 +372,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl if (!flag_m) { int count_selected_mods = 0; - for (auto module : design->modules()) { + for (auto* module : design->modules()) { if (design->selected_whole_module(module->name)) flag_m = true; if (design->selected(module)) @@ -410,7 +388,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl f << stringf("autoidx %d\n", autoidx); } - for (auto module : design->modules()) { + for (const auto& [_, module] : reversed(design->modules_)) { if (!only_selected || design->selected(module)) { if (only_selected) f << stringf("\n"); @@ -438,10 +416,14 @@ struct RTLILBackend : public Backend { log(" -selected\n"); log(" only write selected parts of the design.\n"); log("\n"); + log(" -sort\n"); + log(" sort design in-place (used to be default).\n"); + log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) override { bool selected = false; + bool do_sort = false; log_header(design, "Executing RTLIL backend.\n"); @@ -452,14 +434,19 @@ struct RTLILBackend : public Backend { selected = true; continue; } + if (arg == "-sort") { + do_sort = true; + continue; + } break; } extra_args(f, filename, args, argidx); - design->sort(); - log("Output filename: %s\n", filename); + if (do_sort) + design->sort(); + *f << stringf("# Generated by %s\n", yosys_maybe_version()); RTLIL_BACKEND::dump_design(*f, design, selected, true, false); } @@ -528,7 +515,7 @@ struct DumpPass : public Pass { if (!empty) { rewrite_filename(filename); std::ofstream *ff = new std::ofstream; - ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc); + ff->open(filename, append ? std::ofstream::app : std::ofstream::trunc); if (ff->fail()) { delete ff; log_error("Can't open file `%s' for writing: %s\n", filename, strerror(errno)); diff --git a/backends/rtlil/rtlil_backend.h b/backends/rtlil/rtlil_backend.h index 35829729c..dd7347def 100644 --- a/backends/rtlil/rtlil_backend.h +++ b/backends/rtlil/rtlil_backend.h @@ -31,6 +31,7 @@ YOSYS_NAMESPACE_BEGIN namespace RTLIL_BACKEND { + void dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj); void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true); void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true); void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true); diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 2bdaf40ce..6c9e67dc5 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -229,6 +229,10 @@ struct VerilogFrontend : public Frontend { log(" add 'dir' to the directories which are used when searching include\n"); log(" files\n"); log("\n"); + log(" -relativeshare\n"); + log(" use paths relative to share directory for source locations\n"); + log(" where possible (experimental).\n"); + log("\n"); log("The command 'verilog_defaults' can be used to register default options for\n"); log("subsequent calls to 'read_verilog'.\n"); log("\n"); @@ -273,6 +277,7 @@ struct VerilogFrontend : public Frontend { bool flag_nowb = false; bool flag_nosynthesis = false; bool flag_yydebug = false; + bool flag_relative_share = false; define_map_t defines_map; std::list include_dirs; @@ -450,6 +455,11 @@ struct VerilogFrontend : public Frontend { attributes.push_back(RTLIL::escape_id(args[++argidx])); continue; } + if (arg == "-relativeshare") { + flag_relative_share = true; + log_experimental("read_verilog -relativeshare"); + continue; + } if (arg == "-D" && argidx+1 < args.size()) { std::string name = args[++argidx], value; size_t equal = name.find('='); @@ -490,6 +500,13 @@ struct VerilogFrontend : public Frontend { log("Parsing %s%s input from `%s' to AST representation.\n", parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str()); + log("verilog frontend filename %s\n", filename.c_str()); + if (flag_relative_share) { + auto share_path = proc_share_dirname(); + if (filename.substr(0, share_path.length()) == share_path) + filename = std::string("+/") + filename.substr(share_path.length()); + log("new filename %s\n", filename.c_str()); + } AST::sv_mode_but_global_and_used_for_literally_one_condition = parse_mode.sv; std::string code_after_preproc; diff --git a/kernel/hashlib.h b/kernel/hashlib.h index c95ce1e7b..ed329bba6 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -569,13 +569,16 @@ public: int index; const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { } public: - typedef std::forward_iterator_tag iterator_category; + typedef std::bidirectional_iterator_tag iterator_category; typedef std::pair value_type; typedef ptrdiff_t difference_type; - typedef std::pair* pointer; - typedef std::pair& reference; + typedef const std::pair* pointer; + typedef const std::pair& reference; const_iterator() { } const_iterator operator++() { index--; return *this; } + const_iterator operator++(int) { const_iterator tmp = *this; index--; return tmp; } + const_iterator operator--() { index++; return *this; } + const_iterator operator--(int) { const_iterator tmp = *this; index++; return tmp; } const_iterator operator+=(int amt) { index -= amt; return *this; } bool operator<(const const_iterator &other) const { return index > other.index; } bool operator==(const const_iterator &other) const { return index == other.index; } @@ -609,6 +612,13 @@ public: const std::pair *operator->() const { return &ptr->entries[index].udata; } operator const_iterator() const { return const_iterator(ptr, index); } }; + using reverse_iterator = std::reverse_iterator; + reverse_iterator rbegin() const { + return std::make_reverse_iterator(end()); + } + reverse_iterator rend() const { + return std::make_reverse_iterator(begin()); + } constexpr dict() { @@ -858,7 +868,7 @@ public: const_iterator begin() const { return const_iterator(this, int(entries.size())-1); } const_iterator element(int n) const { return const_iterator(this, int(entries.size())-1-n); } - const_iterator end() const { return const_iterator(nullptr, -1); } + const_iterator end() const { return const_iterator(this, -1); } }; template diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 4f34d6f7b..7d53fdd32 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -5888,6 +5888,7 @@ RTLIL::CaseRule *RTLIL::CaseRule::clone() const RTLIL::CaseRule *new_caserule = new RTLIL::CaseRule; new_caserule->compare = compare; new_caserule->actions = actions; + new_caserule->attributes = attributes; for (auto &it : switches) new_caserule->switches.push_back(it->clone()); return new_caserule; diff --git a/kernel/utils.h b/kernel/utils.h index 6c9fe36a5..5c739aceb 100644 --- a/kernel/utils.h +++ b/kernel/utils.h @@ -21,6 +21,7 @@ // do not depend on any other components of yosys (except stuff like log_*). #include "kernel/yosys.h" +#include #ifndef UTILS_H #define UTILS_H @@ -276,6 +277,16 @@ inline int ceil_log2(int x) #endif } +template +auto reversed(const T& container) { + struct reverse_view { + const T& cont; + auto begin() const { return cont.rbegin(); } + auto end() const { return cont.rend(); } + }; + return reverse_view{container}; +} + YOSYS_NAMESPACE_END #endif diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 8432c27fd..897dd8459 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -122,8 +122,6 @@ struct BugpointPass : public Pass { int run_yosys(RTLIL::Design *design, string runner, string yosys_cmd, string yosys_arg, string suffix, bool catch_err) { - design->sort(); - string bugpoint_file = "bugpoint-case"; if (suffix.size()) bugpoint_file += stringf(".%.8s", suffix); diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 30b8e17ab..281a8795a 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -1032,6 +1032,10 @@ struct TechmapPass : public Pass { log(" -dont_map \n"); log(" leave the given cell type unmapped by ignoring any mapping rules for it\n"); log("\n"); + log(" -relativeshare\n"); + log(" use paths relative to share directory for source locations\n"); + log(" where possible (experimental).\n"); + log("\n"); log("When a module in the map file has the 'techmap_celltype' attribute set, it will\n"); log("match cells with a type that match the text value of this attribute. Otherwise\n"); log("the module name will be used to match the cell. Multiple space-separated cell\n"); @@ -1185,6 +1189,11 @@ struct TechmapPass : public Pass { verilog_frontend += " -I " + args[++argidx]; continue; } + if (args[argidx] == "-relativeshare") { + verilog_frontend += " -relativeshare"; + log_experimental("techmap -relativeshare"); + continue; + } if (args[argidx] == "-assert") { worker.assert_mode = true; continue; diff --git a/passes/tests/raise_error.cc b/passes/tests/raise_error.cc index 7233e78fa..b21ec7d1d 100644 --- a/passes/tests/raise_error.cc +++ b/passes/tests/raise_error.cc @@ -47,7 +47,7 @@ struct RaiseErrorPass : public Pass { extra_args(args, argidx, design, true); RTLIL::NamedObject *err_obj = nullptr; - + for (auto mod : design->all_selected_modules()) { if (mod->has_attribute(ID::raise_error)) { err_obj = mod->clone(); diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 9c85fbbc7..0dbb7cbec 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -98,13 +98,17 @@ struct SynthPass : public ScriptPass { log(" mapping library in the `techmap` step. this option can be\n"); log(" repeated.\n"); log("\n"); + log(" -relativeshare\n"); + log(" use paths relative to share directory for source locations\n"); + log(" where possible (experimental).\n"); + log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); log("\n"); } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, hieropt; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, hieropt, relative_share; int lut; std::vector techmap_maps; @@ -124,6 +128,7 @@ struct SynthPass : public ScriptPass { flowmap = false; booth = false; hieropt = false; + relative_share = false; abc = "abc"; techmap_maps.clear(); } @@ -211,6 +216,11 @@ struct SynthPass : public ScriptPass { hieropt = true; continue; } + if (args[argidx] == "-relativeshare") { + relative_share = true; + log_experimental("synth -relativeshare"); + continue; + } break; } extra_args(args, argidx, design); @@ -239,6 +249,10 @@ struct SynthPass : public ScriptPass { else hieropt_flag = hieropt ? " -hier" : ""; + std::string techmap_cmd = "techmap"; + if (relative_share) + techmap_cmd += " -relativeshare"; + if (check_label("begin")) { if (help_mode) { run("hierarchy -check [-top | -auto-top]"); @@ -268,9 +282,9 @@ struct SynthPass : public ScriptPass { run("peepopt"); run("opt_clean"); if (help_mode) - run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)"); + run(techmap_cmd + " -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)"); else if (lut) - run(stringf("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", lut)); + run(stringf("%s -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", techmap_cmd, lut)); if (booth || help_mode) run("booth", " (if -booth)"); if (!noalumacc) @@ -287,22 +301,22 @@ struct SynthPass : public ScriptPass { run("memory_map"); run("opt -full"); if (help_mode) { - run("techmap", " (unless -extra-map)"); - run("techmap -map +/techmap.v -map ", " (if -extra-map)"); + run(techmap_cmd, " (unless -extra-map)"); + run(techmap_cmd + " -map +/techmap.v -map ", " (if -extra-map)"); } else { std::string techmap_opts; if (!techmap_maps.empty()) techmap_opts += " -map +/techmap.v"; for (auto fn : techmap_maps) techmap_opts += stringf(" -map %s", fn); - run("techmap" + techmap_opts); + run(techmap_cmd + techmap_opts); } if (help_mode) { - run("techmap -map +/gate2lut.v", "(if -noabc and -lut)"); + run(techmap_cmd + " -map +/gate2lut.v", "(if -noabc and -lut)"); run("clean; opt_lut", " (if -noabc and -lut)"); run("flowmap -maxlut K", " (if -flowmap and -lut)"); } else if (noabc && lut) { - run(stringf("techmap -map +/gate2lut.v -D LUT_WIDTH=%d", lut)); + run(stringf("%s -map +/gate2lut.v -D LUT_WIDTH=%d", techmap_cmd, lut)); run("clean; opt_lut"); } else if (flowmap) { run(stringf("flowmap -maxlut %d", lut)); diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 3b95ff91e..f74dc8e26 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -69,7 +69,7 @@ struct SynthPass : public ScriptPass log(" use the specified Verilog file for extra primitives (can be specified multiple\n"); log(" times).\n"); log("\n"); - log(" -extra-map \n"); + log(" -extra-map \n"); log(" use the specified Verilog file for extra techmap rules (can be specified multiple\n"); log(" times).\n"); log("\n"); diff --git a/tests/bugpoint/raise_error.ys b/tests/bugpoint/raise_error.ys index 8fb10eb96..79127deff 100644 --- a/tests/bugpoint/raise_error.ys +++ b/tests/bugpoint/raise_error.ys @@ -22,34 +22,37 @@ logger -check-expected # raise_error with int exits with status design -load read +setattr -mod -unset raise_error def other +dump bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 7 select -assert-mod-count 1 =* select -assert-mod-count 1 top # raise_error -always still uses 'raise_error' attribute if possible design -load read +setattr -mod -unset raise_error def other bugpoint -suffix error -yosys ../../yosys -command "raise_error -always" -expect-return 7 select -assert-mod-count 1 =* select -assert-mod-count 1 top # raise_error with string prints message and exits with 1 design -load read -rename top abc +setattr -mod -unset raise_error top def bugpoint -suffix error -yosys ../../yosys -command raise_error -grep "help me" -expect-return 1 select -assert-mod-count 1 =* select -assert-mod-count 1 other # raise_error with no value exits with 1 design -load read -rename def zzy +setattr -mod -unset raise_error top delete other bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 1 select -assert-mod-count 1 =* -select -assert-mod-count 1 zzy +select -assert-mod-count 1 def # raise_error -stderr prints to stderr and exits with 1 design -load read -rename top abc +setattr -mod -unset raise_error top def bugpoint -suffix error -yosys ../../yosys -command "raise_error -stderr" -err-grep "help me" -expect-return 1 select -assert-mod-count 1 =* select -assert-mod-count 1 other diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py index 7a09966d8..e4c78a1fb 100644 --- a/tests/functional/test_functional.py +++ b/tests/functional/test_functional.py @@ -24,7 +24,7 @@ def compile_cpp(in_path, out_path, args): run(['g++', '-g', '-std=c++17'] + args + [str(in_path), '-o', str(out_path)]) def yosys_synth(verilog_file, rtlil_file): - yosys(f"read_verilog {quote(verilog_file)} ; prep ; write_rtlil {quote(rtlil_file)}") + yosys(f"read_verilog {quote(verilog_file)} ; prep ; setundef -undriven -undef ; write_rtlil {quote(rtlil_file)}") # simulate an rtlil file with yosys, comparing with a given vcd file, and writing out the yosys simulation results into a second vcd file def yosys_sim(rtlil_file, vcd_reference_file, vcd_out_file, preprocessing = ""): @@ -91,4 +91,4 @@ def test_print_graph(tmp_path): tb_file = base_path / 'tests/functional/picorv32_tb.v' cpu_file = base_path / 'tests/functional/picorv32.v' # currently we only check that we can print the graph without getting an error, not that it prints anything sensibl - yosys(f"read_verilog {quote(tb_file)} {quote(cpu_file)}; prep -top gold; flatten; clk2fflogic; test_generic") + yosys(f"read_verilog {quote(tb_file)} {quote(cpu_file)}; prep -top gold; setundef -undriven -undef ; flatten; clk2fflogic; test_generic") diff --git a/tests/rtlil/.gitignore b/tests/rtlil/.gitignore new file mode 100644 index 000000000..abe251a76 --- /dev/null +++ b/tests/rtlil/.gitignore @@ -0,0 +1 @@ +/temp \ No newline at end of file diff --git a/tests/rtlil/everything.v b/tests/rtlil/everything.v new file mode 100644 index 000000000..666d630c2 --- /dev/null +++ b/tests/rtlil/everything.v @@ -0,0 +1,40 @@ +module alu( + input clk, + input [7:0] A, + input [7:0] B, + input [3:0] operation, + output reg [7:0] result, + output reg CF, + output reg ZF, + output reg SF +); + + localparam ALU_OP_ADD = 4'b0000; + localparam ALU_OP_SUB = 4'b0001; + + reg [8:0] tmp; + + always @(posedge clk) + begin + case (operation) + ALU_OP_ADD : + tmp = A + B; + ALU_OP_SUB : + tmp = A - B; + endcase + + CF <= tmp[8]; + ZF <= tmp[7:0] == 0; + SF <= tmp[7]; + + result <= tmp[7:0]; + end +endmodule + +module foo( + input [7:0] a, input [7:0] b, output [7:0] y +); + wire [7:0] bb; + assign b = bb; + assign y = a + bb; +endmodule diff --git a/tests/rtlil/roundtrip-design.sh b/tests/rtlil/roundtrip-design.sh new file mode 100644 index 000000000..018e363c7 --- /dev/null +++ b/tests/rtlil/roundtrip-design.sh @@ -0,0 +1,10 @@ +set -euo pipefail +YS=../../yosys + +mkdir -p temp + +$YS -p "read_verilog -sv everything.v; write_rtlil temp/roundtrip-design-push.il; design -push; design -pop; write_rtlil temp/roundtrip-design-pop.il" +diff temp/roundtrip-design-push.il temp/roundtrip-design-pop.il + +$YS -p "read_verilog -sv everything.v; write_rtlil temp/roundtrip-design-save.il; design -save foo; design -load foo; write_rtlil temp/roundtrip-design-load.il" +diff temp/roundtrip-design-save.il temp/roundtrip-design-load.il diff --git a/tests/rtlil/roundtrip-text.sh b/tests/rtlil/roundtrip-text.sh new file mode 100644 index 000000000..35417cff7 --- /dev/null +++ b/tests/rtlil/roundtrip-text.sh @@ -0,0 +1,31 @@ +set -euo pipefail +YS=../../yosys + +mkdir -p temp + +# non-POSIX sed -i inconsistency workaround +remove_empty_lines() { + local file="$1" + sed '/^$/d' "$file" > temp/tmp + mv temp/tmp "$file" +} + +# write_rtlil and dump are equivalent +$YS -p "read_verilog -sv everything.v; copy alu zzz; proc zzz; dump -o temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.write.il" +remove_empty_lines temp/roundtrip-text.dump.il +remove_empty_lines temp/roundtrip-text.write.il +# Trim first line ("Generated by Yosys ...") +tail -n +2 temp/roundtrip-text.write.il > temp/roundtrip-text.write-nogen.il +diff temp/roundtrip-text.dump.il temp/roundtrip-text.write-nogen.il + +# Loading and writing it out again doesn't change the RTLIL +$YS -p "read_rtlil temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.reload.il" +remove_empty_lines temp/roundtrip-text.reload.il +tail -n +2 temp/roundtrip-text.reload.il > temp/roundtrip-text.reload-nogen.il +diff temp/roundtrip-text.dump.il temp/roundtrip-text.reload-nogen.il + +# Hashing differences don't change the RTLIL +$YS --hash-seed=2345678 -p "read_rtlil temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.reload-hash.il" +remove_empty_lines temp/roundtrip-text.reload-hash.il +tail -n +2 temp/roundtrip-text.reload-hash.il > temp/roundtrip-text.reload-hash-nogen.il +diff temp/roundtrip-text.dump.il temp/roundtrip-text.reload-hash-nogen.il diff --git a/tests/rtlil/run-test.sh b/tests/rtlil/run-test.sh new file mode 100755 index 000000000..70b282a9a --- /dev/null +++ b/tests/rtlil/run-test.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -eu +source ../gen-tests-makefile.sh +generate_mk --bash