diff options
-rw-r--r-- | CHANGELOG | 15 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | backends/smt2/smt2.cc | 77 | ||||
-rw-r--r-- | backends/smt2/smtio.py | 21 | ||||
-rw-r--r-- | frontends/verific/verific.cc | 50 | ||||
-rw-r--r-- | kernel/constids.inc | 2 | ||||
-rw-r--r-- | kernel/rtlil.cc | 10 | ||||
-rw-r--r-- | kernel/rtlil.h | 4 | ||||
-rw-r--r-- | manual/command-reference-manual.tex | 251 | ||||
-rw-r--r-- | passes/cmds/sta.cc | 5 | ||||
-rw-r--r-- | passes/fsm/fsmdata.h | 4 | ||||
-rw-r--r-- | passes/opt/opt_ffinv.cc | 4 | ||||
-rw-r--r-- | passes/opt/wreduce.cc | 10 | ||||
-rw-r--r-- | passes/techmap/iopadmap.cc | 28 | ||||
-rw-r--r-- | tests/various/.gitignore | 2 | ||||
-rw-r--r-- | tests/various/smtlib2_module-expected.smt2 | 88 | ||||
-rwxr-xr-x | tests/various/smtlib2_module.sh | 5 | ||||
-rw-r--r-- | tests/various/smtlib2_module.v | 33 |
18 files changed, 481 insertions, 130 deletions
@@ -4,6 +4,17 @@ List of major changes and improvements between releases Yosys 0.17 .. Yosys 0.17-dev -------------------------- + * New commands and options + - Added "memory_libmap" pass + - Added "memory_bmux2rom" pass - converts muxes to ROMs + - Added "memory_dff -no-rw-check" + - Added "opt_ffinv" pass - push inverters through FFs + - Added "proc_rom" pass - convert switches to ROMs + - Added "proc -norom" option - will omit the proc_rom pass + - Added option "-no-rw-check" to synth passes + - Added "synth_ice40 -spram" option for automatic inference of SB_SPRAM256KA + - Added options "-nobram" and "-nolutram" to synth_machxo2 pass + * Formal Verification - Fixed the signedness of $past's return value to be the same as the argument's instead of always unsigned. @@ -17,6 +28,10 @@ Yosys 0.17 .. Yosys 0.17-dev - Fixed size and signedness computation of functions used in ternary expressions or case item expressions + * Verific support + - Proper file location for readmem commands + - Added "-vlog-libext" option to specify search extension for libraries + Yosys 0.16 .. Yosys 0.17 -------------------------- * New commands and options @@ -129,7 +129,7 @@ LDFLAGS += -rdynamic LDLIBS += -lrt endif -YOSYS_VER := 0.17+72 +YOSYS_VER := 0.17+94 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index ed6f3aff9..7481e0510 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -53,6 +53,8 @@ struct Smt2Worker std::map<int, int> bvsizes; dict<IdString, char*> ids; + bool is_smtlib2_module; + const char *get_id(IdString n) { if (ids.count(n) == 0) { @@ -112,9 +114,10 @@ struct Smt2Worker } Smt2Worker(RTLIL::Module *module, bool bvmode, bool memmode, bool wiresmode, bool verbose, bool statebv, bool statedt, bool forallmode, - dict<IdString, int> &mod_stbv_width, dict<IdString, dict<IdString, pair<bool, bool>>> &mod_clk_cache) : - ct(module->design), sigmap(module), module(module), bvmode(bvmode), memmode(memmode), wiresmode(wiresmode), - verbose(verbose), statebv(statebv), statedt(statedt), forallmode(forallmode), mod_stbv_width(mod_stbv_width) + dict<IdString, int> &mod_stbv_width, dict<IdString, dict<IdString, pair<bool, bool>>> &mod_clk_cache) + : ct(module->design), sigmap(module), module(module), bvmode(bvmode), memmode(memmode), wiresmode(wiresmode), verbose(verbose), + statebv(statebv), statedt(statedt), forallmode(forallmode), mod_stbv_width(mod_stbv_width), + is_smtlib2_module(module->has_attribute(ID::smtlib2_module)) { pool<SigBit> noclock; @@ -124,6 +127,9 @@ struct Smt2Worker memories = Mem::get_all_memories(module); for (auto &mem : memories) { + if (is_smtlib2_module) + log_error("Memory %s.%s not allowed in module with smtlib2_module attribute", get_id(module), mem.memid.c_str()); + mem.narrow(); mem_dict[mem.memid] = &mem; for (auto &port : mem.wr_ports) @@ -893,10 +899,25 @@ struct Smt2Worker log_id(cell->type), log_id(module), log_id(cell)); } + void verify_smtlib2_module() + { + if (!module->get_blackbox_attribute()) + log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", log_id(module)); + if (module->cells().size() > 0) + log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", log_id(module)); + for (auto wire : module->wires()) + if (!wire->port_id) + log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", log_id(module), + log_id(wire)); + } + void run() { if (verbose) log("=> export logic driving outputs\n"); + if (is_smtlib2_module) + verify_smtlib2_module(); + pool<SigBit> reg_bits; for (auto cell : module->cells()) if (cell->type.in(ID($ff), ID($dff), ID($_FF_), ID($_DFF_P_), ID($_DFF_N_))) { @@ -905,11 +926,25 @@ struct Smt2Worker reg_bits.insert(bit); } + std::string smtlib2_inputs; + std::vector<std::string> smtlib2_decls; + if (is_smtlib2_module) { + for (auto wire : module->wires()) { + if (!wire->port_input) + continue; + smtlib2_inputs += stringf("(|%s| (|%s_n %s| state))\n", get_id(wire), get_id(module), get_id(wire)); + } + } + for (auto wire : module->wires()) { bool is_register = false; for (auto bit : SigSpec(wire)) if (reg_bits.count(bit)) is_register = true; + bool is_smtlib2_comb_expr = wire->has_attribute(ID::smtlib2_comb_expr); + if (is_smtlib2_comb_expr && !is_smtlib2_module) + log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", log_id(module), + log_id(wire)); if (wire->port_id || is_register || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name.isPublic())) { RTLIL::SigSpec sig = sigmap(wire); std::vector<std::string> comments; @@ -924,11 +959,22 @@ struct Smt2Worker if (GetSize(wire) == 1 && (clock_posedge.count(sig) || clock_negedge.count(sig))) comments.push_back(stringf("; yosys-smt2-clock %s%s%s\n", get_id(wire), clock_posedge.count(sig) ? " posedge" : "", clock_negedge.count(sig) ? " negedge" : "")); + std::string smtlib2_comb_expr; + if (is_smtlib2_comb_expr) { + smtlib2_comb_expr = + "(let (\n" + smtlib2_inputs + ")\n" + wire->get_string_attribute(ID::smtlib2_comb_expr) + "\n)"; + if (wire->port_input || !wire->port_output) + log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", log_id(module), log_id(wire)); + if (!bvmode && GetSize(sig) > 1) + log_error("smtlib2_comb_expr is unsupported on multi-bit wires when -nobv is specified: wire %s.%s", + log_id(module), log_id(wire)); + } + auto &out_decls = is_smtlib2_comb_expr ? smtlib2_decls : decls; if (bvmode && GetSize(sig) > 1) { - std::string sig_bv = get_bv(sig); + std::string sig_bv = is_smtlib2_comb_expr ? smtlib2_comb_expr : get_bv(sig); if (!comments.empty()) - decls.insert(decls.end(), comments.begin(), comments.end()); - decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) (_ BitVec %d) %s)\n", + out_decls.insert(out_decls.end(), comments.begin(), comments.end()); + out_decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) (_ BitVec %d) %s)\n", get_id(module), get_id(wire), get_id(module), GetSize(sig), sig_bv.c_str())); if (wire->port_input) ex_input_eq.push_back(stringf(" (= (|%s_n %s| state) (|%s_n %s| other_state))", @@ -936,19 +982,19 @@ struct Smt2Worker } else { std::vector<std::string> sig_bool; for (int i = 0; i < GetSize(sig); i++) { - sig_bool.push_back(get_bool(sig[i])); + sig_bool.push_back(is_smtlib2_comb_expr ? smtlib2_comb_expr : get_bool(sig[i])); } if (!comments.empty()) - decls.insert(decls.end(), comments.begin(), comments.end()); + out_decls.insert(out_decls.end(), comments.begin(), comments.end()); for (int i = 0; i < GetSize(sig); i++) { if (GetSize(sig) > 1) { - decls.push_back(stringf("(define-fun |%s_n %s %d| ((state |%s_s|)) Bool %s)\n", + out_decls.push_back(stringf("(define-fun |%s_n %s %d| ((state |%s_s|)) Bool %s)\n", get_id(module), get_id(wire), i, get_id(module), sig_bool[i].c_str())); if (wire->port_input) ex_input_eq.push_back(stringf(" (= (|%s_n %s %d| state) (|%s_n %s %d| other_state))", get_id(module), get_id(wire), i, get_id(module), get_id(wire), i)); } else { - decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) Bool %s)\n", + out_decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) Bool %s)\n", get_id(module), get_id(wire), get_id(module), sig_bool[i].c_str())); if (wire->port_input) ex_input_eq.push_back(stringf(" (= (|%s_n %s| state) (|%s_n %s| other_state))", @@ -959,11 +1005,17 @@ struct Smt2Worker } } + decls.insert(decls.end(), smtlib2_decls.begin(), smtlib2_decls.end()); + if (verbose) log("=> export logic associated with the initial state\n"); vector<string> init_list; for (auto wire : module->wires()) if (wire->attributes.count(ID::init)) { + if (is_smtlib2_module) + log_error("init attribute not allowed on wires in module with smtlib2_module attribute: wire %s.%s", + log_id(module), log_id(wire)); + RTLIL::SigSpec sig = sigmap(wire); Const val = wire->attributes.at(ID::init); val.bits.resize(GetSize(sig), State::Sx); @@ -1687,7 +1739,10 @@ struct Smt2Backend : public Backend { for (auto module : sorted_modules) { - if (module->get_blackbox_attribute() || module->has_processes_warn()) + if (module->get_blackbox_attribute() && !module->has_attribute(ID::smtlib2_module)) + continue; + + if (module->has_processes_warn()) continue; log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 14feec30d..64e4cd79a 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -123,6 +123,7 @@ class SmtIo: self.forall = False self.timeout = 0 self.produce_models = True + self.recheck = False self.smt2cache = [list()] self.smt2_options = dict() self.p = None @@ -176,7 +177,10 @@ class SmtIo: self.unroll = False if self.solver == "yices": - if self.noincr or self.forall: + if self.forall: + self.noincr = True + + if self.noincr: self.popen_vargs = ['yices-smt2'] + self.solver_opts else: self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts @@ -189,11 +193,12 @@ class SmtIo: if self.timeout != 0: self.popen_vargs.append('-T:%d' % self.timeout); - if self.solver == "cvc4": + if self.solver in ["cvc4", "cvc5"]: + self.recheck = True if self.noincr: - self.popen_vargs = ['cvc4', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts + self.popen_vargs = [self.solver, '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts else: - self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts + self.popen_vargs = [self.solver, '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts if self.timeout != 0: self.popen_vargs.append('--tlimit=%d000' % self.timeout); @@ -404,6 +409,8 @@ class SmtIo: stmt = re.sub(r" *;.*", "", stmt) if stmt == "": return + recheck = None + if unroll and self.unroll: stmt = self.unroll_buffer + stmt self.unroll_buffer = "" @@ -415,6 +422,9 @@ class SmtIo: s = self.parse(stmt) + if self.recheck and s and s[0].startswith("get-"): + recheck = self.unroll_idcnt + if self.debug_print: print("-> %s" % s) @@ -440,6 +450,9 @@ class SmtIo: stmt = self.unparse(self.unroll_stmt(s)) + if recheck is not None and recheck != self.unroll_idcnt: + self.check_sat(["sat"]) + if stmt == "(push 1)": self.unroll_stack.append(( copy(self.unroll_sorts), diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 328593099..6351483db 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -53,6 +53,9 @@ USING_YOSYS_NAMESPACE #include "VhdlUnits.h" #endif +#include "VerificStream.h" +#include "FileSystem.h" + #ifdef YOSYSHQ_VERIFIC_EXTENSIONS #include "InitialAssertions.h" #endif @@ -83,7 +86,7 @@ bool verific_import_pending; string verific_error_msg; int verific_sva_fsm_limit; -vector<string> verific_incdirs, verific_libdirs; +vector<string> verific_incdirs, verific_libdirs, verific_libexts; void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args) { @@ -118,6 +121,34 @@ string get_full_netlist_name(Netlist *nl) return nl->CellBaseName(); } +class YosysStreamCallBackHandler : public VerificStreamCallBackHandler +{ +public: + YosysStreamCallBackHandler() : VerificStreamCallBackHandler() { } + virtual ~YosysStreamCallBackHandler() { } + + virtual verific_stream *GetSysCallStream(const char *file_path) + { + if (!file_path) return nullptr; + + linefile_type src_loc = GetFromLocation(); + + char *this_file_name = nullptr; + if (src_loc && !FileSystem::IsAbsolutePath(file_path)) { + const char *src_file_name = LineFile::GetFileName(src_loc); + char *dir_name = FileSystem::DirectoryPath(src_file_name); + if (dir_name) { + this_file_name = Strings::save(dir_name, "/", file_path); + Strings::free(dir_name); + file_path = this_file_name; + } + } + verific_stream *strm = new verific_ifstream(file_path); + Strings::free(this_file_name); + return strm; + } +}; + // ================================================================== VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit) : @@ -2292,6 +2323,7 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par LineFile::DeleteAllLineFiles(); verific_incdirs.clear(); verific_libdirs.clear(); + verific_libexts.clear(); verific_import_pending = false; if (!verific_error_msg.empty()) @@ -2402,6 +2434,11 @@ struct VerificPass : public Pass { log("find undefined modules.\n"); log("\n"); log("\n"); + log(" verific -vlog-libext <extension>..\n"); + log("\n"); + log("Add Verilog library extensions, used when searching in library directories.\n"); + log("\n"); + log("\n"); log(" verific -vlog-define <macro>[=<value>]..\n"); log("\n"); log("Add Verilog defines.\n"); @@ -2648,6 +2685,8 @@ struct VerificPass : public Pass { int argidx = 1; std::string work = "work"; + YosysStreamCallBackHandler cb; + veri_file::RegisterCallBackVerificStream(&cb); if (GetSize(args) > argidx && (args[argidx] == "-set-error" || args[argidx] == "-set-warning" || args[argidx] == "-set-info" || args[argidx] == "-set-ignore")) @@ -2683,6 +2722,12 @@ struct VerificPass : public Pass { goto check_error; } + if (GetSize(args) > argidx && args[argidx] == "-vlog-libext") { + for (argidx++; argidx < GetSize(args); argidx++) + verific_libexts.push_back(args[argidx]); + goto check_error; + } + if (GetSize(args) > argidx && args[argidx] == "-vlog-define") { for (argidx++; argidx < GetSize(args); argidx++) { string name = args[argidx]; @@ -2823,6 +2868,8 @@ struct VerificPass : public Pass { veri_file::AddIncludeDir(dir.c_str()); for (auto &dir : verific_libdirs) veri_file::AddYDir(dir.c_str()); + for (auto &ext : verific_libexts) + veri_file::AddLibExt(ext.c_str()); while (argidx < GetSize(args)) file_names.Insert(args[argidx++].c_str()); @@ -3312,6 +3359,7 @@ struct VerificPass : public Pass { LineFile::DeleteAllLineFiles(); verific_incdirs.clear(); verific_libdirs.clear(); + verific_libexts.clear(); verific_import_pending = false; goto check_error; } diff --git a/kernel/constids.inc b/kernel/constids.inc index 443ac3bcb..0f6dfc29b 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -196,6 +196,8 @@ X(STATE_NUM) X(STATE_NUM_LOG2) X(STATE_RST) X(STATE_TABLE) +X(smtlib2_module) +X(smtlib2_comb_expr) X(submod) X(syn_ramstyle) X(syn_romstyle) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 72dcb89af..8346b56e0 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -204,7 +204,7 @@ RTLIL::Const::Const() flags = RTLIL::CONST_FLAG_NONE; } -RTLIL::Const::Const(std::string str) +RTLIL::Const::Const(const std::string &str) { flags = RTLIL::CONST_FLAG_STRING; bits.reserve(str.size() * 8); @@ -243,14 +243,6 @@ RTLIL::Const::Const(const std::vector<bool> &bits) this->bits.emplace_back(b ? State::S1 : State::S0); } -RTLIL::Const::Const(const RTLIL::Const &c) -{ - flags = c.flags; - this->bits.reserve(c.size()); - for (const auto &b : c.bits) - this->bits.push_back(b); -} - bool RTLIL::Const::operator <(const RTLIL::Const &other) const { if (bits.size() != other.bits.size()) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index d8300f159..7a0b6b9c7 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -636,12 +636,12 @@ struct RTLIL::Const std::vector<RTLIL::State> bits; Const(); - Const(std::string str); + Const(const std::string &str); Const(int val, int width = 32); Const(RTLIL::State bit, int width = 1); Const(const std::vector<RTLIL::State> &bits) : bits(bits) { flags = CONST_FLAG_NONE; } Const(const std::vector<bool> &bits); - Const(const RTLIL::Const &c); + Const(const RTLIL::Const &c) = default; RTLIL::Const &operator =(const RTLIL::Const &other) = default; bool operator <(const RTLIL::Const &other) const; diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex index bafce6de6..4108527d8 100644 --- a/manual/command-reference-manual.tex +++ b/manual/command-reference-manual.tex @@ -2744,14 +2744,15 @@ is used then the $macc cell is mapped to $add, $sub, etc. cells instead. \section{memory -- translate memories to basic cells} \label{cmd:memory} \begin{lstlisting}[numbers=left,frame=single] - memory [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-bram <bram_rules>] [selection] + memory [-norom] [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-no-rw-check] [-bram <bram_rules>] [selection] This pass calls all the other memory_* passes in a useful order: opt_mem opt_mem_priority opt_mem_feedback - memory_dff (skipped if called with -nordff or -memx) + memory_bmux2rom (skipped if called with -norom) + memory_dff [-no-rw-check] (skipped if called with -nordff or -memx) opt_clean memory_share [-nowiden] [-nosat] opt_mem_widen @@ -2765,6 +2766,14 @@ This converts memories to word-wide DFFs and address decoders or multiport memory blocks if called with the -nomap option. \end{lstlisting} +\section{memory\_bmux2rom -- convert muxes to ROMs} +\label{cmd:memory_bmux2rom} +\begin{lstlisting}[numbers=left,frame=single] + memory_bmux2rom [options] [selection] + +This pass converts $bmux cells with constant A input to ROMs. +\end{lstlisting} + \section{memory\_bram -- map memories to block rams} \label{cmd:memory_bram} \begin{lstlisting}[numbers=left,frame=single] @@ -2878,11 +2887,45 @@ memory cells. \section{memory\_dff -- merge input/output DFFs into memory read ports} \label{cmd:memory_dff} \begin{lstlisting}[numbers=left,frame=single] - memory_dff [options] [selection] + memory_dff [-no-rw-check] [selection] This pass detects DFFs at memory read ports and merges them into the memory port. I.e. it consumes an asynchronous memory port and the flip-flops at its interface and yields a synchronous memory port. + + -no-rw-check + marks all recognized read ports as "return don't-care value on + read/write collision" (same result as setting the no_rw_check + attribute on all memories). +\end{lstlisting} + +\section{memory\_libmap -- map memories to cells} +\label{cmd:memory_libmap} +\begin{lstlisting}[numbers=left,frame=single] + memory_libmap -lib <library_file> [-D <condition>] [selection] + +This pass takes a description of available RAM cell types and maps +all selected memories to one of them, or leaves them to be mapped to FFs. + + -lib <library_file> + Selects a library file containing RAM cell definitions. This option + can be passed more than once to select multiple libraries. + See passes/memory/memlib.md for description of the library format. + + -D <condition> + Enables a condition that can be checked within the library file + to eg. select between slightly different hardware variants. + This option can be passed any number of times. + + -logic-cost-rom <num> + -logic-cost-ram <num> + Sets the cost of a single bit for memory lowered to soft logic. + + -no-auto-distributed + -no-auto-block + -no-auto-huge + Disables automatic mapping of given kind of RAMs. Manual mapping + (using ram_style or other attributes) is still supported. \end{lstlisting} \section{memory\_map -- translate multiport memories to basic cells} @@ -3270,6 +3313,15 @@ It also performs some simple expression rewriting. replaced by 'a'. the -keepdc option disables all such optimizations. \end{lstlisting} +\section{opt\_ffinv -- push inverters through FFs} +\label{cmd:opt_ffinv} +\begin{lstlisting}[numbers=left,frame=single] + opt_ffinv [selection] + +This pass pushes inverters to the other side of a FF when they can be merged +into LUTs on the other side. +\end{lstlisting} + \section{opt\_lut -- optimize LUT cells} \label{cmd:opt_lut} \begin{lstlisting}[numbers=left,frame=single] @@ -3595,6 +3647,7 @@ This pass calls all the other proc_* passes in the most common order. proc_prune proc_init proc_arst + proc_rom proc_mux proc_dlatch proc_dff @@ -3610,6 +3663,9 @@ The following options are supported: -nomux Will omit the proc_mux pass. + -norom + Will omit the proc_rom pass. + -global_arst [!]<netname> This option is passed through to proc_arst. @@ -3716,6 +3772,14 @@ a later assignment to the same signal and removes them. This pass identifies unreachable branches in decision trees and removes them. \end{lstlisting} +\section{proc\_rom -- convert switches to ROMs} +\label{cmd:proc_rom} +\begin{lstlisting}[numbers=left,frame=single] + proc_rom [selection] + +This pass converts switches into read-only memories when appropriate. +\end{lstlisting} + \section{qbfsat -- solve a 2QBF-SAT problem in the circuit} \label{cmd:qbfsat} \begin{lstlisting}[numbers=left,frame=single] @@ -4498,15 +4562,16 @@ described here. -unset <name> do not modify the current selection. instead remove a previously saved selection under the given name (see @<name> below). + -assert-none do not modify the current selection. instead assert that the given - selection is empty. i.e. produce an error if any object matching the - selection is found. + selection is empty. i.e. produce an error if any object or module + matching the selection is found. -assert-any do not modify the current selection. instead assert that the given - selection is non-empty. i.e. produce an error if no object matching - the selection is found. + selection is non-empty. i.e. produce an error if no object or module + matching the selection is found. -assert-count N do not modify the current selection. instead assert that the given @@ -5257,6 +5322,11 @@ on partly selected designs. -flowmap use FlowMap LUT techmapping instead of ABC + -no-rw-check + marks all recognized read ports as "return don't-care value on + read/write collision" (same result as setting the no_rw_check + attribute on all memories). + The following commands are executed by this synthesis command: @@ -5424,16 +5494,9 @@ The following commands are executed by this synthesis command: coarse: synth -run coarse - map_bram: (skip if -nobram) - memory_bram -rules +/anlogic/brams.txt - techmap -map +/anlogic/brams_map.v - setundef -zero -params t:EG_PHY_BRAM - setundef -zero -params t:EG_PHY_BRAM32K - - map_lutram: (skip if -nolutram) - memory_bram -rules +/anlogic/lutrams.txt - techmap -map +/anlogic/lutrams_map.v - setundef -zero -params t:EG_LOGIC_DRAM16X4 + map_ram: + memory_libmap -lib +/anlogic/lutrams.txt -lib +/anlogic/brams.txt [-no-auto-block] [-no-auto-distributed] (-no-auto-block if -nobram, -no-auto-distributed if -nolutram) + techmap -map +/anlogic/lutrams_map.v -map +/anlogic/brams_map.v map_ffram: opt -fast -mux_undef -undriven -fine @@ -5697,6 +5760,11 @@ This command runs synthesis for ECP5 FPGAs. -nodsp do not map multipliers to MULT18X18D + -no-rw-check + marks all recognized read ports as "return don't-care value on + read/write collision" (same result as setting the no_rw_check + attribute on all memories). + The following commands are executed by this synthesis command: @@ -5726,20 +5794,16 @@ The following commands are executed by this synthesis command: chtype -set $mul t:$__soft_mul (unless -nodsp) alumacc opt - memory -nomap + memory -nomap [-no-rw-check] opt_clean - map_bram: (skip if -nobram) - memory_bram -rules +/ecp5/brams.txt - techmap -map +/ecp5/brams_map.v - - map_lutram: (skip if -nolutram) - memory_bram -rules +/ecp5/lutrams.txt - techmap -map +/ecp5/lutrams_map.v + map_ram: + memory_libmap -lib +/ecp5/lutrams.txt -lib +/ecp5/brams.txt [-no-auto-block] [-no-auto-distributed] (-no-auto-block if -nobram, -no-auto-distributed if -nolutram) + techmap -map +/ecp5/lutrams_map.v -map +/ecp5/brams_map.v map_ffram: opt -fast -mux_undef -undriven -fine - memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic + memory_map opt -undriven -fine map_gates: @@ -5835,9 +5899,10 @@ The following commands are executed by this synthesis command: coarse: synth -run coarse - memory_bram -rules +/efinix/brams.txt + + map_ram: + memory_libmap -lib +/efinix/brams.txt techmap -map +/efinix/brams_map.v - setundef -zero -params t:EFX_RAM_5K map_ffram: opt -fast -mux_undef -undriven -fine @@ -5969,8 +6034,7 @@ The following commands are executed by this synthesis command: opt_clean map_bram: (skip if '-nobram') - memory_bram -rules +/gatemate/brams.txt - setundef -zero -params t:$__CC_BRAM_CASCADE t:$__CC_BRAM_40K_SDP t:$__CC_BRAM_20K_SDP t:$__CC_BRAM_20K_TDP t:$__CC_BRAM_40K_TDP + memory_libmap -lib +/gatemate/brams.txt techmap -map +/gatemate/brams_map.v map_ffram: @@ -6076,6 +6140,11 @@ This command runs synthesis for Gowin FPGAs. This work is experimental. -abc9 use new ABC9 flow (EXPERIMENTAL) + -no-rw-check + marks all recognized read ports as "return don't-care value on + read/write collision" (same result as setting the no_rw_check + attribute on all memories). + The following commands are executed by this synthesis command: @@ -6090,16 +6159,11 @@ The following commands are executed by this synthesis command: deminout coarse: - synth -run coarse - - map_bram: (skip if -nobram) - memory_bram -rules +/gowin/brams.txt - techmap -map +/gowin/brams_map.v + synth -run coarse [-no-rw-check] - map_lutram: (skip if -nolutram) - memory_bram -rules +/gowin/lutrams.txt - techmap -map +/gowin/lutrams_map.v - setundef -params -zero t:RAM16S4 + map_ram: + memory_libmap -lib +/gowin/lutrams.txt -lib +/gowin/brams.txt [-no-auto-block] [-no-auto-distributed] (-no-auto-block if -nobram, -no-auto-distributed if -nolutram) + techmap -map +/gowin/lutrams_map.v -map +/gowin/brams_map.v map_ffram: opt -fast -mux_undef -undriven -fine @@ -6283,6 +6347,9 @@ This command runs synthesis for iCE40 FPGAs. -nobram do not use SB_RAM40_4K* cells in output netlist + -spram + enable automatic inference of SB_SPRAM256KA + -dsp use iCE40 UltraPlus DSP cells for large arithmetic @@ -6302,6 +6369,11 @@ This command runs synthesis for iCE40 FPGAs. -flowmap use FlowMap LUT techmapping instead of abc (EXPERIMENTAL) + -no-rw-check + marks all recognized read ports as "return don't-care value on + read/write collision" (same result as setting the no_rw_check + attribute on all memories). + The following commands are executed by this synthesis command: @@ -6329,7 +6401,7 @@ The following commands are executed by this synthesis command: techmap -map +/cmp2lut.v -D LUT_WIDTH=4 opt_expr opt_clean - memory_dff + memory_dff [-no-rw-check] wreduce t:$mul techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16 (if -dsp) select a:mul2dsp (if -dsp) @@ -6341,17 +6413,17 @@ The following commands are executed by this synthesis command: chtype -set $mul t:$__soft_mul (if -dsp) alumacc opt - memory -nomap + memory -nomap [-no-rw-check] opt_clean - map_bram: (skip if -nobram) - memory_bram -rules +/ice40/brams.txt - techmap -map +/ice40/brams_map.v + map_ram: + memory_libmap -lib +/ice40/brams.txt -lib +/ice40/spram.txt -no-auto-huge [-no-auto-huge] [-no-auto-block] (-no-auto-huge unless -spram, -no-auto-block if -nobram) + techmap -map +/ice40/brams_map.v -map +/ice40/spram_map.v ice40_braminit map_ffram: opt -fast -mux_undef -undriven -fine - memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic + memory_map opt -undriven -fine map_gates: @@ -6669,6 +6741,12 @@ This command runs synthesis for MachXO2 FPGAs. from label is synonymous to 'begin', and empty to label is synonymous to the end of the command list. + -nobram + do not use block RAM cells in output netlist + + -nolutram + do not use LUT RAM cells in output netlist + -noflatten do not flatten design before synthesis @@ -6695,6 +6773,10 @@ The following commands are executed by this synthesis command: coarse: synth -run coarse + map_ram: + memory_libmap -lib +/machxo2/lutrams.txt -lib +/machxo2/brams.txt [-no-auto-block] [-no-auto-distributed] (-no-auto-block if -nobram, -no-auto-distributed if -nolutram) + techmap -map +/machxo2/lutrams_map.v -map +/machxo2/brams_map.v + fine: memory_map opt -full @@ -6830,24 +6912,13 @@ The following commands are executed by this synthesis command: memory -nomap opt_clean - map_lram: (skip if -nolram) - memory_bram -rules +/nexus/lrams.txt - setundef -zero -params t:$__NX_PDPSC512K - techmap -map +/nexus/lrams_map.v - - map_bram: (skip if -nobram) - memory_bram -rules +/nexus/brams.txt - setundef -zero -params t:$__NX_PDP16K - techmap -map +/nexus/brams_map.v - - map_lutram: (skip if -nolutram) - memory_bram -rules +/nexus/lutrams.txt - setundef -zero -params t:$__NEXUS_DPR16X4 - techmap -map +/nexus/lutrams_map.v + map_ram: + memory_libmap -lib +/nexus/lutrams.txt -lib +/nexus/brams.txt -lib +/nexus/lrams.txt -no-auto-huge [-no-auto-block] [-no-auto-distributed] (-no-auto-block if -nobram, -no-auto-distributed if -nolutram) + techmap -map +/nexus/lutrams_map.v -map +/nexus/brams_map.v -map +/nexus/lrams_map.v map_ffram: opt -fast -mux_undef -undriven -fine - memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic + memory_map opt -undriven -fine map_gates: @@ -7238,17 +7309,10 @@ The following commands are executed by this synthesis command: memory -nomap opt_clean - map_uram: (only if '-uram') - memory_bram -rules +/xilinx/{family}_urams.txt - techmap -map +/xilinx/{family}_urams_map.v - - map_bram: (skip if '-nobram') - memory_bram -rules +/xilinx/{family}_brams.txt - techmap -map +/xilinx/{family}_brams_map.v - - map_lutram: (skip if '-nolutram') - memory_bram -rules +/xilinx/lut[46]_lutrams.txt - techmap -map +/xilinx/lutrams_map.v + map_memory: + memory_libmap [...] + techmap -map +/xilinx/lutrams_<family>_map.v + techmap -map +/xilinx/brams_<family>_map.v map_ffram: opt -fast -full @@ -7718,31 +7782,36 @@ Like -sv, but define FORMAL instead of SYNTHESIS. Load the specified VHDL files into Verific. - verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal] <command-file> + verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009| + -sv2012|-sv|-formal] <command-file> Load and execute the specified command file. Override verilog parsing mode can be set. The macros YOSYS, SYNTHESIS/FORMAL, and VERIFIC are defined implicitly. -Command file parser supports following commands: - +define - defines macro - -u - upper case all identifier (makes Verilog parser case insensitive) - -v - register library name (file) - -y - register library name (directory) - +incdir - specify include dir - +libext - specify library extension - +liborder - add library in ordered list - +librescan - unresolved modules will be always searched starting with the first - library specified by -y/-v options. - -f/-file - nested -f option - -F - nested -F option - - parse mode: +Command file parser supports following commands in file: + +define+<MACRO>=<VALUE> - defines macro + -u - upper case all identifier (makes Verilog parser + case insensitive) + -v <filepath> - register library name (file) + -y <filepath> - register library name (directory) + +incdir+<filepath> - specify include dir + +libext+<filepath> - specify library extension + +liborder+<id> - add library in ordered list + +librescan - unresolved modules will be always searched + starting with the first library specified + by -y/-v options. + -f/-file <filepath> - nested -f option + -F <filepath> - nested -F option (relative path) + parse files: + <filepath> + +systemverilogext+<filepath> + +verilog1995ext+<filepath> + +verilog2001ext+<filepath> + + analysis mode: -ams - +systemverilogext +v2k - +verilog1995ext - +verilog2001ext -sverilog @@ -7879,8 +7948,8 @@ Application options: Parameter can also contain comma separated list of file locations. -blfile <file> - Do not run application on locations specified in file, they can represent filename - or filename and location in file. + Do not run application on locations specified in file, they can + represent filename or filename and location in file. Applications: diff --git a/passes/cmds/sta.cc b/passes/cmds/sta.cc index 13e1ee13c..4ad0e96be 100644 --- a/passes/cmds/sta.cc +++ b/passes/cmds/sta.cc @@ -58,11 +58,14 @@ struct StaWorker { TimingInfo timing; + pool<IdString> unrecognised_cells; + for (auto cell : module->cells()) { Module *inst_module = design->module(cell->type); if (!inst_module) { - log_warning("Cell type '%s' not recognised! Ignoring.\n", log_id(cell->type)); + if (unrecognised_cells.insert(cell->type).second) + log_warning("Cell type '%s' not recognised! Ignoring.\n", log_id(cell->type)); continue; } diff --git a/passes/fsm/fsmdata.h b/passes/fsm/fsmdata.h index 4ba3b4e4f..97371efab 100644 --- a/passes/fsm/fsmdata.h +++ b/passes/fsm/fsmdata.h @@ -91,8 +91,8 @@ struct FsmData if (reset_state < 0 || reset_state >= state_num) reset_state = -1; - RTLIL::Const state_table = cell->parameters[ID::STATE_TABLE]; - RTLIL::Const trans_table = cell->parameters[ID::TRANS_TABLE]; + const RTLIL::Const &state_table = cell->parameters[ID::STATE_TABLE]; + const RTLIL::Const &trans_table = cell->parameters[ID::TRANS_TABLE]; for (int i = 0; i < state_num; i++) { RTLIL::Const state_code; diff --git a/passes/opt/opt_ffinv.cc b/passes/opt/opt_ffinv.cc index fd76dd2be..fe5b59fa5 100644 --- a/passes/opt/opt_ffinv.cc +++ b/passes/opt/opt_ffinv.cc @@ -72,6 +72,8 @@ struct OptFfInvWorker for (auto &port: q_ports) { if (port.cell == ff.cell && port.port == ID::Q) continue; + if (port.cell == d_inv) + return false; if (port.port != ID::A) return false; if (!port.cell->type.in(ID($not), ID($_NOT_), ID($lut))) @@ -148,6 +150,8 @@ struct OptFfInvWorker for (auto &port: q_ports) { if (port.cell == ff.cell && port.port == ID::Q) continue; + if (port.cell == d_lut) + return false; if (port.port != ID::A) return false; if (port.cell->type.in(ID($not), ID($_NOT_))) { diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index aaad28ef0..08ab6de6f 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -30,6 +30,7 @@ struct WreduceConfig { pool<IdString> supported_cell_types; bool keepdc = false; + bool mux_undef = false; WreduceConfig() { @@ -83,7 +84,7 @@ struct WreduceWorker SigBit ref = sig_a[i]; for (int k = 0; k < GetSize(sig_s); k++) { - if ((config->keepdc || (ref != State::Sx && sig_b[k*GetSize(sig_a) + i] != State::Sx)) && ref != sig_b[k*GetSize(sig_a) + i]) + if ((config->keepdc || !config->mux_undef || (ref != State::Sx && sig_b[k*GetSize(sig_a) + i] != State::Sx)) && ref != sig_b[k*GetSize(sig_a) + i]) goto no_match_ab; if (sig_b[k*GetSize(sig_a) + i] != State::Sx) ref = sig_b[k*GetSize(sig_a) + i]; @@ -479,6 +480,9 @@ struct WreducePass : public Pass { log(" Do not change the width of memory address ports. Use this options in\n"); log(" flows that use the 'memory_memx' pass.\n"); log("\n"); + log(" -mux_undef\n"); + log(" remove 'undef' inputs from $mux, $pmux and $_MUX_ cells\n"); + log("\n"); log(" -keepdc\n"); log(" Do not optimize explicit don't-care values.\n"); log("\n"); @@ -500,6 +504,10 @@ struct WreducePass : public Pass { config.keepdc = true; continue; } + if (args[argidx] == "-mux_undef") { + config.mux_undef = true; + continue; + } break; } extra_args(args, argidx, design); diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index 437ad5156..322eb7779 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -240,13 +240,13 @@ struct IopadmapPass : public Pass { for (auto module : design->selected_modules()) { dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits; - pool<SigSig> remove_conns; + dict<SigSig, pool<int>> remove_conns; if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty()) { dict<SigBit, Cell *> tbuf_bits; pool<SigBit> driven_bits; - dict<SigBit, SigSig> z_conns; + dict<SigBit, std::pair<SigSig, int>> z_conns; // Gather tristate buffers and always-on drivers. for (auto cell : module->cells()) @@ -266,7 +266,7 @@ struct IopadmapPass : public Pass { SigBit dstbit = conn.first[i]; SigBit srcbit = conn.second[i]; if (!srcbit.wire && srcbit.data == State::Sz) { - z_conns[dstbit] = conn; + z_conns[dstbit] = {conn, i}; continue; } driven_bits.insert(dstbit); @@ -317,8 +317,9 @@ struct IopadmapPass : public Pass { // enable. en_sig = SigBit(State::S0); data_sig = SigBit(State::Sx); - if (z_conns.count(wire_bit)) - remove_conns.insert(z_conns[wire_bit]); + auto it = z_conns.find(wire_bit); + if (it != z_conns.end()) + remove_conns[it->second.first].insert(it->second.second); } if (wire->port_input) @@ -477,9 +478,22 @@ struct IopadmapPass : public Pass { if (!remove_conns.empty()) { std::vector<SigSig> new_conns; - for (auto &conn : module->connections()) - if (!remove_conns.count(conn)) + for (auto &conn : module->connections()) { + auto it = remove_conns.find(conn); + if (it == remove_conns.end()) { new_conns.push_back(conn); + } else { + SigSpec lhs, rhs; + for (int i = 0; i < GetSize(conn.first); i++) { + if (!it->second.count(i)) { + lhs.append(conn.first[i]); + rhs.append(conn.second[i]); + } + } + new_conns.push_back(SigSig(lhs, rhs)); + + } + } module->new_connections(new_conns); } diff --git a/tests/various/.gitignore b/tests/various/.gitignore index c6373468a..83e634820 100644 --- a/tests/various/.gitignore +++ b/tests/various/.gitignore @@ -6,3 +6,5 @@ /plugin.so /plugin.so.dSYM /temp +/smtlib2_module.smt2 +/smtlib2_module-filtered.smt2 diff --git a/tests/various/smtlib2_module-expected.smt2 b/tests/various/smtlib2_module-expected.smt2 new file mode 100644 index 000000000..ace858ca8 --- /dev/null +++ b/tests/various/smtlib2_module-expected.smt2 @@ -0,0 +1,88 @@ +; SMT-LIBv2 description generated by Yosys $VERSION +; yosys-smt2-module smtlib2 +(declare-sort |smtlib2_s| 0) +(declare-fun |smtlib2_is| (|smtlib2_s|) Bool) +(declare-fun |smtlib2#0| (|smtlib2_s|) (_ BitVec 8)) ; \a +; yosys-smt2-input a 8 +(define-fun |smtlib2_n a| ((state |smtlib2_s|)) (_ BitVec 8) (|smtlib2#0| state)) +(declare-fun |smtlib2#1| (|smtlib2_s|) (_ BitVec 8)) ; \b +; yosys-smt2-input b 8 +(define-fun |smtlib2_n b| ((state |smtlib2_s|)) (_ BitVec 8) (|smtlib2#1| state)) +; yosys-smt2-output add 8 +(define-fun |smtlib2_n add| ((state |smtlib2_s|)) (_ BitVec 8) (let ( +(|a| (|smtlib2_n a| state)) +(|b| (|smtlib2_n b| state)) +) +(bvadd a b) +)) +; yosys-smt2-output eq 1 +(define-fun |smtlib2_n eq| ((state |smtlib2_s|)) Bool (let ( +(|a| (|smtlib2_n a| state)) +(|b| (|smtlib2_n b| state)) +) +(= a b) +)) +; yosys-smt2-output sub 8 +(define-fun |smtlib2_n sub| ((state |smtlib2_s|)) (_ BitVec 8) (let ( +(|a| (|smtlib2_n a| state)) +(|b| (|smtlib2_n b| state)) +) +(bvadd a (bvneg b)) +)) +(define-fun |smtlib2_a| ((state |smtlib2_s|)) Bool true) +(define-fun |smtlib2_u| ((state |smtlib2_s|)) Bool true) +(define-fun |smtlib2_i| ((state |smtlib2_s|)) Bool true) +(define-fun |smtlib2_h| ((state |smtlib2_s|)) Bool true) +(define-fun |smtlib2_t| ((state |smtlib2_s|) (next_state |smtlib2_s|)) Bool true) ; end of module smtlib2 +; yosys-smt2-module uut +(declare-sort |uut_s| 0) +(declare-fun |uut_is| (|uut_s|) Bool) +; yosys-smt2-cell smtlib2 s +(declare-fun |uut#0| (|uut_s|) (_ BitVec 8)) ; \add +(declare-fun |uut#1| (|uut_s|) Bool) ; \eq +(declare-fun |uut#2| (|uut_s|) (_ BitVec 8)) ; \sub +(declare-fun |uut_h s| (|uut_s|) |smtlib2_s|) +; yosys-smt2-anyconst uut#3 8 smtlib2_module.v:14.17-14.26 +(declare-fun |uut#3| (|uut_s|) (_ BitVec 8)) ; \a +; yosys-smt2-anyconst uut#4 8 smtlib2_module.v:14.32-14.41 +(declare-fun |uut#4| (|uut_s|) (_ BitVec 8)) ; \b +(define-fun |uut#5| ((state |uut_s|)) (_ BitVec 8) (bvadd (|uut#3| state) (|uut#4| state))) ; \add2 +(define-fun |uut#6| ((state |uut_s|)) Bool (= (|uut#0| state) (|uut#5| state))) ; $0$formal$smtlib2_module.v:28$1_CHECK[0:0]$9 +; yosys-smt2-assert 0 $assert$smtlib2_module.v:28$19 smtlib2_module.v:28.17-29.22 +(define-fun |uut_a 0| ((state |uut_s|)) Bool (or (|uut#6| state) (not true))) ; $assert$smtlib2_module.v:28$19 +(define-fun |uut#7| ((state |uut_s|)) (_ BitVec 8) (bvsub (|uut#3| state) (|uut#4| state))) ; \sub2 +(define-fun |uut#8| ((state |uut_s|)) Bool (= (|uut#2| state) (|uut#7| state))) ; $0$formal$smtlib2_module.v:29$2_CHECK[0:0]$11 +; yosys-smt2-assert 1 $assert$smtlib2_module.v:29$20 smtlib2_module.v:29.23-30.22 +(define-fun |uut_a 1| ((state |uut_s|)) Bool (or (|uut#8| state) (not true))) ; $assert$smtlib2_module.v:29$20 +(define-fun |uut#9| ((state |uut_s|)) Bool (= (|uut#3| state) (|uut#4| state))) ; $eq$smtlib2_module.v:31$17_Y +(define-fun |uut#10| ((state |uut_s|)) Bool (= (ite (|uut#1| state) #b1 #b0) (ite (|uut#9| state) #b1 #b0))) ; $0$formal$smtlib2_module.v:30$3_CHECK[0:0]$13 +; yosys-smt2-assert 2 $assert$smtlib2_module.v:30$21 smtlib2_module.v:30.23-31.25 +(define-fun |uut_a 2| ((state |uut_s|)) Bool (or (|uut#10| state) (not true))) ; $assert$smtlib2_module.v:30$21 +(define-fun |uut_a| ((state |uut_s|)) Bool (and + (|uut_a 0| state) + (|uut_a 1| state) + (|uut_a 2| state) + (|smtlib2_a| (|uut_h s| state)) +)) +(define-fun |uut_u| ((state |uut_s|)) Bool + (|smtlib2_u| (|uut_h s| state)) +) +(define-fun |uut_i| ((state |uut_s|)) Bool + (|smtlib2_i| (|uut_h s| state)) +) +(define-fun |uut_h| ((state |uut_s|)) Bool (and + (= (|uut_is| state) (|smtlib2_is| (|uut_h s| state))) + (= (|uut#3| state) (|smtlib2_n a| (|uut_h s| state))) ; smtlib2.a + (= (|uut#0| state) (|smtlib2_n add| (|uut_h s| state))) ; smtlib2.add + (= (|uut#4| state) (|smtlib2_n b| (|uut_h s| state))) ; smtlib2.b + (= (|uut#1| state) (|smtlib2_n eq| (|uut_h s| state))) ; smtlib2.eq + (= (|uut#2| state) (|smtlib2_n sub| (|uut_h s| state))) ; smtlib2.sub + (|smtlib2_h| (|uut_h s| state)) +)) +(define-fun |uut_t| ((state |uut_s|) (next_state |uut_s|)) Bool (and + (= (|uut#4| state) (|uut#4| next_state)) ; $anyconst$5 \b + (= (|uut#3| state) (|uut#3| next_state)) ; $anyconst$4 \a + (|smtlib2_t| (|uut_h s| state) (|uut_h s| next_state)) +)) ; end of module uut +; yosys-smt2-topmod uut +; end of yosys output diff --git a/tests/various/smtlib2_module.sh b/tests/various/smtlib2_module.sh new file mode 100755 index 000000000..491f65148 --- /dev/null +++ b/tests/various/smtlib2_module.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex +../../yosys -q -p 'read_verilog -formal smtlib2_module.v; prep; write_smt2 smtlib2_module.smt2' +sed 's/; SMT-LIBv2 description generated by Yosys .*/; SMT-LIBv2 description generated by Yosys $VERSION/;s/ *$//' smtlib2_module.smt2 > smtlib2_module-filtered.smt2 +diff -au smtlib2_module-expected.smt2 smtlib2_module-filtered.smt2 diff --git a/tests/various/smtlib2_module.v b/tests/various/smtlib2_module.v new file mode 100644 index 000000000..4aad86905 --- /dev/null +++ b/tests/various/smtlib2_module.v @@ -0,0 +1,33 @@ +(* smtlib2_module *) +module smtlib2(a, b, add, sub, eq); + input [7:0] a, b; + (* smtlib2_comb_expr = "(bvadd a b)" *) + output [7:0] add; + (* smtlib2_comb_expr = "(bvadd a (bvneg b))" *) + output [7:0] sub; + (* smtlib2_comb_expr = "(= a b)" *) + output eq; +endmodule + +(* top *) +module uut; + wire [7:0] a = $anyconst, b = $anyconst, add, sub, add2, sub2; + wire eq; + + assign add2 = a + b; + assign sub2 = a - b; + + smtlib2 s ( + .a(a), + .b(b), + .add(add), + .sub(sub), + .eq(eq) + ); + + always @* begin + assert(add == add2); + assert(sub == sub2); + assert(eq == (a == b)); + end +endmodule |